blob: 0f84bfe99a01e6f850fc67d10a06b43adb4f8627 [file] [log] [blame]
Phil Nash89d1e6c2011-05-24 08:23:02 +01001/*
Phil Nash9444bbc2012-10-12 07:58:17 +01002 * Generated: 2012-10-12 07:57:48.487873
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 {
Phil Nash9902ac92012-10-09 20:58:33 +0100916 return m_isFalse;
Phil Nash67305122012-10-09 11:48:55 +0100917 }
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;
Phil Nash9902ac92012-10-09 20:58:33 +0100922 bool m_isFalse;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100923};
924
Phil Nashd31737f2012-05-09 19:04:00 +0100925} // end namespace Catch
926
Phil Nash89d2a3f2012-05-16 15:09:17 +0100927namespace Catch {
Phil Nash176eb812012-05-11 08:17:16 +0100928
929template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100930class Expression {
Phil Nash176eb812012-05-11 08:17:16 +0100931 void operator = ( const Expression& );
932
933public:
934 Expression( ResultInfoBuilder& result, T lhs )
Phil Nash9902ac92012-10-09 20:58:33 +0100935 : m_result( result.setLhs( Catch::toString( lhs ) ) ),
Phil Nash176eb812012-05-11 08:17:16 +0100936 m_lhs( lhs )
937 {}
938
939 template<typename RhsT>
940 ResultInfoBuilder& operator == ( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +0100941 return captureExpression<Internal::IsEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100942 }
943
944 template<typename RhsT>
945 ResultInfoBuilder& operator != ( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +0100946 return captureExpression<Internal::IsNotEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100947 }
948
949 template<typename RhsT>
950 ResultInfoBuilder& operator < ( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +0100951 return captureExpression<Internal::IsLessThan>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100952 }
953
954 template<typename RhsT>
955 ResultInfoBuilder& operator > ( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +0100956 return captureExpression<Internal::IsGreaterThan>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100957 }
958
959 template<typename RhsT>
960 ResultInfoBuilder& operator <= ( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +0100961 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100962 }
963
964 template<typename RhsT>
965 ResultInfoBuilder& operator >= ( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +0100966 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100967 }
968
969 ResultInfoBuilder& operator == ( bool rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +0100970 return captureExpression<Internal::IsEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100971 }
972
973 ResultInfoBuilder& operator != ( bool rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +0100974 return captureExpression<Internal::IsNotEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100975 }
976
977 operator ResultInfoBuilder& () {
Phil Nash9902ac92012-10-09 20:58:33 +0100978 return m_result.setResultType( m_lhs ? ResultWas::Ok : ResultWas::ExpressionFailed );
Phil Nash176eb812012-05-11 08:17:16 +0100979 }
980
981 template<typename RhsT>
982 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( const RhsT& );
983
984 template<typename RhsT>
985 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( const RhsT& );
986
987private:
Phil Nash9902ac92012-10-09 20:58:33 +0100988 template<Internal::Operator Op, typename RhsT>
989 ResultInfoBuilder& captureExpression( const RhsT& rhs ) {
990 return m_result
991 .setResultType( Internal::compare<Op>( m_lhs, rhs ) ? ResultWas::Ok : ResultWas::ExpressionFailed )
992 .setRhs( Catch::toString( rhs ) )
993 .setOp( Internal::OperatorTraits<Op>::getName() );
994 }
995
996private:
Phil Nash176eb812012-05-11 08:17:16 +0100997 ResultInfoBuilder& m_result;
998 T m_lhs;
999};
1000
Phil Nash176eb812012-05-11 08:17:16 +01001001} // end namespace Catch
1002
Phil Nash89d2a3f2012-05-16 15:09:17 +01001003#include <sstream>
1004
1005namespace Catch {
1006
1007class ExpressionBuilder {
1008public:
1009
1010 ExpressionBuilder( const SourceLineInfo& lineInfo,
1011 const char* macroName,
1012 const char* expr = "",
Phil Nash9902ac92012-10-09 20:58:33 +01001013 bool isFalse = false )
Phil Nash67305122012-10-09 11:48:55 +01001014 : m_messageStream()
1015 {
1016 m_result
1017 .setCapturedExpression( expr )
Phil Nash9902ac92012-10-09 20:58:33 +01001018 .setIsFalse( isFalse )
Phil Nash67305122012-10-09 11:48:55 +01001019 .setLineInfo( lineInfo )
1020 .setMacroName( macroName );
1021 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001022
1023 template<typename T>
1024 Expression<const T&> operator->* ( const T & operand ) {
1025 Expression<const T&> expr( m_result, operand );
1026 return expr;
1027 }
1028
Phil Nash89d2a3f2012-05-16 15:09:17 +01001029 Expression<bool> operator->* ( bool value ) {
1030 Expression<bool> expr( m_result, value );
1031 return expr;
1032 }
1033
1034 template<typename T>
1035 ExpressionBuilder& operator << ( const T & value ) {
1036 m_messageStream << Catch::toString( value );
1037 return *this;
1038 }
1039
1040 template<typename MatcherT, typename ArgT>
1041 ExpressionBuilder& acceptMatcher( const MatcherT& matcher,
1042 const ArgT& arg,
1043 const std::string& matcherCallAsString ) {
Phil Nash9444bbc2012-10-12 07:58:17 +01001044 std::string matcherAsString = matcher.toString();
Phil Nash89d2a3f2012-05-16 15:09:17 +01001045 if( matcherAsString == "{?}" )
1046 matcherAsString = matcherCallAsString;
Phil Nash67305122012-10-09 11:48:55 +01001047 m_result
1048 .setLhs( Catch::toString( arg ) )
1049 .setRhs( matcherAsString )
1050 .setOp( "matches" )
Phil Nash9444bbc2012-10-12 07:58:17 +01001051 .setResultType( matcher.match( arg ) ? ResultWas::Ok : ResultWas::ExpressionFailed );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001052 return *this;
1053 }
1054
1055 template<typename MatcherT, typename ArgT>
1056 ExpressionBuilder& acceptMatcher( const MatcherT& matcher,
1057 ArgT* arg,
1058 const std::string& matcherCallAsString ) {
Phil Nash9444bbc2012-10-12 07:58:17 +01001059 std::string matcherAsString = matcher.toString();
Phil Nash89d2a3f2012-05-16 15:09:17 +01001060 if( matcherAsString == "{?}" )
1061 matcherAsString = matcherCallAsString;
Phil Nash67305122012-10-09 11:48:55 +01001062 m_result
1063 .setLhs( Catch::toString( arg ) )
1064 .setRhs( matcherAsString )
1065 .setOp( "matches" )
Phil Nash9444bbc2012-10-12 07:58:17 +01001066 .setResultType( matcher.match( arg ) ? ResultWas::Ok : ResultWas::ExpressionFailed );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001067 return *this;
1068 }
1069
1070 ExpressionBuilder& setResultType( ResultWas::OfType resultType ) {
1071 m_result.setResultType( resultType );
1072 return *this;
1073 }
1074
1075 operator ResultInfoBuilder&() {
1076 m_result.setMessage( m_messageStream.str() );
1077 return m_result;
1078 }
1079
1080private:
1081 ResultInfoBuilder m_result;
1082 std::ostringstream m_messageStream;
1083};
1084
1085} // end namespace Catch
1086
Phil Nashd31737f2012-05-09 19:04:00 +01001087// #included from: catch_interfaces_capture.h
Phil Nash3b80af72012-08-09 07:47:30 +01001088#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01001089
Phil Nashd31737f2012-05-09 19:04:00 +01001090#include <string>
Phil Nasha70fbe32012-08-31 08:10:36 +01001091// #included from: catch_totals.hpp
1092#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
1093
Phil Nash9e7e63c2012-09-29 20:54:03 +01001094#include <cstddef>
1095
Phil Nasha70fbe32012-08-31 08:10:36 +01001096namespace Catch {
1097
1098 struct Counts {
1099 Counts() : passed( 0 ), failed( 0 ) {}
1100
1101 Counts operator - ( const Counts& other ) const {
1102 Counts diff;
1103 diff.passed = passed - other.passed;
1104 diff.failed = failed - other.failed;
1105 return diff;
1106 }
1107 Counts& operator += ( const Counts& other ) {
1108 passed += other.passed;
1109 failed += other.failed;
1110 return *this;
1111 }
1112
1113 std::size_t total() const {
1114 return passed + failed;
1115 }
1116
1117 std::size_t passed;
1118 std::size_t failed;
1119 };
1120
1121 struct Totals {
1122
1123 Totals operator - ( const Totals& other ) const {
1124 Totals diff;
1125 diff.assertions = assertions - other.assertions;
1126 diff.testCases = testCases - other.testCases;
1127 return diff;
1128 }
1129
1130 Totals delta( const Totals& prevTotals ) const {
1131 Totals diff = *this - prevTotals;
1132 if( diff.assertions.failed > 0 )
1133 ++diff.testCases.failed;
1134 else
1135 ++diff.testCases.passed;
1136 return diff;
1137 }
1138
1139 Totals& operator += ( const Totals& other ) {
1140 assertions += other.assertions;
1141 testCases += other.testCases;
1142 return *this;
1143 }
1144
1145 Counts assertions;
1146 Counts testCases;
1147 };
1148}
1149
Phil Nashd31737f2012-05-09 19:04:00 +01001150
Phil Nash89d2a3f2012-05-16 15:09:17 +01001151namespace Catch {
1152
Phil Nashd31737f2012-05-09 19:04:00 +01001153 class TestCaseInfo;
1154 class ScopedInfo;
1155 class ResultInfoBuilder;
1156 class ResultInfo;
1157
Phil Nash89d2a3f2012-05-16 15:09:17 +01001158 struct IResultCapture {
Phil Nashd31737f2012-05-09 19:04:00 +01001159
Phil Nasha695eb92012-08-13 07:46:10 +01001160 virtual ~IResultCapture();
Phil Nashd31737f2012-05-09 19:04:00 +01001161
Phil Nash89d2a3f2012-05-16 15:09:17 +01001162 virtual void testEnded( const ResultInfo& result ) = 0;
1163 virtual bool sectionStarted( const std::string& name,
1164 const std::string& description,
1165 const SourceLineInfo& lineInfo,
1166 Counts& assertions ) = 0;
1167 virtual void sectionEnded( const std::string& name, const Counts& assertions ) = 0;
1168 virtual void pushScopedInfo( ScopedInfo* scopedInfo ) = 0;
1169 virtual void popScopedInfo( ScopedInfo* scopedInfo ) = 0;
1170 virtual bool shouldDebugBreak() const = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001171
Phil Nash89d2a3f2012-05-16 15:09:17 +01001172 virtual ResultAction::Value acceptResult( bool result ) = 0;
1173 virtual ResultAction::Value acceptResult( ResultWas::OfType result ) = 0;
1174 virtual ResultAction::Value acceptExpression( const ResultInfoBuilder& resultInfo ) = 0;
1175 virtual void acceptMessage( const std::string& msg ) = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001176
Phil Nash89d2a3f2012-05-16 15:09:17 +01001177 virtual std::string getCurrentTestName() const = 0;
1178 virtual const ResultInfo* getLastResult() const = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001179 };
1180}
1181
1182// #included from: catch_debugger.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01001183#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01001184
Phil Nashd31737f2012-05-09 19:04:00 +01001185#include <iostream>
1186
1187#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
1188#define CATCH_PLATFORM_MAC
1189#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
1190#define CATCH_PLATFORM_IPHONE
1191#elif defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
1192#define CATCH_PLATFORM_WINDOWS
1193#endif
1194
1195#ifdef CATCH_PLATFORM_MAC
1196
1197 #include <assert.h>
1198 #include <stdbool.h>
1199 #include <sys/types.h>
1200 #include <unistd.h>
1201 #include <sys/sysctl.h>
1202
Phil Nash89d2a3f2012-05-16 15:09:17 +01001203 namespace Catch{
1204
Phil Nashd31737f2012-05-09 19:04:00 +01001205 // The following function is taken directly from the following technical note:
1206 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
1207
Phil Nashd31737f2012-05-09 19:04:00 +01001208 // Returns true if the current process is being debugged (either
1209 // running under the debugger or has a debugger attached post facto).
Phil Nash89d2a3f2012-05-16 15:09:17 +01001210 inline bool isDebuggerActive(){
1211
Phil Nashd31737f2012-05-09 19:04:00 +01001212 int junk;
1213 int mib[4];
1214 struct kinfo_proc info;
1215 size_t size;
1216
1217 // Initialize the flags so that, if sysctl fails for some bizarre
1218 // reason, we get a predictable result.
1219
1220 info.kp_proc.p_flag = 0;
1221
1222 // Initialize mib, which tells sysctl the info we want, in this case
1223 // we're looking for information about a specific process ID.
1224
1225 mib[0] = CTL_KERN;
1226 mib[1] = KERN_PROC;
1227 mib[2] = KERN_PROC_PID;
1228 mib[3] = getpid();
1229
1230 // Call sysctl.
1231
1232 size = sizeof(info);
1233 junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
1234 assert(junk == 0);
1235
1236 // We're being debugged if the P_TRACED flag is set.
1237
1238 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
1239 }
1240 }
1241
1242 // The following code snippet taken from:
1243 // http://cocoawithlove.com/2008/03/break-into-debugger.html
1244 #ifdef DEBUG
1245 #if defined(__ppc64__) || defined(__ppc__)
1246 #define BreakIntoDebugger() \
Phil Nash89d2a3f2012-05-16 15:09:17 +01001247 if( Catch::isDebuggerActive() ) { \
Phil Nashd31737f2012-05-09 19:04:00 +01001248 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
1249 : : : "memory","r0","r3","r4" ); \
1250 }
1251 #else
1252 #define BreakIntoDebugger() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
1253 #endif
1254 #else
1255 inline void BreakIntoDebugger(){}
1256 #endif
1257
1258#elif defined(_MSC_VER)
1259 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
1260 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { __debugbreak(); }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001261 inline bool isDebuggerActive() {
Phil Nashd31737f2012-05-09 19:04:00 +01001262 return IsDebuggerPresent() != 0;
1263 }
Phil Nash176eb812012-05-11 08:17:16 +01001264#elif defined(__MINGW32__)
1265 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
1266 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
1267 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { DebugBreak(); }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001268 inline bool isDebuggerActive() {
Phil Nash176eb812012-05-11 08:17:16 +01001269 return IsDebuggerPresent() != 0;
1270 }
Phil Nashd31737f2012-05-09 19:04:00 +01001271#else
1272 inline void BreakIntoDebugger(){}
1273 inline bool isDebuggerActive() { return false; }
1274#endif
1275
1276#ifdef CATCH_PLATFORM_WINDOWS
1277extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001278inline void writeToDebugConsole( const std::string& text ) {
Phil Nashd31737f2012-05-09 19:04:00 +01001279 ::OutputDebugStringA( text.c_str() );
1280}
1281#else
Phil Nash89d2a3f2012-05-16 15:09:17 +01001282inline void writeToDebugConsole( const std::string& text ) {
Phil Nashd31737f2012-05-09 19:04:00 +01001283 // !TBD: Need a version for Mac/ XCode and other IDEs
1284 std::cout << text;
1285}
1286#endif // CATCH_PLATFORM_WINDOWS
1287
Phil Nash89d2a3f2012-05-16 15:09:17 +01001288#include <ostream>
Phil Nashd31737f2012-05-09 19:04:00 +01001289
Phil Nash89d2a3f2012-05-16 15:09:17 +01001290namespace Catch {
Phil Nashd31737f2012-05-09 19:04:00 +01001291
1292struct TestFailureException{};
Phil Nashd31737f2012-05-09 19:04:00 +01001293
Phil Nash89d2a3f2012-05-16 15:09:17 +01001294class ScopedInfo {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001295public:
Phil Nashd31737f2012-05-09 19:04:00 +01001296 ScopedInfo() : m_oss() {
Phil Nash371db8b2012-05-21 18:52:09 +01001297 getCurrentContext().getResultCapture().pushScopedInfo( this );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001298 }
1299
Phil Nashd31737f2012-05-09 19:04:00 +01001300 ~ScopedInfo() {
Phil Nash371db8b2012-05-21 18:52:09 +01001301 getCurrentContext().getResultCapture().popScopedInfo( this );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001302 }
1303
Phil Nashd31737f2012-05-09 19:04:00 +01001304 template<typename T>
1305 ScopedInfo& operator << ( const T& value ) {
1306 m_oss << value;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001307 return *this;
1308 }
1309
Phil Nash799ecf92012-09-24 08:30:13 +01001310 ResultInfo getInfo () const {
Phil Nash803f6b72012-10-04 08:14:48 +01001311 return ResultInfoBuilder()
1312 .setResultType( ResultWas::Info )
1313 .setMessage( m_oss.str() )
Phil Nash67305122012-10-09 11:48:55 +01001314 .setMacroName( "SCOPED_INFO" )
1315 .build();
Phil Nash89d1e6c2011-05-24 08:23:02 +01001316 }
1317
1318private:
1319 std::ostringstream m_oss;
1320};
1321
Phil Nash89d1e6c2011-05-24 08:23:02 +01001322// This is just here to avoid compiler warnings with macro constants
Phil Nashd31737f2012-05-09 19:04:00 +01001323inline bool isTrue( bool value ){ return value; }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001324
1325} // end namespace Catch
1326
1327///////////////////////////////////////////////////////////////////////////////
Phil Nashd31737f2012-05-09 19:04:00 +01001328#define INTERNAL_CATCH_ACCEPT_EXPR( expr, stopOnFailure, originalExpr ) \
Phil Nashe4636872012-06-05 20:51:05 +01001329 if( Catch::ResultAction::Value internal_catch_action = Catch::getCurrentContext().getResultCapture().acceptExpression( expr ) ) { \
Phil Nash19b2aa62012-06-01 19:40:27 +01001330 if( internal_catch_action & Catch::ResultAction::Debug ) BreakIntoDebugger(); \
1331 if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001332 if( Catch::isTrue( stopOnFailure ) ) throw Catch::TestFailureException(); \
Phil Nashd31737f2012-05-09 19:04:00 +01001333 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 +01001334 }
1335
1336///////////////////////////////////////////////////////////////////////////////
Phil Nash9902ac92012-10-09 20:58:33 +01001337#define INTERNAL_CATCH_TEST( expr, isFalse, stopOnFailure, macroName ) \
Phil Nashe4636872012-06-05 20:51:05 +01001338 do { try { \
Phil Nash9902ac92012-10-09 20:58:33 +01001339 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr, isFalse )->*expr ), stopOnFailure, expr ); \
Phil Nashe4636872012-06-05 20:51:05 +01001340 } catch( Catch::TestFailureException& ) { \
Phil Nash333e6e62012-02-17 19:50:59 +00001341 throw; \
Phil Nashe4636872012-06-05 20:51:05 +01001342 } catch( ... ) { \
Phil Nash3b80af72012-08-09 07:47:30 +01001343 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 +00001344 throw; \
Phil Nashe4636872012-06-05 20:51:05 +01001345 } } while( Catch::isTrue( false ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01001346
1347///////////////////////////////////////////////////////////////////////////////
Phil Nash9902ac92012-10-09 20:58:33 +01001348#define INTERNAL_CATCH_IF( expr, isFalse, stopOnFailure, macroName ) \
1349 INTERNAL_CATCH_TEST( expr, isFalse, stopOnFailure, macroName ); \
Phil Nash371db8b2012-05-21 18:52:09 +01001350 if( Catch::getCurrentContext().getResultCapture().getLastResult()->ok() )
Phil Nasha162e222012-02-10 08:30:13 +00001351
1352///////////////////////////////////////////////////////////////////////////////
Phil Nash9902ac92012-10-09 20:58:33 +01001353#define INTERNAL_CATCH_ELSE( expr, isFalse, stopOnFailure, macroName ) \
1354 INTERNAL_CATCH_TEST( expr, isFalse, stopOnFailure, macroName ); \
Phil Nash371db8b2012-05-21 18:52:09 +01001355 if( !Catch::getCurrentContext().getResultCapture().getLastResult()->ok() )
Phil Nasha162e222012-02-10 08:30:13 +00001356
1357///////////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01001358#define INTERNAL_CATCH_NO_THROW( expr, stopOnFailure, macroName ) \
Phil Nashe4636872012-06-05 20:51:05 +01001359 try { \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001360 expr; \
Phil Nash89d2a3f2012-05-16 15:09:17 +01001361 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure, false ); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001362 } \
Phil Nashe4636872012-06-05 20:51:05 +01001363 catch( ... ) { \
Phil Nash3b80af72012-08-09 07:47:30 +01001364 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 +01001365 }
1366
1367///////////////////////////////////////////////////////////////////////////////
1368#define INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \
Phil Nashe4636872012-06-05 20:51:05 +01001369 try { \
1370 if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \
1371 expr; \
1372 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::DidntThrowException ), stopOnFailure, false ); \
1373 } \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001374 } \
Phil Nashe4636872012-06-05 20:51:05 +01001375 catch( Catch::TestFailureException& ) { \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001376 throw; \
1377 } \
Phil Nashe4636872012-06-05 20:51:05 +01001378 catch( exceptionType ) { \
Phil Nash89d2a3f2012-05-16 15:09:17 +01001379 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure, false ); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001380 }
1381
1382///////////////////////////////////////////////////////////////////////////////
1383#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, stopOnFailure, macroName ) \
1384 INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \
Phil Nashe4636872012-06-05 20:51:05 +01001385 catch( ... ) { \
Phil Nash3b80af72012-08-09 07:47:30 +01001386 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 +01001387 }
1388
1389///////////////////////////////////////////////////////////////////////////////
1390#define INTERNAL_CATCH_MSG( reason, resultType, stopOnFailure, macroName ) \
Phil Nash371db8b2012-05-21 18:52:09 +01001391 Catch::getCurrentContext().getResultCapture().acceptExpression( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName ) << reason ).setResultType( resultType ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001392
1393///////////////////////////////////////////////////////////////////////////////
1394#define INTERNAL_CATCH_SCOPED_INFO( log ) \
1395 Catch::ScopedInfo INTERNAL_CATCH_UNIQUE_NAME( info ); \
1396 INTERNAL_CATCH_UNIQUE_NAME( info ) << log
1397
Phil Nash78d95a02012-03-04 21:22:36 +00001398///////////////////////////////////////////////////////////////////////////////
1399#define INTERNAL_CHECK_THAT( arg, matcher, stopOnFailure, macroName ) \
Phil Nashe4636872012-06-05 20:51:05 +01001400 do { try { \
Phil Nasha8570df2012-05-24 08:29:41 +01001401 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 +01001402 } catch( Catch::TestFailureException& ) { \
Phil Nash78d95a02012-03-04 21:22:36 +00001403 throw; \
Phil Nashe4636872012-06-05 20:51:05 +01001404 } catch( ... ) { \
Phil Nash3b80af72012-08-09 07:47:30 +01001405 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 +00001406 throw; \
1407 }}while( Catch::isTrue( false ) )
1408
Phil Nash89d1e6c2011-05-24 08:23:02 +01001409// #included from: internal/catch_section.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01001410#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01001411
Phil Nash89d1e6c2011-05-24 08:23:02 +01001412#include <string>
1413
Phil Nash89d2a3f2012-05-16 15:09:17 +01001414namespace Catch {
1415
1416 class Section {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001417 public:
Phil Nash89d2a3f2012-05-16 15:09:17 +01001418 Section( const std::string& name,
1419 const std::string& description,
1420 const SourceLineInfo& lineInfo )
Phil Nash89d1e6c2011-05-24 08:23:02 +01001421 : m_name( name ),
Phil Nash371db8b2012-05-21 18:52:09 +01001422 m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( name, description, lineInfo, m_assertions ) )
Phil Nash89d2a3f2012-05-16 15:09:17 +01001423 {}
Phil Nash89d1e6c2011-05-24 08:23:02 +01001424
Phil Nash89d2a3f2012-05-16 15:09:17 +01001425 ~Section() {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001426 if( m_sectionIncluded )
Phil Nash371db8b2012-05-21 18:52:09 +01001427 getCurrentContext().getResultCapture().sectionEnded( m_name, m_assertions );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001428 }
1429
Phil Nash89d1e6c2011-05-24 08:23:02 +01001430 // This indicates whether the section should be executed or not
Phil Nash89d2a3f2012-05-16 15:09:17 +01001431 operator bool() {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001432 return m_sectionIncluded;
1433 }
1434
1435 private:
1436
1437 std::string m_name;
Phil Nashf7299fc2012-02-25 09:39:45 +00001438 Counts m_assertions;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001439 bool m_sectionIncluded;
1440 };
1441
1442} // end namespace Catch
1443
1444#define INTERNAL_CATCH_SECTION( name, desc ) \
Phil Nashd31737f2012-05-09 19:04:00 +01001445 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( name, desc, CATCH_INTERNAL_LINEINFO ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01001446
1447// #included from: internal/catch_generators.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01001448#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01001449
Phil Nash89d1e6c2011-05-24 08:23:02 +01001450#include <iterator>
1451#include <vector>
1452#include <string>
1453#include <stdlib.h>
1454
Phil Nash89d2a3f2012-05-16 15:09:17 +01001455namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001456
1457template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001458struct IGenerator {
1459 virtual ~IGenerator() {}
1460 virtual T getValue( std::size_t index ) const = 0;
1461 virtual std::size_t size () const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001462};
1463
1464template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001465class BetweenGenerator : public IGenerator<T> {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001466public:
Phil Nash89d2a3f2012-05-16 15:09:17 +01001467 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
Phil Nash89d1e6c2011-05-24 08:23:02 +01001468
Phil Nash89d2a3f2012-05-16 15:09:17 +01001469 virtual T getValue( std::size_t index ) const {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001470 return m_from+static_cast<T>( index );
1471 }
1472
Phil Nash89d2a3f2012-05-16 15:09:17 +01001473 virtual std::size_t size() const {
Phil Nashd31737f2012-05-09 19:04:00 +01001474 return static_cast<std::size_t>( 1+m_to-m_from );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001475 }
1476
1477private:
1478
1479 T m_from;
1480 T m_to;
1481};
1482
1483template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001484class ValuesGenerator : public IGenerator<T> {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001485public:
Phil Nash89d2a3f2012-05-16 15:09:17 +01001486 ValuesGenerator(){}
Phil Nash89d1e6c2011-05-24 08:23:02 +01001487
Phil Nash89d2a3f2012-05-16 15:09:17 +01001488 void add( T value ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001489 m_values.push_back( value );
1490 }
1491
Phil Nash89d2a3f2012-05-16 15:09:17 +01001492 virtual T getValue( std::size_t index ) const {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001493 return m_values[index];
1494 }
1495
Phil Nash89d2a3f2012-05-16 15:09:17 +01001496 virtual std::size_t size() const {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001497 return m_values.size();
1498 }
1499
1500private:
Phil Nash89d1e6c2011-05-24 08:23:02 +01001501 std::vector<T> m_values;
1502};
1503
1504template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001505class CompositeGenerator {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001506public:
Phil Nash89d2a3f2012-05-16 15:09:17 +01001507 CompositeGenerator() : m_totalSize( 0 ) {}
Phil Nash89d1e6c2011-05-24 08:23:02 +01001508
Phil Nash89d1e6c2011-05-24 08:23:02 +01001509 // *** Move semantics, similar to auto_ptr ***
1510 CompositeGenerator( CompositeGenerator& other )
Phil Nash89d2a3f2012-05-16 15:09:17 +01001511 : m_fileInfo( other.m_fileInfo ),
1512 m_totalSize( 0 )
Phil Nash89d1e6c2011-05-24 08:23:02 +01001513 {
1514 move( other );
1515 }
1516
Phil Nash89d2a3f2012-05-16 15:09:17 +01001517 CompositeGenerator& setFileInfo( const char* fileInfo ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001518 m_fileInfo = fileInfo;
1519 return *this;
1520 }
1521
Phil Nash89d2a3f2012-05-16 15:09:17 +01001522 ~CompositeGenerator() {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001523 deleteAll( m_composed );
1524 }
1525
Phil Nash89d2a3f2012-05-16 15:09:17 +01001526 operator T () const {
Phil Nash371db8b2012-05-21 18:52:09 +01001527 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001528
1529 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
1530 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
1531 for( size_t index = 0; it != itEnd; ++it )
1532 {
1533 const IGenerator<T>* generator = *it;
1534 if( overallIndex >= index && overallIndex < index + generator->size() )
1535 {
1536 return generator->getValue( overallIndex-index );
1537 }
1538 index += generator->size();
1539 }
1540 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
1541 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
1542 }
1543
Phil Nash89d2a3f2012-05-16 15:09:17 +01001544 void add( const IGenerator<T>* generator ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001545 m_totalSize += generator->size();
1546 m_composed.push_back( generator );
1547 }
1548
Phil Nash89d2a3f2012-05-16 15:09:17 +01001549 CompositeGenerator& then( CompositeGenerator& other ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001550 move( other );
1551 return *this;
1552 }
1553
Phil Nash89d2a3f2012-05-16 15:09:17 +01001554 CompositeGenerator& then( T value ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001555 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1556 valuesGen->add( value );
1557 add( valuesGen );
1558 return *this;
1559 }
1560
1561private:
1562
Phil Nash89d2a3f2012-05-16 15:09:17 +01001563 void move( CompositeGenerator& other ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001564 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
1565 m_totalSize += other.m_totalSize;
1566 other.m_composed.clear();
1567 }
1568
1569 std::vector<const IGenerator<T>*> m_composed;
1570 std::string m_fileInfo;
1571 size_t m_totalSize;
1572};
1573
1574namespace Generators
1575{
Phil Nash89d1e6c2011-05-24 08:23:02 +01001576 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001577 CompositeGenerator<T> between( T from, T to ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001578 CompositeGenerator<T> generators;
1579 generators.add( new BetweenGenerator<T>( from, to ) );
1580 return generators;
1581 }
1582
Phil Nash89d1e6c2011-05-24 08:23:02 +01001583 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001584 CompositeGenerator<T> values( T val1, T val2 ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001585 CompositeGenerator<T> generators;
1586 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1587 valuesGen->add( val1 );
1588 valuesGen->add( val2 );
1589 generators.add( valuesGen );
1590 return generators;
1591 }
1592
Phil Nash89d1e6c2011-05-24 08:23:02 +01001593 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001594 CompositeGenerator<T> values( T val1, T val2, T val3 ){
Phil Nash89d1e6c2011-05-24 08:23:02 +01001595 CompositeGenerator<T> generators;
1596 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1597 valuesGen->add( val1 );
1598 valuesGen->add( val2 );
1599 valuesGen->add( val3 );
1600 generators.add( valuesGen );
1601 return generators;
1602 }
1603
Phil Nash89d1e6c2011-05-24 08:23:02 +01001604 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001605 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001606 CompositeGenerator<T> generators;
1607 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1608 valuesGen->add( val1 );
1609 valuesGen->add( val2 );
1610 valuesGen->add( val3 );
1611 valuesGen->add( val4 );
1612 generators.add( valuesGen );
1613 return generators;
1614 }
1615
1616} // end namespace Generators
1617
1618using namespace Generators;
1619
1620} // end namespace Catch
1621
1622#define INTERNAL_CATCH_LINESTR2( line ) #line
1623#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
1624
1625#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
1626
1627// #included from: internal/catch_interfaces_exception.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04001628#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01001629
Phil Nash89d1e6c2011-05-24 08:23:02 +01001630#include <string>
Phil Nash3b80af72012-08-09 07:47:30 +01001631// #included from: catch_interfaces_registry_hub.h
1632#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
1633
Phil Nasha70fbe32012-08-31 08:10:36 +01001634// #included from: catch_interfaces_reporter.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04001635#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001636
1637// #included from: catch_config.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04001638#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001639
1640// #included from: catch_test_spec.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04001641#define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001642
1643// #included from: catch_test_case_info.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04001644#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001645
1646#include <string>
Phil Nashfc1baac2012-09-15 17:53:27 +01001647#include <set>
Phil Nasha70fbe32012-08-31 08:10:36 +01001648
1649namespace Catch {
1650
1651 struct ITestCase;
1652
1653 class TestCaseInfo {
1654 public:
1655 TestCaseInfo();
1656
1657 TestCaseInfo( ITestCase* testCase,
1658 const char* name,
1659 const char* description,
1660 const SourceLineInfo& lineInfo );
1661
1662 TestCaseInfo( const TestCaseInfo& other, const std::string& name );
1663 TestCaseInfo( const TestCaseInfo& other );
1664
1665 void invoke() const;
1666 const std::string& getName() const;
1667 const std::string& getDescription() const;
1668 const SourceLineInfo& getLineInfo() const;
1669 bool isHidden() const;
Phil Nashfc1baac2012-09-15 17:53:27 +01001670 bool hasTag( const std::string& tag ) const;
Phil Nash799ecf92012-09-24 08:30:13 +01001671 bool matchesTags( const std::string& tagPattern ) const;
Phil Nash67ec8702012-09-26 18:38:26 +01001672 const std::set<std::string>& getTags() const;
Phil Nasha70fbe32012-08-31 08:10:36 +01001673
1674 void swap( TestCaseInfo& other );
1675 bool operator == ( const TestCaseInfo& other ) const;
1676 bool operator < ( const TestCaseInfo& other ) const;
1677 TestCaseInfo& operator = ( const TestCaseInfo& other );
1678
1679 private:
1680 Ptr<ITestCase> m_test;
1681 std::string m_name;
1682 std::string m_description;
Phil Nashfc1baac2012-09-15 17:53:27 +01001683 std::set<std::string> m_tags;
Phil Nasha70fbe32012-08-31 08:10:36 +01001684 SourceLineInfo m_lineInfo;
Phil Nashfc1baac2012-09-15 17:53:27 +01001685 bool m_isHidden;
Phil Nasha70fbe32012-08-31 08:10:36 +01001686 };
1687}
1688
Phil Nash67ec8702012-09-26 18:38:26 +01001689// #included from: catch_tags.hpp
1690#define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED
1691
1692#include <string>
1693#include <set>
1694#include <map>
1695#include <vector>
1696
1697#ifdef __clang__
1698#pragma clang diagnostic ignored "-Wpadded"
1699#endif
1700
1701namespace Catch {
1702 class TagParser {
1703 public:
1704 virtual ~TagParser();
1705
1706 void parse( const std::string& str ) {
1707 std::size_t pos = 0;
1708 while( pos < str.size() ) {
1709 char c = str[pos];
1710 if( c == '[' ) {
1711 std::size_t end = str.find_first_of( ']', pos );
1712 if( end != std::string::npos ) {
1713 acceptTag( str.substr( pos+1, end-pos-1 ) );
1714 pos = end+1;
1715 }
1716 else {
1717 acceptChar( c );
1718 pos++;
1719 }
1720 }
1721 else {
1722 acceptChar( c );
1723 pos++;
1724 }
1725 }
1726 endParse();
1727 }
1728
1729 protected:
1730 virtual void acceptTag( const std::string& tag ) = 0;
1731 virtual void acceptChar( char c ) = 0;
1732 virtual void endParse() {}
1733
1734 private:
1735 };
1736
1737 class TagExtracter : public TagParser {
1738 public:
1739
1740 TagExtracter( std::set<std::string>& tags )
1741 : m_tags( tags )
1742 {}
1743 virtual ~TagExtracter();
1744
1745 void parse( std::string& description ) {
1746 TagParser::parse( description );
1747 description = m_remainder;
1748 }
1749
1750 private:
1751 virtual void acceptTag( const std::string& tag ) {
1752 m_tags.insert( tag );
1753 }
1754 virtual void acceptChar( char c ) {
1755 m_remainder += c;
1756 }
1757
1758 std::set<std::string>& m_tags;
1759 std::string m_remainder;
1760 };
1761
1762 class Tag {
1763 public:
1764 Tag()
1765 : m_isNegated( false )
1766 {}
1767
1768 Tag( const std::string& name, bool isNegated )
1769 : m_name( name ),
1770 m_isNegated( isNegated )
1771 {}
1772
1773 std::string getName() const {
1774 return m_name;
1775 }
1776 bool isNegated() const {
1777 return m_isNegated;
1778 }
1779
1780 bool operator ! () const {
1781 return m_name.empty();
1782 }
1783
1784 private:
1785 std::string m_name;
1786 bool m_isNegated;
1787 };
1788
1789 class TagSet {
1790 typedef std::map<std::string, Tag> TagMap;
1791 public:
1792 void add( const Tag& tag ) {
1793 m_tags.insert( std::make_pair( tag.getName(), tag ) );
1794 }
1795
Phil Nash67ec8702012-09-26 18:38:26 +01001796 bool empty() const {
1797 return m_tags.empty();
1798 }
1799
1800 bool matches( const std::set<std::string>& tags ) const {
1801 TagMap::const_iterator it = m_tags.begin();
1802 TagMap::const_iterator itEnd = m_tags.end();
1803 for(; it != itEnd; ++it ) {
1804 bool found = tags.find( it->first ) != tags.end();
1805 if( found == it->second.isNegated() )
1806 return false;
1807 }
1808 return true;
1809 }
1810
1811 private:
1812 TagMap m_tags;
1813 };
1814
1815 class TagExpression {
1816 public:
1817 bool matches( const std::set<std::string>& tags ) const {
1818 std::vector<TagSet>::const_iterator it = m_tagSets.begin();
1819 std::vector<TagSet>::const_iterator itEnd = m_tagSets.end();
1820 for(; it != itEnd; ++it )
1821 if( it->matches( tags ) )
1822 return true;
1823 return false;
1824 }
1825
1826 private:
1827 friend class TagExpressionParser;
1828
1829 std::vector<TagSet> m_tagSets;
1830 };
1831
1832 class TagExpressionParser : public TagParser {
1833 public:
1834 TagExpressionParser( TagExpression& exp )
1835 : m_isNegated( false ),
1836 m_exp( exp )
1837 {}
1838
1839 ~TagExpressionParser();
1840
1841 private:
1842 virtual void acceptTag( const std::string& tag ) {
1843 m_currentTagSet.add( Tag( tag, m_isNegated ) );
1844 m_isNegated = false;
1845 }
1846 virtual void acceptChar( char c ) {
1847 switch( c ) {
1848 case '~':
1849 m_isNegated = true;
1850 break;
1851 case ',':
1852 m_exp.m_tagSets.push_back( m_currentTagSet );
1853 break;
1854 }
1855 }
1856 virtual void endParse() {
1857 if( !m_currentTagSet.empty() )
1858 m_exp.m_tagSets.push_back( m_currentTagSet );
1859 }
1860
1861 bool m_isNegated;
1862 TagSet m_currentTagSet;
1863 TagExpression& m_exp;
1864 };
1865
1866} // end namespace Catch
1867
Phil Nasha70fbe32012-08-31 08:10:36 +01001868#include <string>
1869#include <vector>
1870
1871namespace Catch {
1872
1873 struct IfFilterMatches{ enum DoWhat {
Phil Nashe2d215e2012-09-07 17:52:35 +01001874 AutoDetectBehaviour,
Phil Nasha70fbe32012-08-31 08:10:36 +01001875 IncludeTests,
1876 ExcludeTests
1877 }; };
1878
1879 class TestCaseFilter {
1880 enum WildcardPosition {
1881 NoWildcard = 0,
1882 WildcardAtStart = 1,
1883 WildcardAtEnd = 2,
1884 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
1885 };
1886
1887 public:
Phil Nashe2d215e2012-09-07 17:52:35 +01001888 TestCaseFilter( const std::string& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::AutoDetectBehaviour )
Phil Nasha70fbe32012-08-31 08:10:36 +01001889 : m_stringToMatch( testSpec ),
1890 m_filterType( matchBehaviour ),
1891 m_wildcardPosition( NoWildcard )
1892 {
Phil Nashe2d215e2012-09-07 17:52:35 +01001893 if( m_filterType == IfFilterMatches::AutoDetectBehaviour ) {
1894 if( startsWith( m_stringToMatch, "exclude:" ) ) {
1895 m_stringToMatch = m_stringToMatch.substr( 8 );
1896 m_filterType = IfFilterMatches::ExcludeTests;
1897 }
1898 else if( startsWith( m_stringToMatch, "~" ) ) {
1899 m_stringToMatch = m_stringToMatch.substr( 1 );
1900 m_filterType = IfFilterMatches::ExcludeTests;
1901 }
1902 else {
1903 m_filterType = IfFilterMatches::IncludeTests;
1904 }
1905 }
1906
Phil Nasha70fbe32012-08-31 08:10:36 +01001907 if( m_stringToMatch[0] == '*' ) {
1908 m_stringToMatch = m_stringToMatch.substr( 1 );
1909 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtStart );
1910 }
1911 if( m_stringToMatch[m_stringToMatch.size()-1] == '*' ) {
1912 m_stringToMatch = m_stringToMatch.substr( 0, m_stringToMatch.size()-1 );
1913 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtEnd );
1914 }
1915 }
1916
1917 IfFilterMatches::DoWhat getFilterType() const {
1918 return m_filterType;
1919 }
1920
1921 bool shouldInclude( const TestCaseInfo& testCase ) const {
1922 return isMatch( testCase ) == (m_filterType == IfFilterMatches::IncludeTests);
1923 }
1924 private:
1925
1926#ifdef __clang__
1927#pragma clang diagnostic push
1928#pragma clang diagnostic ignored "-Wunreachable-code"
1929#endif
1930
1931 bool isMatch( const TestCaseInfo& testCase ) const {
1932 const std::string& name = testCase.getName();
1933
1934 switch( m_wildcardPosition ) {
1935 case NoWildcard:
1936 return m_stringToMatch == name;
1937 case WildcardAtStart:
1938 return endsWith( name, m_stringToMatch );
1939 case WildcardAtEnd:
1940 return startsWith( name, m_stringToMatch );
1941 case WildcardAtBothEnds:
1942 return contains( name, m_stringToMatch );
1943 }
1944 throw std::logic_error( "Unhandled wildcard type" );
1945 }
1946
1947#ifdef __clang__
1948#pragma clang diagnostic pop
1949#endif
1950
1951 std::string m_stringToMatch;
1952 IfFilterMatches::DoWhat m_filterType;
1953 WildcardPosition m_wildcardPosition;
1954 };
1955
1956 class TestCaseFilters {
1957 public:
1958 TestCaseFilters( const std::string& name ) : m_name( name ) {}
1959
1960 std::string getName() const {
1961 return m_name;
1962 }
1963
1964 void addFilter( const TestCaseFilter& filter ) {
1965 if( filter.getFilterType() == IfFilterMatches::ExcludeTests )
1966 m_exclusionFilters.push_back( filter );
1967 else
1968 m_inclusionFilters.push_back( filter );
1969 }
1970
Phil Nash67ec8702012-09-26 18:38:26 +01001971 void addTags( const std::string& tagPattern ) {
1972 TagExpression exp;
1973 TagExpressionParser( exp ).parse( tagPattern );
1974
1975 m_tagExpressions.push_back( exp );
1976 }
1977
Phil Nasha70fbe32012-08-31 08:10:36 +01001978 bool shouldInclude( const TestCaseInfo& testCase ) const {
Phil Nash67ec8702012-09-26 18:38:26 +01001979 if( !m_tagExpressions.empty() ) {
1980 std::vector<TagExpression>::const_iterator it = m_tagExpressions.begin();
1981 std::vector<TagExpression>::const_iterator itEnd = m_tagExpressions.end();
1982 for(; it != itEnd; ++it )
1983 if( it->matches( testCase.getTags() ) )
1984 break;
1985 if( it == itEnd )
1986 return false;
1987 }
1988
Phil Nasha70fbe32012-08-31 08:10:36 +01001989 if( !m_inclusionFilters.empty() ) {
1990 std::vector<TestCaseFilter>::const_iterator it = m_inclusionFilters.begin();
1991 std::vector<TestCaseFilter>::const_iterator itEnd = m_inclusionFilters.end();
1992 for(; it != itEnd; ++it )
1993 if( it->shouldInclude( testCase ) )
1994 break;
1995 if( it == itEnd )
1996 return false;
1997 }
Phil Nash67ec8702012-09-26 18:38:26 +01001998 else if( m_exclusionFilters.empty() && m_tagExpressions.empty() ) {
Phil Nashfc1baac2012-09-15 17:53:27 +01001999 return !testCase.isHidden();
2000 }
2001
Phil Nasha70fbe32012-08-31 08:10:36 +01002002 std::vector<TestCaseFilter>::const_iterator it = m_exclusionFilters.begin();
2003 std::vector<TestCaseFilter>::const_iterator itEnd = m_exclusionFilters.end();
2004 for(; it != itEnd; ++it )
2005 if( !it->shouldInclude( testCase ) )
2006 return false;
2007 return true;
2008 }
2009 private:
Phil Nash67ec8702012-09-26 18:38:26 +01002010 std::vector<TagExpression> m_tagExpressions;
Phil Nasha70fbe32012-08-31 08:10:36 +01002011 std::vector<TestCaseFilter> m_inclusionFilters;
2012 std::vector<TestCaseFilter> m_exclusionFilters;
2013 std::string m_name;
2014 };
2015
2016}
2017
2018// #included from: catch_interfaces_config.h
2019#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
2020
2021namespace Catch {
2022
2023 struct IConfig {
2024
2025 virtual ~IConfig();
2026
2027 virtual bool allowThrows() const = 0;
2028 };
2029}
2030
Phil Nash67ec8702012-09-26 18:38:26 +01002031// #included from: catch_stream.hpp
2032#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
2033
Phil Nash9e7e63c2012-09-29 20:54:03 +01002034// #included from: catch_streambuf.h
2035#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
2036
2037#include <streambuf>
2038
2039namespace Catch {
2040
2041 class StreamBufBase : public std::streambuf {
2042 public:
2043 virtual ~StreamBufBase();
2044 };
2045}
2046
Phil Nash67ec8702012-09-26 18:38:26 +01002047#include <stdexcept>
2048#include <cstdio>
2049
2050namespace Catch {
2051
2052 template<typename WriterF, size_t bufferSize=256>
2053 class StreamBufImpl : public StreamBufBase {
2054 char data[bufferSize];
2055 WriterF m_writer;
2056
2057 public:
2058 StreamBufImpl() {
2059 setp( data, data + sizeof(data) );
2060 }
2061
2062 ~StreamBufImpl() {
2063 sync();
2064 }
2065
2066 private:
2067 int overflow( int c ) {
2068 sync();
2069
2070 if( c != EOF ) {
2071 if( pbase() == epptr() )
2072 m_writer( std::string( 1, static_cast<char>( c ) ) );
2073 else
2074 sputc( static_cast<char>( c ) );
2075 }
2076 return 0;
2077 }
2078
2079 int sync() {
2080 if( pbase() != pptr() ) {
2081 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
2082 setp( pbase(), epptr() );
2083 }
2084 return 0;
2085 }
2086 };
2087
2088 ///////////////////////////////////////////////////////////////////////////
2089
2090 struct OutputDebugWriter {
2091
2092 void operator()( const std::string &str ) {
2093 writeToDebugConsole( str );
2094 }
2095 };
2096
2097 class Stream {
2098 public:
2099 Stream()
2100 : streamBuf( NULL ), isOwned( false )
2101 {}
2102
2103 Stream( std::streambuf* _streamBuf, bool _isOwned )
2104 : streamBuf( _streamBuf ), isOwned( _isOwned )
2105 {}
2106
2107 void release() {
2108 if( isOwned ) {
2109 delete streamBuf;
2110 streamBuf = NULL;
2111 isOwned = false;
2112 }
2113 }
2114
2115 std::streambuf* streamBuf;
2116
2117 private:
2118 bool isOwned;
2119 };
2120}
2121
Phil Nasha70fbe32012-08-31 08:10:36 +01002122#include <memory>
2123#include <vector>
2124#include <string>
2125#include <iostream>
2126
2127namespace Catch {
2128
2129 struct Include { enum WhichResults {
2130 FailedOnly,
2131 SuccessfulResults
2132 }; };
2133
2134 struct List{ enum What {
2135 None = 0,
2136
2137 Reports = 1,
2138 Tests = 2,
2139 All = 3,
2140
2141 TestNames = 6,
2142
2143 WhatMask = 0xf,
2144
2145 AsText = 0x10,
2146 AsXml = 0x20,
2147
2148 AsMask = 0xf0
2149 }; };
2150
2151 struct ConfigData {
2152
2153 struct WarnAbout { enum What {
2154 Nothing = 0x00,
2155 NoAssertions = 0x01
2156 }; };
2157
2158 ConfigData()
2159 : listSpec( List::None ),
2160 shouldDebugBreak( false ),
2161 includeWhichResults( Include::FailedOnly ),
2162 cutoff( -1 ),
2163 allowThrows( true ),
2164 warnings( WarnAbout::Nothing )
2165 {}
2166
2167 std::string reporter;
2168 std::string outputFilename;
2169 List::What listSpec;
2170 std::vector<TestCaseFilters> filters;
2171 bool shouldDebugBreak;
2172 std::string stream;
2173 Include::WhichResults includeWhichResults;
2174 std::string name;
2175 int cutoff;
2176 bool allowThrows;
2177 WarnAbout::What warnings;
2178 };
2179
2180 class Config : public IConfig {
2181 private:
2182 Config( const Config& other );
2183 Config& operator = ( const Config& other );
2184 virtual void dummy();
2185 public:
2186
2187 Config()
Phil Nash67ec8702012-09-26 18:38:26 +01002188 : m_os( std::cout.rdbuf() )
Phil Nasha70fbe32012-08-31 08:10:36 +01002189 {}
2190
2191 Config( const ConfigData& data )
2192 : m_data( data ),
Phil Nasha70fbe32012-08-31 08:10:36 +01002193 m_os( std::cout.rdbuf() )
2194 {}
2195
2196 virtual ~Config() {
2197 m_os.rdbuf( std::cout.rdbuf() );
Phil Nash67ec8702012-09-26 18:38:26 +01002198 m_stream.release();
Phil Nasha70fbe32012-08-31 08:10:36 +01002199 }
2200
2201 void setFilename( const std::string& filename ) {
2202 m_data.outputFilename = filename;
2203 }
2204
2205 List::What getListSpec( void ) const {
2206 return m_data.listSpec;
2207 }
2208
2209 const std::string& getFilename() const {
2210 return m_data.outputFilename ;
2211 }
2212
2213 List::What listWhat() const {
2214 return static_cast<List::What>( m_data.listSpec & List::WhatMask );
2215 }
2216
2217 List::What listAs() const {
2218 return static_cast<List::What>( m_data.listSpec & List::AsMask );
2219 }
2220
2221 std::string getName() const {
2222 return m_data.name;
2223 }
2224
2225 bool shouldDebugBreak() const {
2226 return m_data.shouldDebugBreak;
2227 }
2228
2229 virtual std::ostream& stream() const {
2230 return m_os;
2231 }
2232
2233 void setStreamBuf( std::streambuf* buf ) {
2234 m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
2235 }
2236
2237 void useStream( const std::string& streamName ) {
Phil Nash67ec8702012-09-26 18:38:26 +01002238 Stream stream = createStream( streamName );
2239 setStreamBuf( stream.streamBuf );
2240 m_stream.release();
2241 m_stream = stream;
Phil Nasha70fbe32012-08-31 08:10:36 +01002242 }
2243
Phil Nashe2d215e2012-09-07 17:52:35 +01002244 void addTestSpec( const std::string& testSpec ) {
2245 TestCaseFilters filters( testSpec );
2246 filters.addFilter( TestCaseFilter( testSpec ) );
2247 m_data.filters.push_back( filters );
2248 }
2249
Phil Nasha70fbe32012-08-31 08:10:36 +01002250 virtual bool includeSuccessfulResults() const {
2251 return m_data.includeWhichResults == Include::SuccessfulResults;
2252 }
2253
2254 int getCutoff() const {
2255 return m_data.cutoff;
2256 }
2257
2258 virtual bool allowThrows() const {
2259 return m_data.allowThrows;
2260 }
2261
2262 const ConfigData& data() const {
2263 return m_data;
2264 }
2265 ConfigData& data() {
2266 return m_data;
2267 }
2268
2269 private:
2270 ConfigData m_data;
2271
2272 // !TBD Move these out of here
Phil Nash67ec8702012-09-26 18:38:26 +01002273 Stream m_stream;
Phil Nasha70fbe32012-08-31 08:10:36 +01002274 mutable std::ostream m_os;
2275 };
2276
2277} // end namespace Catch
2278
2279#include <string>
2280#include <ostream>
2281#include <map>
2282
2283namespace Catch
2284{
2285 struct ReporterConfig
2286 {
2287 ReporterConfig( const std::string& _name,
2288 std::ostream& _stream,
2289 bool _includeSuccessfulResults,
2290 const ConfigData& _fullConfig )
2291 : name( _name ),
2292 stream( _stream ),
2293 includeSuccessfulResults( _includeSuccessfulResults ),
2294 fullConfig( _fullConfig )
2295 {}
2296
Phil Nash799ecf92012-09-24 08:30:13 +01002297 ReporterConfig( const ReporterConfig& other )
2298 : name( other.name ),
2299 stream( other.stream ),
2300 includeSuccessfulResults( other.includeSuccessfulResults ),
2301 fullConfig( other.fullConfig )
2302 {}
2303
Phil Nasha70fbe32012-08-31 08:10:36 +01002304 std::string name;
2305 std::ostream& stream;
2306 bool includeSuccessfulResults;
2307 ConfigData fullConfig;
Phil Nash799ecf92012-09-24 08:30:13 +01002308
2309 private:
2310 void operator=(const ReporterConfig&);
Phil Nasha70fbe32012-08-31 08:10:36 +01002311 };
2312
2313 class TestCaseInfo;
2314 class ResultInfo;
2315
2316 struct IReporter : IShared {
2317 virtual ~IReporter();
2318 virtual bool shouldRedirectStdout() const = 0;
2319 virtual void StartTesting() = 0;
2320 virtual void EndTesting( const Totals& totals ) = 0;
2321 virtual void StartGroup( const std::string& groupName ) = 0;
2322 virtual void EndGroup( const std::string& groupName, const Totals& totals ) = 0;
2323 virtual void StartSection( const std::string& sectionName, const std::string& description ) = 0;
2324 virtual void NoAssertionsInSection( const std::string& sectionName ) = 0;
2325 virtual void NoAssertionsInTestCase( const std::string& testName ) = 0;
2326 virtual void EndSection( const std::string& sectionName, const Counts& assertions ) = 0;
2327 virtual void StartTestCase( const TestCaseInfo& testInfo ) = 0;
2328 virtual void Aborted() = 0;
2329 virtual void EndTestCase( const TestCaseInfo& testInfo, const Totals& totals, const std::string& stdOut, const std::string& stdErr ) = 0;
2330 virtual void Result( const ResultInfo& result ) = 0;
2331 };
2332
2333 struct IReporterFactory {
2334 virtual ~IReporterFactory();
2335 virtual IReporter* create( const ReporterConfig& config ) const = 0;
2336 virtual std::string getDescription() const = 0;
2337 };
2338
2339 struct IReporterRegistry {
2340 typedef std::map<std::string, IReporterFactory*> FactoryMap;
2341
2342 virtual ~IReporterRegistry();
2343 virtual IReporter* create( const std::string& name, const ReporterConfig& config ) const = 0;
2344 virtual const FactoryMap& getFactories() const = 0;
2345 };
2346
2347 inline std::string trim( const std::string& str ) {
2348 std::string::size_type start = str.find_first_not_of( "\n\r\t " );
2349 std::string::size_type end = str.find_last_not_of( "\n\r\t " );
2350
2351 return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
2352 }
2353}
2354
Phil Nash3b80af72012-08-09 07:47:30 +01002355#include <vector>
Phil Nash3b80af72012-08-09 07:47:30 +01002356
2357namespace Catch {
2358
2359 class TestCaseInfo;
Phil Nash3b80af72012-08-09 07:47:30 +01002360 struct ITestCaseRegistry;
2361 struct IExceptionTranslatorRegistry;
2362 struct IExceptionTranslator;
2363
2364 struct IRegistryHub {
Phil Nasha695eb92012-08-13 07:46:10 +01002365 virtual ~IRegistryHub();
Phil Nash3b80af72012-08-09 07:47:30 +01002366
2367 virtual const IReporterRegistry& getReporterRegistry() const = 0;
2368 virtual const ITestCaseRegistry& getTestCaseRegistry() const = 0;
2369 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
2370 };
2371
2372 struct IMutableRegistryHub {
Phil Nasha695eb92012-08-13 07:46:10 +01002373 virtual ~IMutableRegistryHub();
Phil Nash3b80af72012-08-09 07:47:30 +01002374 virtual void registerReporter( const std::string& name, IReporterFactory* factory ) = 0;
2375 virtual void registerTest( const TestCaseInfo& testInfo ) = 0;
2376 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
2377 };
2378
2379 IRegistryHub& getRegistryHub();
2380 IMutableRegistryHub& getMutableRegistryHub();
2381 void cleanUp();
2382}
2383
Phil Nash89d1e6c2011-05-24 08:23:02 +01002384
Phil Nash89d2a3f2012-05-16 15:09:17 +01002385namespace Catch {
2386
Phil Nash89d1e6c2011-05-24 08:23:02 +01002387 typedef std::string(*exceptionTranslateFunction)();
2388
Phil Nash89d2a3f2012-05-16 15:09:17 +01002389 struct IExceptionTranslator {
Phil Nasha695eb92012-08-13 07:46:10 +01002390 virtual ~IExceptionTranslator();
Phil Nash89d1e6c2011-05-24 08:23:02 +01002391 virtual std::string translate() const = 0;
2392 };
2393
Phil Nash89d2a3f2012-05-16 15:09:17 +01002394 struct IExceptionTranslatorRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +01002395 virtual ~IExceptionTranslatorRegistry();
Phil Nash89d1e6c2011-05-24 08:23:02 +01002396
Phil Nash89d2a3f2012-05-16 15:09:17 +01002397 virtual std::string translateActiveException() const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002398 };
2399
Phil Nash89d2a3f2012-05-16 15:09:17 +01002400 class ExceptionTranslatorRegistrar {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002401 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01002402 class ExceptionTranslator : public IExceptionTranslator {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002403 public:
2404
Phil Nash89d2a3f2012-05-16 15:09:17 +01002405 ExceptionTranslator( std::string(*translateFunction)( T& ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002406 : m_translateFunction( translateFunction )
2407 {}
2408
Phil Nash89d2a3f2012-05-16 15:09:17 +01002409 virtual std::string translate() const {
2410 try {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002411 throw;
2412 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01002413 catch( T& ex ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002414 return m_translateFunction( ex );
2415 }
2416 }
2417
2418 protected:
2419 std::string(*m_translateFunction)( T& );
2420 };
2421
2422 public:
2423 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01002424 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
Phil Nash3b80af72012-08-09 07:47:30 +01002425 getMutableRegistryHub().registerTranslator
Phil Nash89d1e6c2011-05-24 08:23:02 +01002426 ( new ExceptionTranslator<T>( translateFunction ) );
2427 }
2428 };
2429}
2430
2431///////////////////////////////////////////////////////////////////////////////
2432#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
2433 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
2434 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
2435 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
2436
2437// #included from: internal/catch_approx.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002438#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01002439
Phil Nash89d1e6c2011-05-24 08:23:02 +01002440#include <cmath>
2441#include <limits>
2442
Phil Nash89d2a3f2012-05-16 15:09:17 +01002443namespace Catch {
2444namespace Detail {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002445
Phil Nash89d2a3f2012-05-16 15:09:17 +01002446 class Approx {
2447 public:
2448 explicit Approx ( double value )
2449 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
2450 m_scale( 1.0 ),
2451 m_value( value )
2452 {}
Phil Nashf721a962011-06-07 14:13:57 +01002453
Phil Nash89d2a3f2012-05-16 15:09:17 +01002454 Approx( const Approx& other )
2455 : m_epsilon( other.m_epsilon ),
2456 m_scale( other.m_scale ),
2457 m_value( other.m_value )
2458 {}
Phil Nashf721a962011-06-07 14:13:57 +01002459
Phil Nash89d2a3f2012-05-16 15:09:17 +01002460 static Approx custom() {
2461 return Approx( 0 );
2462 }
Phil Nashf721a962011-06-07 14:13:57 +01002463
Phil Nash89d2a3f2012-05-16 15:09:17 +01002464 Approx operator()( double value ) {
2465 Approx approx( value );
2466 approx.epsilon( m_epsilon );
2467 approx.scale( m_scale );
2468 return approx;
2469 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002470
Phil Nash89d2a3f2012-05-16 15:09:17 +01002471 friend bool operator == ( double lhs, const Approx& rhs ) {
2472 // Thanks to Richard Harris for his help refining this formula
2473 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
2474 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002475
Phil Nash89d2a3f2012-05-16 15:09:17 +01002476 friend bool operator == ( const Approx& lhs, double rhs ) {
2477 return operator==( rhs, lhs );
2478 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002479
Phil Nash89d2a3f2012-05-16 15:09:17 +01002480 friend bool operator != ( double lhs, const Approx& rhs ) {
2481 return !operator==( lhs, rhs );
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 Approx& epsilon( double newEpsilon ) {
2489 m_epsilon = newEpsilon;
2490 return *this;
2491 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002492
Phil Nash89d2a3f2012-05-16 15:09:17 +01002493 Approx& scale( double newScale ) {
2494 m_scale = newScale;
2495 return *this;
2496 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002497
Phil Nash89d2a3f2012-05-16 15:09:17 +01002498 std::string toString() const {
2499 std::ostringstream oss;
Phil Nash67305122012-10-09 11:48:55 +01002500 oss << "Approx( " << m_value << " )";
Phil Nash89d2a3f2012-05-16 15:09:17 +01002501 return oss.str();
2502 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002503
Phil Nash89d2a3f2012-05-16 15:09:17 +01002504 private:
2505 double m_epsilon;
2506 double m_scale;
2507 double m_value;
2508 };
2509}
2510
2511template<>
2512inline std::string toString<Detail::Approx>( const Detail::Approx& value ) {
2513 return value.toString();
2514}
Phil Nash89d1e6c2011-05-24 08:23:02 +01002515
2516} // end namespace Catch
2517
Phil Nash371db8b2012-05-21 18:52:09 +01002518// #included from: internal/catch_matchers.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002519#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01002520
2521namespace Catch {
2522namespace Matchers {
2523 namespace Impl {
Phil Nash9444bbc2012-10-12 07:58:17 +01002524
2525 template<typename ExpressionT>
2526 struct Matcher : SharedImpl<IShared>
2527 {
2528 virtual ~Matcher() {}
2529 virtual Ptr<Matcher> clone() const = 0;
2530 virtual bool match( const ExpressionT& expr ) const = 0;
2531 virtual std::string toString() const = 0;
2532 };
2533
2534 template<typename DerivedT, typename ExpressionT>
2535 struct MatcherImpl : Matcher<ExpressionT> {
2536
2537 virtual Ptr<Matcher<ExpressionT> > clone() const {
2538 return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<const DerivedT&>( *this ) ) );
2539 }
2540 };
2541
2542 namespace Generic {
2543
2544 template<typename ExpressionT>
2545 class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
2546 public:
2547
2548 AllOf() {}
2549 AllOf( const AllOf& other ) : m_matchers( other.m_matchers ) {}
2550
2551 AllOf& add( const Matcher<ExpressionT>& matcher ) {
2552 m_matchers.push_back( matcher.clone() );
2553 return *this;
2554 }
2555 virtual bool match( const ExpressionT& expr ) const
2556 {
2557 for( std::size_t i = 0; i < m_matchers.size(); ++i )
2558 if( !m_matchers[i]->match( expr ) )
2559 return false;
2560 return true;
2561 }
2562 virtual std::string toString() const {
2563 std::ostringstream oss;
2564 oss << "( ";
2565 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
2566 if( i != 0 )
2567 oss << " and ";
2568 oss << m_matchers[i]->toString();
2569 }
2570 oss << " )";
2571 return oss.str();
2572 }
2573
2574 private:
2575 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
2576 };
2577
2578 template<typename ExpressionT>
2579 class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
2580 public:
2581
2582 AnyOf() {}
2583 AnyOf( const AnyOf& other ) : m_matchers( other.m_matchers ) {}
2584
2585 AnyOf& add( const Matcher<ExpressionT>& matcher ) {
2586 m_matchers.push_back( matcher.clone() );
2587 return *this;
2588 }
2589 virtual bool match( const ExpressionT& expr ) const
2590 {
2591 for( std::size_t i = 0; i < m_matchers.size(); ++i )
2592 if( m_matchers[i]->match( expr ) )
2593 return true;
2594 return false;
2595 }
2596 virtual std::string toString() const {
2597 std::ostringstream oss;
2598 oss << "( ";
2599 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
2600 if( i != 0 )
2601 oss << " or ";
2602 oss << m_matchers[i]->toString();
2603 }
2604 oss << " )";
2605 return oss.str();
2606 }
2607
2608 private:
2609 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
2610 };
2611
2612 }
2613
Phil Nash371db8b2012-05-21 18:52:09 +01002614 namespace StdString {
2615
Phil Nash9444bbc2012-10-12 07:58:17 +01002616 struct Equals : MatcherImpl<Equals, std::string> {
Phil Nasha8570df2012-05-24 08:29:41 +01002617 Equals( const std::string& str ) : m_str( str ){}
Phil Nash9444bbc2012-10-12 07:58:17 +01002618 Equals( const Equals& other ) : m_str( other.m_str ){}
Phil Nasha8570df2012-05-24 08:29:41 +01002619
Phil Nash9444bbc2012-10-12 07:58:17 +01002620 virtual ~Equals();
2621
2622 virtual bool match( const std::string& expr ) const {
2623 return m_str == expr;
2624 }
2625 virtual std::string toString() const {
2626 return "equals: \"" + m_str + "\"";
Phil Nasha8570df2012-05-24 08:29:41 +01002627 }
2628
Phil Nasha8570df2012-05-24 08:29:41 +01002629 std::string m_str;
2630 };
2631
Phil Nash9444bbc2012-10-12 07:58:17 +01002632 struct Contains : MatcherImpl<Contains, std::string> {
Phil Nash371db8b2012-05-21 18:52:09 +01002633 Contains( const std::string& substr ) : m_substr( substr ){}
Phil Nash9444bbc2012-10-12 07:58:17 +01002634 Contains( const Contains& other ) : m_substr( other.m_substr ){}
Phil Nash371db8b2012-05-21 18:52:09 +01002635
Phil Nash9444bbc2012-10-12 07:58:17 +01002636 virtual ~Contains();
2637
2638 virtual bool match( const std::string& expr ) const {
2639 return expr.find( m_substr ) != std::string::npos;
2640 }
2641 virtual std::string toString() const {
2642 return "contains: \"" + m_substr + "\"";
Phil Nash371db8b2012-05-21 18:52:09 +01002643 }
2644
Phil Nash371db8b2012-05-21 18:52:09 +01002645 std::string m_substr;
2646 };
2647
Phil Nash9444bbc2012-10-12 07:58:17 +01002648 struct StartsWith : MatcherImpl<StartsWith, std::string> {
Phil Nash371db8b2012-05-21 18:52:09 +01002649 StartsWith( const std::string& substr ) : m_substr( substr ){}
Phil Nash9444bbc2012-10-12 07:58:17 +01002650 StartsWith( const StartsWith& other ) : m_substr( other.m_substr ){}
Phil Nash371db8b2012-05-21 18:52:09 +01002651
Phil Nash9444bbc2012-10-12 07:58:17 +01002652 virtual ~StartsWith();
2653
2654 virtual bool match( const std::string& expr ) const {
2655 return expr.find( m_substr ) == 0;
2656 }
2657 virtual std::string toString() const {
2658 return "starts with: \"" + m_substr + "\"";
Phil Nash371db8b2012-05-21 18:52:09 +01002659 }
2660
Phil Nash371db8b2012-05-21 18:52:09 +01002661 std::string m_substr;
2662 };
2663
Phil Nash9444bbc2012-10-12 07:58:17 +01002664 struct EndsWith : MatcherImpl<EndsWith, std::string> {
Phil Nash371db8b2012-05-21 18:52:09 +01002665 EndsWith( const std::string& substr ) : m_substr( substr ){}
Phil Nash9444bbc2012-10-12 07:58:17 +01002666 EndsWith( const EndsWith& other ) : m_substr( other.m_substr ){}
Phil Nash371db8b2012-05-21 18:52:09 +01002667
Phil Nash9444bbc2012-10-12 07:58:17 +01002668 virtual ~EndsWith();
2669
2670 virtual bool match( const std::string& expr ) const {
2671 return expr.find( m_substr ) == expr.size() - m_substr.size();
2672 }
2673 virtual std::string toString() const {
2674 return "ends with: \"" + m_substr + "\"";
Phil Nash371db8b2012-05-21 18:52:09 +01002675 }
2676
Phil Nash371db8b2012-05-21 18:52:09 +01002677 std::string m_substr;
2678 };
2679 } // namespace StdString
2680 } // namespace Impl
2681
Phil Nash9444bbc2012-10-12 07:58:17 +01002682 // The following functions create the actual matcher objects.
2683 // This allows the types to be inferred
2684 template<typename ExpressionT>
2685 inline Impl::Generic::AllOf<ExpressionT> AllOf( const Impl::Matcher<ExpressionT>& m1,
2686 const Impl::Matcher<ExpressionT>& m2 ) {
2687 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
2688 }
2689 template<typename ExpressionT>
2690 inline Impl::Generic::AllOf<ExpressionT> AllOf( const Impl::Matcher<ExpressionT>& m1,
2691 const Impl::Matcher<ExpressionT>& m2,
2692 const Impl::Matcher<ExpressionT>& m3 ) {
2693 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
2694 }
2695 template<typename ExpressionT>
2696 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( const Impl::Matcher<ExpressionT>& m1,
2697 const Impl::Matcher<ExpressionT>& m2 ) {
2698 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
2699 }
2700 template<typename ExpressionT>
2701 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( const Impl::Matcher<ExpressionT>& m1,
2702 const Impl::Matcher<ExpressionT>& m2,
2703 const Impl::Matcher<ExpressionT>& m3 ) {
2704 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
2705 }
2706
Phil Nasha8570df2012-05-24 08:29:41 +01002707 inline Impl::StdString::Equals Equals( const std::string& str ){ return Impl::StdString::Equals( str ); }
Phil Nash371db8b2012-05-21 18:52:09 +01002708 inline Impl::StdString::Contains Contains( const std::string& substr ){ return Impl::StdString::Contains( substr ); }
2709 inline Impl::StdString::StartsWith StartsWith( const std::string& substr ){ return Impl::StdString::StartsWith( substr ); }
2710 inline Impl::StdString::EndsWith EndsWith( const std::string& substr ){ return Impl::StdString::EndsWith( substr ); }
2711
2712} // namespace Matchers
2713
2714using namespace Matchers;
2715
2716} // namespace Catch
2717
Phil Nash0f9c5512012-06-02 23:12:42 +01002718// These files are included here so the single_include script doesn't put them
2719// in the conditionally compiled sections
Phil Nash0f9c5512012-06-02 23:12:42 +01002720// #included from: internal/catch_interfaces_runner.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04002721#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
Phil Nash0f9c5512012-06-02 23:12:42 +01002722
2723#include <string>
2724
2725namespace Catch {
2726 class TestCaseInfo;
2727
2728 struct IRunner {
Phil Nasha695eb92012-08-13 07:46:10 +01002729 virtual ~IRunner();
Phil Nash0f9c5512012-06-02 23:12:42 +01002730 };
2731}
2732
2733
Phil Nash371db8b2012-05-21 18:52:09 +01002734#ifdef __OBJC__
2735// #included from: internal/catch_objc.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002736#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01002737
Phil Nash371db8b2012-05-21 18:52:09 +01002738#import <objc/runtime.h>
2739
2740#include <string>
2741
2742// NB. Any general catch headers included here must be included
2743// in catch.hpp first to make sure they are included by the single
2744// header for non obj-usage
Phil Nash81528252011-08-15 09:06:31 +01002745
Phil Nash83224e62011-08-12 18:53:28 +01002746///////////////////////////////////////////////////////////////////////////////
2747// This protocol is really only here for (self) documenting purposes, since
2748// all its methods are optional.
2749@protocol OcFixture
2750
2751@optional
2752
2753-(void) setUp;
2754-(void) tearDown;
2755
2756@end
2757
Phil Nash89d2a3f2012-05-16 15:09:17 +01002758namespace Catch {
Phil Nash83224e62011-08-12 18:53:28 +01002759
Phil Nash5bc030d2012-08-16 18:48:50 +01002760 class OcMethod : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002761
2762 public:
2763 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
2764
2765 virtual void invoke() const {
Phil Nash53c990a2012-03-17 18:20:06 +00002766 id obj = [[m_cls alloc] init];
Phil Nash83224e62011-08-12 18:53:28 +01002767
Phil Nash53c990a2012-03-17 18:20:06 +00002768 performOptionalSelector( obj, @selector(setUp) );
2769 performOptionalSelector( obj, m_sel );
2770 performOptionalSelector( obj, @selector(tearDown) );
Phil Nash83224e62011-08-12 18:53:28 +01002771
Phil Nash53c990a2012-03-17 18:20:06 +00002772 arcSafeRelease( obj );
Phil Nash83224e62011-08-12 18:53:28 +01002773 }
Phil Nash83224e62011-08-12 18:53:28 +01002774 private:
Phil Nash5bc030d2012-08-16 18:48:50 +01002775 virtual ~OcMethod() {}
2776
Phil Nash83224e62011-08-12 18:53:28 +01002777 Class m_cls;
2778 SEL m_sel;
2779 };
2780
Phil Nash89d2a3f2012-05-16 15:09:17 +01002781 namespace Detail{
Phil Nash83224e62011-08-12 18:53:28 +01002782
Phil Nash89d2a3f2012-05-16 15:09:17 +01002783 inline bool startsWith( const std::string& str, const std::string& sub ) {
Phil Nash83224e62011-08-12 18:53:28 +01002784 return str.length() > sub.length() && str.substr( 0, sub.length() ) == sub;
2785 }
2786
Phil Nash89d2a3f2012-05-16 15:09:17 +01002787 inline std::string getAnnotation( Class cls,
2788 const std::string& annotationName,
2789 const std::string& testCaseName ) {
Phil Nash83224e62011-08-12 18:53:28 +01002790 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2791 SEL sel = NSSelectorFromString( selStr );
Phil Nash53c990a2012-03-17 18:20:06 +00002792 arcSafeRelease( selStr );
2793 id value = performOptionalSelector( cls, sel );
2794 if( value )
2795 return [(NSString*)value UTF8String];
Phil Nash83224e62011-08-12 18:53:28 +01002796 return "";
2797 }
2798 }
2799
Phil Nash89d2a3f2012-05-16 15:09:17 +01002800 inline size_t registerTestMethods() {
Phil Nash83224e62011-08-12 18:53:28 +01002801 size_t noTestMethods = 0;
2802 int noClasses = objc_getClassList( NULL, 0 );
2803
Phil Nash861a1e72012-04-28 12:29:52 +01002804 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
Phil Nash53c990a2012-03-17 18:20:06 +00002805 objc_getClassList( classes, noClasses );
Phil Nash83224e62011-08-12 18:53:28 +01002806
Phil Nash89d2a3f2012-05-16 15:09:17 +01002807 for( int c = 0; c < noClasses; c++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01002808 Class cls = classes[c];
2809 {
2810 u_int count;
2811 Method* methods = class_copyMethodList( cls, &count );
Phil Nash7004f4a2012-05-22 08:56:59 +01002812 for( u_int m = 0; m < count ; m++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01002813 SEL selector = method_getName(methods[m]);
2814 std::string methodName = sel_getName(selector);
Phil Nash89d2a3f2012-05-16 15:09:17 +01002815 if( Detail::startsWith( methodName, "Catch_TestCase_" ) ) {
Phil Nash83224e62011-08-12 18:53:28 +01002816 std::string testCaseName = methodName.substr( 15 );
Phil Nash53c990a2012-03-17 18:20:06 +00002817 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
2818 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
Phil Nash83224e62011-08-12 18:53:28 +01002819
Phil Nash3b80af72012-08-09 07:47:30 +01002820 getMutableRegistryHub().registerTest( TestCaseInfo( new OcMethod( cls, selector ), name.c_str(), desc.c_str(), SourceLineInfo() ) );
Phil Nash83224e62011-08-12 18:53:28 +01002821 noTestMethods++;
Phil Nash83224e62011-08-12 18:53:28 +01002822 }
2823 }
2824 free(methods);
2825 }
2826 }
2827 return noTestMethods;
2828 }
Phil Nash78d95a02012-03-04 21:22:36 +00002829
Phil Nash89d2a3f2012-05-16 15:09:17 +01002830 namespace Matchers {
2831 namespace Impl {
2832 namespace NSStringMatchers {
2833
2834 struct StringHolder {
Phil Nash78d95a02012-03-04 21:22:36 +00002835 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
Phil Nash89d2a3f2012-05-16 15:09:17 +01002836 StringHolder() {
Phil Nash53c990a2012-03-17 18:20:06 +00002837 arcSafeRelease( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00002838 }
2839
2840 NSString* m_substr;
2841 };
2842
Phil Nash89d2a3f2012-05-16 15:09:17 +01002843 struct Equals : StringHolder {
Phil Nash8d18d162012-03-14 20:06:14 +00002844 Equals( NSString* substr ) : StringHolder( substr ){}
2845
Phil Nash89d2a3f2012-05-16 15:09:17 +01002846 bool operator()( NSString* str ) const {
Phil Nash8d18d162012-03-14 20:06:14 +00002847 return [str isEqualToString:m_substr];
2848 }
2849
Phil Nash89d2a3f2012-05-16 15:09:17 +01002850 friend std::ostream& operator<<( std::ostream& os, const Equals& matcher ) {
Phil Nash8d18d162012-03-14 20:06:14 +00002851 os << "equals string: " << Catch::toString( matcher.m_substr );
2852 return os;
2853 }
2854 };
2855
Phil Nash89d2a3f2012-05-16 15:09:17 +01002856 struct Contains : StringHolder {
Phil Nash78d95a02012-03-04 21:22:36 +00002857 Contains( NSString* substr ) : StringHolder( substr ){}
2858
Phil Nash89d2a3f2012-05-16 15:09:17 +01002859 bool operator()( NSString* str ) const {
Phil Nash78d95a02012-03-04 21:22:36 +00002860 return [str rangeOfString:m_substr].location != NSNotFound;
2861 }
2862
Phil Nash89d2a3f2012-05-16 15:09:17 +01002863 friend std::ostream& operator<<( std::ostream& os, const Contains& matcher ) {
Phil Nash78d95a02012-03-04 21:22:36 +00002864 os << "contains: " << Catch::toString( matcher.m_substr );
2865 return os;
2866 }
2867 };
2868
Phil Nash89d2a3f2012-05-16 15:09:17 +01002869 struct StartsWith : StringHolder {
Phil Nash78d95a02012-03-04 21:22:36 +00002870 StartsWith( NSString* substr ) : StringHolder( substr ){}
2871
Phil Nash89d2a3f2012-05-16 15:09:17 +01002872 bool operator()( NSString* str ) const {
Phil Nash78d95a02012-03-04 21:22:36 +00002873 return [str rangeOfString:m_substr].location == 0;
2874 }
2875
Phil Nash89d2a3f2012-05-16 15:09:17 +01002876 friend std::ostream& operator<<( std::ostream& os, const StartsWith& matcher ) {
Phil Nash78d95a02012-03-04 21:22:36 +00002877 os << "starts with: " << Catch::toString( matcher.m_substr );
2878 return os;
2879 }
2880 };
Phil Nash89d2a3f2012-05-16 15:09:17 +01002881 struct EndsWith : StringHolder {
Phil Nash78d95a02012-03-04 21:22:36 +00002882 EndsWith( NSString* substr ) : StringHolder( substr ){}
2883
Phil Nash89d2a3f2012-05-16 15:09:17 +01002884 bool operator()( NSString* str ) const {
Phil Nash78d95a02012-03-04 21:22:36 +00002885 return [str rangeOfString:m_substr].location == [str length] - [m_substr length];
2886 }
2887
Phil Nash89d2a3f2012-05-16 15:09:17 +01002888 friend std::ostream& operator<<( std::ostream& os, const EndsWith& matcher ) {
Phil Nash78d95a02012-03-04 21:22:36 +00002889 os << "ends with: " << Catch::toString( matcher.m_substr );
2890 return os;
2891 }
2892 };
2893
2894 } // namespace NSStringMatchers
2895 } // namespace Impl
2896
Phil Nash8d18d162012-03-14 20:06:14 +00002897 inline Impl::NSStringMatchers::Equals
2898 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
2899
Phil Nash78d95a02012-03-04 21:22:36 +00002900 inline Impl::NSStringMatchers::Contains
2901 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00002902
Phil Nash78d95a02012-03-04 21:22:36 +00002903 inline Impl::NSStringMatchers::StartsWith
2904 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00002905
Phil Nash78d95a02012-03-04 21:22:36 +00002906 inline Impl::NSStringMatchers::EndsWith
2907 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
2908
2909 } // namespace Matchers
2910
2911 using namespace Matchers;
2912
2913} // namespace Catch
Phil Nash83224e62011-08-12 18:53:28 +01002914
2915///////////////////////////////////////////////////////////////////////////////
2916#define OC_TEST_CASE( name, desc )\
Phil Nash53c990a2012-03-17 18:20:06 +00002917+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01002918{\
Phil Nash53c990a2012-03-17 18:20:06 +00002919return @ name; \
Phil Nash83224e62011-08-12 18:53:28 +01002920}\
Phil Nash53c990a2012-03-17 18:20:06 +00002921+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01002922{ \
Phil Nash53c990a2012-03-17 18:20:06 +00002923return @ desc; \
Phil Nash83224e62011-08-12 18:53:28 +01002924} \
2925-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
2926
2927#endif
2928
2929#if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER )
Phil Nasha695eb92012-08-13 07:46:10 +01002930// #included from: internal/catch_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04002931#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01002932
2933// Collect all the implementation files together here
2934// These are the equivalent of what would usually be cpp files
2935
Phil Nash5bc030d2012-08-16 18:48:50 +01002936#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01002937#pragma clang diagnostic push
2938#pragma clang diagnostic ignored "-Wweak-vtables"
Phil Nash5bc030d2012-08-16 18:48:50 +01002939#endif
Phil Nasha695eb92012-08-13 07:46:10 +01002940
Phil Nash83224e62011-08-12 18:53:28 +01002941// #included from: catch_runner.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002942#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
Phil Nash83224e62011-08-12 18:53:28 +01002943
Phil Nasha695eb92012-08-13 07:46:10 +01002944// #included from: internal/catch_commandline.hpp
2945#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
2946
Phil Nasha695eb92012-08-13 07:46:10 +01002947namespace Catch {
2948
2949 class Command {
2950 public:
2951 Command(){}
2952
Phil Nashecf934b2012-08-27 21:42:55 +01002953 explicit Command( const std::string& name ) : m_name( name ) {
2954 }
Phil Nasha695eb92012-08-13 07:46:10 +01002955
2956 Command& operator += ( const std::string& arg ) {
2957 m_args.push_back( arg );
2958 return *this;
2959 }
2960 Command& operator += ( const Command& other ) {
2961 std::copy( other.m_args.begin(), other.m_args.end(), std::back_inserter( m_args ) );
2962 if( m_name.empty() )
2963 m_name = other.m_name;
2964 return *this;
2965 }
2966 Command operator + ( const Command& other ) {
2967 Command newCommand( *this );
2968 newCommand += other;
2969 return newCommand;
2970 }
2971
2972 operator SafeBool::type() const {
Phil Nashe571e6f2012-08-24 18:54:56 +01002973 return SafeBool::makeSafe( !m_name.empty() || !m_args.empty() );
Phil Nasha695eb92012-08-13 07:46:10 +01002974 }
2975
2976 std::string name() const { return m_name; }
2977 std::string operator[]( std::size_t i ) const { return m_args[i]; }
2978 std::size_t argsCount() const { return m_args.size(); }
2979
2980 CATCH_ATTRIBUTE_NORETURN
2981 void raiseError( const std::string& message ) const {
2982 std::ostringstream oss;
Phil Nashecf934b2012-08-27 21:42:55 +01002983 if( m_name.empty() )
2984 oss << "Error while parsing " << m_name << ". " << message << ".";
2985 else
2986 oss << "Error while parsing arguments. " << message << ".";
2987
Phil Nasha695eb92012-08-13 07:46:10 +01002988 if( m_args.size() > 0 )
Phil Nashecf934b2012-08-27 21:42:55 +01002989 oss << " Arguments were:";
Phil Nasha695eb92012-08-13 07:46:10 +01002990 for( std::size_t i = 0; i < m_args.size(); ++i )
2991 oss << " " << m_args[i];
2992 throw std::domain_error( oss.str() );
2993 }
2994
2995 private:
2996
2997 std::string m_name;
2998 std::vector<std::string> m_args;
2999 };
3000
3001 class CommandParser {
3002 public:
3003 CommandParser( int argc, char const * const * argv ) : m_argc( static_cast<std::size_t>( argc ) ), m_argv( argv ) {}
3004
Phil Nashe2d215e2012-09-07 17:52:35 +01003005 std::string exeName() const {
3006 return m_argv[0];
3007 }
Phil Nasha695eb92012-08-13 07:46:10 +01003008 Command find( const std::string& arg1, const std::string& arg2, const std::string& arg3 ) const {
3009 return find( arg1 ) + find( arg2 ) + find( arg3 );
3010 }
3011
3012 Command find( const std::string& shortArg, const std::string& longArg ) const {
3013 return find( shortArg ) + find( longArg );
3014 }
3015 Command find( const std::string& arg ) const {
Phil Nashecf934b2012-08-27 21:42:55 +01003016 if( arg.empty() )
3017 return getArgs( "", 1 );
3018 else
3019 for( std::size_t i = 1; i < m_argc; ++i )
3020 if( m_argv[i] == arg )
3021 return getArgs( m_argv[i], i+1 );
Phil Nasha695eb92012-08-13 07:46:10 +01003022 return Command();
3023 }
Phil Nashe571e6f2012-08-24 18:54:56 +01003024 Command getDefaultArgs() const {
3025 return getArgs( "", 1 );
3026 }
Phil Nasha695eb92012-08-13 07:46:10 +01003027
3028 private:
Phil Nashe571e6f2012-08-24 18:54:56 +01003029 Command getArgs( const std::string& cmdName, std::size_t from ) const {
3030 Command command( cmdName );
3031 for( std::size_t i = from; i < m_argc && m_argv[i][0] != '-'; ++i )
Phil Nasha695eb92012-08-13 07:46:10 +01003032 command += m_argv[i];
3033 return command;
3034 }
3035
3036 std::size_t m_argc;
3037 char const * const * m_argv;
3038 };
3039
Phil Nashecf934b2012-08-27 21:42:55 +01003040 class OptionParser : public SharedImpl<IShared> {
3041 public:
3042 OptionParser( int minArgs = 0, int maxArgs = 0 )
3043 : m_minArgs( minArgs ), m_maxArgs( maxArgs )
3044 {}
Phil Nasha695eb92012-08-13 07:46:10 +01003045
Phil Nashecf934b2012-08-27 21:42:55 +01003046 virtual ~OptionParser() {}
Phil Nasha695eb92012-08-13 07:46:10 +01003047
Phil Nashecf934b2012-08-27 21:42:55 +01003048 Command find( const CommandParser& parser ) const {
3049 Command cmd;
3050 for( std::vector<std::string>::const_iterator it = m_optionNames.begin();
3051 it != m_optionNames.end();
3052 ++it )
3053 cmd += parser.find( *it );
3054 return cmd;
3055 }
3056
3057 void validateArgs( const Command& args ) const {
3058 if( tooFewArgs( args ) || tooManyArgs( args ) ) {
3059 std::ostringstream oss;
3060 if( m_maxArgs == -1 )
3061 oss <<"Expected at least " << pluralise( static_cast<std::size_t>( m_minArgs ), "argument" );
3062 else if( m_minArgs == m_maxArgs )
3063 oss <<"Expected " << pluralise( static_cast<std::size_t>( m_minArgs ), "argument" );
Phil Nasha695eb92012-08-13 07:46:10 +01003064 else
Phil Nashecf934b2012-08-27 21:42:55 +01003065 oss <<"Expected between " << m_minArgs << " and " << m_maxArgs << " argument";
3066 args.raiseError( oss.str() );
Phil Nasha695eb92012-08-13 07:46:10 +01003067 }
Phil Nashecf934b2012-08-27 21:42:55 +01003068 }
3069
3070 void parseIntoConfig( const CommandParser& parser, ConfigData& config ) {
3071 if( Command cmd = find( parser ) ) {
3072 validateArgs( cmd );
3073 parseIntoConfig( cmd, config );
3074 }
3075 }
3076
3077 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) = 0;
3078 virtual std::string argsSynopsis() const = 0;
3079 virtual std::string optionSummary() const = 0;
Phil Nashe2d215e2012-09-07 17:52:35 +01003080 virtual std::string optionDescription() const { return ""; };
Phil Nashecf934b2012-08-27 21:42:55 +01003081
3082 std::string optionNames() const {
3083 std::string names;
3084 for( std::vector<std::string>::const_iterator it = m_optionNames.begin();
3085 it != m_optionNames.end();
3086 ++it ) {
3087 if( !it->empty() ) {
3088 if( !names.empty() )
3089 names += ", ";
3090 names += *it;
3091 }
3092 else {
3093 names = "[" + names;
3094 }
3095 }
3096 if( names[0] == '[' )
3097 names += "]";
3098 return names;
3099 }
3100
3101 protected:
3102
3103 bool tooFewArgs( const Command& args ) const {
3104 return args.argsCount() < static_cast<std::size_t>( m_minArgs );
3105 }
3106 bool tooManyArgs( const Command& args ) const {
3107 return m_maxArgs >= 0 && args.argsCount() > static_cast<std::size_t>( m_maxArgs );
3108 }
3109 std::vector<std::string> m_optionNames;
3110 int m_minArgs;
3111 int m_maxArgs;
3112 };
3113
3114 namespace Options {
3115
3116 class HelpOptionParser : public OptionParser {
3117 public:
3118 HelpOptionParser() {
3119 m_optionNames.push_back( "-?" );
3120 m_optionNames.push_back( "-h" );
3121 m_optionNames.push_back( "--help" );
3122 }
3123 virtual std::string argsSynopsis() const {
Phil Nash67ec8702012-09-26 18:38:26 +01003124 return "[<option for help on> ...]";
Phil Nashecf934b2012-08-27 21:42:55 +01003125 }
3126 virtual std::string optionSummary() const {
Phil Nash67ec8702012-09-26 18:38:26 +01003127 return "Shows this usage summary, or help on a specific option, or options, if supplied";
Phil Nashe2d215e2012-09-07 17:52:35 +01003128 }
3129 virtual std::string optionDescription() const {
3130 return "";
Phil Nashecf934b2012-08-27 21:42:55 +01003131 }
3132
3133 virtual void parseIntoConfig( const Command&, ConfigData& ) {
3134 // Does not affect config
3135 }
3136 };
3137
3138 class TestCaseOptionParser : public OptionParser {
3139 public:
3140 TestCaseOptionParser() : OptionParser( 1, -1 ) {
3141 m_optionNames.push_back( "-t" );
3142 m_optionNames.push_back( "--test" );
3143 m_optionNames.push_back( "" ); // default option
3144 }
3145 virtual std::string argsSynopsis() const {
3146 return "<testspec> [<testspec>...]";
3147 }
3148 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003149 return "Specifies which test case or cases to run";
3150 }
3151
3152 // Lines are split at the nearest prior space char to the 80 char column.
3153 // Tab chars are removed from the output but their positions are used to align
3154 // subsequently wrapped lines
3155 virtual std::string optionDescription() const {
Phil Nashf7418eb2012-09-09 11:44:30 +01003156 return
3157 "This option allows one ore more test specs to be supplied. Each spec either fully "
3158 "specifies a test case or is a pattern containing wildcards to match a set of test "
3159 "cases. If this option is not provided then all test cases, except those prefixed "
3160 "by './' are run\n"
3161 "\n"
3162 "Specs must be enclosed in \"quotes\" if they contain spaces. If they do not "
3163 "contain spaces the quotes are optional.\n"
3164 "\n"
3165 "Wildcards consist of the * character at the beginning, end, or both and can substitute for "
3166 "any number of any characters (including none)\n"
3167 "\n"
3168 "If spec is prefixed with exclude: or the ~ character then the pattern matches an exclusion. "
3169 "This means that tests matching the pattern are excluded from the set - even if a prior "
Phil Nash799ecf92012-09-24 08:30:13 +01003170 "inclusion spec included them. Subsequent inclusion specs will take precedence, however. "
Phil Nashf7418eb2012-09-09 11:44:30 +01003171 "Inclusions and exclusions are evaluated in left-to-right order.\n"
3172 "\n"
3173 "Examples:\n"
3174 "\n"
3175 " -t thisTestOnly \tMatches the test case called, 'thisTestOnly'\n"
3176 " -t \"this test only\" \tMatches the test case called, 'this test only'\n"
3177 " -t these/* \tMatches all cases starting with 'these/'\n"
3178 " -t exclude:notThis \tMatches all tests except, 'notThis'\n"
3179 " -t ~notThis \tMatches all tests except, 'notThis'\n"
3180 " -t ~*private* \tMatches all tests except those that contain 'private'\n"
3181 " -t a/* ~a/b/* a/b/c \tMatches all tests that start with 'a/', except those "
3182 "that start with 'a/b/', except 'a/b/c', which is included";
Phil Nashecf934b2012-08-27 21:42:55 +01003183 }
3184
3185 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3186 std::string groupName;
3187 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
3188 if( i != 0 )
3189 groupName += " ";
3190 groupName += cmd[i];
3191 }
3192 TestCaseFilters filters( groupName );
Phil Nashe2d215e2012-09-07 17:52:35 +01003193 for( std::size_t i = 0; i < cmd.argsCount(); ++i )
3194 filters.addFilter( TestCaseFilter( cmd[i] ) );
Phil Nashecf934b2012-08-27 21:42:55 +01003195 config.filters.push_back( filters );
3196 }
3197 };
3198
Phil Nash799ecf92012-09-24 08:30:13 +01003199 class TagOptionParser : public OptionParser {
3200 public:
3201 TagOptionParser() : OptionParser( 1, -1 ) {
3202 m_optionNames.push_back( "-g" );
3203 m_optionNames.push_back( "--tag" );
3204 }
3205 virtual std::string argsSynopsis() const {
3206 return "<tagspec> [,<tagspec>...]";
3207 }
3208 virtual std::string optionSummary() const {
3209 return "Matches test cases against tags or tag patterns";
3210 }
3211
3212 // Lines are split at the nearest prior space char to the 80 char column.
3213 // Tab chars are removed from the output but their positions are used to align
3214 // subsequently wrapped lines
3215 virtual std::string optionDescription() const {
3216 return
3217 "!TBD";
3218 }
3219
3220 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
Phil Nash67ec8702012-09-26 18:38:26 +01003221 std::string groupName;
3222 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
3223 if( i != 0 )
3224 groupName += " ";
3225 groupName += cmd[i];
3226 }
3227 TestCaseFilters filters( groupName );
3228 for( std::size_t i = 0; i < cmd.argsCount(); ++i )
3229 filters.addTags( cmd[i] );
3230 config.filters.push_back( filters );
Phil Nash799ecf92012-09-24 08:30:13 +01003231 }
3232 };
3233
Phil Nashecf934b2012-08-27 21:42:55 +01003234 class ListOptionParser : public OptionParser {
3235 public:
3236 ListOptionParser() : OptionParser( 0, 2 ) {
3237 m_optionNames.push_back( "-l" );
3238 m_optionNames.push_back( "--list" );
3239 }
3240 virtual std::string argsSynopsis() const {
3241 return "[all | tests | reporters [xml]]";
3242 }
3243 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003244 return "Lists available tests or reporters";
3245 }
3246
3247 virtual std::string optionDescription() const {
Phil Nashf7418eb2012-09-09 11:44:30 +01003248 return
3249 "With no arguments this option will list all registered tests - one per line.\n"
3250 "Supplying the xml argument formats the list as an xml document (which may be useful for "
3251 "consumption by other tools).\n"
3252 "Supplying the tests or reporters lists tests or reporters respectively - with descriptions.\n"
3253 "\n"
3254 "Examples:\n"
3255 "\n"
3256 " -l\n"
3257 " -l tests\n"
3258 " -l reporters xml\n"
3259 " -l xml";
Phil Nashecf934b2012-08-27 21:42:55 +01003260 }
3261
3262 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3263 config.listSpec = List::TestNames;
3264 if( cmd.argsCount() >= 1 ) {
3265 if( cmd[0] == "all" )
3266 config.listSpec = List::All;
3267 else if( cmd[0] == "tests" )
3268 config.listSpec = List::Tests;
3269 else if( cmd[0] == "reporters" )
3270 config.listSpec = List::Reports;
3271 else
3272 cmd.raiseError( "Expected [tests] or [reporters]" );
3273 }
3274 if( cmd.argsCount() >= 2 ) {
3275 if( cmd[1] == "xml" )
3276 config.listSpec = static_cast<List::What>( config.listSpec | List::AsXml );
3277 else if( cmd[1] == "text" )
3278 config.listSpec = static_cast<List::What>( config.listSpec | List::AsText );
3279 else
3280 cmd.raiseError( "Expected [xml] or [text]" );
3281 }
3282 }
3283 };
3284
3285 class ReporterOptionParser : public OptionParser {
3286 public:
3287 ReporterOptionParser() : OptionParser( 1, 1 ) {
3288 m_optionNames.push_back( "-r" );
3289 m_optionNames.push_back( "--reporter" );
3290 }
3291 virtual std::string argsSynopsis() const {
3292 return "<reporter name>";
3293 }
3294 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003295 return "Specifies type of reporter";
3296 }
3297
3298 virtual std::string optionDescription() const {
Phil Nashf7418eb2012-09-09 11:44:30 +01003299 return
3300 "A reporter is an object that formats and structures the output of running "
3301 "tests, and potentially summarises the results. By default a basic reporter "
3302 "is used that writes IDE friendly results. CATCH comes bundled with some "
3303 "alternative reporters, but more can be added in client code.\n"
3304 "\n"
3305 "The bundled reporters are:\n"
3306 " -r basic\n"
3307 " -r xml\n"
3308 " -r junit\n"
3309 "\n"
3310 "The JUnit reporter is an xml format that follows the structure of the JUnit "
3311 "XML Report ANT task, as consumed by a number of third-party tools, "
3312 "including Continuous Integration servers such as Jenkins.\n"
3313 "If not otherwise needed, the standard XML reporter is preferred as this is "
3314 "a streaming reporter, whereas the Junit reporter needs to hold all its "
3315 "results until the end so it can write the overall results into attributes "
3316 "of the root node.";
Phil Nashecf934b2012-08-27 21:42:55 +01003317 }
3318
3319 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3320 config.reporter = cmd[0];
3321 }
3322 };
3323
3324 class OutputOptionParser : public OptionParser {
3325 public:
3326 OutputOptionParser() : OptionParser( 1, 1 ) {
3327 m_optionNames.push_back( "-o" );
3328 m_optionNames.push_back( "--out" );
3329 }
3330 virtual std::string argsSynopsis() const {
3331 return "<file name>|<%stream name>";
3332 }
3333 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003334 return "Sends output to a file or stream";
Phil Nashecf934b2012-08-27 21:42:55 +01003335 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003336 virtual std::string optionDescription() const {
3337 return
3338 "Use this option to send all output to a file or a stream. By default output is "
Phil Nash799ecf92012-09-24 08:30:13 +01003339 "sent to stdout (note that uses of stdout and stderr from within test cases are "
Phil Nashf7418eb2012-09-09 11:44:30 +01003340 "redirected and included in the report - so even stderr will effectively end up "
Phil Nash799ecf92012-09-24 08:30:13 +01003341 "on stdout). If the name begins with % it is interpreted as a stream. "
Phil Nashf7418eb2012-09-09 11:44:30 +01003342 "Otherwise it is treated as a filename.\n"
3343 "\n"
3344 "Examples are:\n"
3345 "\n"
3346 " -o filename.txt\n"
3347 " -o \"long filename.txt\"\n"
3348 " -o %stdout\n"
3349 " -o %stderr\n"
3350 " -o %debug \t(The IDE's debug output window - currently only Windows' "
3351 "OutputDebugString is supported).";
3352 }
Phil Nashecf934b2012-08-27 21:42:55 +01003353 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3354 if( cmd[0][0] == '%' )
3355 config.stream = cmd[0].substr( 1 );
Phil Nasha695eb92012-08-13 07:46:10 +01003356 else
Phil Nashecf934b2012-08-27 21:42:55 +01003357 config.outputFilename = cmd[0];
Phil Nasha695eb92012-08-13 07:46:10 +01003358 }
Phil Nashecf934b2012-08-27 21:42:55 +01003359 };
Phil Nasha695eb92012-08-13 07:46:10 +01003360
Phil Nashf7418eb2012-09-09 11:44:30 +01003361 class SuccessOptionParser : public OptionParser {
Phil Nashecf934b2012-08-27 21:42:55 +01003362 public:
Phil Nashf7418eb2012-09-09 11:44:30 +01003363 SuccessOptionParser() {
Phil Nashecf934b2012-08-27 21:42:55 +01003364 m_optionNames.push_back( "-s" );
3365 m_optionNames.push_back( "--success" );
Phil Nash56d5c422012-08-23 20:08:50 +01003366 }
Phil Nashecf934b2012-08-27 21:42:55 +01003367 virtual std::string argsSynopsis() const {
3368 return "";
Phil Nash56d5c422012-08-23 20:08:50 +01003369 }
Phil Nashecf934b2012-08-27 21:42:55 +01003370 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003371 return "Shows results for successful tests";
Phil Nasha695eb92012-08-13 07:46:10 +01003372 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003373 virtual std::string optionDescription() const {
3374 return
3375 "Usually you only want to see reporting for failed tests. Sometimes it's useful "
3376 "to see all the output (especially when you don't trust that that test you just "
Phil Nash799ecf92012-09-24 08:30:13 +01003377 "added worked first time!). To see successful, as well as failing, test results "
Phil Nashf7418eb2012-09-09 11:44:30 +01003378 "just pass this option.";
3379 }
Phil Nash78c92e62012-08-27 21:48:15 +01003380 virtual void parseIntoConfig( const Command&, ConfigData& config ) {
Phil Nashecf934b2012-08-27 21:42:55 +01003381 config.includeWhichResults = Include::SuccessfulResults;
3382 }
3383 };
Phil Nasha695eb92012-08-13 07:46:10 +01003384
Phil Nashecf934b2012-08-27 21:42:55 +01003385 class DebugBreakOptionParser : public OptionParser {
3386 public:
3387 DebugBreakOptionParser() {
3388 m_optionNames.push_back( "-b" );
3389 m_optionNames.push_back( "--break" );
3390 }
3391 virtual std::string argsSynopsis() const {
3392 return "";
3393 }
3394 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003395 return "Breaks into the debugger on failure";
Phil Nashecf934b2012-08-27 21:42:55 +01003396 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003397 virtual std::string optionDescription() const {
3398 return
3399 "In some IDEs (currently XCode and Visual Studio) it is possible for CATCH to "
3400 "break into the debugger on a test failure. This can be very helpful during "
3401 "debug sessions - especially when there is more than one path through a "
3402 "particular test. In addition to the command line option, ensure you have "
3403 "built your code with the DEBUG preprocessor symbol";
3404 }
Phil Nashecf934b2012-08-27 21:42:55 +01003405
Phil Nash78c92e62012-08-27 21:48:15 +01003406 virtual void parseIntoConfig( const Command&, ConfigData& config ) {
Phil Nashecf934b2012-08-27 21:42:55 +01003407 config.shouldDebugBreak = true;
3408 }
3409 };
3410
3411 class NameOptionParser : public OptionParser {
3412 public:
3413 NameOptionParser() : OptionParser( 1, 1 ) {
3414 m_optionNames.push_back( "-n" );
3415 m_optionNames.push_back( "--name" );
3416 }
3417 virtual std::string argsSynopsis() const {
3418 return "<name>";
3419 }
3420 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003421 return "Names a test run";
Phil Nashecf934b2012-08-27 21:42:55 +01003422 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003423 virtual std::string optionDescription() const {
3424 return
3425 "If a name is supplied it will be used by the reporter to provide an overall "
3426 "name for the test run. This can be useful if you are sending to a file, for "
3427 "example, and need to distinguish different test runs - either from different "
3428 "Catch executables or runs of the same executable with different options.\n"
3429 "\n"
3430 "Examples:\n"
3431 "\n"
3432 " -n testRun\n"
3433 " -n \"tests of the widget component\"";
3434 }
Phil Nashecf934b2012-08-27 21:42:55 +01003435
3436 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3437 config.name = cmd[0];
3438 }
3439 };
3440
3441 class AbortOptionParser : public OptionParser {
3442 public:
3443 AbortOptionParser() : OptionParser( 0, 1 ) {
3444 m_optionNames.push_back( "-a" );
3445 m_optionNames.push_back( "--abort" );
3446 }
3447 virtual std::string argsSynopsis() const {
3448 return "[#]";
3449 }
3450 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003451 return "Aborts after a certain number of failures";
Phil Nashecf934b2012-08-27 21:42:55 +01003452 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003453 virtual std::string optionDescription() const {
3454 return
3455 "If a REQUIRE assertion fails the test case aborts, but subsequent test cases "
3456 "are still run. If a CHECK assertion fails even the current test case is not "
3457 "aborted.\n"
3458 "\n"
3459 "Sometimes this results in a flood of failure messages and you'd rather just "
3460 "see the first few. Specifying -a or --abort on its own will abort the whole "
3461 "test run on the first failed assertion of any kind. Following it with a "
3462 "number causes it to abort after that number of assertion failures.";
3463 }
Phil Nashecf934b2012-08-27 21:42:55 +01003464
3465 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3466 int threshold = 1;
3467 if( cmd.argsCount() == 1 ) {
3468 std::stringstream ss;
3469 ss << cmd[0];
3470 ss >> threshold;
3471 if( ss.fail() || threshold <= 0 )
3472 cmd.raiseError( "threshold must be a number greater than zero" );
3473 }
3474 config.cutoff = threshold;
3475 }
3476 };
3477
3478 class NoThrowOptionParser : public OptionParser {
3479 public:
3480 NoThrowOptionParser() {
3481 m_optionNames.push_back( "-nt" );
3482 m_optionNames.push_back( "--nothrow" );
3483 }
3484 virtual std::string argsSynopsis() const {
3485 return "";
3486 }
3487 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003488 return "Elides assertions expected to throw";
Phil Nashecf934b2012-08-27 21:42:55 +01003489 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003490 virtual std::string optionDescription() const {
3491 return
3492 "Skips all assertions that test that an exception is thrown, "
3493 "e.g. REQUIRE_THROWS.\n"
3494 "\n"
3495 "These can be a nuisance in certain debugging environments that may break when "
3496 "exceptions are thrown (while this is usually optional for handled exceptions, "
3497 "it can be useful to have enabled if you are trying to track down something "
3498 "unexpected).\n"
3499 "\n"
3500 "When running with this option the throw checking assertions are skipped so "
3501 "as not to contribute additional noise.";
3502 }
Phil Nashecf934b2012-08-27 21:42:55 +01003503
Phil Nash78c92e62012-08-27 21:48:15 +01003504 virtual void parseIntoConfig( const Command&, ConfigData& config ) {
Phil Nashecf934b2012-08-27 21:42:55 +01003505 config.allowThrows = false;
3506 }
3507 };
Phil Nasha70fbe32012-08-31 08:10:36 +01003508
3509 class WarningsOptionParser : public OptionParser {
3510 public:
3511 WarningsOptionParser() : OptionParser( 1, -1 ) {
3512 m_optionNames.push_back( "-w" );
3513 m_optionNames.push_back( "--warnings" );
3514 }
3515 virtual std::string argsSynopsis() const {
3516 return "<warning>";
3517 }
3518 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003519 return "Enable warnings";
Phil Nasha70fbe32012-08-31 08:10:36 +01003520 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003521 virtual std::string optionDescription() const {
3522 return
3523 "Enables the named warnings. If the warnings are violated the test case is "
3524 "failed.\n"
3525 "\n"
3526 "At present only one warning has been provided: NoAssertions. If this warning "
3527 "is enabled then any test case that completes without an assertions (CHECK, "
3528 "REQUIRE etc) being encountered violates the warning.\n"
3529 "\n"
3530 "e.g.:\n"
3531 "\n"
3532 " -w NoAssertions";
3533 }
Phil Nasha70fbe32012-08-31 08:10:36 +01003534
3535 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3536 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
3537 if( cmd[i] == "NoAssertions" )
3538 config.warnings = (ConfigData::WarnAbout::What)( config.warnings | ConfigData::WarnAbout::NoAssertions );
3539 else
3540 cmd.raiseError( "Unrecognised warning: " + cmd[i] );
3541 }
3542 }
3543 };
Phil Nasha695eb92012-08-13 07:46:10 +01003544 }
3545
Phil Nashecf934b2012-08-27 21:42:55 +01003546 class AllOptions
3547 {
3548 public:
3549 typedef std::vector<Ptr<OptionParser> > Parsers;
3550 typedef Parsers::const_iterator const_iterator;
3551 typedef Parsers::const_iterator iterator;
3552
3553 AllOptions() {
Phil Nasha70fbe32012-08-31 08:10:36 +01003554 add<Options::TestCaseOptionParser>(); // Keep this one first
3555
Phil Nash67ec8702012-09-26 18:38:26 +01003556 add<Options::TagOptionParser>();
Phil Nashecf934b2012-08-27 21:42:55 +01003557 add<Options::ListOptionParser>();
3558 add<Options::ReporterOptionParser>();
3559 add<Options::OutputOptionParser>();
Phil Nashf7418eb2012-09-09 11:44:30 +01003560 add<Options::SuccessOptionParser>();
Phil Nashecf934b2012-08-27 21:42:55 +01003561 add<Options::DebugBreakOptionParser>();
3562 add<Options::NameOptionParser>();
3563 add<Options::AbortOptionParser>();
3564 add<Options::NoThrowOptionParser>();
Phil Nasha70fbe32012-08-31 08:10:36 +01003565 add<Options::WarningsOptionParser>();
3566
3567 add<Options::HelpOptionParser>(); // Keep this one last
Phil Nashecf934b2012-08-27 21:42:55 +01003568 }
3569
3570 void parseIntoConfig( const CommandParser& parser, ConfigData& config ) {
3571 for( const_iterator it = m_parsers.begin(); it != m_parsers.end(); ++it )
3572 (*it)->parseIntoConfig( parser, config );
3573 }
3574
3575 const_iterator begin() const {
3576 return m_parsers.begin();
3577 }
3578 const_iterator end() const {
3579 return m_parsers.end();
3580 }
3581 private:
3582
3583 template<typename T>
3584 void add() {
3585 m_parsers.push_back( new T() );
3586 }
3587 Parsers m_parsers;
3588
3589 };
3590
Phil Nasha695eb92012-08-13 07:46:10 +01003591} // end namespace Catch
3592
3593// #included from: internal/catch_list.hpp
3594#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
3595
3596#include <limits>
3597
3598namespace Catch {
Phil Nash56d5c422012-08-23 20:08:50 +01003599 inline bool matchesFilters( const std::vector<TestCaseFilters>& filters, const TestCaseInfo& testCase ) {
3600 std::vector<TestCaseFilters>::const_iterator it = filters.begin();
3601 std::vector<TestCaseFilters>::const_iterator itEnd = filters.end();
3602 for(; it != itEnd; ++it )
3603 if( !it->shouldInclude( testCase ) )
3604 return false;
3605 return true;
3606 }
3607 inline void List( const ConfigData& config ) {
Phil Nasha695eb92012-08-13 07:46:10 +01003608
Phil Nash5bc030d2012-08-16 18:48:50 +01003609 if( config.listSpec & List::Reports ) {
Phil Nasha695eb92012-08-13 07:46:10 +01003610 std::cout << "Available reports:\n";
3611 IReporterRegistry::FactoryMap::const_iterator it = getRegistryHub().getReporterRegistry().getFactories().begin();
3612 IReporterRegistry::FactoryMap::const_iterator itEnd = getRegistryHub().getReporterRegistry().getFactories().end();
3613 for(; it != itEnd; ++it ) {
3614 // !TBD: consider listAs()
3615 std::cout << "\t" << it->first << "\n\t\t'" << it->second->getDescription() << "'\n";
3616 }
3617 std::cout << std::endl;
3618 }
3619
Phil Nash5bc030d2012-08-16 18:48:50 +01003620 if( config.listSpec & List::Tests ) {
Phil Nash56d5c422012-08-23 20:08:50 +01003621 if( config.filters.empty() )
Phil Nash4c97fc52012-08-24 08:23:50 +01003622 std::cout << "All available test cases:\n";
Phil Nash56d5c422012-08-23 20:08:50 +01003623 else
Phil Nash4c97fc52012-08-24 08:23:50 +01003624 std::cout << "Matching test cases:\n";
Phil Nasha695eb92012-08-13 07:46:10 +01003625 std::vector<TestCaseInfo>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin();
3626 std::vector<TestCaseInfo>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end();
Phil Nash4c97fc52012-08-24 08:23:50 +01003627 std::size_t matchedTests = 0;
Phil Nasha695eb92012-08-13 07:46:10 +01003628 for(; it != itEnd; ++it ) {
Phil Nash56d5c422012-08-23 20:08:50 +01003629 if( matchesFilters( config.filters, *it ) ) {
Phil Nash4c97fc52012-08-24 08:23:50 +01003630 matchedTests++;
Phil Nash56d5c422012-08-23 20:08:50 +01003631 // !TBD: consider listAs()
3632 std::cout << "\t" << it->getName() << "\n";
3633 if( ( config.listSpec & List::TestNames ) != List::TestNames )
3634 std::cout << "\t\t '" << it->getDescription() << "'\n";
3635 }
Phil Nasha695eb92012-08-13 07:46:10 +01003636 }
Phil Nash4c97fc52012-08-24 08:23:50 +01003637 if( config.filters.empty() )
3638 std::cout << pluralise( matchedTests, "test case" ) << std::endl;
3639 else
3640 std::cout << pluralise( matchedTests, "matching test case" ) << std::endl;
Phil Nasha695eb92012-08-13 07:46:10 +01003641 }
3642
Phil Nash5bc030d2012-08-16 18:48:50 +01003643 if( ( config.listSpec & List::All ) == 0 ) {
Phil Nash56d5c422012-08-23 20:08:50 +01003644 std::ostringstream oss;
3645 oss << "Unknown list type";
3646 throw std::domain_error( oss.str() );
Phil Nasha695eb92012-08-13 07:46:10 +01003647 }
Phil Nasha695eb92012-08-13 07:46:10 +01003648 }
3649
3650} // end namespace Catch
3651
3652// #included from: internal/catch_runner_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04003653#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003654
3655// #included from: catch_running_test.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04003656#define TWOBLUECUBES_CATCH_RUNNING_TEST_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003657
3658// #included from: catch_section_info.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04003659#define TWOBLUECUBES_CATCH_SECTION_INFO_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003660
3661#include <map>
3662#include <string>
3663
3664namespace Catch {
3665
3666 class SectionInfo {
3667 public:
3668
3669 enum Status {
3670 Root,
3671 Unknown,
3672 Branch,
3673 TestedBranch,
3674 TestedLeaf
3675 };
3676
3677 SectionInfo( SectionInfo* parent )
3678 : m_status( Unknown ),
3679 m_parent( parent )
3680 {}
3681
3682 SectionInfo()
3683 : m_status( Root ),
3684 m_parent( NULL )
3685 {}
3686
3687 ~SectionInfo() {
3688 deleteAllValues( m_subSections );
3689 }
3690
3691 bool shouldRun() const {
3692 return m_status < TestedBranch;
3693 }
3694
3695 bool ran() {
3696 if( m_status < Branch ) {
3697 m_status = TestedLeaf;
3698 return true;
3699 }
3700 return false;
3701 }
3702
Phil Nasha70fbe32012-08-31 08:10:36 +01003703 bool isBranch() const {
3704 return m_status == Branch;
3705 }
3706
Phil Nasha695eb92012-08-13 07:46:10 +01003707 void ranToCompletion() {
3708 if( m_status == Branch && !hasUntestedSections() )
3709 m_status = TestedBranch;
3710 }
3711
3712 SectionInfo* findSubSection( const std::string& name ) {
3713 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.find( name );
3714 return it != m_subSections.end()
3715 ? it->second
3716 : NULL;
3717 }
3718
3719 SectionInfo* addSubSection( const std::string& name ) {
3720 SectionInfo* subSection = new SectionInfo( this );
3721 m_subSections.insert( std::make_pair( name, subSection ) );
3722 m_status = Branch;
3723 return subSection;
3724 }
3725
3726 SectionInfo* getParent() {
3727 return m_parent;
3728 }
3729
3730 bool hasUntestedSections() const {
3731 if( m_status == Unknown )
3732 return true;
3733
3734 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.begin();
3735 std::map<std::string, SectionInfo*>::const_iterator itEnd = m_subSections.end();
3736 for(; it != itEnd; ++it ) {
3737 if( it->second->hasUntestedSections() )
3738 return true;
3739 }
3740 return false;
3741 }
3742
3743 private:
3744 Status m_status;
3745 std::map<std::string, SectionInfo*> m_subSections;
3746 SectionInfo* m_parent;
3747 };
3748}
3749
3750namespace Catch {
3751
3752 class RunningTest {
3753
3754 enum RunStatus {
3755 NothingRun,
3756 EncounteredASection,
3757 RanAtLeastOneSection,
3758 RanToCompletionWithSections,
3759 RanToCompletionWithNoSections
3760 };
3761
3762 public:
3763 explicit RunningTest( const TestCaseInfo* info = NULL )
3764 : m_info( info ),
3765 m_runStatus( RanAtLeastOneSection ),
3766 m_currentSection( &m_rootSection ),
3767 m_changed( false )
3768 {}
3769
3770 bool wasSectionSeen() const {
3771 return m_runStatus == RanAtLeastOneSection ||
3772 m_runStatus == RanToCompletionWithSections;
3773 }
3774
Phil Nasha70fbe32012-08-31 08:10:36 +01003775 bool isBranchSection() const {
3776 return m_currentSection &&
3777 m_currentSection->isBranch();
3778 }
3779
3780 bool hasSections() const {
3781 return m_runStatus == RanAtLeastOneSection ||
3782 m_runStatus == RanToCompletionWithSections ||
3783 m_runStatus == EncounteredASection;
3784 }
3785
Phil Nasha695eb92012-08-13 07:46:10 +01003786 void reset() {
3787 m_runStatus = NothingRun;
3788 m_changed = false;
3789 m_lastSectionToRun = NULL;
3790 }
3791
3792 void ranToCompletion() {
3793 if( m_runStatus == RanAtLeastOneSection ||
3794 m_runStatus == EncounteredASection ) {
3795 m_runStatus = RanToCompletionWithSections;
3796 if( m_lastSectionToRun ) {
3797 m_lastSectionToRun->ranToCompletion();
3798 m_changed = true;
3799 }
3800 }
3801 else {
3802 m_runStatus = RanToCompletionWithNoSections;
3803 }
3804 }
3805
3806 bool addSection( const std::string& name ) {
3807 if( m_runStatus == NothingRun )
3808 m_runStatus = EncounteredASection;
3809
3810 SectionInfo* thisSection = m_currentSection->findSubSection( name );
3811 if( !thisSection ) {
3812 thisSection = m_currentSection->addSubSection( name );
3813 m_changed = true;
3814 }
3815
3816 if( !wasSectionSeen() && thisSection->shouldRun() ) {
3817 m_currentSection = thisSection;
3818 m_lastSectionToRun = NULL;
3819 return true;
3820 }
3821 return false;
3822 }
3823
3824 void endSection( const std::string& ) {
3825 if( m_currentSection->ran() ) {
3826 m_runStatus = RanAtLeastOneSection;
3827 m_changed = true;
3828 }
3829 else if( m_runStatus == EncounteredASection ) {
3830 m_runStatus = RanAtLeastOneSection;
3831 m_lastSectionToRun = m_currentSection;
3832 }
3833 m_currentSection = m_currentSection->getParent();
3834 }
3835
3836 const TestCaseInfo& getTestCaseInfo() const {
3837 return *m_info;
3838 }
3839
3840 bool hasUntestedSections() const {
3841 return m_runStatus == RanAtLeastOneSection ||
3842 ( m_rootSection.hasUntestedSections() && m_changed );
3843 }
3844
3845 private:
3846 const TestCaseInfo* m_info;
3847 RunStatus m_runStatus;
3848 SectionInfo m_rootSection;
3849 SectionInfo* m_currentSection;
3850 SectionInfo* m_lastSectionToRun;
3851 bool m_changed;
3852 };
3853}
3854
3855#include <set>
3856#include <string>
3857
3858namespace Catch {
3859
3860 class StreamRedirect {
3861
3862 public:
3863 StreamRedirect( std::ostream& stream, std::string& targetString )
3864 : m_stream( stream ),
3865 m_prevBuf( stream.rdbuf() ),
3866 m_targetString( targetString )
3867 {
3868 stream.rdbuf( m_oss.rdbuf() );
3869 }
3870
3871 ~StreamRedirect() {
3872 m_targetString += m_oss.str();
3873 m_stream.rdbuf( m_prevBuf );
3874 }
3875
3876 private:
3877 std::ostream& m_stream;
3878 std::streambuf* m_prevBuf;
3879 std::ostringstream m_oss;
3880 std::string& m_targetString;
3881 };
3882
3883 ///////////////////////////////////////////////////////////////////////////
3884
3885 class Runner : public IResultCapture, public IRunner {
3886
3887 Runner( const Runner& );
3888 void operator =( const Runner& );
3889
3890 public:
3891
Phil Nash56d5c422012-08-23 20:08:50 +01003892 explicit Runner( const Config& config, const Ptr<IReporter>& reporter )
Phil Nasha695eb92012-08-13 07:46:10 +01003893 : m_context( getCurrentMutableContext() ),
3894 m_runningTest( NULL ),
3895 m_config( config ),
3896 m_reporter( reporter ),
3897 m_prevRunner( &m_context.getRunner() ),
3898 m_prevResultCapture( &m_context.getResultCapture() ),
3899 m_prevConfig( m_context.getConfig() )
3900 {
3901 m_context.setRunner( this );
3902 m_context.setConfig( &m_config );
3903 m_context.setResultCapture( this );
3904 m_reporter->StartTesting();
3905 }
3906
3907 virtual ~Runner() {
3908 m_reporter->EndTesting( m_totals );
3909 m_context.setRunner( m_prevRunner );
3910 m_context.setConfig( NULL );
3911 m_context.setResultCapture( m_prevResultCapture );
3912 m_context.setConfig( m_prevConfig );
3913 }
3914
Phil Nash56d5c422012-08-23 20:08:50 +01003915 Totals runMatching( const std::string& testSpec ) {
Phil Nasha695eb92012-08-13 07:46:10 +01003916
Phil Nash56d5c422012-08-23 20:08:50 +01003917 std::vector<TestCaseInfo> matchingTests = getRegistryHub().getTestCaseRegistry().getMatchingTestCases( testSpec );
Phil Nash5bc030d2012-08-16 18:48:50 +01003918
3919 Totals totals;
Phil Nash5bc030d2012-08-16 18:48:50 +01003920
Phil Nash56d5c422012-08-23 20:08:50 +01003921 m_reporter->StartGroup( testSpec );
3922
3923 std::vector<TestCaseInfo>::const_iterator it = matchingTests.begin();
3924 std::vector<TestCaseInfo>::const_iterator itEnd = matchingTests.end();
3925 for(; it != itEnd; ++it )
3926 totals += runTest( *it );
3927 // !TBD use std::accumulate?
3928
3929 m_reporter->EndGroup( testSpec, totals );
Phil Nash5bc030d2012-08-16 18:48:50 +01003930 return totals;
3931 }
3932
3933 Totals runTest( const TestCaseInfo& testInfo ) {
Phil Nasha695eb92012-08-13 07:46:10 +01003934 Totals prevTotals = m_totals;
3935
3936 std::string redirectedCout;
3937 std::string redirectedCerr;
3938
3939 m_reporter->StartTestCase( testInfo );
3940
3941 m_runningTest = new RunningTest( &testInfo );
3942
3943 do {
3944 do {
Phil Nasha695eb92012-08-13 07:46:10 +01003945 m_currentResult.setLineInfo( m_runningTest->getTestCaseInfo().getLineInfo() );
3946 runCurrentTest( redirectedCout, redirectedCerr );
Phil Nasha695eb92012-08-13 07:46:10 +01003947 }
3948 while( m_runningTest->hasUntestedSections() && !aborting() );
3949 }
3950 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
3951
3952 delete m_runningTest;
3953 m_runningTest = NULL;
3954
3955 Totals deltaTotals = m_totals.delta( prevTotals );
3956 m_totals.testCases += deltaTotals.testCases;
3957 m_reporter->EndTestCase( testInfo, deltaTotals, redirectedCout, redirectedCerr );
Phil Nash5bc030d2012-08-16 18:48:50 +01003958 return deltaTotals;
Phil Nasha695eb92012-08-13 07:46:10 +01003959 }
3960
3961 const Config& config() const {
3962 return m_config;
3963 }
3964
3965 private: // IResultCapture
3966
3967 virtual ResultAction::Value acceptResult( bool result ) {
3968 return acceptResult( result ? ResultWas::Ok : ResultWas::ExpressionFailed );
3969 }
3970
3971 virtual ResultAction::Value acceptResult( ResultWas::OfType result ) {
3972 m_currentResult.setResultType( result );
3973 return actOnCurrentResult();
3974 }
3975
3976 virtual ResultAction::Value acceptExpression( const ResultInfoBuilder& resultInfo ) {
3977 m_currentResult = resultInfo;
3978 return actOnCurrentResult();
3979 }
3980
3981 virtual void acceptMessage( const std::string& msg ) {
3982 m_currentResult.setMessage( msg );
3983 }
3984
3985 virtual void testEnded( const ResultInfo& result ) {
3986 if( result.getResultType() == ResultWas::Ok ) {
3987 m_totals.assertions.passed++;
3988 }
3989 else if( !result.ok() ) {
3990 m_totals.assertions.failed++;
3991
Phil Nash799ecf92012-09-24 08:30:13 +01003992 {
3993 std::vector<ScopedInfo*>::const_iterator it = m_scopedInfos.begin();
3994 std::vector<ScopedInfo*>::const_iterator itEnd = m_scopedInfos.end();
3995 for(; it != itEnd; ++it )
3996 m_reporter->Result( (*it)->getInfo() );
3997 }
3998 {
3999 std::vector<ResultInfo>::const_iterator it = m_info.begin();
4000 std::vector<ResultInfo>::const_iterator itEnd = m_info.end();
4001 for(; it != itEnd; ++it )
4002 m_reporter->Result( *it );
4003 }
Phil Nasha695eb92012-08-13 07:46:10 +01004004 m_info.clear();
4005 }
4006
4007 if( result.getResultType() == ResultWas::Info )
4008 m_info.push_back( result );
4009 else
4010 m_reporter->Result( result );
4011 }
4012
4013 virtual bool sectionStarted (
4014 const std::string& name,
4015 const std::string& description,
4016 const SourceLineInfo& lineInfo,
4017 Counts& assertions
4018 )
4019 {
4020 std::ostringstream oss;
4021 oss << name << "@" << lineInfo;
4022
4023 if( !m_runningTest->addSection( oss.str() ) )
4024 return false;
4025
4026 m_currentResult.setLineInfo( lineInfo );
4027 m_reporter->StartSection( name, description );
4028 assertions = m_totals.assertions;
4029
4030 return true;
4031 }
4032
4033 virtual void sectionEnded( const std::string& name, const Counts& prevAssertions ) {
Phil Nasha70fbe32012-08-31 08:10:36 +01004034 Counts assertions = m_totals.assertions - prevAssertions;
4035 if( assertions.total() == 0 &&
4036 ( m_config.data().warnings & ConfigData::WarnAbout::NoAssertions ) &&
4037 !m_runningTest->isBranchSection() ) {
4038 m_reporter->NoAssertionsInSection( name );
4039 m_totals.assertions.failed++;
4040 assertions.failed++;
4041 }
Phil Nasha695eb92012-08-13 07:46:10 +01004042 m_runningTest->endSection( name );
Phil Nasha70fbe32012-08-31 08:10:36 +01004043 m_reporter->EndSection( name, assertions );
Phil Nasha695eb92012-08-13 07:46:10 +01004044 }
4045
4046 virtual void pushScopedInfo( ScopedInfo* scopedInfo ) {
4047 m_scopedInfos.push_back( scopedInfo );
4048 }
4049
4050 virtual void popScopedInfo( ScopedInfo* scopedInfo ) {
4051 if( m_scopedInfos.back() == scopedInfo )
4052 m_scopedInfos.pop_back();
4053 }
4054
4055 virtual bool shouldDebugBreak() const {
4056 return m_config.shouldDebugBreak();
4057 }
4058
4059 virtual std::string getCurrentTestName() const {
4060 return m_runningTest
4061 ? m_runningTest->getTestCaseInfo().getName()
4062 : "";
4063 }
4064
4065 virtual const ResultInfo* getLastResult() const {
4066 return &m_lastResult;
4067 }
4068
Phil Nash56d5c422012-08-23 20:08:50 +01004069 public:
4070 // !TBD We need to do this another way!
Phil Nasha695eb92012-08-13 07:46:10 +01004071 bool aborting() const {
4072 return m_totals.assertions.failed == static_cast<std::size_t>( m_config.getCutoff() );
4073 }
4074
Phil Nash56d5c422012-08-23 20:08:50 +01004075 private:
4076
Phil Nasha695eb92012-08-13 07:46:10 +01004077 ResultAction::Value actOnCurrentResult() {
Phil Nash67305122012-10-09 11:48:55 +01004078 m_lastResult = m_currentResult.build();
4079 testEnded( m_lastResult );
Phil Nasha695eb92012-08-13 07:46:10 +01004080
4081 m_currentResult = ResultInfoBuilder();
4082
4083 ResultAction::Value action = ResultAction::None;
4084
4085 if( !m_lastResult.ok() ) {
4086 action = ResultAction::Failed;
4087 if( shouldDebugBreak() )
4088 action = (ResultAction::Value)( action | ResultAction::Debug );
4089 if( aborting() )
4090 action = (ResultAction::Value)( action | ResultAction::Abort );
4091 }
4092 return action;
4093 }
4094
4095 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
4096 try {
4097 m_runningTest->reset();
Phil Nasha70fbe32012-08-31 08:10:36 +01004098 Counts prevAssertions = m_totals.assertions;
Phil Nasha695eb92012-08-13 07:46:10 +01004099 if( m_reporter->shouldRedirectStdout() ) {
4100 StreamRedirect coutRedir( std::cout, redirectedCout );
4101 StreamRedirect cerrRedir( std::cerr, redirectedCerr );
4102 m_runningTest->getTestCaseInfo().invoke();
4103 }
4104 else {
4105 m_runningTest->getTestCaseInfo().invoke();
4106 }
Phil Nasha70fbe32012-08-31 08:10:36 +01004107 Counts assertions = m_totals.assertions - prevAssertions;
4108 if( assertions.total() == 0 &&
4109 ( m_config.data().warnings & ConfigData::WarnAbout::NoAssertions ) &&
4110 !m_runningTest->hasSections() ) {
4111 m_totals.assertions.failed++;
4112 m_reporter->NoAssertionsInTestCase( m_runningTest->getTestCaseInfo().getName() );
4113 }
Phil Nasha695eb92012-08-13 07:46:10 +01004114 m_runningTest->ranToCompletion();
4115 }
4116 catch( TestFailureException& ) {
4117 // This just means the test was aborted due to failure
4118 }
4119 catch(...) {
4120 acceptMessage( getRegistryHub().getExceptionTranslatorRegistry().translateActiveException() );
4121 acceptResult( ResultWas::ThrewException );
4122 }
4123 m_info.clear();
4124 }
4125
4126 private:
4127 IMutableContext& m_context;
4128 RunningTest* m_runningTest;
4129 ResultInfoBuilder m_currentResult;
4130 ResultInfo m_lastResult;
4131
4132 const Config& m_config;
4133 Totals m_totals;
4134 Ptr<IReporter> m_reporter;
4135 std::vector<ScopedInfo*> m_scopedInfos;
4136 std::vector<ResultInfo> m_info;
4137 IRunner* m_prevRunner;
4138 IResultCapture* m_prevResultCapture;
4139 const IConfig* m_prevConfig;
4140 };
4141
4142} // end namespace Catch
4143
Phil Nash89d1e6c2011-05-24 08:23:02 +01004144#include <fstream>
4145#include <stdlib.h>
4146#include <limits>
4147
Phil Nash89d2a3f2012-05-16 15:09:17 +01004148namespace Catch {
4149
Phil Nash56d5c422012-08-23 20:08:50 +01004150 class Runner2 { // This will become Runner when Runner becomes Context
Phil Nash163088a2012-05-31 19:40:26 +01004151
Phil Nash56d5c422012-08-23 20:08:50 +01004152 public:
4153 Runner2( Config& configWrapper )
4154 : m_configWrapper( configWrapper ),
4155 m_config( configWrapper.data() )
Phil Nash06e959b2012-05-25 08:52:05 +01004156 {
Phil Nash67ec8702012-09-26 18:38:26 +01004157 openStream();
Phil Nash56d5c422012-08-23 20:08:50 +01004158 makeReporter();
4159 }
Phil Nash06e959b2012-05-25 08:52:05 +01004160
Phil Nash56d5c422012-08-23 20:08:50 +01004161 Totals runTests() {
4162
4163 std::vector<TestCaseFilters> filterGroups = m_config.filters;
4164 if( filterGroups.empty() ) {
4165 TestCaseFilters filterGroup( "" );
Phil Nash56d5c422012-08-23 20:08:50 +01004166 filterGroups.push_back( filterGroup );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004167 }
Phil Nash56d5c422012-08-23 20:08:50 +01004168
4169 Runner context( m_configWrapper, m_reporter ); // This Runner will be renamed Context
4170 Totals totals;
4171
4172 std::vector<TestCaseFilters>::const_iterator it = filterGroups.begin();
4173 std::vector<TestCaseFilters>::const_iterator itEnd = filterGroups.end();
Phil Nashe2d215e2012-09-07 17:52:35 +01004174 for(; it != itEnd && !context.aborting(); ++it ) {
Phil Nash56d5c422012-08-23 20:08:50 +01004175 m_reporter->StartGroup( it->getName() );
Phil Nash62b70392012-08-31 18:46:13 +01004176 totals += runTestsForGroup( context, *it );
Phil Nash56d5c422012-08-23 20:08:50 +01004177 if( context.aborting() )
4178 m_reporter->Aborted();
4179 m_reporter->EndGroup( it->getName(), totals );
4180 }
4181 return totals;
4182 }
4183
4184 Totals runTestsForGroup( Runner& context, const TestCaseFilters& filterGroup ) {
4185 Totals totals;
4186 std::vector<TestCaseInfo>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin();
4187 std::vector<TestCaseInfo>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end();
4188 int testsRunForGroup = 0;
4189 for(; it != itEnd; ++it ) {
4190 if( filterGroup.shouldInclude( *it ) ) {
4191 testsRunForGroup++;
4192 if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
4193
4194 if( context.aborting() )
4195 break;
4196
4197 totals += context.runTest( *it );
4198 m_testsAlreadyRun.insert( *it );
4199 }
Phil Nash06e959b2012-05-25 08:52:05 +01004200 }
4201 }
Phil Nash56d5c422012-08-23 20:08:50 +01004202 if( testsRunForGroup == 0 )
4203 std::cerr << "\n[No test cases matched with: " << filterGroup.getName() << "]" << std::endl;
4204 return totals;
4205
Phil Nash89d1e6c2011-05-24 08:23:02 +01004206 }
Phil Nash56d5c422012-08-23 20:08:50 +01004207
4208 private:
Phil Nash67ec8702012-09-26 18:38:26 +01004209 void openStream() {
4210 if( !m_config.stream.empty() )
4211 m_configWrapper.useStream( m_config.stream );
4212
Phil Nash56d5c422012-08-23 20:08:50 +01004213 // Open output file, if specified
4214 if( !m_config.outputFilename.empty() ) {
4215 m_ofs.open( m_config.outputFilename.c_str() );
4216 if( m_ofs.fail() ) {
4217 std::ostringstream oss;
4218 oss << "Unable to open file: '" << m_config.outputFilename << "'";
4219 throw std::domain_error( oss.str() );
4220 }
4221 m_configWrapper.setStreamBuf( m_ofs.rdbuf() );
4222 }
4223 }
4224 void makeReporter() {
4225 std::string reporterName = m_config.reporter.empty()
4226 ? "basic"
4227 : m_config.reporter;
4228
Phil Nasha70fbe32012-08-31 08:10:36 +01004229 ReporterConfig reporterConfig( m_config.name, m_configWrapper.stream(), m_config.includeWhichResults == Include::SuccessfulResults, m_config );
Phil Nash56d5c422012-08-23 20:08:50 +01004230
4231 m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, reporterConfig );
4232 if( !m_reporter ) {
4233 std::ostringstream oss;
4234 oss << "No reporter registered with name: '" << reporterName << "'";
4235 throw std::domain_error( oss.str() );
4236 }
4237 }
4238
4239 private:
4240 Config& m_configWrapper;
4241 const ConfigData& m_config;
4242 std::ofstream m_ofs;
4243 Ptr<IReporter> m_reporter;
4244 std::set<TestCaseInfo> m_testsAlreadyRun;
4245 };
4246
4247 inline int Main( Config& configWrapper ) {
4248 int result = 0;
4249 try
4250 {
4251 Runner2 runner( configWrapper );
4252
4253 const ConfigData& config = configWrapper.data();
4254
4255 // Handle list request
4256 if( config.listSpec != List::None ) {
4257 List( config );
Phil Nash799ecf92012-09-24 08:30:13 +01004258 Catch::cleanUp();
Phil Nash56d5c422012-08-23 20:08:50 +01004259 return 0;
4260 }
4261
4262 result = static_cast<int>( runner.runTests().assertions.failed );
4263
4264 }
4265 catch( std::exception& ex ) {
4266 std::cerr << ex.what() << std::endl;
4267 result = (std::numeric_limits<int>::max)();
4268 }
4269
Phil Nash3b80af72012-08-09 07:47:30 +01004270 Catch::cleanUp();
Phil Nash371db8b2012-05-21 18:52:09 +01004271 return result;
Phil Nash89d1e6c2011-05-24 08:23:02 +01004272 }
4273
Phil Nash163088a2012-05-31 19:40:26 +01004274 inline void showUsage( std::ostream& os ) {
Phil Nashecf934b2012-08-27 21:42:55 +01004275 AllOptions options;
Phil Nashe2d215e2012-09-07 17:52:35 +01004276
Phil Nashecf934b2012-08-27 21:42:55 +01004277 for( AllOptions::const_iterator it = options.begin(); it != options.end(); ++it ) {
4278 OptionParser& opt = **it;
4279 os << " " << opt.optionNames() << " " << opt.argsSynopsis() << "\n";
4280 }
4281 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 +01004282 }
Phil Nashe2d215e2012-09-07 17:52:35 +01004283
4284 inline void addIndent( std::ostream& os, std::size_t indent ) {
4285 while( indent-- > 0 )
4286 os << ' ';
4287 }
4288
4289 inline void recursivelyWrapLine( std::ostream& os, std::string paragraph, std::size_t columns, std::size_t indent ) {
4290 std::size_t width = columns-indent;
4291 std::size_t tab = 0;
4292 std::size_t wrapPoint = width;
4293 for( std::size_t pos = 0; pos < paragraph.size(); ++pos ) {
4294 if( pos == width ) {
4295 addIndent( os, indent );
4296 os << paragraph.substr( 0, wrapPoint ) << "\n";
4297 return recursivelyWrapLine( os, paragraph.substr( wrapPoint+1 ), columns, indent+tab );
4298 }
4299 if( paragraph[pos] == '\t' ) {
4300 tab = pos;
4301 paragraph = paragraph.substr( 0, tab ) + paragraph.substr( tab+1 );
4302 pos--;
4303 }
4304 else if( paragraph[pos] == ' ' ) {
4305 wrapPoint = pos;
4306 }
4307 }
4308 addIndent( os, indent );
4309 os << paragraph << "\n";
4310 }
Phil Nashf7418eb2012-09-09 11:44:30 +01004311
Phil Nashe2d215e2012-09-07 17:52:35 +01004312 inline std::string addLineBreaks( const std::string& str, std::size_t columns, std::size_t indent = 0 ) {
4313 std::ostringstream oss;
4314 std::string::size_type pos = 0;
4315 std::string::size_type newline = str.find_first_of( '\n' );
4316 while( newline != std::string::npos ) {
4317 std::string paragraph = str.substr( pos, newline-pos );
4318 recursivelyWrapLine( oss, paragraph, columns, indent );
4319 pos = newline+1;
4320 newline = str.find_first_of( '\n', pos );
4321 }
Phil Nashf7418eb2012-09-09 11:44:30 +01004322 if( pos != str.size() )
4323 recursivelyWrapLine( oss, str.substr( pos, str.size()-pos ), columns, indent );
4324
Phil Nashe2d215e2012-09-07 17:52:35 +01004325 return oss.str();
4326 }
4327
4328 inline void showHelp( const CommandParser& parser ) {
4329 std::string exeName = parser.exeName();
Phil Nash89d1e6c2011-05-24 08:23:02 +01004330 std::string::size_type pos = exeName.find_last_of( "/\\" );
Phil Nash89d2a3f2012-05-16 15:09:17 +01004331 if( pos != std::string::npos ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01004332 exeName = exeName.substr( pos+1 );
4333 }
4334
Phil Nashe2d215e2012-09-07 17:52:35 +01004335 AllOptions options;
4336 Options::HelpOptionParser helpOpt;
4337 bool displayedSpecificOption = false;
4338 for( AllOptions::const_iterator it = options.begin(); it != options.end(); ++it ) {
4339 OptionParser& opt = **it;
4340 if( opt.find( parser ) && opt.optionNames() != helpOpt.optionNames() ) {
4341 displayedSpecificOption = true;
4342 std::cout << "\n" << opt.optionNames() << " " << opt.argsSynopsis() << "\n\n"
4343 << opt.optionSummary() << "\n\n"
4344
4345 << addLineBreaks( opt.optionDescription(), 80, 2 ) << "\n" << std::endl;
4346 }
4347 }
4348
4349 if( !displayedSpecificOption ) {
4350 std::cout << exeName << " is a CATCH host application. Options are as follows:\n\n";
4351 showUsage( std::cout );
4352 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01004353 }
4354
Phil Nash89d2a3f2012-05-16 15:09:17 +01004355 inline int Main( int argc, char* const argv[], Config& config ) {
Phil Nash163088a2012-05-31 19:40:26 +01004356
Phil Nashabf27162012-07-05 18:37:58 +01004357 try {
4358 CommandParser parser( argc, argv );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004359
Phil Nashecf934b2012-08-27 21:42:55 +01004360 if( Command cmd = Options::HelpOptionParser().find( parser ) ) {
Phil Nashabf27162012-07-05 18:37:58 +01004361 if( cmd.argsCount() != 0 )
4362 cmd.raiseError( "Does not accept arguments" );
4363
Phil Nashe2d215e2012-09-07 17:52:35 +01004364 showHelp( parser );
Phil Nash3b80af72012-08-09 07:47:30 +01004365 Catch::cleanUp();
Phil Nashabf27162012-07-05 18:37:58 +01004366 return 0;
4367 }
4368
Phil Nashecf934b2012-08-27 21:42:55 +01004369 AllOptions options;
4370
4371 options.parseIntoConfig( parser, config.data() );
Phil Nashabf27162012-07-05 18:37:58 +01004372 }
4373 catch( std::exception& ex ) {
Phil Nash6f220862012-07-23 08:24:52 +01004374 std::cerr << ex.what() << "\n\nUsage: ...\n\n";
Phil Nash163088a2012-05-31 19:40:26 +01004375 showUsage( std::cerr );
Phil Nash3b80af72012-08-09 07:47:30 +01004376 Catch::cleanUp();
Phil Nash89d1e6c2011-05-24 08:23:02 +01004377 return (std::numeric_limits<int>::max)();
4378 }
4379
Phil Nash89d1e6c2011-05-24 08:23:02 +01004380 return Main( config );
4381 }
4382
Phil Nash89d2a3f2012-05-16 15:09:17 +01004383 inline int Main( int argc, char* const argv[] ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01004384 Config config;
Phil Nash371db8b2012-05-21 18:52:09 +01004385// !TBD: This doesn't always work, for some reason
Phil Nash89d1e6c2011-05-24 08:23:02 +01004386// if( isDebuggerActive() )
4387// config.useStream( "debug" );
Phil Nash371db8b2012-05-21 18:52:09 +01004388 return Main( argc, argv, config );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004389 }
4390
4391} // end namespace Catch
4392
Phil Nash3b80af72012-08-09 07:47:30 +01004393// #included from: catch_registry_hub.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004394#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01004395
4396// #included from: catch_test_case_registry_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004397#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01004398
4399#include <vector>
4400#include <set>
4401#include <sstream>
4402#include <iostream>
4403
4404namespace Catch {
4405
4406 class TestRegistry : public ITestCaseRegistry {
4407 public:
4408 TestRegistry() : m_unnamedCount( 0 ) {}
Phil Nasha695eb92012-08-13 07:46:10 +01004409 virtual ~TestRegistry();
Phil Nash3b80af72012-08-09 07:47:30 +01004410
4411 virtual void registerTest( const TestCaseInfo& testInfo ) {
4412 if( testInfo.getName() == "" ) {
4413 std::ostringstream oss;
4414 oss << testInfo.getName() << "unnamed/" << ++m_unnamedCount;
4415 return registerTest( TestCaseInfo( testInfo, oss.str() ) );
4416 }
4417
4418 if( m_functions.find( testInfo ) == m_functions.end() ) {
4419 m_functions.insert( testInfo );
4420 m_functionsInOrder.push_back( testInfo );
Phil Nash5bc030d2012-08-16 18:48:50 +01004421 if( !testInfo.isHidden() )
4422 m_nonHiddenFunctions.push_back( testInfo );
Phil Nash3b80af72012-08-09 07:47:30 +01004423 }
4424 else {
4425 const TestCaseInfo& prev = *m_functions.find( testInfo );
4426 std::cerr << "error: TEST_CASE( \"" << testInfo.getName() << "\" ) already defined.\n"
4427 << "\tFirst seen at " << SourceLineInfo( prev.getLineInfo() ) << "\n"
4428 << "\tRedefined at " << SourceLineInfo( testInfo.getLineInfo() ) << std::endl;
4429 exit(1);
4430 }
4431 }
4432
4433 virtual const std::vector<TestCaseInfo>& getAllTests() const {
4434 return m_functionsInOrder;
4435 }
4436
Phil Nash5bc030d2012-08-16 18:48:50 +01004437 virtual const std::vector<TestCaseInfo>& getAllNonHiddenTests() const {
4438 return m_nonHiddenFunctions;
4439 }
4440
Phil Nash56d5c422012-08-23 20:08:50 +01004441 // !TBD deprecated
Phil Nash3b80af72012-08-09 07:47:30 +01004442 virtual std::vector<TestCaseInfo> getMatchingTestCases( const std::string& rawTestSpec ) const {
Phil Nash5bc030d2012-08-16 18:48:50 +01004443 std::vector<TestCaseInfo> matchingTests;
4444 getMatchingTestCases( rawTestSpec, matchingTests );
4445 return matchingTests;
4446 }
4447
Phil Nash56d5c422012-08-23 20:08:50 +01004448 // !TBD deprecated
Phil Nash5bc030d2012-08-16 18:48:50 +01004449 virtual void getMatchingTestCases( const std::string& rawTestSpec, std::vector<TestCaseInfo>& matchingTestsOut ) const {
Phil Nash56d5c422012-08-23 20:08:50 +01004450 TestCaseFilter filter( rawTestSpec );
Phil Nash5bc030d2012-08-16 18:48:50 +01004451
Phil Nash3b80af72012-08-09 07:47:30 +01004452 std::vector<TestCaseInfo>::const_iterator it = m_functionsInOrder.begin();
4453 std::vector<TestCaseInfo>::const_iterator itEnd = m_functionsInOrder.end();
4454 for(; it != itEnd; ++it ) {
Phil Nash56d5c422012-08-23 20:08:50 +01004455 if( filter.shouldInclude( *it ) ) {
Phil Nash5bc030d2012-08-16 18:48:50 +01004456 matchingTestsOut.push_back( *it );
Phil Nash3b80af72012-08-09 07:47:30 +01004457 }
4458 }
Phil Nash3b80af72012-08-09 07:47:30 +01004459 }
Phil Nash56d5c422012-08-23 20:08:50 +01004460 virtual void getMatchingTestCases( const TestCaseFilters& filters, std::vector<TestCaseInfo>& matchingTestsOut ) const {
4461 std::vector<TestCaseInfo>::const_iterator it = m_functionsInOrder.begin();
4462 std::vector<TestCaseInfo>::const_iterator itEnd = m_functionsInOrder.end();
4463 // !TBD: replace with algorithm
4464 for(; it != itEnd; ++it )
4465 if( filters.shouldInclude( *it ) )
4466 matchingTestsOut.push_back( *it );
4467 }
Phil Nash3b80af72012-08-09 07:47:30 +01004468
4469 private:
4470
4471 std::set<TestCaseInfo> m_functions;
4472 std::vector<TestCaseInfo> m_functionsInOrder;
Phil Nash5bc030d2012-08-16 18:48:50 +01004473 std::vector<TestCaseInfo> m_nonHiddenFunctions;
Phil Nash3b80af72012-08-09 07:47:30 +01004474 size_t m_unnamedCount;
4475 };
4476
4477 ///////////////////////////////////////////////////////////////////////////
4478
Phil Nash5bc030d2012-08-16 18:48:50 +01004479 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
Phil Nash3b80af72012-08-09 07:47:30 +01004480 public:
4481
4482 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
4483
4484 virtual void invoke() const {
4485 m_fun();
4486 }
4487
Phil Nash3b80af72012-08-09 07:47:30 +01004488 private:
Phil Nash5bc030d2012-08-16 18:48:50 +01004489 virtual ~FreeFunctionTestCase();
4490
Phil Nash3b80af72012-08-09 07:47:30 +01004491 TestFunction m_fun;
4492 };
4493
4494 ///////////////////////////////////////////////////////////////////////////
4495
4496 AutoReg::AutoReg( TestFunction function,
4497 const char* name,
4498 const char* description,
4499 const SourceLineInfo& lineInfo ) {
4500 registerTestCase( new FreeFunctionTestCase( function ), name, description, lineInfo );
4501 }
4502
4503 AutoReg::~AutoReg() {}
4504
4505 void AutoReg::registerTestCase( ITestCase* testCase,
4506 const char* name,
4507 const char* description,
4508 const SourceLineInfo& lineInfo ) {
4509 getMutableRegistryHub().registerTest( TestCaseInfo( testCase, name, description, lineInfo ) );
4510 }
4511
4512} // end namespace Catch
4513
4514// #included from: catch_reporter_registry.hpp
4515#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
4516
4517#include <map>
4518
4519namespace Catch {
4520
4521 class ReporterRegistry : public IReporterRegistry {
4522
4523 public:
4524
Phil Nasha695eb92012-08-13 07:46:10 +01004525 virtual ~ReporterRegistry() {
Phil Nash3b80af72012-08-09 07:47:30 +01004526 deleteAllValues( m_factories );
4527 }
4528
4529 virtual IReporter* create( const std::string& name, const ReporterConfig& config ) const {
4530 FactoryMap::const_iterator it = m_factories.find( name );
4531 if( it == m_factories.end() )
4532 return NULL;
4533 return it->second->create( config );
4534 }
4535
4536 void registerReporter( const std::string& name, IReporterFactory* factory ) {
4537 m_factories.insert( std::make_pair( name, factory ) );
4538 }
4539
4540 const FactoryMap& getFactories() const {
4541 return m_factories;
4542 }
4543
4544 private:
4545 FactoryMap m_factories;
4546 };
4547}
4548
4549// #included from: catch_exception_translator_registry.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004550#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01004551
4552#ifdef __OBJC__
4553#import "Foundation/Foundation.h"
4554#endif
4555
4556namespace Catch {
4557
4558 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
4559 public:
4560 ~ExceptionTranslatorRegistry() {
4561 deleteAll( m_translators );
4562 }
4563
4564 virtual void registerTranslator( const IExceptionTranslator* translator ) {
4565 m_translators.push_back( translator );
4566 }
4567
4568 virtual std::string translateActiveException() const {
4569 try {
4570#ifdef __OBJC__
4571 // In Objective-C try objective-c exceptions first
4572 @try {
4573 throw;
4574 }
4575 @catch (NSException *exception) {
4576 return toString( [exception description] );
4577 }
4578#else
4579 throw;
4580#endif
4581 }
4582 catch( std::exception& ex ) {
4583 return ex.what();
4584 }
4585 catch( std::string& msg ) {
4586 return msg;
4587 }
4588 catch( const char* msg ) {
4589 return msg;
4590 }
4591 catch(...) {
4592 return tryTranslators( m_translators.begin() );
4593 }
4594 }
4595
4596 std::string tryTranslators( std::vector<const IExceptionTranslator*>::const_iterator it ) const {
4597 if( it == m_translators.end() )
4598 return "Unknown exception";
4599
4600 try {
4601 return (*it)->translate();
4602 }
4603 catch(...) {
4604 return tryTranslators( it+1 );
4605 }
4606 }
4607
4608 private:
4609 std::vector<const IExceptionTranslator*> m_translators;
4610 };
4611}
4612
4613namespace Catch {
4614
4615 namespace {
4616
4617 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
4618
4619 RegistryHub( const RegistryHub& );
4620 void operator=( const RegistryHub& );
4621
4622 public: // IRegistryHub
4623 RegistryHub() {
4624 }
4625 virtual const IReporterRegistry& getReporterRegistry() const {
4626 return m_reporterRegistry;
4627 }
4628 virtual const ITestCaseRegistry& getTestCaseRegistry() const {
4629 return m_testCaseRegistry;
4630 }
4631 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
4632 return m_exceptionTranslatorRegistry;
4633 }
4634
4635 public: // IMutableRegistryHub
4636 virtual void registerReporter( const std::string& name, IReporterFactory* factory ) {
4637 m_reporterRegistry.registerReporter( name, factory );
4638 }
4639 virtual void registerTest( const TestCaseInfo& testInfo ) {
4640 m_testCaseRegistry.registerTest( testInfo );
4641 }
4642 virtual void registerTranslator( const IExceptionTranslator* translator ) {
4643 m_exceptionTranslatorRegistry.registerTranslator( translator );
4644 }
4645
4646 private:
4647 TestRegistry m_testCaseRegistry;
4648 ReporterRegistry m_reporterRegistry;
4649 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
4650 };
4651
4652 // Single, global, instance
4653 inline RegistryHub*& getTheRegistryHub() {
4654 static RegistryHub* theRegistryHub = NULL;
4655 if( !theRegistryHub )
4656 theRegistryHub = new RegistryHub();
4657 return theRegistryHub;
4658 }
4659 }
4660
4661 IRegistryHub& getRegistryHub() {
4662 return *getTheRegistryHub();
4663 }
4664 IMutableRegistryHub& getMutableRegistryHub() {
4665 return *getTheRegistryHub();
4666 }
4667 void cleanUp() {
4668 delete getTheRegistryHub();
4669 getTheRegistryHub() = NULL;
4670 cleanUpContext();
4671 }
4672
4673} // end namespace Catch
Matt Wozniskif29c8982012-09-17 01:42:29 -04004674
Phil Nash3b80af72012-08-09 07:47:30 +01004675// #included from: catch_notimplemented_exception.hpp
4676#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
4677
4678#include <ostream>
4679
4680namespace Catch {
4681
4682 NotImplementedException::NotImplementedException( const SourceLineInfo& lineInfo )
4683 : m_lineInfo( lineInfo ) {
4684 std::ostringstream oss;
4685 oss << lineInfo << "function ";
4686 if( !lineInfo.function.empty() )
4687 oss << lineInfo.function << " ";
4688 oss << "not implemented";
4689 m_what = oss.str();
4690 }
4691
4692 const char* NotImplementedException::what() const throw() {
4693 return m_what.c_str();
4694 }
4695
4696} // end namespace Catch
4697
4698// #included from: catch_context_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004699#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01004700
Phil Nash3b80af72012-08-09 07:47:30 +01004701namespace Catch {
4702
4703 class Context : public IMutableContext {
4704
4705 Context() : m_config( NULL ) {}
4706 Context( const Context& );
4707 void operator=( const Context& );
4708
4709 public: // IContext
4710 virtual IResultCapture& getResultCapture() {
4711 return *m_resultCapture;
4712 }
4713 virtual IRunner& getRunner() {
4714 return *m_runner;
4715 }
4716 virtual size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ) {
4717 return getGeneratorsForCurrentTest()
4718 .getGeneratorInfo( fileInfo, totalSize )
4719 .getCurrentIndex();
4720 }
4721 virtual bool advanceGeneratorsForCurrentTest() {
4722 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
4723 return generators && generators->moveNext();
4724 }
4725
4726 virtual const IConfig* getConfig() const {
4727 return m_config;
4728 }
4729
4730 public: // IMutableContext
4731 virtual void setResultCapture( IResultCapture* resultCapture ) {
4732 m_resultCapture = resultCapture;
4733 }
4734 virtual void setRunner( IRunner* runner ) {
4735 m_runner = runner;
4736 }
4737 virtual void setConfig( const IConfig* config ) {
4738 m_config = config;
4739 }
4740
4741 friend IMutableContext& getCurrentMutableContext();
4742
4743 private:
4744 IGeneratorsForTest* findGeneratorsForCurrentTest() {
4745 std::string testName = getResultCapture().getCurrentTestName();
4746
4747 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
4748 m_generatorsByTestName.find( testName );
4749 return it != m_generatorsByTestName.end()
4750 ? it->second
4751 : NULL;
4752 }
4753
4754 IGeneratorsForTest& getGeneratorsForCurrentTest() {
4755 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
4756 if( !generators ) {
4757 std::string testName = getResultCapture().getCurrentTestName();
4758 generators = createGeneratorsForTest();
4759 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
4760 }
4761 return *generators;
4762 }
4763
4764 private:
4765 IRunner* m_runner;
4766 IResultCapture* m_resultCapture;
4767 const IConfig* m_config;
4768 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
4769 };
4770
4771 namespace {
4772 Context* currentContext = NULL;
4773 }
4774 IMutableContext& getCurrentMutableContext() {
4775 if( !currentContext )
4776 currentContext = new Context();
4777 return *currentContext;
4778 }
4779 IContext& getCurrentContext() {
4780 return getCurrentMutableContext();
4781 }
4782
Phil Nash67ec8702012-09-26 18:38:26 +01004783 Stream createStream( const std::string& streamName ) {
4784 if( streamName == "stdout" ) return Stream( std::cout.rdbuf(), false );
4785 if( streamName == "stderr" ) return Stream( std::cerr.rdbuf(), false );
4786 if( streamName == "debug" ) return Stream( new StreamBufImpl<OutputDebugWriter>, true );
Phil Nash3b80af72012-08-09 07:47:30 +01004787
4788 throw std::domain_error( "Unknown stream: " + streamName );
4789 }
4790
4791 void cleanUpContext() {
4792 delete currentContext;
4793 currentContext = NULL;
4794 }
4795}
Matt Wozniskif29c8982012-09-17 01:42:29 -04004796
Phil Nash3b80af72012-08-09 07:47:30 +01004797// #included from: catch_console_colour_impl.hpp
4798#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
4799
Phil Nash56d5c422012-08-23 20:08:50 +01004800// #included from: catch_console_colour.hpp
4801#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
4802
4803namespace Catch {
4804
4805 struct ConsoleColourImpl;
4806
4807 class TextColour : NonCopyable {
4808 public:
4809
4810 enum Colours {
4811 None,
4812
4813 FileName,
4814 ResultError,
4815 ResultSuccess,
4816
4817 Error,
4818 Success,
4819
4820 OriginalExpression,
4821 ReconstructedExpression
4822 };
4823
4824 TextColour( Colours colour = None );
4825 void set( Colours colour );
4826 ~TextColour();
4827
4828 private:
4829 ConsoleColourImpl* m_impl;
4830 };
4831
4832} // end namespace Catch
4833
Phil Nash3b80af72012-08-09 07:47:30 +01004834#ifdef CATCH_PLATFORM_WINDOWS
4835
4836#include <windows.h>
4837
4838namespace Catch {
4839
4840 namespace {
4841
4842 WORD mapConsoleColour( TextColour::Colours colour ) {
4843 switch( colour ) {
4844 case TextColour::FileName:
4845 return FOREGROUND_INTENSITY; // greyed out
4846 case TextColour::ResultError:
4847 return FOREGROUND_RED | FOREGROUND_INTENSITY; // bright red
4848 case TextColour::ResultSuccess:
4849 return FOREGROUND_GREEN | FOREGROUND_INTENSITY; // bright green
4850 case TextColour::Error:
4851 return FOREGROUND_RED; // dark red
4852 case TextColour::Success:
4853 return FOREGROUND_GREEN; // dark green
4854 case TextColour::OriginalExpression:
4855 return FOREGROUND_BLUE | FOREGROUND_GREEN; // turquoise
4856 case TextColour::ReconstructedExpression:
4857 return FOREGROUND_RED | FOREGROUND_GREEN; // greeny-yellow
4858 default: return 0;
4859 }
4860 }
4861 }
4862
4863 struct ConsoleColourImpl {
4864
4865 ConsoleColourImpl()
4866 : hStdout( GetStdHandle(STD_OUTPUT_HANDLE) ),
4867 wOldColorAttrs( 0 )
4868 {
4869 GetConsoleScreenBufferInfo( hStdout, &csbiInfo );
4870 wOldColorAttrs = csbiInfo.wAttributes;
4871 }
4872
4873 ~ConsoleColourImpl() {
4874 SetConsoleTextAttribute( hStdout, wOldColorAttrs );
4875 }
4876
4877 void set( TextColour::Colours colour ) {
4878 WORD consoleColour = mapConsoleColour( colour );
4879 if( consoleColour > 0 )
4880 SetConsoleTextAttribute( hStdout, consoleColour );
4881 }
4882
4883 HANDLE hStdout;
4884 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
4885 WORD wOldColorAttrs;
4886 };
4887
4888 TextColour::TextColour( Colours colour )
4889 : m_impl( new ConsoleColourImpl() )
4890 {
4891 if( colour )
4892 m_impl->set( colour );
4893 }
4894
4895 TextColour::~TextColour() {
4896 delete m_impl;
4897 }
4898
4899 void TextColour::set( Colours colour ) {
4900 m_impl->set( colour );
4901 }
4902
4903} // end namespace Catch
4904
4905#else
4906
4907namespace Catch {
4908 TextColour::TextColour( Colours ){}
4909 TextColour::~TextColour(){}
4910 void TextColour::set( Colours ){}
4911
4912} // end namespace Catch
4913
4914#endif
4915
4916// #included from: catch_generators_impl.hpp
4917#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
4918
4919#include <vector>
4920#include <string>
4921#include <map>
4922
4923namespace Catch {
4924
4925 struct GeneratorInfo : IGeneratorInfo {
4926
4927 GeneratorInfo( std::size_t size )
4928 : m_size( size ),
4929 m_currentIndex( 0 )
4930 {}
4931
4932 bool moveNext() {
4933 if( ++m_currentIndex == m_size ) {
4934 m_currentIndex = 0;
4935 return false;
4936 }
4937 return true;
4938 }
4939
4940 std::size_t getCurrentIndex() const {
4941 return m_currentIndex;
4942 }
4943
4944 std::size_t m_size;
4945 std::size_t m_currentIndex;
4946 };
4947
4948 ///////////////////////////////////////////////////////////////////////////
4949
4950 class GeneratorsForTest : public IGeneratorsForTest {
4951
4952 public:
4953 ~GeneratorsForTest() {
4954 deleteAll( m_generatorsInOrder );
4955 }
4956
4957 IGeneratorInfo& getGeneratorInfo( const std::string& fileInfo, std::size_t size ) {
4958 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
4959 if( it == m_generatorsByName.end() ) {
4960 IGeneratorInfo* info = new GeneratorInfo( size );
4961 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
4962 m_generatorsInOrder.push_back( info );
4963 return *info;
4964 }
4965 return *it->second;
4966 }
4967
4968 bool moveNext() {
4969 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
4970 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
4971 for(; it != itEnd; ++it ) {
4972 if( (*it)->moveNext() )
4973 return true;
4974 }
4975 return false;
4976 }
4977
4978 private:
4979 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
4980 std::vector<IGeneratorInfo*> m_generatorsInOrder;
4981 };
4982
4983 IGeneratorsForTest* createGeneratorsForTest()
4984 {
4985 return new GeneratorsForTest();
4986 }
4987
4988} // end namespace Catch
4989
4990// #included from: catch_resultinfo.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004991#define TWOBLUECUBES_CATCH_RESULTINFO_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01004992
4993namespace Catch {
4994
Phil Nash67305122012-10-09 11:48:55 +01004995 ResultInfo::ResultInfo() {}
Phil Nash3b80af72012-08-09 07:47:30 +01004996
Phil Nash67305122012-10-09 11:48:55 +01004997 ResultInfo::ResultInfo( const ResultData& data ) : m_data( data ) {}
Phil Nash3b80af72012-08-09 07:47:30 +01004998
4999 ResultInfo::~ResultInfo() {}
5000
5001 bool ResultInfo::ok() const {
Phil Nash67305122012-10-09 11:48:55 +01005002 return isOk( m_data.resultType );
Phil Nash3b80af72012-08-09 07:47:30 +01005003 }
5004
5005 ResultWas::OfType ResultInfo::getResultType() const {
Phil Nash67305122012-10-09 11:48:55 +01005006 return m_data.resultType;
Phil Nash3b80af72012-08-09 07:47:30 +01005007 }
5008
5009 bool ResultInfo::hasExpression() const {
Phil Nash67305122012-10-09 11:48:55 +01005010 return !m_data.capturedExpression.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01005011 }
5012
5013 bool ResultInfo::hasMessage() const {
Phil Nash67305122012-10-09 11:48:55 +01005014 return !m_data.message.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01005015 }
5016
5017 std::string ResultInfo::getExpression() const {
Phil Nash67305122012-10-09 11:48:55 +01005018 return m_data.capturedExpression;
Phil Nash3b80af72012-08-09 07:47:30 +01005019 }
5020
5021 bool ResultInfo::hasExpandedExpression() const {
Phil Nash67305122012-10-09 11:48:55 +01005022 return hasExpression() && getExpandedExpression() != getExpression();
Phil Nash3b80af72012-08-09 07:47:30 +01005023 }
5024
5025 std::string ResultInfo::getExpandedExpression() const {
Phil Nash67305122012-10-09 11:48:55 +01005026 return m_data.reconstructedExpression;
Phil Nash3b80af72012-08-09 07:47:30 +01005027 }
5028
5029 std::string ResultInfo::getMessage() const {
Phil Nash67305122012-10-09 11:48:55 +01005030 return m_data.message;
Phil Nash3b80af72012-08-09 07:47:30 +01005031 }
5032
5033 std::string ResultInfo::getFilename() const {
Phil Nash67305122012-10-09 11:48:55 +01005034 return m_data.lineInfo.file;
Phil Nash3b80af72012-08-09 07:47:30 +01005035 }
5036
5037 std::size_t ResultInfo::getLine() const {
Phil Nash67305122012-10-09 11:48:55 +01005038 return m_data.lineInfo.line;
Phil Nash3b80af72012-08-09 07:47:30 +01005039 }
5040
5041 std::string ResultInfo::getTestMacroName() const {
Phil Nash67305122012-10-09 11:48:55 +01005042 return m_data.macroName;
Phil Nash3b80af72012-08-09 07:47:30 +01005043 }
5044
5045} // end namespace Catch
5046
5047// #included from: catch_resultinfo_builder.hpp
5048#define TWOBLUECUBES_CATCH_RESULTINFO_BUILDER_HPP_INCLUDED
5049
5050namespace Catch {
5051
Phil Nash803f6b72012-10-04 08:14:48 +01005052 ResultInfoBuilder::ResultInfoBuilder() {}
5053
5054 ResultInfoBuilder& ResultInfoBuilder::setResultType( ResultWas::OfType result ) {
Phil Nash9902ac92012-10-09 20:58:33 +01005055 // Flip bool results if isFalse is set
5056 if( m_isFalse && result == ResultWas::Ok )
Phil Nash67305122012-10-09 11:48:55 +01005057 m_data.resultType = ResultWas::ExpressionFailed;
Phil Nash9902ac92012-10-09 20:58:33 +01005058 else if( m_isFalse && result == ResultWas::ExpressionFailed )
Phil Nash67305122012-10-09 11:48:55 +01005059 m_data.resultType = ResultWas::Ok;
Phil Nash3b80af72012-08-09 07:47:30 +01005060 else
Phil Nash67305122012-10-09 11:48:55 +01005061 m_data.resultType = result;
5062 return *this;
5063 }
5064 ResultInfoBuilder& ResultInfoBuilder::setCapturedExpression( const std::string& capturedExpression ) {
5065 m_data.capturedExpression = capturedExpression;
5066 return *this;
5067 }
5068 ResultInfoBuilder& ResultInfoBuilder::setIsFalse( bool isFalse ) {
Phil Nash9902ac92012-10-09 20:58:33 +01005069 m_isFalse = isFalse;
Phil Nash803f6b72012-10-04 08:14:48 +01005070 return *this;
Phil Nash3b80af72012-08-09 07:47:30 +01005071 }
5072
Phil Nash803f6b72012-10-04 08:14:48 +01005073 ResultInfoBuilder& ResultInfoBuilder::setMessage( const std::string& message ) {
Phil Nash67305122012-10-09 11:48:55 +01005074 m_data.message = message;
Phil Nash803f6b72012-10-04 08:14:48 +01005075 return *this;
Phil Nash3b80af72012-08-09 07:47:30 +01005076 }
5077
Phil Nash803f6b72012-10-04 08:14:48 +01005078 ResultInfoBuilder& ResultInfoBuilder::setLineInfo( const SourceLineInfo& lineInfo ) {
Phil Nash67305122012-10-09 11:48:55 +01005079 m_data.lineInfo = lineInfo;
5080 return *this;
5081 }
5082
5083 ResultInfoBuilder& ResultInfoBuilder::setMacroName( const std::string& macroName ) {
5084 m_data.macroName = macroName;
Phil Nash803f6b72012-10-04 08:14:48 +01005085 return *this;
Phil Nash3b80af72012-08-09 07:47:30 +01005086 }
5087
Phil Nash803f6b72012-10-04 08:14:48 +01005088 ResultInfoBuilder& ResultInfoBuilder::setLhs( const std::string& lhs ) {
Phil Nash3b80af72012-08-09 07:47:30 +01005089 m_lhs = lhs;
Phil Nash803f6b72012-10-04 08:14:48 +01005090 return *this;
Phil Nash3b80af72012-08-09 07:47:30 +01005091 }
5092
Phil Nash803f6b72012-10-04 08:14:48 +01005093 ResultInfoBuilder& ResultInfoBuilder::setRhs( const std::string& rhs ) {
Phil Nash3b80af72012-08-09 07:47:30 +01005094 m_rhs = rhs;
Phil Nash803f6b72012-10-04 08:14:48 +01005095 return *this;
Phil Nash3b80af72012-08-09 07:47:30 +01005096 }
5097
Phil Nash803f6b72012-10-04 08:14:48 +01005098 ResultInfoBuilder& ResultInfoBuilder::setOp( const std::string& op ) {
Phil Nash3b80af72012-08-09 07:47:30 +01005099 m_op = op;
Phil Nash803f6b72012-10-04 08:14:48 +01005100 return *this;
5101 }
5102
Phil Nash67305122012-10-09 11:48:55 +01005103 ResultInfo ResultInfoBuilder::build() const
5104 {
5105 ResultData data = m_data;
5106 data.reconstructedExpression = reconstructExpression();
Phil Nash9902ac92012-10-09 20:58:33 +01005107 if( m_isFalse ) {
Phil Nash67305122012-10-09 11:48:55 +01005108 if( m_op == "" ) {
5109 data.capturedExpression = "!" + data.capturedExpression;
5110 data.reconstructedExpression = "!" + data.reconstructedExpression;
5111 }
5112 else {
5113 data.capturedExpression = "!(" + data.capturedExpression + ")";
5114 data.reconstructedExpression = "!(" + data.reconstructedExpression + ")";
5115 }
5116 }
5117 return ResultInfo( data );
Phil Nash3b80af72012-08-09 07:47:30 +01005118 }
5119
Phil Nash67305122012-10-09 11:48:55 +01005120 std::string ResultInfoBuilder::reconstructExpression() const {
5121 if( m_op == "" )
5122 return m_lhs.empty() ? m_data.capturedExpression : m_op + m_lhs;
5123 else if( m_op == "matches" )
5124 return m_lhs + " " + m_rhs;
5125 else if( m_op != "!" ) {
5126 if( m_lhs.size() + m_rhs.size() < 30 )
5127 return m_lhs + " " + m_op + " " + m_rhs;
5128 else if( m_lhs.size() < 70 && m_rhs.size() < 70 )
5129 return "\n\t" + m_lhs + "\n\t" + m_op + "\n\t" + m_rhs;
5130 else
5131 return "\n" + m_lhs + "\n" + m_op + "\n" + m_rhs + "\n\n";
5132 }
5133 else
5134 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 +01005135 }
5136
5137} // end namespace Catch
5138
Phil Nash5bc030d2012-08-16 18:48:50 +01005139// #included from: catch_test_case_info.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005140#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
Phil Nash5bc030d2012-08-16 18:48:50 +01005141
5142namespace Catch {
5143
5144 TestCaseInfo::TestCaseInfo( ITestCase* testCase,
5145 const char* name,
5146 const char* description,
5147 const SourceLineInfo& lineInfo )
5148 : m_test( testCase ),
5149 m_name( name ),
5150 m_description( description ),
Phil Nashfc1baac2012-09-15 17:53:27 +01005151 m_lineInfo( lineInfo ),
5152 m_isHidden( startsWith( name, "./" ) )
5153 {
Phil Nash799ecf92012-09-24 08:30:13 +01005154 TagExtracter( m_tags ).parse( m_description );
Phil Nashfc1baac2012-09-15 17:53:27 +01005155 if( hasTag( "hide" ) )
5156 m_isHidden = true;
5157 }
Phil Nash5bc030d2012-08-16 18:48:50 +01005158
5159 TestCaseInfo::TestCaseInfo()
5160 : m_test( NULL ),
5161 m_name(),
Phil Nashfc1baac2012-09-15 17:53:27 +01005162 m_description(),
5163 m_isHidden( false )
Phil Nash5bc030d2012-08-16 18:48:50 +01005164 {}
5165
5166 TestCaseInfo::TestCaseInfo( const TestCaseInfo& other, const std::string& name )
5167 : m_test( other.m_test ),
5168 m_name( name ),
5169 m_description( other.m_description ),
Phil Nashfc1baac2012-09-15 17:53:27 +01005170 m_tags( other.m_tags ),
5171 m_lineInfo( other.m_lineInfo ),
5172 m_isHidden( other.m_isHidden )
Phil Nash5bc030d2012-08-16 18:48:50 +01005173 {}
5174
Phil Nashd2ec8492012-08-23 19:48:57 +01005175 TestCaseInfo::TestCaseInfo( const TestCaseInfo& other )
5176 : m_test( other.m_test ),
5177 m_name( other.m_name ),
5178 m_description( other.m_description ),
Phil Nashfc1baac2012-09-15 17:53:27 +01005179 m_tags( other.m_tags ),
5180 m_lineInfo( other.m_lineInfo ),
5181 m_isHidden( other.m_isHidden )
Phil Nashd2ec8492012-08-23 19:48:57 +01005182 {}
5183
Phil Nash5bc030d2012-08-16 18:48:50 +01005184 void TestCaseInfo::invoke() const {
5185 m_test->invoke();
5186 }
5187
5188 const std::string& TestCaseInfo::getName() const {
5189 return m_name;
5190 }
5191
5192 const std::string& TestCaseInfo::getDescription() const {
5193 return m_description;
5194 }
5195
5196 const SourceLineInfo& TestCaseInfo::getLineInfo() const {
5197 return m_lineInfo;
5198 }
5199
5200 bool TestCaseInfo::isHidden() const {
Phil Nashfc1baac2012-09-15 17:53:27 +01005201 return m_isHidden;
5202 }
5203
5204 bool TestCaseInfo::hasTag( const std::string& tag ) const {
5205 return m_tags.find( tag ) != m_tags.end();
5206 }
Phil Nash799ecf92012-09-24 08:30:13 +01005207 bool TestCaseInfo::matchesTags( const std::string& tagPattern ) const {
5208 TagExpression exp;
5209 TagExpressionParser( exp ).parse( tagPattern );
5210 return exp.matches( m_tags );
5211 }
Phil Nash67ec8702012-09-26 18:38:26 +01005212 const std::set<std::string>& TestCaseInfo::getTags() const {
Phil Nashfc1baac2012-09-15 17:53:27 +01005213 return m_tags;
Phil Nash5bc030d2012-08-16 18:48:50 +01005214 }
5215
5216 void TestCaseInfo::swap( TestCaseInfo& other ) {
5217 m_test.swap( other.m_test );
5218 m_name.swap( other.m_name );
5219 m_description.swap( other.m_description );
5220 m_lineInfo.swap( other.m_lineInfo );
5221 }
5222
5223 bool TestCaseInfo::operator == ( const TestCaseInfo& other ) const {
5224 return m_test.get() == other.m_test.get() && m_name == other.m_name;
5225 }
5226
5227 bool TestCaseInfo::operator < ( const TestCaseInfo& other ) const {
5228 return m_name < other.m_name;
5229 }
Phil Nashd2ec8492012-08-23 19:48:57 +01005230 TestCaseInfo& TestCaseInfo::operator = ( const TestCaseInfo& other ) {
5231 TestCaseInfo temp( other );
5232 swap( temp );
5233 return *this;
5234 }
Phil Nash799ecf92012-09-24 08:30:13 +01005235
5236} // end namespace Catch
Phil Nash5bc030d2012-08-16 18:48:50 +01005237
Phil Nash56d5c422012-08-23 20:08:50 +01005238// #included from: ../reporters/catch_reporter_basic.hpp
5239#define TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
5240
5241// #included from: ../internal/catch_reporter_registrars.hpp
5242#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
5243
5244namespace Catch {
5245
5246 template<typename T>
5247 class ReporterRegistrar {
5248
5249 class ReporterFactory : public IReporterFactory {
5250
5251 virtual IReporter* create( const ReporterConfig& config ) const {
5252 return new T( config );
5253 }
5254
5255 virtual std::string getDescription() const {
5256 return T::getDescription();
5257 }
5258 };
5259
5260 public:
5261
5262 ReporterRegistrar( const std::string& name ) {
5263 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
5264 }
5265 };
5266}
5267
5268#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
5269 Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name );
5270
5271namespace Catch {
5272
Phil Nash56d5c422012-08-23 20:08:50 +01005273 class BasicReporter : public SharedImpl<IReporter> {
5274
5275 struct SpanInfo {
5276
5277 SpanInfo()
5278 : emitted( false )
5279 {}
5280
5281 SpanInfo( const std::string& spanName )
5282 : name( spanName ),
5283 emitted( false )
5284 {}
5285
5286 SpanInfo( const SpanInfo& other )
5287 : name( other.name ),
5288 emitted( other.emitted )
5289 {}
5290
5291 std::string name;
5292 bool emitted;
5293 };
5294
5295 public:
5296 BasicReporter( const ReporterConfig& config )
5297 : m_config( config ),
5298 m_firstSectionInTestCase( true ),
5299 m_aborted( false )
5300 {}
5301
5302 virtual ~BasicReporter();
5303
5304 static std::string getDescription() {
5305 return "Reports test results as lines of text";
5306 }
5307
5308 private:
5309
5310 void ReportCounts( const std::string& label, const Counts& counts, const std::string& allPrefix = "All " ) {
5311 if( counts.passed )
5312 m_config.stream << counts.failed << " of " << counts.total() << " " << label << "s failed";
5313 else
5314 m_config.stream << ( counts.failed > 1 ? allPrefix : "" ) << pluralise( counts.failed, label ) << " failed";
5315 }
5316
5317 void ReportCounts( const Totals& totals, const std::string& allPrefix = "All " ) {
5318 if( totals.assertions.total() == 0 ) {
5319 m_config.stream << "No tests ran";
5320 }
5321 else if( totals.assertions.failed ) {
5322 TextColour colour( TextColour::ResultError );
5323 ReportCounts( "test case", totals.testCases, allPrefix );
5324 if( totals.testCases.failed > 0 ) {
5325 m_config.stream << " (";
5326 ReportCounts( "assertion", totals.assertions, allPrefix );
5327 m_config.stream << ")";
5328 }
5329 }
5330 else {
5331 TextColour colour( TextColour::ResultSuccess );
5332 m_config.stream << allPrefix << "tests passed ("
5333 << pluralise( totals.assertions.passed, "assertion" ) << " in "
5334 << pluralise( totals.testCases.passed, "test case" ) << ")";
5335 }
5336 }
5337
5338 private: // IReporter
5339
5340 virtual bool shouldRedirectStdout() const {
5341 return false;
5342 }
5343
5344 virtual void StartTesting() {
5345 m_testingSpan = SpanInfo();
5346 }
5347
5348 virtual void Aborted() {
5349 m_aborted = true;
5350 }
5351
5352 virtual void EndTesting( const Totals& totals ) {
5353 // Output the overall test results even if "Started Testing" was not emitted
5354 if( m_aborted ) {
5355 m_config.stream << "\n[Testing aborted. ";
5356 ReportCounts( totals, "The first " );
5357 }
5358 else {
5359 m_config.stream << "\n[Testing completed. ";
5360 ReportCounts( totals );
5361 }
5362 m_config.stream << "]\n" << std::endl;
5363 }
5364
5365 virtual void StartGroup( const std::string& groupName ) {
5366 m_groupSpan = groupName;
5367 }
5368
5369 virtual void EndGroup( const std::string& groupName, const Totals& totals ) {
5370 if( m_groupSpan.emitted && !groupName.empty() ) {
5371 m_config.stream << "[End of group: '" << groupName << "'. ";
5372 ReportCounts( totals );
5373 m_config.stream << "]\n" << std::endl;
5374 m_groupSpan = SpanInfo();
5375 }
5376 }
5377
5378 virtual void StartTestCase( const TestCaseInfo& testInfo ) {
5379 m_testSpan = testInfo.getName();
5380 }
5381
5382 virtual void StartSection( const std::string& sectionName, const std::string& ) {
5383 m_sectionSpans.push_back( SpanInfo( sectionName ) );
5384 }
5385
Phil Nasha70fbe32012-08-31 08:10:36 +01005386 virtual void NoAssertionsInSection( const std::string& sectionName ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01005387 startSpansLazily();
Phil Nasha70fbe32012-08-31 08:10:36 +01005388 TextColour colour( TextColour::ResultError );
5389 m_config.stream << "\nNo assertions in section, '" << sectionName << "'\n" << std::endl;
5390 }
5391 virtual void NoAssertionsInTestCase( const std::string& testName ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01005392 startSpansLazily();
Phil Nasha70fbe32012-08-31 08:10:36 +01005393 TextColour colour( TextColour::ResultError );
5394 m_config.stream << "\nNo assertions in test case, '" << testName << "'\n" << std::endl;
5395 }
5396
Phil Nash56d5c422012-08-23 20:08:50 +01005397 virtual void EndSection( const std::string& sectionName, const Counts& assertions ) {
Phil Nasha70fbe32012-08-31 08:10:36 +01005398
Phil Nash56d5c422012-08-23 20:08:50 +01005399 SpanInfo& sectionSpan = m_sectionSpans.back();
5400 if( sectionSpan.emitted && !sectionSpan.name.empty() ) {
5401 m_config.stream << "[End of section: '" << sectionName << "' ";
5402
5403 if( assertions.failed ) {
5404 TextColour colour( TextColour::ResultError );
5405 ReportCounts( "assertion", assertions);
5406 }
5407 else {
5408 TextColour colour( TextColour::ResultSuccess );
5409 m_config.stream << ( assertions.passed > 1 ? "All " : "" )
5410 << pluralise( assertions.passed, "assertion" ) << " passed" ;
5411 }
5412 m_config.stream << "]\n" << std::endl;
5413 }
5414 m_sectionSpans.pop_back();
5415 }
5416
5417 virtual void Result( const ResultInfo& resultInfo ) {
5418 if( !m_config.includeSuccessfulResults && resultInfo.getResultType() == ResultWas::Ok )
5419 return;
5420
Phil Nashe2d215e2012-09-07 17:52:35 +01005421 startSpansLazily();
Phil Nash56d5c422012-08-23 20:08:50 +01005422
5423 if( !resultInfo.getFilename().empty() ) {
5424 TextColour colour( TextColour::FileName );
5425 m_config.stream << SourceLineInfo( resultInfo.getFilename(), resultInfo.getLine() );
5426 }
5427
5428 if( resultInfo.hasExpression() ) {
5429 TextColour colour( TextColour::OriginalExpression );
5430 m_config.stream << resultInfo.getExpression();
5431 if( resultInfo.ok() ) {
5432 TextColour successColour( TextColour::Success );
5433 m_config.stream << " succeeded";
5434 }
5435 else {
5436 TextColour errorColour( TextColour::Error );
5437 m_config.stream << " failed";
5438 }
5439 }
5440 switch( resultInfo.getResultType() ) {
5441 case ResultWas::ThrewException:
5442 {
5443 TextColour colour( TextColour::Error );
5444 if( resultInfo.hasExpression() )
5445 m_config.stream << " with unexpected";
5446 else
5447 m_config.stream << "Unexpected";
5448 m_config.stream << " exception with message: '" << resultInfo.getMessage() << "'";
5449 }
5450 break;
5451 case ResultWas::DidntThrowException:
5452 {
5453 TextColour colour( TextColour::Error );
5454 if( resultInfo.hasExpression() )
5455 m_config.stream << " because no exception was thrown where one was expected";
5456 else
5457 m_config.stream << "No exception thrown where one was expected";
5458 }
5459 break;
5460 case ResultWas::Info:
5461 streamVariableLengthText( "info", resultInfo.getMessage() );
5462 break;
5463 case ResultWas::Warning:
5464 m_config.stream << "warning:\n'" << resultInfo.getMessage() << "'";
5465 break;
5466 case ResultWas::ExplicitFailure:
5467 {
5468 TextColour colour( TextColour::Error );
5469 m_config.stream << "failed with message: '" << resultInfo.getMessage() << "'";
5470 }
5471 break;
5472 case ResultWas::Unknown: // These cases are here to prevent compiler warnings
5473 case ResultWas::Ok:
5474 case ResultWas::FailureBit:
5475 case ResultWas::ExpressionFailed:
5476 case ResultWas::Exception:
5477 if( !resultInfo.hasExpression() ) {
5478 if( resultInfo.ok() ) {
5479 TextColour colour( TextColour::Success );
5480 m_config.stream << " succeeded";
5481 }
5482 else {
5483 TextColour colour( TextColour::Error );
5484 m_config.stream << " failed";
5485 }
5486 }
5487 break;
5488 }
5489
5490 if( resultInfo.hasExpandedExpression() ) {
5491 m_config.stream << " for: ";
Phil Nash9444bbc2012-10-12 07:58:17 +01005492 if( resultInfo.getExpandedExpression().size() > 40 )
5493 m_config.stream << "\n";
5494 if( resultInfo.getExpandedExpression().size() < 70 )
5495 m_config.stream << "\t";
Phil Nash56d5c422012-08-23 20:08:50 +01005496 TextColour colour( TextColour::ReconstructedExpression );
5497 m_config.stream << resultInfo.getExpandedExpression();
5498 }
5499 m_config.stream << std::endl;
5500 }
5501
5502 virtual void EndTestCase( const TestCaseInfo& testInfo,
5503 const Totals& totals,
5504 const std::string& stdOut,
5505 const std::string& stdErr ) {
5506 if( !stdOut.empty() ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01005507 startSpansLazily();
Phil Nash56d5c422012-08-23 20:08:50 +01005508 streamVariableLengthText( "stdout", stdOut );
5509 }
5510
5511 if( !stdErr.empty() ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01005512 startSpansLazily();
Phil Nash56d5c422012-08-23 20:08:50 +01005513 streamVariableLengthText( "stderr", stdErr );
5514 }
5515
5516 if( m_testSpan.emitted ) {
5517 m_config.stream << "[Finished: '" << testInfo.getName() << "' ";
5518 ReportCounts( totals );
5519 m_config.stream << "]" << std::endl;
5520 }
5521 }
5522
5523 private: // helpers
5524
Phil Nashe2d215e2012-09-07 17:52:35 +01005525 void startSpansLazily() {
Phil Nash56d5c422012-08-23 20:08:50 +01005526 if( !m_testingSpan.emitted ) {
5527 if( m_config.name.empty() )
5528 m_config.stream << "[Started testing]" << std::endl;
5529 else
5530 m_config.stream << "[Started testing: " << m_config.name << "]" << std::endl;
5531 m_testingSpan.emitted = true;
5532 }
5533
5534 if( !m_groupSpan.emitted && !m_groupSpan.name.empty() ) {
5535 m_config.stream << "[Started group: '" << m_groupSpan.name << "']" << std::endl;
5536 m_groupSpan.emitted = true;
5537 }
5538
5539 if( !m_testSpan.emitted ) {
5540 m_config.stream << std::endl << "[Running: " << m_testSpan.name << "]" << std::endl;
5541 m_testSpan.emitted = true;
5542 }
5543
5544 if( !m_sectionSpans.empty() ) {
5545 SpanInfo& sectionSpan = m_sectionSpans.back();
5546 if( !sectionSpan.emitted && !sectionSpan.name.empty() ) {
5547 if( m_firstSectionInTestCase ) {
5548 m_config.stream << "\n";
5549 m_firstSectionInTestCase = false;
5550 }
5551 std::vector<SpanInfo>::iterator it = m_sectionSpans.begin();
5552 std::vector<SpanInfo>::iterator itEnd = m_sectionSpans.end();
5553 for(; it != itEnd; ++it ) {
5554 SpanInfo& prevSpan = *it;
5555 if( !prevSpan.emitted && !prevSpan.name.empty() ) {
5556 m_config.stream << "[Started section: '" << prevSpan.name << "']" << std::endl;
5557 prevSpan.emitted = true;
5558 }
5559 }
5560 }
5561 }
5562 }
5563
5564 void streamVariableLengthText( const std::string& prefix, const std::string& text ) {
5565 std::string trimmed = trim( text );
5566 if( trimmed.find_first_of( "\r\n" ) == std::string::npos ) {
5567 m_config.stream << "[" << prefix << ": " << trimmed << "]\n";
5568 }
5569 else {
5570 m_config.stream << "\n[" << prefix << "] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" << trimmed
5571 << "\n[end of " << prefix << "] <<<<<<<<<<<<<<<<<<<<<<<<\n";
5572 }
5573 }
5574
5575 private:
5576 ReporterConfig m_config;
5577 bool m_firstSectionInTestCase;
5578
5579 SpanInfo m_testingSpan;
5580 SpanInfo m_groupSpan;
5581 SpanInfo m_testSpan;
5582 std::vector<SpanInfo> m_sectionSpans;
5583 bool m_aborted;
5584 };
5585
5586} // end namespace Catch
5587
5588// #included from: ../reporters/catch_reporter_xml.hpp
5589#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
5590
5591// #included from: ../internal/catch_xmlwriter.hpp
5592#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
5593
5594#include <sstream>
Phil Nash9e7e63c2012-09-29 20:54:03 +01005595#include <iostream>
Phil Nash56d5c422012-08-23 20:08:50 +01005596#include <string>
5597#include <vector>
5598
5599namespace Catch {
5600
5601 class XmlWriter {
5602 public:
5603
5604 class ScopedElement {
5605 public:
5606 ScopedElement( XmlWriter* writer )
5607 : m_writer( writer )
5608 {}
5609
5610 ScopedElement( const ScopedElement& other )
5611 : m_writer( other.m_writer ){
5612 other.m_writer = NULL;
5613 }
5614
5615 ~ScopedElement() {
5616 if( m_writer )
5617 m_writer->endElement();
5618 }
5619
5620 ScopedElement& writeText( const std::string& text ) {
5621 m_writer->writeText( text );
5622 return *this;
5623 }
5624
5625 template<typename T>
5626 ScopedElement& writeAttribute( const std::string& name, const T& attribute ) {
5627 m_writer->writeAttribute( name, attribute );
5628 return *this;
5629 }
5630
5631 private:
5632 mutable XmlWriter* m_writer;
5633 };
5634
5635 XmlWriter()
5636 : m_tagIsOpen( false ),
5637 m_needsNewline( false ),
5638 m_os( &std::cout )
5639 {}
5640
5641 XmlWriter( std::ostream& os )
5642 : m_tagIsOpen( false ),
5643 m_needsNewline( false ),
5644 m_os( &os )
5645 {}
5646
5647 ~XmlWriter() {
5648 while( !m_tags.empty() )
5649 endElement();
5650 }
5651
5652 XmlWriter& operator = ( const XmlWriter& other ) {
5653 XmlWriter temp( other );
5654 swap( temp );
5655 return *this;
5656 }
5657
5658 void swap( XmlWriter& other ) {
5659 std::swap( m_tagIsOpen, other.m_tagIsOpen );
5660 std::swap( m_needsNewline, other.m_needsNewline );
5661 std::swap( m_tags, other.m_tags );
5662 std::swap( m_indent, other.m_indent );
5663 std::swap( m_os, other.m_os );
5664 }
5665
5666 XmlWriter& startElement( const std::string& name ) {
5667 ensureTagClosed();
5668 newlineIfNecessary();
5669 stream() << m_indent << "<" << name;
5670 m_tags.push_back( name );
5671 m_indent += " ";
5672 m_tagIsOpen = true;
5673 return *this;
5674 }
5675
5676 ScopedElement scopedElement( const std::string& name ) {
5677 ScopedElement scoped( this );
5678 startElement( name );
5679 return scoped;
5680 }
5681
5682 XmlWriter& endElement() {
5683 newlineIfNecessary();
5684 m_indent = m_indent.substr( 0, m_indent.size()-2 );
5685 if( m_tagIsOpen ) {
5686 stream() << "/>\n";
5687 m_tagIsOpen = false;
5688 }
5689 else {
5690 stream() << m_indent << "</" << m_tags.back() << ">\n";
5691 }
5692 m_tags.pop_back();
5693 return *this;
5694 }
5695
5696 XmlWriter& writeAttribute( const std::string& name, const std::string& attribute ) {
5697 if( !name.empty() && !attribute.empty() ) {
5698 stream() << " " << name << "=\"";
5699 writeEncodedText( attribute );
5700 stream() << "\"";
5701 }
5702 return *this;
5703 }
5704
5705 XmlWriter& writeAttribute( const std::string& name, bool attribute ) {
5706 stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
5707 return *this;
5708 }
5709
5710 template<typename T>
5711 XmlWriter& writeAttribute( const std::string& name, const T& attribute ) {
5712 if( !name.empty() )
5713 stream() << " " << name << "=\"" << attribute << "\"";
5714 return *this;
5715 }
5716
5717 XmlWriter& writeText( const std::string& text ) {
5718 if( !text.empty() ){
5719 bool tagWasOpen = m_tagIsOpen;
5720 ensureTagClosed();
5721 if( tagWasOpen )
5722 stream() << m_indent;
5723 writeEncodedText( text );
5724 m_needsNewline = true;
5725 }
5726 return *this;
5727 }
5728
5729 XmlWriter& writeComment( const std::string& text ) {
5730 ensureTagClosed();
5731 stream() << m_indent << "<!--" << text << "-->";
5732 m_needsNewline = true;
5733 return *this;
5734 }
5735
5736 XmlWriter& writeBlankLine() {
5737 ensureTagClosed();
5738 stream() << "\n";
5739 return *this;
5740 }
5741
5742 private:
5743
5744 std::ostream& stream() {
5745 return *m_os;
5746 }
5747
5748 void ensureTagClosed() {
5749 if( m_tagIsOpen ) {
5750 stream() << ">\n";
5751 m_tagIsOpen = false;
5752 }
5753 }
5754
5755 void newlineIfNecessary() {
5756 if( m_needsNewline ) {
5757 stream() << "\n";
5758 m_needsNewline = false;
5759 }
5760 }
5761
5762 void writeEncodedText( const std::string& text ) {
5763 static const char* charsToEncode = "<&\"";
5764 std::string mtext = text;
5765 std::string::size_type pos = mtext.find_first_of( charsToEncode );
5766 while( pos != std::string::npos ) {
5767 stream() << mtext.substr( 0, pos );
5768
5769 switch( mtext[pos] ) {
5770 case '<':
5771 stream() << "&lt;";
5772 break;
5773 case '&':
5774 stream() << "&amp;";
5775 break;
5776 case '\"':
5777 stream() << "&quot;";
5778 break;
5779 }
5780 mtext = mtext.substr( pos+1 );
5781 pos = mtext.find_first_of( charsToEncode );
5782 }
5783 stream() << mtext;
5784 }
5785
5786 bool m_tagIsOpen;
5787 bool m_needsNewline;
5788 std::vector<std::string> m_tags;
5789 std::string m_indent;
5790 std::ostream* m_os;
5791 };
5792
5793}
5794namespace Catch {
5795 class XmlReporter : public SharedImpl<IReporter> {
5796 public:
5797 XmlReporter( const ReporterConfig& config ) : m_config( config ) {}
5798
5799 static std::string getDescription() {
5800 return "Reports test results as an XML document";
5801 }
5802 virtual ~XmlReporter();
5803
5804 private: // IReporter
5805
5806 virtual bool shouldRedirectStdout() const {
5807 return true;
5808 }
5809
5810 virtual void StartTesting() {
5811 m_xml = XmlWriter( m_config.stream );
5812 m_xml.startElement( "Catch" );
5813 if( !m_config.name.empty() )
5814 m_xml.writeAttribute( "name", m_config.name );
5815 }
5816
5817 virtual void EndTesting( const Totals& totals ) {
5818 m_xml.scopedElement( "OverallResults" )
5819 .writeAttribute( "successes", totals.assertions.passed )
5820 .writeAttribute( "failures", totals.assertions.failed );
5821 m_xml.endElement();
5822 }
5823
5824 virtual void StartGroup( const std::string& groupName ) {
5825 m_xml.startElement( "Group" )
5826 .writeAttribute( "name", groupName );
5827 }
5828
5829 virtual void EndGroup( const std::string&, const Totals& totals ) {
5830 m_xml.scopedElement( "OverallResults" )
5831 .writeAttribute( "successes", totals.assertions.passed )
5832 .writeAttribute( "failures", totals.assertions.failed );
5833 m_xml.endElement();
5834 }
5835
5836 virtual void StartSection( const std::string& sectionName, const std::string& description ) {
5837 m_xml.startElement( "Section" )
5838 .writeAttribute( "name", sectionName )
5839 .writeAttribute( "description", description );
5840 }
Phil Nasha70fbe32012-08-31 08:10:36 +01005841 virtual void NoAssertionsInSection( const std::string& ) {}
5842 virtual void NoAssertionsInTestCase( const std::string& ) {}
Phil Nash56d5c422012-08-23 20:08:50 +01005843
5844 virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) {
5845 m_xml.scopedElement( "OverallResults" )
5846 .writeAttribute( "successes", assertions.passed )
5847 .writeAttribute( "failures", assertions.failed );
5848 m_xml.endElement();
5849 }
5850
5851 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) {
5852 m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.getName() );
5853 m_currentTestSuccess = true;
5854 }
5855
5856 virtual void Result( const Catch::ResultInfo& resultInfo ) {
5857 if( !m_config.includeSuccessfulResults && resultInfo.getResultType() == ResultWas::Ok )
5858 return;
5859
5860 if( resultInfo.hasExpression() ) {
5861 m_xml.startElement( "Expression" )
5862 .writeAttribute( "success", resultInfo.ok() )
5863 .writeAttribute( "filename", resultInfo.getFilename() )
5864 .writeAttribute( "line", resultInfo.getLine() );
5865
5866 m_xml.scopedElement( "Original" )
5867 .writeText( resultInfo.getExpression() );
5868 m_xml.scopedElement( "Expanded" )
5869 .writeText( resultInfo.getExpandedExpression() );
5870 m_currentTestSuccess &= resultInfo.ok();
5871 }
5872
5873 switch( resultInfo.getResultType() ) {
5874 case ResultWas::ThrewException:
5875 m_xml.scopedElement( "Exception" )
5876 .writeAttribute( "filename", resultInfo.getFilename() )
5877 .writeAttribute( "line", resultInfo.getLine() )
5878 .writeText( resultInfo.getMessage() );
5879 m_currentTestSuccess = false;
5880 break;
5881 case ResultWas::Info:
5882 m_xml.scopedElement( "Info" )
5883 .writeText( resultInfo.getMessage() );
5884 break;
5885 case ResultWas::Warning:
5886 m_xml.scopedElement( "Warning" )
5887 .writeText( resultInfo.getMessage() );
5888 break;
5889 case ResultWas::ExplicitFailure:
5890 m_xml.scopedElement( "Failure" )
5891 .writeText( resultInfo.getMessage() );
5892 m_currentTestSuccess = false;
5893 break;
5894 case ResultWas::Unknown:
5895 case ResultWas::Ok:
5896 case ResultWas::FailureBit:
5897 case ResultWas::ExpressionFailed:
5898 case ResultWas::Exception:
5899 case ResultWas::DidntThrowException:
5900 break;
5901 }
5902 if( resultInfo.hasExpression() )
5903 m_xml.endElement();
5904 }
5905
5906 virtual void Aborted() {
5907 // !TBD
5908 }
5909
5910 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) {
5911 m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess );
5912 m_xml.endElement();
5913 }
5914
5915 private:
5916 ReporterConfig m_config;
5917 bool m_currentTestSuccess;
5918 XmlWriter m_xml;
5919 };
5920
5921} // end namespace Catch
5922
5923// #included from: ../reporters/catch_reporter_junit.hpp
5924#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
5925
5926namespace Catch {
5927
5928 class JunitReporter : public SharedImpl<IReporter> {
5929
5930 struct TestStats {
5931 std::string m_element;
5932 std::string m_resultType;
5933 std::string m_message;
5934 std::string m_content;
5935 };
5936
5937 struct TestCaseStats {
5938
5939 TestCaseStats( const std::string& name = std::string() ) :m_name( name ){}
5940
5941 double m_timeInSeconds;
5942 std::string m_status;
5943 std::string m_className;
5944 std::string m_name;
5945 std::vector<TestStats> m_testStats;
5946 };
5947
5948 struct Stats {
5949
5950 Stats( const std::string& name = std::string() )
5951 : m_testsCount( 0 ),
5952 m_failuresCount( 0 ),
5953 m_disabledCount( 0 ),
5954 m_errorsCount( 0 ),
5955 m_timeInSeconds( 0 ),
5956 m_name( name )
5957 {}
5958
5959 std::size_t m_testsCount;
5960 std::size_t m_failuresCount;
5961 std::size_t m_disabledCount;
5962 std::size_t m_errorsCount;
5963 double m_timeInSeconds;
5964 std::string m_name;
5965
5966 std::vector<TestCaseStats> m_testCaseStats;
5967 };
5968
5969 public:
5970 JunitReporter( const ReporterConfig& config )
5971 : m_config( config ),
5972 m_testSuiteStats( "AllTests" ),
5973 m_currentStats( &m_testSuiteStats )
5974 {}
5975 virtual ~JunitReporter();
5976
5977 static std::string getDescription() {
5978 return "Reports test results in an XML format that looks like Ant's junitreport target";
5979 }
5980
5981 private: // IReporter
5982
5983 virtual bool shouldRedirectStdout() const {
5984 return true;
5985 }
5986
5987 virtual void StartTesting(){}
5988
5989 virtual void StartGroup( const std::string& groupName ) {
5990 m_statsForSuites.push_back( Stats( groupName ) );
5991 m_currentStats = &m_statsForSuites.back();
5992 }
5993
5994 virtual void EndGroup( const std::string&, const Totals& totals ) {
5995 m_currentStats->m_testsCount = totals.assertions.total();
5996 m_currentStats = &m_testSuiteStats;
5997 }
5998
5999 virtual void StartSection( const std::string&, const std::string& ){}
6000
Phil Nasha70fbe32012-08-31 08:10:36 +01006001 virtual void NoAssertionsInSection( const std::string& ) {}
6002 virtual void NoAssertionsInTestCase( const std::string& ) {}
6003
6004 virtual void EndSection( const std::string&, const Counts& ) {}
Phil Nash56d5c422012-08-23 20:08:50 +01006005
6006 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) {
6007 m_currentStats->m_testCaseStats.push_back( TestCaseStats( testInfo.getName() ) );
6008 }
6009
6010 virtual void Result( const Catch::ResultInfo& resultInfo ) {
6011 if( resultInfo.getResultType() != ResultWas::Ok || m_config.includeSuccessfulResults ) {
6012 TestCaseStats& testCaseStats = m_currentStats->m_testCaseStats.back();
6013 TestStats stats;
6014 std::ostringstream oss;
6015 if( !resultInfo.getMessage().empty() )
6016 oss << resultInfo.getMessage() << " at ";
6017 oss << SourceLineInfo( resultInfo.getFilename(), resultInfo.getLine() );
6018 stats.m_content = oss.str();
6019 stats.m_message = resultInfo.getExpandedExpression();
6020 stats.m_resultType = resultInfo.getTestMacroName();
6021
6022 switch( resultInfo.getResultType() ) {
6023 case ResultWas::ThrewException:
6024 stats.m_element = "error";
6025 m_currentStats->m_errorsCount++;
6026 break;
6027 case ResultWas::Info:
6028 stats.m_element = "info"; // !TBD ?
6029 break;
6030 case ResultWas::Warning:
6031 stats.m_element = "warning"; // !TBD ?
6032 break;
6033 case ResultWas::ExplicitFailure:
6034 stats.m_element = "failure";
6035 m_currentStats->m_failuresCount++;
6036 break;
6037 case ResultWas::ExpressionFailed:
6038 stats.m_element = "failure";
6039 m_currentStats->m_failuresCount++;
6040 break;
6041 case ResultWas::Ok:
6042 stats.m_element = "success";
6043 break;
6044 case ResultWas::Unknown:
6045 case ResultWas::FailureBit:
6046 case ResultWas::Exception:
6047 case ResultWas::DidntThrowException:
6048 break;
6049 }
6050 testCaseStats.m_testStats.push_back( stats );
6051 }
6052 }
6053
6054 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string& stdOut, const std::string& stdErr ) {
6055 if( !stdOut.empty() )
6056 m_stdOut << stdOut << "\n";
6057 if( !stdErr.empty() )
6058 m_stdErr << stdErr << "\n";
6059 }
6060
6061 virtual void Aborted() {
6062 // !TBD
6063 }
6064
6065 virtual void EndTesting( const Totals& ) {
6066 std::ostream& str = m_config.stream;
6067 {
6068 XmlWriter xml( str );
6069
6070 if( m_statsForSuites.size() > 0 )
6071 xml.startElement( "testsuites" );
6072
6073 std::vector<Stats>::const_iterator it = m_statsForSuites.begin();
6074 std::vector<Stats>::const_iterator itEnd = m_statsForSuites.end();
6075
6076 for(; it != itEnd; ++it ) {
6077 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
6078 xml.writeAttribute( "name", it->m_name );
6079 xml.writeAttribute( "errors", it->m_errorsCount );
6080 xml.writeAttribute( "failures", it->m_failuresCount );
6081 xml.writeAttribute( "tests", it->m_testsCount );
6082 xml.writeAttribute( "hostname", "tbd" );
6083 xml.writeAttribute( "time", "tbd" );
6084 xml.writeAttribute( "timestamp", "tbd" );
6085
6086 OutputTestCases( xml, *it );
6087 }
6088
6089 xml.scopedElement( "system-out" ).writeText( trim( m_stdOut.str() ) );
6090 xml.scopedElement( "system-err" ).writeText( trim( m_stdErr.str() ) );
6091 }
6092 }
6093
6094 void OutputTestCases( XmlWriter& xml, const Stats& stats ) {
6095 std::vector<TestCaseStats>::const_iterator it = stats.m_testCaseStats.begin();
6096 std::vector<TestCaseStats>::const_iterator itEnd = stats.m_testCaseStats.end();
6097 for(; it != itEnd; ++it ) {
6098 xml.writeBlankLine();
6099 xml.writeComment( "Test case" );
6100
6101 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
6102 xml.writeAttribute( "classname", it->m_className );
6103 xml.writeAttribute( "name", it->m_name );
6104 xml.writeAttribute( "time", "tbd" );
6105
6106 OutputTestResult( xml, *it );
6107 }
6108 }
6109
6110 void OutputTestResult( XmlWriter& xml, const TestCaseStats& stats ) {
6111 std::vector<TestStats>::const_iterator it = stats.m_testStats.begin();
6112 std::vector<TestStats>::const_iterator itEnd = stats.m_testStats.end();
6113 for(; it != itEnd; ++it ) {
6114 if( it->m_element != "success" ) {
6115 XmlWriter::ScopedElement e = xml.scopedElement( it->m_element );
6116
6117 xml.writeAttribute( "message", it->m_message );
6118 xml.writeAttribute( "type", it->m_resultType );
6119 if( !it->m_content.empty() )
6120 xml.writeText( it->m_content );
6121 }
6122 }
6123 }
6124
6125 private:
6126 ReporterConfig m_config;
6127 bool m_currentTestSuccess;
6128
6129 Stats m_testSuiteStats;
6130 Stats* m_currentStats;
6131 std::vector<Stats> m_statsForSuites;
6132 std::ostringstream m_stdOut;
6133 std::ostringstream m_stdErr;
6134 };
6135
6136} // end namespace Catch
6137
Phil Nasha695eb92012-08-13 07:46:10 +01006138namespace Catch {
6139 NonCopyable::~NonCopyable() {}
6140 IShared::~IShared() {}
6141 StreamBufBase::~StreamBufBase() {}
6142 IContext::~IContext() {}
6143 IResultCapture::~IResultCapture() {}
6144 ITestCase::~ITestCase() {}
6145 ITestCaseRegistry::~ITestCaseRegistry() {}
6146 IRegistryHub::~IRegistryHub() {}
6147 IMutableRegistryHub::~IMutableRegistryHub() {}
6148 IExceptionTranslator::~IExceptionTranslator() {}
6149 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
6150 IReporter::~IReporter() {}
6151 IReporterFactory::~IReporterFactory() {}
6152 IReporterRegistry::~IReporterRegistry() {}
6153 BasicReporter::~BasicReporter() {}
6154 IRunner::~IRunner() {}
6155 IMutableContext::~IMutableContext() {}
6156 IConfig::~IConfig() {}
6157 XmlReporter::~XmlReporter() {}
6158 JunitReporter::~JunitReporter() {}
6159 TestRegistry::~TestRegistry() {}
6160 FreeFunctionTestCase::~FreeFunctionTestCase() {}
6161 IGeneratorInfo::~IGeneratorInfo() {}
6162 IGeneratorsForTest::~IGeneratorsForTest() {}
Phil Nash799ecf92012-09-24 08:30:13 +01006163 TagParser::~TagParser() {}
6164 TagExtracter::~TagExtracter() {}
6165 TagExpressionParser::~TagExpressionParser() {}
Phil Nasha695eb92012-08-13 07:46:10 +01006166
Phil Nash9444bbc2012-10-12 07:58:17 +01006167 Matchers::Impl::StdString::Equals::~Equals() {}
6168 Matchers::Impl::StdString::Contains::~Contains() {}
6169 Matchers::Impl::StdString::StartsWith::~StartsWith() {}
6170 Matchers::Impl::StdString::EndsWith::~EndsWith() {}
6171
Phil Nasha695eb92012-08-13 07:46:10 +01006172 void Config::dummy() {}
6173
Phil Nash56d5c422012-08-23 20:08:50 +01006174 INTERNAL_CATCH_REGISTER_REPORTER( "basic", BasicReporter )
6175 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
6176 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
6177
Phil Nasha695eb92012-08-13 07:46:10 +01006178}
6179
Phil Nash5bc030d2012-08-16 18:48:50 +01006180#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01006181#pragma clang diagnostic pop
Phil Nash89d1e6c2011-05-24 08:23:02 +01006182#endif
Matt Wozniskif29c8982012-09-17 01:42:29 -04006183
Phil Nash5bc030d2012-08-16 18:48:50 +01006184#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01006185
6186#ifdef CATCH_CONFIG_MAIN
6187// #included from: internal/catch_default_main.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01006188#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01006189
Phil Nash176eb812012-05-11 08:17:16 +01006190#ifndef __OBJC__
Phil Nash89d1e6c2011-05-24 08:23:02 +01006191
Phil Nash176eb812012-05-11 08:17:16 +01006192// Standard C/C++ main entry point
6193int main (int argc, char * const argv[]) {
6194 return Catch::Main( argc, argv );
6195}
6196
6197#else // __OBJC__
6198
6199// Objective-C entry point
6200int main (int argc, char * const argv[]) {
Phil Nash53c990a2012-03-17 18:20:06 +00006201#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +01006202 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Phil Nash53c990a2012-03-17 18:20:06 +00006203#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01006204
6205 Catch::registerTestMethods();
Phil Nash89d1e6c2011-05-24 08:23:02 +01006206 int result = Catch::Main( argc, (char* const*)argv );
6207
Phil Nash53c990a2012-03-17 18:20:06 +00006208#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +01006209 [pool drain];
Phil Nash53c990a2012-03-17 18:20:06 +00006210#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01006211
Phil Nashdd5b9c22012-02-18 09:58:30 +00006212 return result;
Phil Nash89d1e6c2011-05-24 08:23:02 +01006213}
6214
Phil Nash176eb812012-05-11 08:17:16 +01006215#endif // __OBJC__
6216
Phil Nash89d1e6c2011-05-24 08:23:02 +01006217#endif
6218
Phil Nash89d1e6c2011-05-24 08:23:02 +01006219//////
6220
Phil Nash46bcd4b2012-07-20 18:43:48 +01006221// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
6222#ifdef CATCH_CONFIG_PREFIX_ALL
6223
6224#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, false, true, "CATCH_REQUIRE" )
6225#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, true, "CATCH_REQUIRE_FALSE" )
6226
6227#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., true, "CATCH_REQUIRE_THROWS" )
6228#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, true, "CATCH_REQUIRE_THROWS_AS" )
6229#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, true, "CATCH_REQUIRE_NOTHROW" )
6230
6231#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, false, false, "CATCH_CHECK" )
6232#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, false, "CATCH_CHECK_FALSE" )
6233#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, false, false, "CATCH_CHECKED_IF" )
6234#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, false, false, "CATCH_CHECKED_ELSE" )
6235
6236#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., false, "CATCH_CHECK_THROWS" )
6237#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, false, "CATCH_CHECK_THROWS_AS" )
6238#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, false, "CATCH_CHECK_NOTHROW" )
6239
6240#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, false, "CATCH_CHECK_THAT" )
6241#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, true, "CATCH_REQUIRE_THAT" )
6242
6243#define CATCH_INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, false, "CATCH_INFO" )
6244#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, false, "CATCH_WARN" )
6245#define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, true, "CATCH_FAIL" )
Phil Nash74d1d312012-08-31 18:37:47 +01006246#define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, false, "CATCH_SUCCEED" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01006247#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg )
6248#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, false, "CATCH_CAPTURE" )
Phil Nash803f6b72012-10-04 08:14:48 +01006249#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_SCOPED_INFO( #msg " := " << msg )
Phil Nash46bcd4b2012-07-20 18:43:48 +01006250
6251#define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
6252
6253#define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
6254#define CATCH_TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
6255#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" )
6256#define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
6257
6258#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
6259
6260#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
6261
6262///////////////
6263// Still to be implemented
6264//#define CHECK_NOFAIL( expr ) // !TBD - reports violation, but doesn't fail Test
6265
6266// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
6267#else
6268
Phil Nash89d1e6c2011-05-24 08:23:02 +01006269#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, false, true, "REQUIRE" )
6270#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, true, "REQUIRE_FALSE" )
6271
6272#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., true, "REQUIRE_THROWS" )
6273#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, true, "REQUIRE_THROWS_AS" )
6274#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, true, "REQUIRE_NOTHROW" )
6275
6276#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, false, false, "CHECK" )
6277#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, false, "CHECK_FALSE" )
Phil Nasha162e222012-02-10 08:30:13 +00006278#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, false, false, "CHECKED_IF" )
6279#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, false, false, "CHECKED_ELSE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006280
6281#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., false, "CHECK_THROWS" )
6282#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, false, "CHECK_THROWS_AS" )
6283#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, false, "CHECK_NOTHROW" )
6284
Phil Nash78d95a02012-03-04 21:22:36 +00006285#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, false, "CHECK_THAT" )
6286#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, true, "REQUIRE_THAT" )
6287
Phil Nash89d1e6c2011-05-24 08:23:02 +01006288#define INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, false, "INFO" )
6289#define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, false, "WARN" )
6290#define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, true, "FAIL" )
Phil Nasha70fbe32012-08-31 08:10:36 +01006291#define SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, false, "SUCCEED" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006292#define SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg )
6293#define CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, false, "CAPTURE" )
Phil Nash803f6b72012-10-04 08:14:48 +01006294#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_SCOPED_INFO( #msg " := " << msg )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006295
6296#define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
6297
6298#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
6299#define TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
6300#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01006301#define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006302
6303#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006304
6305#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
6306
Phil Nash46bcd4b2012-07-20 18:43:48 +01006307#endif
6308
6309#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006310
6311using Catch::Detail::Approx;
6312
Phil Nash5bc030d2012-08-16 18:48:50 +01006313#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01006314#pragma clang diagnostic pop
Phil Nash5bc030d2012-08-16 18:48:50 +01006315#endif
Phil Nasha695eb92012-08-13 07:46:10 +01006316
Phil Nashaec1e5e2012-05-09 19:37:51 +01006317#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01006318