blob: ec51c72803e18bf6121f4e493455849d5eb6be4f [file] [log] [blame]
Phil Nash89d1e6c2011-05-24 08:23:02 +01001/*
Phil Nasha90a88a2012-11-19 19:59:10 +00002 * CATCH v0.9 build 5 (integration branch)
3 * Generated: 2012-11-19 19:58:11.700412
Phil Nash4df051b2012-05-22 22:22:22 +01004 * ----------------------------------------------------------
Phil Nashaec1e5e2012-05-09 19:37:51 +01005 * This file has been merged from multiple headers. Please don't edit it directly
6 * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
Phil Nash89d1e6c2011-05-24 08:23:02 +01007 *
8 * Distributed under the Boost Software License, Version 1.0. (See accompanying
9 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Phil Nash89d1e6c2011-05-24 08:23:02 +010010 */
Phil Nashaec1e5e2012-05-09 19:37:51 +010011#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
12#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010013
Phil Nash3b80af72012-08-09 07:47:30 +010014#define TWOBLUECUBES_CATCH_HPP_INCLUDED
Phil Nash0f9c5512012-06-02 23:12:42 +010015
Phil Nash5bc030d2012-08-16 18:48:50 +010016#ifdef __clang__
Phil Nash778f9c42012-10-30 09:09:30 +000017#pragma clang diagnostic ignored "-Wglobal-constructors"
Phil Nash5bc030d2012-08-16 18:48:50 +010018
Phil Nasha695eb92012-08-13 07:46:10 +010019#pragma clang diagnostic push
20#pragma clang diagnostic ignored "-Wpadded"
Phil Nash5bc030d2012-08-16 18:48:50 +010021#endif
Phil Nasha695eb92012-08-13 07:46:10 +010022
Phil Nash3b80af72012-08-09 07:47:30 +010023// #included from: internal/catch_notimplemented_exception.h
24#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010025
Phil Nash89d1e6c2011-05-24 08:23:02 +010026// #included from: catch_common.h
Phil Nash3b80af72012-08-09 07:47:30 +010027#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010028
Phil Nash89d1e6c2011-05-24 08:23:02 +010029#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
30#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
31#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
32
33#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
34#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
35
36#ifdef __GNUC__
Phil Nasha695eb92012-08-13 07:46:10 +010037#define CATCH_ATTRIBUTE_NORETURN __attribute__ ((noreturn))
Phil Nash89d1e6c2011-05-24 08:23:02 +010038#else
Phil Nasha695eb92012-08-13 07:46:10 +010039#define CATCH_ATTRIBUTE_NORETURN
Phil Nash89d1e6c2011-05-24 08:23:02 +010040#endif
41
42#include <sstream>
43#include <stdexcept>
44#include <algorithm>
45
Phil Nash89d2a3f2012-05-16 15:09:17 +010046namespace Catch {
47
Phil Nashd31737f2012-05-09 19:04:00 +010048 class NonCopyable {
Phil Nash89d1e6c2011-05-24 08:23:02 +010049 NonCopyable( const NonCopyable& );
50 void operator = ( const NonCopyable& );
51 protected:
Phil Nashd31737f2012-05-09 19:04:00 +010052 NonCopyable() {}
Phil Nasha695eb92012-08-13 07:46:10 +010053 virtual ~NonCopyable();
Phil Nash89d1e6c2011-05-24 08:23:02 +010054 };
55
Phil Nash163088a2012-05-31 19:40:26 +010056 class SafeBool {
57 public:
58 typedef void (SafeBool::*type)() const;
59
60 static type makeSafe( bool value ) {
61 return value ? &SafeBool::trueValue : 0;
62 }
63 private:
64 void trueValue() const {}
65 };
66
Phil Nash89d1e6c2011-05-24 08:23:02 +010067 template<typename ContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +010068 inline void deleteAll( ContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010069 typename ContainerT::const_iterator it = container.begin();
70 typename ContainerT::const_iterator itEnd = container.end();
71 for(; it != itEnd; ++it )
72 {
73 delete *it;
74 }
75 }
76 template<typename AssociativeContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +010077 inline void deleteAllValues( AssociativeContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010078 typename AssociativeContainerT::const_iterator it = container.begin();
79 typename AssociativeContainerT::const_iterator itEnd = container.end();
80 for(; it != itEnd; ++it )
81 {
82 delete it->second;
83 }
84 }
85
86 template<typename ContainerT, typename Function>
Phil Nashd31737f2012-05-09 19:04:00 +010087 inline void forEach( ContainerT& container, Function function ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010088 std::for_each( container.begin(), container.end(), function );
89 }
90
91 template<typename ContainerT, typename Function>
Phil Nashd31737f2012-05-09 19:04:00 +010092 inline void forEach( const ContainerT& container, Function function ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010093 std::for_each( container.begin(), container.end(), function );
94 }
95
Phil Nash56d5c422012-08-23 20:08:50 +010096 inline bool startsWith( const std::string& s, const std::string& prefix ) {
97 return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
98 }
Phil Nash4c97fc52012-08-24 08:23:50 +010099 inline bool endsWith( const std::string& s, const std::string& suffix ) {
100 return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
101 }
102 inline bool contains( const std::string& s, const std::string& infix ) {
103 return s.find( infix ) != std::string::npos;
104 }
105
106 struct pluralise {
107 pluralise( std::size_t count, const std::string& label )
108 : m_count( count ),
109 m_label( label )
110 {}
111
112 friend std::ostream& operator << ( std::ostream& os, const pluralise& pluraliser ) {
113 os << pluraliser.m_count << " " << pluraliser.m_label;
114 if( pluraliser.m_count != 1 )
Phil Nash88b70822012-11-04 21:39:38 +0000115 os << "s";
Phil Nash4c97fc52012-08-24 08:23:50 +0100116 return os;
117 }
118
119 std::size_t m_count;
120 std::string m_label;
121 };
Phil Nash56d5c422012-08-23 20:08:50 +0100122
Phil Nash89d2a3f2012-05-16 15:09:17 +0100123 struct SourceLineInfo {
124
Phil Nashd31737f2012-05-09 19:04:00 +0100125 SourceLineInfo() : line( 0 ){}
Phil Nash62179662012-05-11 19:06:43 +0100126 SourceLineInfo( const std::string& _file, std::size_t _line )
127 : file( _file ),
128 line( _line )
Phil Nash6e0f58d2012-02-15 18:37:21 +0000129 {}
Phil Nashd31737f2012-05-09 19:04:00 +0100130 SourceLineInfo( const SourceLineInfo& other )
131 : file( other.file ),
132 line( other.line )
133 {}
Phil Nash82acc2c2012-10-28 12:07:17 +0000134 bool empty() const {
135 return file.empty();
136 }
Phil Nash6e0f58d2012-02-15 18:37:21 +0000137
138 std::string file;
139 std::size_t line;
140 };
141
Phil Nashd31737f2012-05-09 19:04:00 +0100142 inline std::ostream& operator << ( std::ostream& os, const SourceLineInfo& info ) {
Phil Nash6e0f58d2012-02-15 18:37:21 +0000143#ifndef __GNUG__
144 os << info.file << "(" << info.line << "): ";
145#else
146 os << info.file << ":" << info.line << ": ";
147#endif
148 return os;
149 }
150
Phil Nasha695eb92012-08-13 07:46:10 +0100151 CATCH_ATTRIBUTE_NORETURN
152 inline void throwLogicError( const std::string& message, const SourceLineInfo& locationInfo ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100153 std::ostringstream oss;
Phil Nasha695eb92012-08-13 07:46:10 +0100154 oss << "Internal Catch error: '" << message << "' at: " << locationInfo;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100155 throw std::logic_error( oss.str() );
156 }
157}
158
Phil Nasha695eb92012-08-13 07:46:10 +0100159#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
160#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100161
Phil Nash3b80af72012-08-09 07:47:30 +0100162#include <ostream>
163
164namespace Catch {
165
166 class NotImplementedException : public std::exception
167 {
168 public:
169 NotImplementedException( const SourceLineInfo& lineInfo );
170
171 virtual ~NotImplementedException() throw() {}
172
173 virtual const char* what() const throw();
174
175 private:
176 std::string m_what;
177 SourceLineInfo m_lineInfo;
178 };
179
180} // end namespace Catch
181
182///////////////////////////////////////////////////////////////////////////////
183#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
184
185// #included from: internal/catch_context.h
186#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
187
Phil Nasha70fbe32012-08-31 08:10:36 +0100188// #included from: catch_interfaces_generators.h
189#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +0100190
Phil Nasha70fbe32012-08-31 08:10:36 +0100191#include <string>
Phil Nashf7299fc2012-02-25 09:39:45 +0000192
Phil Nash89d2a3f2012-05-16 15:09:17 +0100193namespace Catch {
194
Phil Nasha70fbe32012-08-31 08:10:36 +0100195 struct IGeneratorInfo {
196 virtual ~IGeneratorInfo();
197 virtual bool moveNext() = 0;
198 virtual std::size_t getCurrentIndex() const = 0;
Phil Nashf7299fc2012-02-25 09:39:45 +0000199 };
200
Phil Nasha70fbe32012-08-31 08:10:36 +0100201 struct IGeneratorsForTest {
202 virtual ~IGeneratorsForTest();
Phil Nash89d2a3f2012-05-16 15:09:17 +0100203
Phil Nasha70fbe32012-08-31 08:10:36 +0100204 virtual IGeneratorInfo& getGeneratorInfo( const std::string& fileInfo, std::size_t size ) = 0;
205 virtual bool moveNext() = 0;
Phil Nashf7299fc2012-02-25 09:39:45 +0000206 };
Phil Nasha70fbe32012-08-31 08:10:36 +0100207
208 IGeneratorsForTest* createGeneratorsForTest();
209
210} // end namespace Catch
211
212#include <memory>
213#include <vector>
214#include <stdlib.h>
215
216namespace Catch {
217
218 class TestCaseInfo;
Phil Nash67ec8702012-09-26 18:38:26 +0100219 class Stream;
Phil Nasha70fbe32012-08-31 08:10:36 +0100220 struct IResultCapture;
221 struct IRunner;
222 struct IGeneratorsForTest;
223 struct IConfig;
224
Phil Nasha70fbe32012-08-31 08:10:36 +0100225 struct IContext
226 {
227 virtual ~IContext();
228
229 virtual IResultCapture& getResultCapture() = 0;
230 virtual IRunner& getRunner() = 0;
231 virtual size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ) = 0;
232 virtual bool advanceGeneratorsForCurrentTest() = 0;
233 virtual const IConfig* getConfig() const = 0;
234 };
235
236 struct IMutableContext : IContext
237 {
238 virtual ~IMutableContext();
239 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
240 virtual void setRunner( IRunner* runner ) = 0;
241 virtual void setConfig( const IConfig* config ) = 0;
242 };
243
244 IContext& getCurrentContext();
245 IMutableContext& getCurrentMutableContext();
246 void cleanUpContext();
Phil Nash67ec8702012-09-26 18:38:26 +0100247 Stream createStream( const std::string& streamName );
Phil Nasha70fbe32012-08-31 08:10:36 +0100248
Phil Nashf7299fc2012-02-25 09:39:45 +0000249}
250
Phil Nasha70fbe32012-08-31 08:10:36 +0100251// #included from: internal/catch_test_registry.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -0400252#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +0100253
254// #included from: catch_interfaces_testcase.h
255#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
256
Phil Nash49e6d532012-05-05 19:35:35 +0100257// #included from: catch_ptr.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100258#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
Phil Nash49e6d532012-05-05 19:35:35 +0100259
Phil Nash89d2a3f2012-05-16 15:09:17 +0100260namespace Catch {
261
Phil Nash49e6d532012-05-05 19:35:35 +0100262 // An intrusive reference counting smart pointer.
263 // T must implement addRef() and release() methods
264 // typically implementing the IShared interface
265 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100266 class Ptr {
Phil Nash49e6d532012-05-05 19:35:35 +0100267 public:
268 Ptr() : m_p( NULL ){}
269 Ptr( T* p ) : m_p( p ){
Phil Nash61756972012-07-28 20:37:07 +0100270 if( m_p )
271 m_p->addRef();
Phil Nash49e6d532012-05-05 19:35:35 +0100272 }
273 Ptr( const Ptr& other ) : m_p( other.m_p ){
Phil Nash61756972012-07-28 20:37:07 +0100274 if( m_p )
275 m_p->addRef();
Phil Nash49e6d532012-05-05 19:35:35 +0100276 }
277 ~Ptr(){
278 if( m_p )
279 m_p->release();
280 }
281 Ptr& operator = ( T* p ){
282 Ptr temp( p );
283 swap( temp );
284 return *this;
285 }
Phil Nashdeb3ced2012-08-31 18:50:46 +0100286 Ptr& operator = ( const Ptr& other ){
Phil Nash49e6d532012-05-05 19:35:35 +0100287 Ptr temp( other );
288 swap( temp );
289 return *this;
290 }
291 void swap( Ptr& other ){
292 std::swap( m_p, other.m_p );
293 }
294
295 T* get(){
296 return m_p;
297 }
298 const T* get() const{
299 return m_p;
300 }
301
Phil Nash56d5c422012-08-23 20:08:50 +0100302 T& operator*() const {
Phil Nash49e6d532012-05-05 19:35:35 +0100303 return *m_p;
304 }
305
Phil Nash56d5c422012-08-23 20:08:50 +0100306 T* operator->() const {
Phil Nash49e6d532012-05-05 19:35:35 +0100307 return m_p;
308 }
Phil Nash56d5c422012-08-23 20:08:50 +0100309
Phil Nash61756972012-07-28 20:37:07 +0100310 bool operator !() const {
311 return m_p == NULL;
312 }
Phil Nash49e6d532012-05-05 19:35:35 +0100313
314 private:
315 T* m_p;
316 };
317
318 struct IShared : NonCopyable {
Phil Nasha695eb92012-08-13 07:46:10 +0100319 virtual ~IShared();
Phil Nash49e6d532012-05-05 19:35:35 +0100320 virtual void addRef() = 0;
321 virtual void release() = 0;
322 };
323
324 template<typename T>
325 struct SharedImpl : T {
326
327 SharedImpl() : m_rc( 0 ){}
328
329 virtual void addRef(){
330 ++m_rc;
331 }
332 virtual void release(){
333 if( --m_rc == 0 )
334 delete this;
335 }
336
337 int m_rc;
338 };
339
340} // end namespace Catch
341
Phil Nash0f9c5512012-06-02 23:12:42 +0100342#include <vector>
343
344namespace Catch {
Phil Nash56d5c422012-08-23 20:08:50 +0100345
346 class TestCaseFilters;
347
Phil Nash5bc030d2012-08-16 18:48:50 +0100348 struct ITestCase : IShared {
Phil Nash0f9c5512012-06-02 23:12:42 +0100349 virtual void invoke () const = 0;
Phil Nash5bc030d2012-08-16 18:48:50 +0100350 protected:
351 virtual ~ITestCase();
Phil Nash0f9c5512012-06-02 23:12:42 +0100352 };
353
354 class TestCaseInfo;
355
356 struct ITestCaseRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +0100357 virtual ~ITestCaseRegistry();
Phil Nash0f9c5512012-06-02 23:12:42 +0100358 virtual const std::vector<TestCaseInfo>& getAllTests() const = 0;
Phil Nash3b80af72012-08-09 07:47:30 +0100359 virtual std::vector<TestCaseInfo> getMatchingTestCases( const std::string& rawTestSpec ) const = 0;
Phil Nash0f9c5512012-06-02 23:12:42 +0100360 };
361}
362
Phil Nash89d2a3f2012-05-16 15:09:17 +0100363namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100364
365template<typename C>
Phil Nash5bc030d2012-08-16 18:48:50 +0100366class MethodTestCase : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +0100367
Phil Nash176eb812012-05-11 08:17:16 +0100368public:
369 MethodTestCase( void (C::*method)() ) : m_method( method ) {}
Phil Nash89d1e6c2011-05-24 08:23:02 +0100370
Phil Nash176eb812012-05-11 08:17:16 +0100371 virtual void invoke() const {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100372 C obj;
373 (obj.*m_method)();
374 }
375
Phil Nash89d1e6c2011-05-24 08:23:02 +0100376private:
Phil Nash5bc030d2012-08-16 18:48:50 +0100377 virtual ~MethodTestCase() {}
378
Phil Nash89d1e6c2011-05-24 08:23:02 +0100379 void (C::*m_method)();
380};
381
382typedef void(*TestFunction)();
383
Phil Nash89d2a3f2012-05-16 15:09:17 +0100384struct AutoReg {
385
Phil Nash176eb812012-05-11 08:17:16 +0100386 AutoReg( TestFunction function,
387 const char* name,
388 const char* description,
389 const SourceLineInfo& lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100390
Phil Nash89d1e6c2011-05-24 08:23:02 +0100391 template<typename C>
Phil Nash176eb812012-05-11 08:17:16 +0100392 AutoReg( void (C::*method)(),
Phil Nash88b70822012-11-04 21:39:38 +0000393 const char* className,
Phil Nash176eb812012-05-11 08:17:16 +0100394 const char* name,
395 const char* description,
396 const SourceLineInfo& lineInfo ) {
Phil Nash88b70822012-11-04 21:39:38 +0000397 registerTestCase( new MethodTestCase<C>( method ), className, name, description, lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100398 }
399
Phil Nash176eb812012-05-11 08:17:16 +0100400 void registerTestCase( ITestCase* testCase,
Phil Nash88b70822012-11-04 21:39:38 +0000401 const char* className,
Phil Nash176eb812012-05-11 08:17:16 +0100402 const char* name,
403 const char* description,
404 const SourceLineInfo& lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100405
Phil Nash176eb812012-05-11 08:17:16 +0100406 ~AutoReg();
Phil Nash89d1e6c2011-05-24 08:23:02 +0100407
408private:
Phil Nash176eb812012-05-11 08:17:16 +0100409 AutoReg( const AutoReg& );
410 void operator= ( const AutoReg& );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100411};
412
413} // end namespace Catch
414
415///////////////////////////////////////////////////////////////////////////////
416#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
Phil Nashd31737f2012-05-09 19:04:00 +0100417 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )(); \
418 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ ), Name, Desc, CATCH_INTERNAL_LINEINFO ); }\
419 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100420
421///////////////////////////////////////////////////////////////////////////////
422#define INTERNAL_CATCH_TESTCASE_NORETURN( Name, Desc ) \
Phil Nasha695eb92012-08-13 07:46:10 +0100423 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )() CATCH_ATTRIBUTE_NORETURN; \
Phil Nashd31737f2012-05-09 19:04:00 +0100424 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ ), Name, Desc, CATCH_INTERNAL_LINEINFO ); }\
425 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100426
427///////////////////////////////////////////////////////////////////////////////
Phil Nash46bcd4b2012-07-20 18:43:48 +0100428#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
Phil Nash88b70822012-11-04 21:39:38 +0000429 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Name, Desc, CATCH_INTERNAL_LINEINFO ); }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100430
431///////////////////////////////////////////////////////////////////////////////
432#define TEST_CASE_METHOD( ClassName, TestName, Desc )\
Phil Nashfd78e0f2011-12-28 19:56:39 +0000433 namespace{ \
Phil Nashd31737f2012-05-09 19:04:00 +0100434 struct INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ ) : ClassName{ \
Phil Nashfd78e0f2011-12-28 19:56:39 +0000435 void test(); \
436 }; \
Phil Nash88b70822012-11-04 21:39:38 +0000437 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ )::test, #ClassName, TestName, Desc, CATCH_INTERNAL_LINEINFO ); \
Phil Nashfd78e0f2011-12-28 19:56:39 +0000438 } \
Phil Nashd31737f2012-05-09 19:04:00 +0100439 void INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ )::test()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100440
441// #included from: internal/catch_capture.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100442#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100443
Phil Nash82acc2c2012-10-28 12:07:17 +0000444// #included from: catch_expression_decomposer.hpp
445#define TWOBLUECUBES_CATCH_EXPRESSION_DECOMPOSER_HPP_INCLUDED
Phil Nash89d2a3f2012-05-16 15:09:17 +0100446
Phil Nash82acc2c2012-10-28 12:07:17 +0000447// #included from: catch_expression_lhs.hpp
448#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
Phil Nash176eb812012-05-11 08:17:16 +0100449
Phil Nash82acc2c2012-10-28 12:07:17 +0000450// #included from: catch_expressionresult_builder.h
451#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_BUILDER_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +0100452
Phil Nashd31737f2012-05-09 19:04:00 +0100453// #included from: catch_tostring.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100454#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +0100455
Phil Nashd31737f2012-05-09 19:04:00 +0100456#include <sstream>
457
Phil Nash0dc9e432012-08-01 08:17:07 +0100458#ifdef __OBJC__
459// #included from: catch_objc_arc.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100460#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
Phil Nash0dc9e432012-08-01 08:17:07 +0100461
462#import <Foundation/Foundation.h>
463
464#ifdef __has_feature
465#define CATCH_ARC_ENABLED __has_feature(objc_arc)
466#else
467#define CATCH_ARC_ENABLED 0
468#endif
469
470void arcSafeRelease( NSObject* obj );
471id performOptionalSelector( id obj, SEL sel );
472
473#if !CATCH_ARC_ENABLED
474inline void arcSafeRelease( NSObject* obj ) {
475 [obj release];
476}
477inline id performOptionalSelector( id obj, SEL sel ) {
478 if( [obj respondsToSelector: sel] )
479 return [obj performSelector: sel];
480 return nil;
481}
482#define CATCH_UNSAFE_UNRETAINED
483#define CATCH_ARC_STRONG
484#else
485inline void arcSafeRelease( NSObject* ){}
486inline id performOptionalSelector( id obj, SEL sel ) {
Phil Nash5bc030d2012-08-16 18:48:50 +0100487#ifdef __clang__
Phil Nash0dc9e432012-08-01 08:17:07 +0100488#pragma clang diagnostic push
489#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
Phil Nash5bc030d2012-08-16 18:48:50 +0100490#endif
Phil Nash0dc9e432012-08-01 08:17:07 +0100491 if( [obj respondsToSelector: sel] )
492 return [obj performSelector: sel];
Phil Nash5bc030d2012-08-16 18:48:50 +0100493#ifdef __clang__
Phil Nash0dc9e432012-08-01 08:17:07 +0100494#pragma clang diagnostic pop
Phil Nash5bc030d2012-08-16 18:48:50 +0100495#endif
Phil Nash0dc9e432012-08-01 08:17:07 +0100496 return nil;
497}
498#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
499#define CATCH_ARC_STRONG __strong
500#endif
501
502#endif
503
Phil Nash89d2a3f2012-05-16 15:09:17 +0100504namespace Catch {
505namespace Detail {
506
Phil Nashd31737f2012-05-09 19:04:00 +0100507 struct NonStreamable {
508 template<typename T> NonStreamable( const T& ){}
509 };
510
511 // If the type does not have its own << overload for ostream then
512 // this one will be used instead
513 inline std::ostream& operator << ( std::ostream& ss, NonStreamable ){
514 return ss << "{?}";
515 }
516
517 template<typename T>
518 inline std::string makeString( const T& value ) {
519 std::ostringstream oss;
520 oss << value;
521 return oss.str();
522 }
523
524 template<typename T>
525 inline std::string makeString( T* p ) {
526 if( !p )
527 return INTERNAL_CATCH_STRINGIFY( NULL );
528 std::ostringstream oss;
529 oss << p;
530 return oss.str();
531 }
532
533 template<typename T>
534 inline std::string makeString( const T* p ) {
535 if( !p )
536 return INTERNAL_CATCH_STRINGIFY( NULL );
537 std::ostringstream oss;
538 oss << p;
539 return oss.str();
540 }
541
542} // end namespace Detail
543
544/// \brief converts any type to a string
545///
546/// The default template forwards on to ostringstream - except when an
547/// ostringstream overload does not exist - in which case it attempts to detect
548/// that and writes {?}.
549/// Overload (not specialise) this template for custom typs that you don't want
550/// to provide an ostream overload for.
551template<typename T>
552std::string toString( const T& value ) {
553 return Detail::makeString( value );
554}
555
556// Built in overloads
557
558inline std::string toString( const std::string& value ) {
559 return "\"" + value + "\"";
560}
561
562inline std::string toString( const std::wstring& value ) {
563 std::ostringstream oss;
564 oss << "\"";
565 for(size_t i = 0; i < value.size(); ++i )
566 oss << static_cast<char>( value[i] <= 0xff ? value[i] : '?');
567 oss << "\"";
568 return oss.str();
569}
570
571inline std::string toString( const char* const value ) {
572 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
573}
574
575inline std::string toString( char* const value ) {
576 return Catch::toString( static_cast<const char*>( value ) );
577}
578
579inline std::string toString( int value ) {
580 std::ostringstream oss;
581 oss << value;
582 return oss.str();
583}
584
585inline std::string toString( unsigned long value ) {
586 std::ostringstream oss;
587 if( value > 8192 )
588 oss << "0x" << std::hex << value;
589 else
590 oss << value;
591 return oss.str();
592}
593
594inline std::string toString( unsigned int value ) {
Phil Nash62179662012-05-11 19:06:43 +0100595 return toString( static_cast<unsigned long>( value ) );
Phil Nashd31737f2012-05-09 19:04:00 +0100596}
597
598inline std::string toString( const double value ) {
599 std::ostringstream oss;
600 oss << value;
601 return oss.str();
602}
603
604inline std::string toString( bool value ) {
605 return value ? "true" : "false";
606}
607
Phil Nash78372d02012-06-06 08:06:40 +0100608inline std::string toString( char value ) {
609 return value < ' '
610 ? toString( (unsigned int)value )
611 : Detail::makeString( value );
612}
613
614inline std::string toString( signed char value ) {
615 return toString( static_cast<char>( value ) );
616}
617
Phil Nash176eb812012-05-11 08:17:16 +0100618#ifdef CATCH_CONFIG_CPP11_NULLPTR
Phil Nash06e959b2012-05-25 08:52:05 +0100619inline std::string toString( std::nullptr_t ) {
Phil Nash176eb812012-05-11 08:17:16 +0100620 return "nullptr";
621}
622#endif
623
Phil Nash0dc9e432012-08-01 08:17:07 +0100624#ifdef __OBJC__
Phil Nash0dc9e432012-08-01 08:17:07 +0100625 inline std::string toString( NSString const * const& nsstring ) {
626 return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
627 }
628 inline std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
629 return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
630 }
631 inline std::string toString( NSObject* const& nsObject ) {
632 return toString( [nsObject description] );
633 }
634#endif
635
Phil Nashd31737f2012-05-09 19:04:00 +0100636} // end namespace Catch
637
Phil Nash82acc2c2012-10-28 12:07:17 +0000638// #included from: catch_assertionresult.h
639#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100640
Phil Nash89d1e6c2011-05-24 08:23:02 +0100641#include <string>
642// #included from: catch_result_type.h
Phil Nash3b80af72012-08-09 07:47:30 +0100643#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100644
Phil Nash89d2a3f2012-05-16 15:09:17 +0100645namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100646
Phil Nash70c5ef92012-11-13 21:46:01 +0000647 // ResultWas::OfType enum
Phil Nashaf1a3212012-11-10 18:46:39 +0000648 struct ResultWas { enum OfType {
649 Unknown = -1,
650 Ok = 0,
651 Info = 1,
652 Warning = 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100653
Phil Nashaf1a3212012-11-10 18:46:39 +0000654 FailureBit = 0x10,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100655
Phil Nashaf1a3212012-11-10 18:46:39 +0000656 ExpressionFailed = FailureBit | 1,
657 ExplicitFailure = FailureBit | 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100658
Phil Nashaf1a3212012-11-10 18:46:39 +0000659 Exception = 0x100 | FailureBit,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100660
Phil Nashaf1a3212012-11-10 18:46:39 +0000661 ThrewException = Exception | 1,
662 DidntThrowException = Exception | 2
Phil Nash89d1e6c2011-05-24 08:23:02 +0100663
Phil Nashaf1a3212012-11-10 18:46:39 +0000664 }; };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100665
Phil Nashaf1a3212012-11-10 18:46:39 +0000666 inline bool isOk( ResultWas::OfType resultType ) {
667 return ( resultType & ResultWas::FailureBit ) == 0;
668 }
Phil Nash67305122012-10-09 11:48:55 +0100669
Phil Nash70c5ef92012-11-13 21:46:01 +0000670 // ResultAction::Value enum
Phil Nashaf1a3212012-11-10 18:46:39 +0000671 struct ResultAction { enum Value {
672 None,
673 Failed = 1, // Failure - but no debug break if Debug bit not set
674 Debug = 2, // If this bit is set, invoke the debugger
675 Abort = 4 // Test run should abort
676 }; };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100677
Phil Nash70c5ef92012-11-13 21:46:01 +0000678 // ResultDisposition::Flags enum
679 struct ResultDisposition { enum Flags {
Phil Nashaf1a3212012-11-10 18:46:39 +0000680 Normal = 0x00,
681
Phil Nash70c5ef92012-11-13 21:46:01 +0000682 ContinueOnFailure = 0x01, // Failures fail test, but execution continues
683 NegateResult = 0x02, // Prefix expressiom with !
684 SuppressFail = 0x04 // Failures are reported but do not fail the test
685 }; };
686
Phil Nashaf1a3212012-11-10 18:46:39 +0000687 inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
688 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
689 }
690
Phil Nash3e2e3182012-11-17 10:49:24 +0000691 inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
692 inline bool shouldNegate( int flags ) { return ( flags & ResultDisposition::NegateResult ) != 0; }
693 inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
Phil Nashaf1a3212012-11-10 18:46:39 +0000694
695} // end namespace Catch
Phil Nash89d1e6c2011-05-24 08:23:02 +0100696
697
Phil Nash89d2a3f2012-05-16 15:09:17 +0100698namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100699
Phil Nash82acc2c2012-10-28 12:07:17 +0000700 struct AssertionInfo
Phil Nash67305122012-10-09 11:48:55 +0100701 {
Phil Nash82acc2c2012-10-28 12:07:17 +0000702 AssertionInfo() {}
Phil Nashd539da92012-11-13 09:44:52 +0000703 AssertionInfo( const std::string& _macroName,
704 const SourceLineInfo& _lineInfo,
705 const std::string& _capturedExpression,
706 ResultDisposition::Flags _resultDisposition );
Phil Nash67305122012-10-09 11:48:55 +0100707
708 std::string macroName;
709 SourceLineInfo lineInfo;
710 std::string capturedExpression;
Phil Nashd539da92012-11-13 09:44:52 +0000711 ResultDisposition::Flags resultDisposition;
Phil Nash82acc2c2012-10-28 12:07:17 +0000712 };
713
714 struct AssertionResultData
715 {
716 AssertionResultData() : resultType( ResultWas::Unknown ) {}
717
Phil Nash67305122012-10-09 11:48:55 +0100718 std::string reconstructedExpression;
719 std::string message;
720 ResultWas::OfType resultType;
721 };
722
Phil Nash82acc2c2012-10-28 12:07:17 +0000723 class AssertionResult {
Phil Nash89d2a3f2012-05-16 15:09:17 +0100724 public:
Phil Nash82acc2c2012-10-28 12:07:17 +0000725 AssertionResult();
726 AssertionResult( const AssertionInfo& info, const AssertionResultData& data );
727 ~AssertionResult();
Phil Nash89d1e6c2011-05-24 08:23:02 +0100728
Phil Nashd539da92012-11-13 09:44:52 +0000729 bool isOk() const;
730 bool succeeded() const;
Phil Nash3b80af72012-08-09 07:47:30 +0100731 ResultWas::OfType getResultType() const;
732 bool hasExpression() const;
733 bool hasMessage() const;
734 std::string getExpression() const;
735 bool hasExpandedExpression() const;
736 std::string getExpandedExpression() const;
737 std::string getMessage() const;
Phil Nash82acc2c2012-10-28 12:07:17 +0000738 SourceLineInfo getSourceInfo() const;
Phil Nash3b80af72012-08-09 07:47:30 +0100739 std::string getTestMacroName() const;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100740
741 protected:
Phil Nash82acc2c2012-10-28 12:07:17 +0000742 AssertionInfo m_info;
743 AssertionResultData m_resultData;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100744 };
745
746} // end namespace Catch
747
Phil Nash89d1e6c2011-05-24 08:23:02 +0100748// #included from: catch_evaluate.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100749#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100750
Phil Nash89d2a3f2012-05-16 15:09:17 +0100751namespace Catch {
752namespace Internal {
753
754 enum Operator {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100755 IsEqualTo,
756 IsNotEqualTo,
757 IsLessThan,
758 IsGreaterThan,
759 IsLessThanOrEqualTo,
760 IsGreaterThanOrEqualTo
761 };
762
Phil Nash371db8b2012-05-21 18:52:09 +0100763 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
764 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
765 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
766 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
767 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
768 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
769 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100770
771 // So the compare overloads can be operator agnostic we convey the operator as a template
772 // enum, which is used to specialise an Evaluator for doing the comparison.
773 template<typename T1, typename T2, Operator Op>
774 class Evaluator{};
775
776 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100777 struct Evaluator<T1, T2, IsEqualTo> {
778 static bool evaluate( const T1& lhs, const T2& rhs) {
Phil Nashd31737f2012-05-09 19:04:00 +0100779 return const_cast<T1&>( lhs ) == const_cast<T2&>( rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100780 }
781 };
782 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100783 struct Evaluator<T1, T2, IsNotEqualTo> {
784 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100785 return const_cast<T1&>( lhs ) != const_cast<T2&>( rhs );
786 }
787 };
788 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100789 struct Evaluator<T1, T2, IsLessThan> {
790 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100791 return const_cast<T1&>( lhs ) < const_cast<T2&>( rhs );
792 }
793 };
794 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100795 struct Evaluator<T1, T2, IsGreaterThan> {
796 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100797 return const_cast<T1&>( lhs ) > const_cast<T2&>( rhs );
798 }
799 };
800 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100801 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
802 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100803 return const_cast<T1&>( lhs ) >= const_cast<T2&>( rhs );
804 }
805 };
806 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100807 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
808 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100809 return const_cast<T1&>( lhs ) <= const_cast<T2&>( rhs );
810 }
811 };
812
813 template<Operator Op, typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100814 bool applyEvaluator( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100815 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
816 }
817
Phil Nashb5b1b1e2012-11-06 19:13:25 +0000818 // This level of indirection allows us to specialise for integer types
819 // to avoid signed/ unsigned warnings
820
Phil Nash89d1e6c2011-05-24 08:23:02 +0100821 // "base" overload
822 template<Operator Op, typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100823 bool compare( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100824 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
825 }
826
827 // unsigned X to int
Phil Nash89d2a3f2012-05-16 15:09:17 +0100828 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100829 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
830 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100831 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100832 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
833 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100834 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100835 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
836 }
837
838 // unsigned X to long
Phil Nash89d2a3f2012-05-16 15:09:17 +0100839 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100840 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
841 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100842 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100843 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
844 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100845 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100846 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
847 }
848
849 // int to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +0100850 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100851 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
852 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100853 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100854 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
855 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100856 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100857 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
858 }
859
860 // long to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +0100861 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -0300862 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100863 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100864 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -0300865 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100866 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100867 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -0300868 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100869 }
870
Phil Nash06e959b2012-05-25 08:52:05 +0100871 // pointer to long (when comparing against NULL)
Phil Nashb5b1b1e2012-11-06 19:13:25 +0000872 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100873 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
Phil Nash6f1543b2012-05-07 19:46:19 +0100874 }
Phil Nashb5b1b1e2012-11-06 19:13:25 +0000875 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
Phil Nash6f1543b2012-05-07 19:46:19 +0100876 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100877 }
878
Phil Nash06e959b2012-05-25 08:52:05 +0100879 // pointer to int (when comparing against NULL)
Phil Nashb5b1b1e2012-11-06 19:13:25 +0000880 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
Phil Nash06e959b2012-05-25 08:52:05 +0100881 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
882 }
Phil Nashb5b1b1e2012-11-06 19:13:25 +0000883 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
Phil Nash06e959b2012-05-25 08:52:05 +0100884 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
885 }
886
Phil Nash89d1e6c2011-05-24 08:23:02 +0100887} // end of namespace Internal
888} // end of namespace Catch
889
Phil Nash89d2a3f2012-05-16 15:09:17 +0100890namespace Catch {
Phil Nashf51d3162011-12-28 10:37:31 +0000891
Phil Nash82acc2c2012-10-28 12:07:17 +0000892// Wraps the (stringised versions of) the lhs, operator and rhs of an expression - as well as
893// the result of evaluating it. This is used to build an AssertionResult object
894class ExpressionResultBuilder {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100895public:
896
Phil Nash82acc2c2012-10-28 12:07:17 +0000897 ExpressionResultBuilder( ResultWas::OfType resultType = ResultWas::Unknown );
898 ExpressionResultBuilder( const ExpressionResultBuilder& other );
899 ExpressionResultBuilder& operator=(const ExpressionResultBuilder& other );
Phil Nashd31737f2012-05-09 19:04:00 +0100900
Phil Nash82acc2c2012-10-28 12:07:17 +0000901 ExpressionResultBuilder& setResultType( ResultWas::OfType result );
902 ExpressionResultBuilder& setResultType( bool result );
903 ExpressionResultBuilder& setLhs( const std::string& lhs );
904 ExpressionResultBuilder& setRhs( const std::string& rhs );
905 ExpressionResultBuilder& setOp( const std::string& op );
Phil Nash78d95a02012-03-04 21:22:36 +0000906
Phil Nashaf1a3212012-11-10 18:46:39 +0000907 ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition );
Phil Nash67305122012-10-09 11:48:55 +0100908
Phil Nash82acc2c2012-10-28 12:07:17 +0000909 template<typename T>
910 ExpressionResultBuilder& operator << ( const T& value ) {
911 m_stream << value;
912 return *this;
Phil Nash67305122012-10-09 11:48:55 +0100913 }
914
Phil Nash82acc2c2012-10-28 12:07:17 +0000915 std::string reconstructExpression( const AssertionInfo& info ) const;
916
917 AssertionResult buildResult( const AssertionInfo& info ) const;
918
Phil Nash89d1e6c2011-05-24 08:23:02 +0100919private:
Phil Nash82acc2c2012-10-28 12:07:17 +0000920 AssertionResultData m_data;
921 struct ExprComponents {
922 ExprComponents() : shouldNegate( false ) {}
923 bool shouldNegate;
924 std::string lhs, rhs, op;
925 } m_exprComponents;
926 std::ostringstream m_stream;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100927};
928
Phil Nashd31737f2012-05-09 19:04:00 +0100929} // end namespace Catch
930
Phil Nash89d2a3f2012-05-16 15:09:17 +0100931namespace Catch {
Phil Nash176eb812012-05-11 08:17:16 +0100932
Phil Nash134e45b2012-10-28 20:57:21 +0000933struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
Phil Nash82acc2c2012-10-28 12:07:17 +0000934
935// Wraps the LHS of an expression and captures the operator and RHS (if any) - wrapping them all
936// in an ExpressionResultBuilder object
Phil Nash176eb812012-05-11 08:17:16 +0100937template<typename T>
Phil Nash82acc2c2012-10-28 12:07:17 +0000938class ExpressionLhs {
939 void operator = ( const ExpressionLhs& );
Phil Nash176eb812012-05-11 08:17:16 +0100940
941public:
Wichert Akkermanfec10532012-11-16 10:47:33 +0100942 ExpressionLhs( T lhs ) : m_lhs( lhs ) {}
Phil Nash176eb812012-05-11 08:17:16 +0100943
944 template<typename RhsT>
Phil Nash82acc2c2012-10-28 12:07:17 +0000945 ExpressionResultBuilder& operator == ( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +0100946 return captureExpression<Internal::IsEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100947 }
948
949 template<typename RhsT>
Phil Nash82acc2c2012-10-28 12:07:17 +0000950 ExpressionResultBuilder& operator != ( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +0100951 return captureExpression<Internal::IsNotEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100952 }
953
954 template<typename RhsT>
Phil Nash82acc2c2012-10-28 12:07:17 +0000955 ExpressionResultBuilder& operator < ( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +0100956 return captureExpression<Internal::IsLessThan>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100957 }
958
959 template<typename RhsT>
Phil Nash82acc2c2012-10-28 12:07:17 +0000960 ExpressionResultBuilder& operator > ( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +0100961 return captureExpression<Internal::IsGreaterThan>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100962 }
963
964 template<typename RhsT>
Phil Nash82acc2c2012-10-28 12:07:17 +0000965 ExpressionResultBuilder& operator <= ( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +0100966 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100967 }
968
969 template<typename RhsT>
Phil Nash82acc2c2012-10-28 12:07:17 +0000970 ExpressionResultBuilder& operator >= ( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +0100971 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100972 }
973
Phil Nash82acc2c2012-10-28 12:07:17 +0000974 ExpressionResultBuilder& operator == ( bool rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +0100975 return captureExpression<Internal::IsEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100976 }
977
Phil Nash82acc2c2012-10-28 12:07:17 +0000978 ExpressionResultBuilder& operator != ( bool rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +0100979 return captureExpression<Internal::IsNotEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100980 }
981
Phil Nashaf1a3212012-11-10 18:46:39 +0000982 ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition ) {
Phil Nash134e45b2012-10-28 20:57:21 +0000983 bool value = m_lhs ? true : false;
984 return m_result
985 .setLhs( Catch::toString( value ) )
986 .setResultType( value )
Phil Nashaf1a3212012-11-10 18:46:39 +0000987 .endExpression( resultDisposition );
Phil Nash176eb812012-05-11 08:17:16 +0100988 }
989
Phil Nash82acc2c2012-10-28 12:07:17 +0000990 // Only simple binary expressions are allowed on the LHS.
991 // If more complex compositions are required then place the sub expression in parentheses
992 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( const RhsT& );
993 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( const RhsT& );
994 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( const RhsT& );
995 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( const RhsT& );
Phil Nash176eb812012-05-11 08:17:16 +0100996
997private:
Phil Nash9902ac92012-10-09 20:58:33 +0100998 template<Internal::Operator Op, typename RhsT>
Phil Nash82acc2c2012-10-28 12:07:17 +0000999 ExpressionResultBuilder& captureExpression( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001000 return m_result
Phil Nash82acc2c2012-10-28 12:07:17 +00001001 .setResultType( Internal::compare<Op>( m_lhs, rhs ) )
Phil Nash134e45b2012-10-28 20:57:21 +00001002 .setLhs( Catch::toString( m_lhs ) )
Phil Nash9902ac92012-10-09 20:58:33 +01001003 .setRhs( Catch::toString( rhs ) )
1004 .setOp( Internal::OperatorTraits<Op>::getName() );
1005 }
1006
1007private:
Phil Nash82acc2c2012-10-28 12:07:17 +00001008 ExpressionResultBuilder m_result;
Phil Nash176eb812012-05-11 08:17:16 +01001009 T m_lhs;
1010};
1011
Phil Nash176eb812012-05-11 08:17:16 +01001012} // end namespace Catch
1013
Phil Nash89d2a3f2012-05-16 15:09:17 +01001014namespace Catch {
1015
Phil Nash82acc2c2012-10-28 12:07:17 +00001016// Captures the LHS of the expression and wraps it in an Expression Lhs object
1017class ExpressionDecomposer {
Phil Nash89d2a3f2012-05-16 15:09:17 +01001018public:
1019
Phil Nash89d2a3f2012-05-16 15:09:17 +01001020 template<typename T>
Phil Nash82acc2c2012-10-28 12:07:17 +00001021 ExpressionLhs<const T&> operator->* ( const T & operand ) {
1022 return ExpressionLhs<const T&>( operand );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001023 }
1024
Phil Nash82acc2c2012-10-28 12:07:17 +00001025 ExpressionLhs<bool> operator->* ( bool value ) {
1026 return ExpressionLhs<bool>( value );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001027 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001028};
1029
1030} // end namespace Catch
1031
Phil Nashd31737f2012-05-09 19:04:00 +01001032// #included from: catch_interfaces_capture.h
Phil Nash3b80af72012-08-09 07:47:30 +01001033#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01001034
Phil Nashd31737f2012-05-09 19:04:00 +01001035#include <string>
Phil Nasha70fbe32012-08-31 08:10:36 +01001036// #included from: catch_totals.hpp
1037#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
1038
Phil Nash9e7e63c2012-09-29 20:54:03 +01001039#include <cstddef>
1040
Phil Nasha70fbe32012-08-31 08:10:36 +01001041namespace Catch {
1042
1043 struct Counts {
1044 Counts() : passed( 0 ), failed( 0 ) {}
1045
1046 Counts operator - ( const Counts& other ) const {
1047 Counts diff;
1048 diff.passed = passed - other.passed;
1049 diff.failed = failed - other.failed;
1050 return diff;
1051 }
1052 Counts& operator += ( const Counts& other ) {
1053 passed += other.passed;
1054 failed += other.failed;
1055 return *this;
1056 }
1057
1058 std::size_t total() const {
1059 return passed + failed;
1060 }
1061
1062 std::size_t passed;
1063 std::size_t failed;
1064 };
1065
1066 struct Totals {
1067
1068 Totals operator - ( const Totals& other ) const {
1069 Totals diff;
1070 diff.assertions = assertions - other.assertions;
1071 diff.testCases = testCases - other.testCases;
1072 return diff;
1073 }
1074
1075 Totals delta( const Totals& prevTotals ) const {
1076 Totals diff = *this - prevTotals;
1077 if( diff.assertions.failed > 0 )
1078 ++diff.testCases.failed;
1079 else
1080 ++diff.testCases.passed;
1081 return diff;
1082 }
1083
1084 Totals& operator += ( const Totals& other ) {
1085 assertions += other.assertions;
1086 testCases += other.testCases;
1087 return *this;
1088 }
1089
1090 Counts assertions;
1091 Counts testCases;
1092 };
1093}
1094
Phil Nashd31737f2012-05-09 19:04:00 +01001095
Phil Nash89d2a3f2012-05-16 15:09:17 +01001096namespace Catch {
1097
Phil Nashd31737f2012-05-09 19:04:00 +01001098 class TestCaseInfo;
1099 class ScopedInfo;
Phil Nash82acc2c2012-10-28 12:07:17 +00001100 class ExpressionResultBuilder;
1101 class AssertionResult;
1102 struct AssertionInfo;
Phil Nashd31737f2012-05-09 19:04:00 +01001103
Phil Nash89d2a3f2012-05-16 15:09:17 +01001104 struct IResultCapture {
Phil Nashd31737f2012-05-09 19:04:00 +01001105
Phil Nasha695eb92012-08-13 07:46:10 +01001106 virtual ~IResultCapture();
Phil Nashd31737f2012-05-09 19:04:00 +01001107
Phil Nash82acc2c2012-10-28 12:07:17 +00001108 virtual void testEnded( const AssertionResult& result ) = 0;
Phil Nash89d2a3f2012-05-16 15:09:17 +01001109 virtual bool sectionStarted( const std::string& name,
1110 const std::string& description,
1111 const SourceLineInfo& lineInfo,
1112 Counts& assertions ) = 0;
1113 virtual void sectionEnded( const std::string& name, const Counts& assertions ) = 0;
1114 virtual void pushScopedInfo( ScopedInfo* scopedInfo ) = 0;
1115 virtual void popScopedInfo( ScopedInfo* scopedInfo ) = 0;
1116 virtual bool shouldDebugBreak() const = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001117
Phil Nash5efa4bc2012-10-29 20:49:22 +00001118 virtual ResultAction::Value acceptExpression( const ExpressionResultBuilder& assertionResult, const AssertionInfo& assertionInfo ) = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001119
Phil Nash89d2a3f2012-05-16 15:09:17 +01001120 virtual std::string getCurrentTestName() const = 0;
Phil Nash82acc2c2012-10-28 12:07:17 +00001121 virtual const AssertionResult* getLastResult() const = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001122 };
1123}
1124
1125// #included from: catch_debugger.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01001126#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01001127
Phil Nashd31737f2012-05-09 19:04:00 +01001128#include <iostream>
1129
1130#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
1131#define CATCH_PLATFORM_MAC
1132#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
1133#define CATCH_PLATFORM_IPHONE
1134#elif defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
1135#define CATCH_PLATFORM_WINDOWS
1136#endif
1137
1138#ifdef CATCH_PLATFORM_MAC
1139
1140 #include <assert.h>
1141 #include <stdbool.h>
1142 #include <sys/types.h>
1143 #include <unistd.h>
1144 #include <sys/sysctl.h>
1145
Phil Nash89d2a3f2012-05-16 15:09:17 +01001146 namespace Catch{
1147
Phil Nashd31737f2012-05-09 19:04:00 +01001148 // The following function is taken directly from the following technical note:
1149 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
1150
Phil Nashd31737f2012-05-09 19:04:00 +01001151 // Returns true if the current process is being debugged (either
1152 // running under the debugger or has a debugger attached post facto).
Phil Nash89d2a3f2012-05-16 15:09:17 +01001153 inline bool isDebuggerActive(){
1154
Phil Nashd31737f2012-05-09 19:04:00 +01001155 int junk;
1156 int mib[4];
1157 struct kinfo_proc info;
1158 size_t size;
1159
1160 // Initialize the flags so that, if sysctl fails for some bizarre
1161 // reason, we get a predictable result.
1162
1163 info.kp_proc.p_flag = 0;
1164
1165 // Initialize mib, which tells sysctl the info we want, in this case
1166 // we're looking for information about a specific process ID.
1167
1168 mib[0] = CTL_KERN;
1169 mib[1] = KERN_PROC;
1170 mib[2] = KERN_PROC_PID;
1171 mib[3] = getpid();
1172
1173 // Call sysctl.
1174
1175 size = sizeof(info);
1176 junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
1177 assert(junk == 0);
1178
1179 // We're being debugged if the P_TRACED flag is set.
1180
1181 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
1182 }
1183 }
1184
1185 // The following code snippet taken from:
1186 // http://cocoawithlove.com/2008/03/break-into-debugger.html
1187 #ifdef DEBUG
1188 #if defined(__ppc64__) || defined(__ppc__)
1189 #define BreakIntoDebugger() \
Phil Nash89d2a3f2012-05-16 15:09:17 +01001190 if( Catch::isDebuggerActive() ) { \
Phil Nashd31737f2012-05-09 19:04:00 +01001191 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
1192 : : : "memory","r0","r3","r4" ); \
1193 }
1194 #else
1195 #define BreakIntoDebugger() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
1196 #endif
1197 #else
1198 inline void BreakIntoDebugger(){}
1199 #endif
1200
1201#elif defined(_MSC_VER)
1202 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
1203 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { __debugbreak(); }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001204 inline bool isDebuggerActive() {
Phil Nashd31737f2012-05-09 19:04:00 +01001205 return IsDebuggerPresent() != 0;
1206 }
Phil Nash176eb812012-05-11 08:17:16 +01001207#elif defined(__MINGW32__)
1208 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
1209 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
1210 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { DebugBreak(); }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001211 inline bool isDebuggerActive() {
Phil Nash176eb812012-05-11 08:17:16 +01001212 return IsDebuggerPresent() != 0;
1213 }
Phil Nashd31737f2012-05-09 19:04:00 +01001214#else
1215 inline void BreakIntoDebugger(){}
1216 inline bool isDebuggerActive() { return false; }
1217#endif
1218
1219#ifdef CATCH_PLATFORM_WINDOWS
1220extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001221inline void writeToDebugConsole( const std::string& text ) {
Phil Nashd31737f2012-05-09 19:04:00 +01001222 ::OutputDebugStringA( text.c_str() );
1223}
1224#else
Phil Nash89d2a3f2012-05-16 15:09:17 +01001225inline void writeToDebugConsole( const std::string& text ) {
Phil Nashd31737f2012-05-09 19:04:00 +01001226 // !TBD: Need a version for Mac/ XCode and other IDEs
1227 std::cout << text;
1228}
1229#endif // CATCH_PLATFORM_WINDOWS
1230
Phil Nash3b80af72012-08-09 07:47:30 +01001231// #included from: catch_interfaces_registry_hub.h
1232#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
1233
Phil Nasha70fbe32012-08-31 08:10:36 +01001234// #included from: catch_interfaces_reporter.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04001235#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001236
1237// #included from: catch_config.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04001238#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001239
1240// #included from: catch_test_spec.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04001241#define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001242
1243// #included from: catch_test_case_info.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04001244#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001245
1246#include <string>
Phil Nashfc1baac2012-09-15 17:53:27 +01001247#include <set>
Phil Nasha70fbe32012-08-31 08:10:36 +01001248
1249namespace Catch {
1250
1251 struct ITestCase;
1252
1253 class TestCaseInfo {
1254 public:
1255 TestCaseInfo();
1256
1257 TestCaseInfo( ITestCase* testCase,
Phil Nash88b70822012-11-04 21:39:38 +00001258 const std::string& className,
1259 const std::string& name,
1260 const std::string& description,
Phil Nasha70fbe32012-08-31 08:10:36 +01001261 const SourceLineInfo& lineInfo );
1262
1263 TestCaseInfo( const TestCaseInfo& other, const std::string& name );
1264 TestCaseInfo( const TestCaseInfo& other );
1265
1266 void invoke() const;
Phil Nash88b70822012-11-04 21:39:38 +00001267
1268 const std::string& getClassName() const;
Phil Nasha70fbe32012-08-31 08:10:36 +01001269 const std::string& getName() const;
1270 const std::string& getDescription() const;
1271 const SourceLineInfo& getLineInfo() const;
1272 bool isHidden() const;
Phil Nashfc1baac2012-09-15 17:53:27 +01001273 bool hasTag( const std::string& tag ) const;
Phil Nash799ecf92012-09-24 08:30:13 +01001274 bool matchesTags( const std::string& tagPattern ) const;
Phil Nash67ec8702012-09-26 18:38:26 +01001275 const std::set<std::string>& getTags() const;
Phil Nasha70fbe32012-08-31 08:10:36 +01001276
1277 void swap( TestCaseInfo& other );
1278 bool operator == ( const TestCaseInfo& other ) const;
1279 bool operator < ( const TestCaseInfo& other ) const;
1280 TestCaseInfo& operator = ( const TestCaseInfo& other );
1281
1282 private:
1283 Ptr<ITestCase> m_test;
Phil Nash88b70822012-11-04 21:39:38 +00001284 std::string m_className;
Phil Nasha70fbe32012-08-31 08:10:36 +01001285 std::string m_name;
1286 std::string m_description;
Phil Nashfc1baac2012-09-15 17:53:27 +01001287 std::set<std::string> m_tags;
Phil Nasha70fbe32012-08-31 08:10:36 +01001288 SourceLineInfo m_lineInfo;
Phil Nashfc1baac2012-09-15 17:53:27 +01001289 bool m_isHidden;
Phil Nasha70fbe32012-08-31 08:10:36 +01001290 };
1291}
1292
Phil Nash67ec8702012-09-26 18:38:26 +01001293// #included from: catch_tags.hpp
1294#define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED
1295
1296#include <string>
1297#include <set>
1298#include <map>
1299#include <vector>
1300
1301#ifdef __clang__
1302#pragma clang diagnostic ignored "-Wpadded"
1303#endif
1304
1305namespace Catch {
1306 class TagParser {
1307 public:
1308 virtual ~TagParser();
1309
1310 void parse( const std::string& str ) {
1311 std::size_t pos = 0;
1312 while( pos < str.size() ) {
1313 char c = str[pos];
1314 if( c == '[' ) {
1315 std::size_t end = str.find_first_of( ']', pos );
1316 if( end != std::string::npos ) {
1317 acceptTag( str.substr( pos+1, end-pos-1 ) );
1318 pos = end+1;
1319 }
1320 else {
1321 acceptChar( c );
1322 pos++;
1323 }
1324 }
1325 else {
1326 acceptChar( c );
1327 pos++;
1328 }
1329 }
1330 endParse();
1331 }
1332
1333 protected:
1334 virtual void acceptTag( const std::string& tag ) = 0;
1335 virtual void acceptChar( char c ) = 0;
1336 virtual void endParse() {}
1337
1338 private:
1339 };
1340
1341 class TagExtracter : public TagParser {
1342 public:
1343
1344 TagExtracter( std::set<std::string>& tags )
1345 : m_tags( tags )
1346 {}
1347 virtual ~TagExtracter();
1348
1349 void parse( std::string& description ) {
1350 TagParser::parse( description );
1351 description = m_remainder;
1352 }
1353
1354 private:
1355 virtual void acceptTag( const std::string& tag ) {
1356 m_tags.insert( tag );
1357 }
1358 virtual void acceptChar( char c ) {
1359 m_remainder += c;
1360 }
1361
Phil Nash88b70822012-11-04 21:39:38 +00001362 TagExtracter& operator=(const TagExtracter&);
1363
Phil Nash67ec8702012-09-26 18:38:26 +01001364 std::set<std::string>& m_tags;
1365 std::string m_remainder;
1366 };
1367
1368 class Tag {
1369 public:
1370 Tag()
Phil Nasha1dc7e32012-11-06 19:34:35 +00001371 : m_isNegated( false )
Phil Nash67ec8702012-09-26 18:38:26 +01001372 {}
1373
1374 Tag( const std::string& name, bool isNegated )
1375 : m_name( name ),
Phil Nasha1dc7e32012-11-06 19:34:35 +00001376 m_isNegated( isNegated )
Phil Nash67ec8702012-09-26 18:38:26 +01001377 {}
1378
1379 std::string getName() const {
1380 return m_name;
1381 }
1382 bool isNegated() const {
1383 return m_isNegated;
1384 }
1385
1386 bool operator ! () const {
1387 return m_name.empty();
1388 }
1389
1390 private:
1391 std::string m_name;
1392 bool m_isNegated;
1393 };
1394
1395 class TagSet {
1396 typedef std::map<std::string, Tag> TagMap;
1397 public:
1398 void add( const Tag& tag ) {
1399 m_tags.insert( std::make_pair( tag.getName(), tag ) );
1400 }
1401
Phil Nash67ec8702012-09-26 18:38:26 +01001402 bool empty() const {
1403 return m_tags.empty();
1404 }
1405
1406 bool matches( const std::set<std::string>& tags ) const {
1407 TagMap::const_iterator it = m_tags.begin();
1408 TagMap::const_iterator itEnd = m_tags.end();
1409 for(; it != itEnd; ++it ) {
1410 bool found = tags.find( it->first ) != tags.end();
1411 if( found == it->second.isNegated() )
1412 return false;
1413 }
1414 return true;
1415 }
1416
1417 private:
1418 TagMap m_tags;
1419 };
1420
1421 class TagExpression {
1422 public:
1423 bool matches( const std::set<std::string>& tags ) const {
1424 std::vector<TagSet>::const_iterator it = m_tagSets.begin();
1425 std::vector<TagSet>::const_iterator itEnd = m_tagSets.end();
1426 for(; it != itEnd; ++it )
1427 if( it->matches( tags ) )
1428 return true;
1429 return false;
1430 }
1431
1432 private:
1433 friend class TagExpressionParser;
1434
1435 std::vector<TagSet> m_tagSets;
1436 };
1437
1438 class TagExpressionParser : public TagParser {
1439 public:
1440 TagExpressionParser( TagExpression& exp )
1441 : m_isNegated( false ),
1442 m_exp( exp )
1443 {}
1444
1445 ~TagExpressionParser();
1446
1447 private:
1448 virtual void acceptTag( const std::string& tag ) {
1449 m_currentTagSet.add( Tag( tag, m_isNegated ) );
1450 m_isNegated = false;
1451 }
1452 virtual void acceptChar( char c ) {
1453 switch( c ) {
1454 case '~':
1455 m_isNegated = true;
1456 break;
1457 case ',':
1458 m_exp.m_tagSets.push_back( m_currentTagSet );
1459 break;
1460 }
1461 }
1462 virtual void endParse() {
1463 if( !m_currentTagSet.empty() )
1464 m_exp.m_tagSets.push_back( m_currentTagSet );
1465 }
1466
Phil Nash88b70822012-11-04 21:39:38 +00001467 TagExpressionParser& operator=(const TagExpressionParser&);
1468
Phil Nash67ec8702012-09-26 18:38:26 +01001469 bool m_isNegated;
1470 TagSet m_currentTagSet;
1471 TagExpression& m_exp;
1472 };
1473
1474} // end namespace Catch
1475
Phil Nasha70fbe32012-08-31 08:10:36 +01001476#include <string>
1477#include <vector>
1478
1479namespace Catch {
1480
1481 struct IfFilterMatches{ enum DoWhat {
Phil Nashe2d215e2012-09-07 17:52:35 +01001482 AutoDetectBehaviour,
Phil Nasha70fbe32012-08-31 08:10:36 +01001483 IncludeTests,
1484 ExcludeTests
1485 }; };
1486
1487 class TestCaseFilter {
1488 enum WildcardPosition {
1489 NoWildcard = 0,
1490 WildcardAtStart = 1,
1491 WildcardAtEnd = 2,
1492 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
1493 };
1494
1495 public:
Phil Nashe2d215e2012-09-07 17:52:35 +01001496 TestCaseFilter( const std::string& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::AutoDetectBehaviour )
Phil Nasha70fbe32012-08-31 08:10:36 +01001497 : m_stringToMatch( testSpec ),
1498 m_filterType( matchBehaviour ),
1499 m_wildcardPosition( NoWildcard )
1500 {
Phil Nashe2d215e2012-09-07 17:52:35 +01001501 if( m_filterType == IfFilterMatches::AutoDetectBehaviour ) {
1502 if( startsWith( m_stringToMatch, "exclude:" ) ) {
1503 m_stringToMatch = m_stringToMatch.substr( 8 );
1504 m_filterType = IfFilterMatches::ExcludeTests;
1505 }
1506 else if( startsWith( m_stringToMatch, "~" ) ) {
1507 m_stringToMatch = m_stringToMatch.substr( 1 );
1508 m_filterType = IfFilterMatches::ExcludeTests;
1509 }
1510 else {
1511 m_filterType = IfFilterMatches::IncludeTests;
1512 }
1513 }
1514
Phil Nasha70fbe32012-08-31 08:10:36 +01001515 if( m_stringToMatch[0] == '*' ) {
1516 m_stringToMatch = m_stringToMatch.substr( 1 );
1517 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtStart );
1518 }
1519 if( m_stringToMatch[m_stringToMatch.size()-1] == '*' ) {
1520 m_stringToMatch = m_stringToMatch.substr( 0, m_stringToMatch.size()-1 );
1521 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtEnd );
1522 }
1523 }
1524
1525 IfFilterMatches::DoWhat getFilterType() const {
1526 return m_filterType;
1527 }
1528
1529 bool shouldInclude( const TestCaseInfo& testCase ) const {
1530 return isMatch( testCase ) == (m_filterType == IfFilterMatches::IncludeTests);
1531 }
1532 private:
1533
1534#ifdef __clang__
1535#pragma clang diagnostic push
1536#pragma clang diagnostic ignored "-Wunreachable-code"
1537#endif
1538
1539 bool isMatch( const TestCaseInfo& testCase ) const {
1540 const std::string& name = testCase.getName();
1541
1542 switch( m_wildcardPosition ) {
1543 case NoWildcard:
1544 return m_stringToMatch == name;
1545 case WildcardAtStart:
1546 return endsWith( name, m_stringToMatch );
1547 case WildcardAtEnd:
1548 return startsWith( name, m_stringToMatch );
1549 case WildcardAtBothEnds:
1550 return contains( name, m_stringToMatch );
1551 }
1552 throw std::logic_error( "Unhandled wildcard type" );
1553 }
1554
1555#ifdef __clang__
1556#pragma clang diagnostic pop
1557#endif
1558
1559 std::string m_stringToMatch;
1560 IfFilterMatches::DoWhat m_filterType;
1561 WildcardPosition m_wildcardPosition;
1562 };
1563
1564 class TestCaseFilters {
1565 public:
1566 TestCaseFilters( const std::string& name ) : m_name( name ) {}
1567
1568 std::string getName() const {
1569 return m_name;
1570 }
1571
1572 void addFilter( const TestCaseFilter& filter ) {
1573 if( filter.getFilterType() == IfFilterMatches::ExcludeTests )
1574 m_exclusionFilters.push_back( filter );
1575 else
1576 m_inclusionFilters.push_back( filter );
1577 }
1578
Phil Nash67ec8702012-09-26 18:38:26 +01001579 void addTags( const std::string& tagPattern ) {
1580 TagExpression exp;
1581 TagExpressionParser( exp ).parse( tagPattern );
1582
1583 m_tagExpressions.push_back( exp );
1584 }
1585
Phil Nasha70fbe32012-08-31 08:10:36 +01001586 bool shouldInclude( const TestCaseInfo& testCase ) const {
Phil Nash67ec8702012-09-26 18:38:26 +01001587 if( !m_tagExpressions.empty() ) {
1588 std::vector<TagExpression>::const_iterator it = m_tagExpressions.begin();
1589 std::vector<TagExpression>::const_iterator itEnd = m_tagExpressions.end();
1590 for(; it != itEnd; ++it )
1591 if( it->matches( testCase.getTags() ) )
1592 break;
1593 if( it == itEnd )
1594 return false;
1595 }
1596
Phil Nasha70fbe32012-08-31 08:10:36 +01001597 if( !m_inclusionFilters.empty() ) {
1598 std::vector<TestCaseFilter>::const_iterator it = m_inclusionFilters.begin();
1599 std::vector<TestCaseFilter>::const_iterator itEnd = m_inclusionFilters.end();
1600 for(; it != itEnd; ++it )
1601 if( it->shouldInclude( testCase ) )
1602 break;
1603 if( it == itEnd )
1604 return false;
1605 }
Phil Nash67ec8702012-09-26 18:38:26 +01001606 else if( m_exclusionFilters.empty() && m_tagExpressions.empty() ) {
Phil Nashfc1baac2012-09-15 17:53:27 +01001607 return !testCase.isHidden();
1608 }
1609
Phil Nasha70fbe32012-08-31 08:10:36 +01001610 std::vector<TestCaseFilter>::const_iterator it = m_exclusionFilters.begin();
1611 std::vector<TestCaseFilter>::const_iterator itEnd = m_exclusionFilters.end();
1612 for(; it != itEnd; ++it )
1613 if( !it->shouldInclude( testCase ) )
1614 return false;
1615 return true;
1616 }
1617 private:
Phil Nash67ec8702012-09-26 18:38:26 +01001618 std::vector<TagExpression> m_tagExpressions;
Phil Nasha70fbe32012-08-31 08:10:36 +01001619 std::vector<TestCaseFilter> m_inclusionFilters;
1620 std::vector<TestCaseFilter> m_exclusionFilters;
1621 std::string m_name;
1622 };
1623
1624}
1625
1626// #included from: catch_interfaces_config.h
1627#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
1628
1629namespace Catch {
1630
1631 struct IConfig {
1632
1633 virtual ~IConfig();
1634
1635 virtual bool allowThrows() const = 0;
1636 };
1637}
1638
Phil Nash67ec8702012-09-26 18:38:26 +01001639// #included from: catch_stream.hpp
1640#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
1641
Phil Nash9e7e63c2012-09-29 20:54:03 +01001642// #included from: catch_streambuf.h
1643#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
1644
1645#include <streambuf>
1646
1647namespace Catch {
1648
1649 class StreamBufBase : public std::streambuf {
1650 public:
1651 virtual ~StreamBufBase();
1652 };
1653}
1654
Phil Nash67ec8702012-09-26 18:38:26 +01001655#include <stdexcept>
1656#include <cstdio>
1657
1658namespace Catch {
1659
1660 template<typename WriterF, size_t bufferSize=256>
1661 class StreamBufImpl : public StreamBufBase {
1662 char data[bufferSize];
1663 WriterF m_writer;
1664
1665 public:
1666 StreamBufImpl() {
1667 setp( data, data + sizeof(data) );
1668 }
1669
1670 ~StreamBufImpl() {
1671 sync();
1672 }
1673
1674 private:
1675 int overflow( int c ) {
1676 sync();
1677
1678 if( c != EOF ) {
1679 if( pbase() == epptr() )
1680 m_writer( std::string( 1, static_cast<char>( c ) ) );
1681 else
1682 sputc( static_cast<char>( c ) );
1683 }
1684 return 0;
1685 }
1686
1687 int sync() {
1688 if( pbase() != pptr() ) {
1689 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
1690 setp( pbase(), epptr() );
1691 }
1692 return 0;
1693 }
1694 };
1695
1696 ///////////////////////////////////////////////////////////////////////////
1697
1698 struct OutputDebugWriter {
1699
1700 void operator()( const std::string &str ) {
1701 writeToDebugConsole( str );
1702 }
1703 };
1704
1705 class Stream {
1706 public:
1707 Stream()
1708 : streamBuf( NULL ), isOwned( false )
1709 {}
1710
1711 Stream( std::streambuf* _streamBuf, bool _isOwned )
1712 : streamBuf( _streamBuf ), isOwned( _isOwned )
1713 {}
1714
1715 void release() {
1716 if( isOwned ) {
1717 delete streamBuf;
1718 streamBuf = NULL;
1719 isOwned = false;
1720 }
1721 }
1722
1723 std::streambuf* streamBuf;
1724
1725 private:
1726 bool isOwned;
1727 };
1728}
1729
Phil Nasha70fbe32012-08-31 08:10:36 +01001730#include <memory>
1731#include <vector>
1732#include <string>
1733#include <iostream>
1734
1735namespace Catch {
1736
1737 struct Include { enum WhichResults {
1738 FailedOnly,
1739 SuccessfulResults
1740 }; };
1741
1742 struct List{ enum What {
1743 None = 0,
1744
1745 Reports = 1,
1746 Tests = 2,
1747 All = 3,
1748
1749 TestNames = 6,
1750
1751 WhatMask = 0xf,
1752
1753 AsText = 0x10,
1754 AsXml = 0x20,
1755
1756 AsMask = 0xf0
1757 }; };
1758
1759 struct ConfigData {
1760
1761 struct WarnAbout { enum What {
1762 Nothing = 0x00,
1763 NoAssertions = 0x01
1764 }; };
1765
1766 ConfigData()
1767 : listSpec( List::None ),
1768 shouldDebugBreak( false ),
1769 includeWhichResults( Include::FailedOnly ),
1770 cutoff( -1 ),
1771 allowThrows( true ),
1772 warnings( WarnAbout::Nothing )
1773 {}
1774
1775 std::string reporter;
1776 std::string outputFilename;
1777 List::What listSpec;
1778 std::vector<TestCaseFilters> filters;
1779 bool shouldDebugBreak;
1780 std::string stream;
1781 Include::WhichResults includeWhichResults;
1782 std::string name;
1783 int cutoff;
1784 bool allowThrows;
1785 WarnAbout::What warnings;
1786 };
1787
1788 class Config : public IConfig {
1789 private:
1790 Config( const Config& other );
1791 Config& operator = ( const Config& other );
1792 virtual void dummy();
1793 public:
1794
1795 Config()
Phil Nash67ec8702012-09-26 18:38:26 +01001796 : m_os( std::cout.rdbuf() )
Phil Nasha70fbe32012-08-31 08:10:36 +01001797 {}
1798
1799 Config( const ConfigData& data )
1800 : m_data( data ),
Phil Nasha70fbe32012-08-31 08:10:36 +01001801 m_os( std::cout.rdbuf() )
1802 {}
1803
1804 virtual ~Config() {
1805 m_os.rdbuf( std::cout.rdbuf() );
Phil Nash67ec8702012-09-26 18:38:26 +01001806 m_stream.release();
Phil Nasha70fbe32012-08-31 08:10:36 +01001807 }
1808
1809 void setFilename( const std::string& filename ) {
1810 m_data.outputFilename = filename;
1811 }
1812
1813 List::What getListSpec( void ) const {
1814 return m_data.listSpec;
1815 }
1816
1817 const std::string& getFilename() const {
1818 return m_data.outputFilename ;
1819 }
1820
1821 List::What listWhat() const {
1822 return static_cast<List::What>( m_data.listSpec & List::WhatMask );
1823 }
1824
1825 List::What listAs() const {
1826 return static_cast<List::What>( m_data.listSpec & List::AsMask );
1827 }
1828
1829 std::string getName() const {
1830 return m_data.name;
1831 }
1832
1833 bool shouldDebugBreak() const {
1834 return m_data.shouldDebugBreak;
1835 }
1836
1837 virtual std::ostream& stream() const {
1838 return m_os;
1839 }
1840
1841 void setStreamBuf( std::streambuf* buf ) {
1842 m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
1843 }
1844
1845 void useStream( const std::string& streamName ) {
Phil Nash67ec8702012-09-26 18:38:26 +01001846 Stream stream = createStream( streamName );
1847 setStreamBuf( stream.streamBuf );
1848 m_stream.release();
1849 m_stream = stream;
Phil Nasha70fbe32012-08-31 08:10:36 +01001850 }
1851
Phil Nashe2d215e2012-09-07 17:52:35 +01001852 void addTestSpec( const std::string& testSpec ) {
1853 TestCaseFilters filters( testSpec );
1854 filters.addFilter( TestCaseFilter( testSpec ) );
1855 m_data.filters.push_back( filters );
1856 }
1857
Phil Nasha70fbe32012-08-31 08:10:36 +01001858 virtual bool includeSuccessfulResults() const {
1859 return m_data.includeWhichResults == Include::SuccessfulResults;
1860 }
1861
1862 int getCutoff() const {
1863 return m_data.cutoff;
1864 }
1865
1866 virtual bool allowThrows() const {
1867 return m_data.allowThrows;
1868 }
1869
1870 const ConfigData& data() const {
1871 return m_data;
1872 }
1873 ConfigData& data() {
1874 return m_data;
1875 }
1876
1877 private:
1878 ConfigData m_data;
1879
1880 // !TBD Move these out of here
Phil Nash67ec8702012-09-26 18:38:26 +01001881 Stream m_stream;
Phil Nasha70fbe32012-08-31 08:10:36 +01001882 mutable std::ostream m_os;
1883 };
1884
1885} // end namespace Catch
1886
1887#include <string>
1888#include <ostream>
1889#include <map>
1890
1891namespace Catch
1892{
1893 struct ReporterConfig
1894 {
1895 ReporterConfig( const std::string& _name,
1896 std::ostream& _stream,
1897 bool _includeSuccessfulResults,
1898 const ConfigData& _fullConfig )
1899 : name( _name ),
1900 stream( _stream ),
1901 includeSuccessfulResults( _includeSuccessfulResults ),
1902 fullConfig( _fullConfig )
1903 {}
1904
Phil Nash799ecf92012-09-24 08:30:13 +01001905 ReporterConfig( const ReporterConfig& other )
1906 : name( other.name ),
1907 stream( other.stream ),
1908 includeSuccessfulResults( other.includeSuccessfulResults ),
1909 fullConfig( other.fullConfig )
1910 {}
1911
Phil Nasha70fbe32012-08-31 08:10:36 +01001912 std::string name;
1913 std::ostream& stream;
1914 bool includeSuccessfulResults;
1915 ConfigData fullConfig;
Phil Nash799ecf92012-09-24 08:30:13 +01001916
1917 private:
1918 void operator=(const ReporterConfig&);
Phil Nasha70fbe32012-08-31 08:10:36 +01001919 };
1920
1921 class TestCaseInfo;
Phil Nash82acc2c2012-10-28 12:07:17 +00001922 class AssertionResult;
Phil Nasha70fbe32012-08-31 08:10:36 +01001923
1924 struct IReporter : IShared {
1925 virtual ~IReporter();
Phil Nash82acc2c2012-10-28 12:07:17 +00001926
Phil Nasha70fbe32012-08-31 08:10:36 +01001927 virtual bool shouldRedirectStdout() const = 0;
Phil Nash82acc2c2012-10-28 12:07:17 +00001928
Phil Nasha70fbe32012-08-31 08:10:36 +01001929 virtual void StartTesting() = 0;
1930 virtual void EndTesting( const Totals& totals ) = 0;
Phil Nash82acc2c2012-10-28 12:07:17 +00001931
Phil Nasha70fbe32012-08-31 08:10:36 +01001932 virtual void StartGroup( const std::string& groupName ) = 0;
1933 virtual void EndGroup( const std::string& groupName, const Totals& totals ) = 0;
Phil Nash82acc2c2012-10-28 12:07:17 +00001934
1935 virtual void StartTestCase( const TestCaseInfo& testInfo ) = 0;
1936 // TestCaseResult
1937 virtual void EndTestCase( const TestCaseInfo& testInfo, const Totals& totals, const std::string& stdOut, const std::string& stdErr ) = 0;
1938
1939 // SectionInfo
Phil Nasha70fbe32012-08-31 08:10:36 +01001940 virtual void StartSection( const std::string& sectionName, const std::string& description ) = 0;
Phil Nash82acc2c2012-10-28 12:07:17 +00001941 // Section Result
1942 virtual void EndSection( const std::string& sectionName, const Counts& assertions ) = 0;
1943
1944 // - merge into SectionResult ?
Phil Nasha70fbe32012-08-31 08:10:36 +01001945 virtual void NoAssertionsInSection( const std::string& sectionName ) = 0;
1946 virtual void NoAssertionsInTestCase( const std::string& testName ) = 0;
Phil Nash82acc2c2012-10-28 12:07:17 +00001947
1948 // - merge into SectionResult, TestCaseResult, GroupResult & TestRunResult
Phil Nasha70fbe32012-08-31 08:10:36 +01001949 virtual void Aborted() = 0;
Phil Nash82acc2c2012-10-28 12:07:17 +00001950
1951 // AssertionReslt
1952 virtual void Result( const AssertionResult& result ) = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +01001953 };
1954
1955 struct IReporterFactory {
1956 virtual ~IReporterFactory();
1957 virtual IReporter* create( const ReporterConfig& config ) const = 0;
1958 virtual std::string getDescription() const = 0;
1959 };
1960
1961 struct IReporterRegistry {
1962 typedef std::map<std::string, IReporterFactory*> FactoryMap;
1963
1964 virtual ~IReporterRegistry();
1965 virtual IReporter* create( const std::string& name, const ReporterConfig& config ) const = 0;
1966 virtual const FactoryMap& getFactories() const = 0;
1967 };
1968
1969 inline std::string trim( const std::string& str ) {
1970 std::string::size_type start = str.find_first_not_of( "\n\r\t " );
1971 std::string::size_type end = str.find_last_not_of( "\n\r\t " );
1972
1973 return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
1974 }
1975}
1976
Phil Nash3b80af72012-08-09 07:47:30 +01001977#include <vector>
Phil Nash3b80af72012-08-09 07:47:30 +01001978
1979namespace Catch {
1980
1981 class TestCaseInfo;
Phil Nash3b80af72012-08-09 07:47:30 +01001982 struct ITestCaseRegistry;
1983 struct IExceptionTranslatorRegistry;
1984 struct IExceptionTranslator;
1985
1986 struct IRegistryHub {
Phil Nasha695eb92012-08-13 07:46:10 +01001987 virtual ~IRegistryHub();
Phil Nash3b80af72012-08-09 07:47:30 +01001988
1989 virtual const IReporterRegistry& getReporterRegistry() const = 0;
1990 virtual const ITestCaseRegistry& getTestCaseRegistry() const = 0;
1991 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
1992 };
1993
1994 struct IMutableRegistryHub {
Phil Nasha695eb92012-08-13 07:46:10 +01001995 virtual ~IMutableRegistryHub();
Phil Nash3b80af72012-08-09 07:47:30 +01001996 virtual void registerReporter( const std::string& name, IReporterFactory* factory ) = 0;
1997 virtual void registerTest( const TestCaseInfo& testInfo ) = 0;
1998 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
1999 };
2000
2001 IRegistryHub& getRegistryHub();
2002 IMutableRegistryHub& getMutableRegistryHub();
2003 void cleanUp();
Phil Nash82acc2c2012-10-28 12:07:17 +00002004 std::string translateActiveException();
2005
Phil Nash3b80af72012-08-09 07:47:30 +01002006}
2007
Phil Nash82acc2c2012-10-28 12:07:17 +00002008#include <ostream>
2009
2010namespace Catch {
2011
2012 inline IResultCapture& getResultCapture() {
2013 return getCurrentContext().getResultCapture();
2014 }
2015
2016 template<typename MatcherT>
2017 ExpressionResultBuilder expressionResultBuilderFromMatcher( const MatcherT& matcher,
2018 const std::string& matcherCallAsString ) {
2019 std::string matcherAsString = matcher.toString();
2020 if( matcherAsString == "{?}" )
2021 matcherAsString = matcherCallAsString;
2022 return ExpressionResultBuilder()
2023 .setRhs( matcherAsString )
2024 .setOp( "matches" );
2025 }
2026
2027 template<typename MatcherT, typename ArgT>
2028 ExpressionResultBuilder expressionResultBuilderFromMatcher( const MatcherT& matcher,
2029 const ArgT& arg,
2030 const std::string& matcherCallAsString ) {
2031 return expressionResultBuilderFromMatcher( matcher, matcherCallAsString )
2032 .setLhs( Catch::toString( arg ) )
2033 .setResultType( matcher.match( arg ) );
2034 }
2035
2036 template<typename MatcherT, typename ArgT>
2037 ExpressionResultBuilder expressionResultBuilderFromMatcher( const MatcherT& matcher,
2038 ArgT* arg,
2039 const std::string& matcherCallAsString ) {
2040 return expressionResultBuilderFromMatcher( matcher, matcherCallAsString )
2041 .setLhs( Catch::toString( arg ) )
2042 .setResultType( matcher.match( arg ) );
2043 }
2044
2045struct TestFailureException{};
2046
2047class ScopedInfo {
2048public:
2049 ScopedInfo() : m_resultBuilder( ResultWas::Info ) {
2050 getResultCapture().pushScopedInfo( this );
2051 }
2052 ~ScopedInfo() {
2053 getResultCapture().popScopedInfo( this );
2054 }
2055 template<typename T>
2056 ScopedInfo& operator << ( const T& value ) {
2057 m_resultBuilder << value;
2058 return *this;
2059 }
2060 AssertionResult buildResult( const AssertionInfo& assertionInfo ) const {
2061 return m_resultBuilder.buildResult( assertionInfo );
2062 }
2063
2064private:
2065 ExpressionResultBuilder m_resultBuilder;
2066};
2067
2068// This is just here to avoid compiler warnings with macro constants and boolean literals
2069inline bool isTrue( bool value ){ return value; }
2070
2071} // end namespace Catch
2072
2073///////////////////////////////////////////////////////////////////////////////
Phil Nash5efa4bc2012-10-29 20:49:22 +00002074#define INTERNAL_CATCH_ASSERTIONINFO_NAME INTERNAL_CATCH_UNIQUE_NAME( __assertionInfo )
2075
2076///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002077#define INTERNAL_CATCH_ACCEPT_EXPR( evaluatedExpr, resultDisposition, originalExpr ) \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002078 if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, INTERNAL_CATCH_ASSERTIONINFO_NAME ) ) { \
Phil Nash82acc2c2012-10-28 12:07:17 +00002079 if( internal_catch_action & Catch::ResultAction::Debug ) BreakIntoDebugger(); \
2080 if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \
Phil Nashaf1a3212012-11-10 18:46:39 +00002081 if( !Catch::shouldContinueOnFailure( resultDisposition ) ) throw Catch::TestFailureException(); \
Phil Nash82acc2c2012-10-28 12:07:17 +00002082 if( Catch::isTrue( false ) ){ bool this_is_here_to_invoke_warnings = ( originalExpr ); Catch::isTrue( this_is_here_to_invoke_warnings ); } \
2083 }
2084
2085///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002086#define INTERNAL_CATCH_ACCEPT_INFO( expr, macroName, resultDisposition ) \
Phil Nashd539da92012-11-13 09:44:52 +00002087 Catch::AssertionInfo INTERNAL_CATCH_ASSERTIONINFO_NAME( macroName, CATCH_INTERNAL_LINEINFO, expr, resultDisposition );
Phil Nash82acc2c2012-10-28 12:07:17 +00002088
2089///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002090#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002091 do { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002092 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002093 try { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002094 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002095 } catch( Catch::TestFailureException& ) { \
2096 throw; \
2097 } catch( ... ) { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002098 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \
2099 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, expr ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002100 throw; \
2101 } \
2102 } while( Catch::isTrue( false ) )
Phil Nash82acc2c2012-10-28 12:07:17 +00002103
2104///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002105#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
2106 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
Phil Nashd539da92012-11-13 09:44:52 +00002107 if( Catch::getResultCapture().getLastResult()->succeeded() )
Phil Nash82acc2c2012-10-28 12:07:17 +00002108
2109///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002110#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
2111 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
Phil Nashd539da92012-11-13 09:44:52 +00002112 if( !Catch::getResultCapture().getLastResult()->succeeded() )
Phil Nash82acc2c2012-10-28 12:07:17 +00002113
2114///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002115#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002116 do { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002117 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002118 try { \
2119 expr; \
Phil Nashaf1a3212012-11-10 18:46:39 +00002120 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002121 } \
2122 catch( ... ) { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002123 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), resultDisposition, false ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002124 } \
2125} while( Catch::isTrue( false ) )
Phil Nash82acc2c2012-10-28 12:07:17 +00002126
2127///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002128#define INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
Phil Nash82acc2c2012-10-28 12:07:17 +00002129 try { \
Phil Nash82acc2c2012-10-28 12:07:17 +00002130 if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \
2131 expr; \
Phil Nashaf1a3212012-11-10 18:46:39 +00002132 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::DidntThrowException ), resultDisposition, false ); \
Phil Nash82acc2c2012-10-28 12:07:17 +00002133 } \
2134 } \
2135 catch( Catch::TestFailureException& ) { \
2136 throw; \
2137 } \
2138 catch( exceptionType ) { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002139 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \
Phil Nash82acc2c2012-10-28 12:07:17 +00002140 }
2141
2142///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002143#define INTERNAL_CATCH_THROWS( expr, exceptionType, resultDisposition, macroName ) \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002144 do { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002145 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
2146 INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002147 } while( Catch::isTrue( false ) )
2148
2149///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002150#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002151 do { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002152 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
2153 INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002154 catch( ... ) { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002155 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
2156 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002157 } \
2158 } while( Catch::isTrue( false ) )
Phil Nash82acc2c2012-10-28 12:07:17 +00002159
2160///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002161#define INTERNAL_CATCH_MSG( reason, resultType, resultDisposition, macroName ) \
Phil Nashec5956f2012-11-06 07:52:28 +00002162 do { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002163 INTERNAL_CATCH_ACCEPT_INFO( "", macroName, resultDisposition ); \
2164 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( resultType ) << reason, resultDisposition, true ) \
Phil Nashec5956f2012-11-06 07:52:28 +00002165 } while( Catch::isTrue( false ) )
Phil Nash82acc2c2012-10-28 12:07:17 +00002166
2167///////////////////////////////////////////////////////////////////////////////
2168#define INTERNAL_CATCH_SCOPED_INFO( log, macroName ) \
Phil Nashaf1a3212012-11-10 18:46:39 +00002169 INTERNAL_CATCH_ACCEPT_INFO( "", macroName, Catch::ResultDisposition::Normal ); \
Phil Nash82acc2c2012-10-28 12:07:17 +00002170 Catch::ScopedInfo INTERNAL_CATCH_UNIQUE_NAME( info ); \
2171 INTERNAL_CATCH_UNIQUE_NAME( info ) << log
2172
2173///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002174#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002175 do { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002176 INTERNAL_CATCH_ACCEPT_INFO( #arg " " #matcher, macroName, resultDisposition ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002177 try { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002178 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002179 } catch( Catch::TestFailureException& ) { \
2180 throw; \
2181 } catch( ... ) { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002182 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
2183 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002184 throw; \
2185 } \
2186 } while( Catch::isTrue( false ) )
Phil Nash82acc2c2012-10-28 12:07:17 +00002187
2188// #included from: internal/catch_section.hpp
2189#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
2190
2191#include <string>
2192
2193namespace Catch {
2194
2195 class Section {
2196 public:
2197 Section( const std::string& name,
2198 const std::string& description,
2199 const SourceLineInfo& lineInfo )
2200 : m_name( name ),
2201 m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( name, description, lineInfo, m_assertions ) )
2202 {}
2203
2204 ~Section() {
2205 if( m_sectionIncluded )
2206 getCurrentContext().getResultCapture().sectionEnded( m_name, m_assertions );
2207 }
2208
2209 // This indicates whether the section should be executed or not
2210 operator bool() {
2211 return m_sectionIncluded;
2212 }
2213
2214 private:
2215
2216 std::string m_name;
2217 Counts m_assertions;
2218 bool m_sectionIncluded;
2219 };
2220
2221} // end namespace Catch
2222
2223#define INTERNAL_CATCH_SECTION( name, desc ) \
2224 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( name, desc, CATCH_INTERNAL_LINEINFO ) )
2225
2226// #included from: internal/catch_generators.hpp
2227#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
2228
2229#include <iterator>
2230#include <vector>
2231#include <string>
2232#include <stdlib.h>
2233
2234namespace Catch {
2235
2236template<typename T>
2237struct IGenerator {
2238 virtual ~IGenerator() {}
2239 virtual T getValue( std::size_t index ) const = 0;
2240 virtual std::size_t size () const = 0;
2241};
2242
2243template<typename T>
2244class BetweenGenerator : public IGenerator<T> {
2245public:
2246 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
2247
2248 virtual T getValue( std::size_t index ) const {
2249 return m_from+static_cast<T>( index );
2250 }
2251
2252 virtual std::size_t size() const {
2253 return static_cast<std::size_t>( 1+m_to-m_from );
2254 }
2255
2256private:
2257
2258 T m_from;
2259 T m_to;
2260};
2261
2262template<typename T>
2263class ValuesGenerator : public IGenerator<T> {
2264public:
2265 ValuesGenerator(){}
2266
2267 void add( T value ) {
2268 m_values.push_back( value );
2269 }
2270
2271 virtual T getValue( std::size_t index ) const {
2272 return m_values[index];
2273 }
2274
2275 virtual std::size_t size() const {
2276 return m_values.size();
2277 }
2278
2279private:
2280 std::vector<T> m_values;
2281};
2282
2283template<typename T>
2284class CompositeGenerator {
2285public:
2286 CompositeGenerator() : m_totalSize( 0 ) {}
2287
2288 // *** Move semantics, similar to auto_ptr ***
2289 CompositeGenerator( CompositeGenerator& other )
2290 : m_fileInfo( other.m_fileInfo ),
2291 m_totalSize( 0 )
2292 {
2293 move( other );
2294 }
2295
2296 CompositeGenerator& setFileInfo( const char* fileInfo ) {
2297 m_fileInfo = fileInfo;
2298 return *this;
2299 }
2300
2301 ~CompositeGenerator() {
2302 deleteAll( m_composed );
2303 }
2304
2305 operator T () const {
2306 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
2307
2308 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
2309 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
2310 for( size_t index = 0; it != itEnd; ++it )
2311 {
2312 const IGenerator<T>* generator = *it;
2313 if( overallIndex >= index && overallIndex < index + generator->size() )
2314 {
2315 return generator->getValue( overallIndex-index );
2316 }
2317 index += generator->size();
2318 }
2319 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
2320 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
2321 }
2322
2323 void add( const IGenerator<T>* generator ) {
2324 m_totalSize += generator->size();
2325 m_composed.push_back( generator );
2326 }
2327
2328 CompositeGenerator& then( CompositeGenerator& other ) {
2329 move( other );
2330 return *this;
2331 }
2332
2333 CompositeGenerator& then( T value ) {
2334 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2335 valuesGen->add( value );
2336 add( valuesGen );
2337 return *this;
2338 }
2339
2340private:
2341
2342 void move( CompositeGenerator& other ) {
2343 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
2344 m_totalSize += other.m_totalSize;
2345 other.m_composed.clear();
2346 }
2347
2348 std::vector<const IGenerator<T>*> m_composed;
2349 std::string m_fileInfo;
2350 size_t m_totalSize;
2351};
2352
2353namespace Generators
2354{
2355 template<typename T>
2356 CompositeGenerator<T> between( T from, T to ) {
2357 CompositeGenerator<T> generators;
2358 generators.add( new BetweenGenerator<T>( from, to ) );
2359 return generators;
2360 }
2361
2362 template<typename T>
2363 CompositeGenerator<T> values( T val1, T val2 ) {
2364 CompositeGenerator<T> generators;
2365 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2366 valuesGen->add( val1 );
2367 valuesGen->add( val2 );
2368 generators.add( valuesGen );
2369 return generators;
2370 }
2371
2372 template<typename T>
2373 CompositeGenerator<T> values( T val1, T val2, T val3 ){
2374 CompositeGenerator<T> generators;
2375 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2376 valuesGen->add( val1 );
2377 valuesGen->add( val2 );
2378 valuesGen->add( val3 );
2379 generators.add( valuesGen );
2380 return generators;
2381 }
2382
2383 template<typename T>
2384 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
2385 CompositeGenerator<T> generators;
2386 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2387 valuesGen->add( val1 );
2388 valuesGen->add( val2 );
2389 valuesGen->add( val3 );
2390 valuesGen->add( val4 );
2391 generators.add( valuesGen );
2392 return generators;
2393 }
2394
2395} // end namespace Generators
2396
2397using namespace Generators;
2398
2399} // end namespace Catch
2400
2401#define INTERNAL_CATCH_LINESTR2( line ) #line
2402#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2403
2404#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2405
2406// #included from: internal/catch_interfaces_exception.h
2407#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2408
2409#include <string>
Phil Nash89d1e6c2011-05-24 08:23:02 +01002410
Phil Nash89d2a3f2012-05-16 15:09:17 +01002411namespace Catch {
2412
Phil Nash89d1e6c2011-05-24 08:23:02 +01002413 typedef std::string(*exceptionTranslateFunction)();
2414
Phil Nash89d2a3f2012-05-16 15:09:17 +01002415 struct IExceptionTranslator {
Phil Nasha695eb92012-08-13 07:46:10 +01002416 virtual ~IExceptionTranslator();
Phil Nash89d1e6c2011-05-24 08:23:02 +01002417 virtual std::string translate() const = 0;
2418 };
2419
Phil Nash89d2a3f2012-05-16 15:09:17 +01002420 struct IExceptionTranslatorRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +01002421 virtual ~IExceptionTranslatorRegistry();
Phil Nash89d1e6c2011-05-24 08:23:02 +01002422
Phil Nash89d2a3f2012-05-16 15:09:17 +01002423 virtual std::string translateActiveException() const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002424 };
2425
Phil Nash89d2a3f2012-05-16 15:09:17 +01002426 class ExceptionTranslatorRegistrar {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002427 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01002428 class ExceptionTranslator : public IExceptionTranslator {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002429 public:
2430
Phil Nash89d2a3f2012-05-16 15:09:17 +01002431 ExceptionTranslator( std::string(*translateFunction)( T& ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002432 : m_translateFunction( translateFunction )
2433 {}
2434
Phil Nash89d2a3f2012-05-16 15:09:17 +01002435 virtual std::string translate() const {
2436 try {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002437 throw;
2438 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01002439 catch( T& ex ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002440 return m_translateFunction( ex );
2441 }
2442 }
2443
2444 protected:
2445 std::string(*m_translateFunction)( T& );
2446 };
2447
2448 public:
2449 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01002450 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
Phil Nash3b80af72012-08-09 07:47:30 +01002451 getMutableRegistryHub().registerTranslator
Phil Nash89d1e6c2011-05-24 08:23:02 +01002452 ( new ExceptionTranslator<T>( translateFunction ) );
2453 }
2454 };
2455}
2456
2457///////////////////////////////////////////////////////////////////////////////
2458#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
2459 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
2460 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
2461 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
2462
2463// #included from: internal/catch_approx.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002464#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01002465
Phil Nash89d1e6c2011-05-24 08:23:02 +01002466#include <cmath>
2467#include <limits>
2468
Phil Nash89d2a3f2012-05-16 15:09:17 +01002469namespace Catch {
2470namespace Detail {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002471
Phil Nash89d2a3f2012-05-16 15:09:17 +01002472 class Approx {
2473 public:
2474 explicit Approx ( double value )
2475 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
2476 m_scale( 1.0 ),
2477 m_value( value )
2478 {}
Phil Nashf721a962011-06-07 14:13:57 +01002479
Phil Nash89d2a3f2012-05-16 15:09:17 +01002480 Approx( const Approx& other )
2481 : m_epsilon( other.m_epsilon ),
2482 m_scale( other.m_scale ),
2483 m_value( other.m_value )
2484 {}
Phil Nashf721a962011-06-07 14:13:57 +01002485
Phil Nash89d2a3f2012-05-16 15:09:17 +01002486 static Approx custom() {
2487 return Approx( 0 );
2488 }
Phil Nashf721a962011-06-07 14:13:57 +01002489
Phil Nash89d2a3f2012-05-16 15:09:17 +01002490 Approx operator()( double value ) {
2491 Approx approx( value );
2492 approx.epsilon( m_epsilon );
2493 approx.scale( m_scale );
2494 return approx;
2495 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002496
Phil Nash89d2a3f2012-05-16 15:09:17 +01002497 friend bool operator == ( double lhs, const Approx& rhs ) {
2498 // Thanks to Richard Harris for his help refining this formula
2499 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
2500 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002501
Phil Nash89d2a3f2012-05-16 15:09:17 +01002502 friend bool operator == ( const Approx& lhs, double rhs ) {
2503 return operator==( rhs, lhs );
2504 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002505
Phil Nash89d2a3f2012-05-16 15:09:17 +01002506 friend bool operator != ( double lhs, const Approx& rhs ) {
2507 return !operator==( lhs, rhs );
2508 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002509
Phil Nash89d2a3f2012-05-16 15:09:17 +01002510 friend bool operator != ( const Approx& lhs, double rhs ) {
2511 return !operator==( rhs, lhs );
2512 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002513
Phil Nash89d2a3f2012-05-16 15:09:17 +01002514 Approx& epsilon( double newEpsilon ) {
2515 m_epsilon = newEpsilon;
2516 return *this;
2517 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002518
Phil Nash89d2a3f2012-05-16 15:09:17 +01002519 Approx& scale( double newScale ) {
2520 m_scale = newScale;
2521 return *this;
2522 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002523
Phil Nash89d2a3f2012-05-16 15:09:17 +01002524 std::string toString() const {
2525 std::ostringstream oss;
Phil Nash67305122012-10-09 11:48:55 +01002526 oss << "Approx( " << m_value << " )";
Phil Nash89d2a3f2012-05-16 15:09:17 +01002527 return oss.str();
2528 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002529
Phil Nash89d2a3f2012-05-16 15:09:17 +01002530 private:
2531 double m_epsilon;
2532 double m_scale;
2533 double m_value;
2534 };
2535}
2536
2537template<>
2538inline std::string toString<Detail::Approx>( const Detail::Approx& value ) {
2539 return value.toString();
2540}
Phil Nash89d1e6c2011-05-24 08:23:02 +01002541
2542} // end namespace Catch
2543
Phil Nash371db8b2012-05-21 18:52:09 +01002544// #included from: internal/catch_matchers.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002545#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01002546
2547namespace Catch {
2548namespace Matchers {
2549 namespace Impl {
Phil Nash9444bbc2012-10-12 07:58:17 +01002550
2551 template<typename ExpressionT>
2552 struct Matcher : SharedImpl<IShared>
2553 {
2554 virtual ~Matcher() {}
2555 virtual Ptr<Matcher> clone() const = 0;
2556 virtual bool match( const ExpressionT& expr ) const = 0;
2557 virtual std::string toString() const = 0;
2558 };
2559
2560 template<typename DerivedT, typename ExpressionT>
2561 struct MatcherImpl : Matcher<ExpressionT> {
2562
2563 virtual Ptr<Matcher<ExpressionT> > clone() const {
2564 return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<const DerivedT&>( *this ) ) );
2565 }
2566 };
2567
2568 namespace Generic {
2569
2570 template<typename ExpressionT>
2571 class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
2572 public:
2573
2574 AllOf() {}
2575 AllOf( const AllOf& other ) : m_matchers( other.m_matchers ) {}
2576
2577 AllOf& add( const Matcher<ExpressionT>& matcher ) {
2578 m_matchers.push_back( matcher.clone() );
2579 return *this;
2580 }
2581 virtual bool match( const ExpressionT& expr ) const
2582 {
2583 for( std::size_t i = 0; i < m_matchers.size(); ++i )
2584 if( !m_matchers[i]->match( expr ) )
2585 return false;
2586 return true;
2587 }
2588 virtual std::string toString() const {
2589 std::ostringstream oss;
2590 oss << "( ";
2591 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
2592 if( i != 0 )
2593 oss << " and ";
2594 oss << m_matchers[i]->toString();
2595 }
2596 oss << " )";
2597 return oss.str();
2598 }
2599
2600 private:
2601 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
2602 };
2603
2604 template<typename ExpressionT>
2605 class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
2606 public:
2607
2608 AnyOf() {}
2609 AnyOf( const AnyOf& other ) : m_matchers( other.m_matchers ) {}
2610
2611 AnyOf& add( const Matcher<ExpressionT>& matcher ) {
2612 m_matchers.push_back( matcher.clone() );
2613 return *this;
2614 }
2615 virtual bool match( const ExpressionT& expr ) const
2616 {
2617 for( std::size_t i = 0; i < m_matchers.size(); ++i )
2618 if( m_matchers[i]->match( expr ) )
2619 return true;
2620 return false;
2621 }
2622 virtual std::string toString() const {
2623 std::ostringstream oss;
2624 oss << "( ";
2625 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
2626 if( i != 0 )
2627 oss << " or ";
2628 oss << m_matchers[i]->toString();
2629 }
2630 oss << " )";
2631 return oss.str();
2632 }
2633
2634 private:
2635 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
2636 };
2637
2638 }
2639
Phil Nash371db8b2012-05-21 18:52:09 +01002640 namespace StdString {
2641
Phil Nash9444bbc2012-10-12 07:58:17 +01002642 struct Equals : MatcherImpl<Equals, std::string> {
Phil Nasha8570df2012-05-24 08:29:41 +01002643 Equals( const std::string& str ) : m_str( str ){}
Phil Nash9444bbc2012-10-12 07:58:17 +01002644 Equals( const Equals& other ) : m_str( other.m_str ){}
Phil Nasha8570df2012-05-24 08:29:41 +01002645
Phil Nash9444bbc2012-10-12 07:58:17 +01002646 virtual ~Equals();
2647
2648 virtual bool match( const std::string& expr ) const {
2649 return m_str == expr;
2650 }
2651 virtual std::string toString() const {
2652 return "equals: \"" + m_str + "\"";
Phil Nasha8570df2012-05-24 08:29:41 +01002653 }
2654
Phil Nasha8570df2012-05-24 08:29:41 +01002655 std::string m_str;
2656 };
2657
Phil Nash9444bbc2012-10-12 07:58:17 +01002658 struct Contains : MatcherImpl<Contains, std::string> {
Phil Nash371db8b2012-05-21 18:52:09 +01002659 Contains( const std::string& substr ) : m_substr( substr ){}
Phil Nash9444bbc2012-10-12 07:58:17 +01002660 Contains( const Contains& other ) : m_substr( other.m_substr ){}
Phil Nash371db8b2012-05-21 18:52:09 +01002661
Phil Nash9444bbc2012-10-12 07:58:17 +01002662 virtual ~Contains();
2663
2664 virtual bool match( const std::string& expr ) const {
2665 return expr.find( m_substr ) != std::string::npos;
2666 }
2667 virtual std::string toString() const {
2668 return "contains: \"" + m_substr + "\"";
Phil Nash371db8b2012-05-21 18:52:09 +01002669 }
2670
Phil Nash371db8b2012-05-21 18:52:09 +01002671 std::string m_substr;
2672 };
2673
Phil Nash9444bbc2012-10-12 07:58:17 +01002674 struct StartsWith : MatcherImpl<StartsWith, std::string> {
Phil Nash371db8b2012-05-21 18:52:09 +01002675 StartsWith( const std::string& substr ) : m_substr( substr ){}
Phil Nash9444bbc2012-10-12 07:58:17 +01002676 StartsWith( const StartsWith& other ) : m_substr( other.m_substr ){}
Phil Nash371db8b2012-05-21 18:52:09 +01002677
Phil Nash9444bbc2012-10-12 07:58:17 +01002678 virtual ~StartsWith();
2679
2680 virtual bool match( const std::string& expr ) const {
2681 return expr.find( m_substr ) == 0;
2682 }
2683 virtual std::string toString() const {
2684 return "starts with: \"" + m_substr + "\"";
Phil Nash371db8b2012-05-21 18:52:09 +01002685 }
2686
Phil Nash371db8b2012-05-21 18:52:09 +01002687 std::string m_substr;
2688 };
2689
Phil Nash9444bbc2012-10-12 07:58:17 +01002690 struct EndsWith : MatcherImpl<EndsWith, std::string> {
Phil Nash371db8b2012-05-21 18:52:09 +01002691 EndsWith( const std::string& substr ) : m_substr( substr ){}
Phil Nash9444bbc2012-10-12 07:58:17 +01002692 EndsWith( const EndsWith& other ) : m_substr( other.m_substr ){}
Phil Nash371db8b2012-05-21 18:52:09 +01002693
Phil Nash9444bbc2012-10-12 07:58:17 +01002694 virtual ~EndsWith();
2695
2696 virtual bool match( const std::string& expr ) const {
2697 return expr.find( m_substr ) == expr.size() - m_substr.size();
2698 }
2699 virtual std::string toString() const {
2700 return "ends with: \"" + m_substr + "\"";
Phil Nash371db8b2012-05-21 18:52:09 +01002701 }
2702
Phil Nash371db8b2012-05-21 18:52:09 +01002703 std::string m_substr;
2704 };
2705 } // namespace StdString
2706 } // namespace Impl
2707
Phil Nash9444bbc2012-10-12 07:58:17 +01002708 // The following functions create the actual matcher objects.
2709 // This allows the types to be inferred
2710 template<typename ExpressionT>
2711 inline Impl::Generic::AllOf<ExpressionT> AllOf( const Impl::Matcher<ExpressionT>& m1,
2712 const Impl::Matcher<ExpressionT>& m2 ) {
2713 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
2714 }
2715 template<typename ExpressionT>
2716 inline Impl::Generic::AllOf<ExpressionT> AllOf( const Impl::Matcher<ExpressionT>& m1,
2717 const Impl::Matcher<ExpressionT>& m2,
2718 const Impl::Matcher<ExpressionT>& m3 ) {
2719 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
2720 }
2721 template<typename ExpressionT>
2722 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( const Impl::Matcher<ExpressionT>& m1,
2723 const Impl::Matcher<ExpressionT>& m2 ) {
2724 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
2725 }
2726 template<typename ExpressionT>
2727 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( const Impl::Matcher<ExpressionT>& m1,
2728 const Impl::Matcher<ExpressionT>& m2,
2729 const Impl::Matcher<ExpressionT>& m3 ) {
2730 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
2731 }
2732
Phil Nasha8570df2012-05-24 08:29:41 +01002733 inline Impl::StdString::Equals Equals( const std::string& str ){ return Impl::StdString::Equals( str ); }
Phil Nash371db8b2012-05-21 18:52:09 +01002734 inline Impl::StdString::Contains Contains( const std::string& substr ){ return Impl::StdString::Contains( substr ); }
2735 inline Impl::StdString::StartsWith StartsWith( const std::string& substr ){ return Impl::StdString::StartsWith( substr ); }
2736 inline Impl::StdString::EndsWith EndsWith( const std::string& substr ){ return Impl::StdString::EndsWith( substr ); }
2737
2738} // namespace Matchers
2739
2740using namespace Matchers;
2741
2742} // namespace Catch
2743
Phil Nash0f9c5512012-06-02 23:12:42 +01002744// These files are included here so the single_include script doesn't put them
2745// in the conditionally compiled sections
Phil Nash0f9c5512012-06-02 23:12:42 +01002746// #included from: internal/catch_interfaces_runner.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04002747#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
Phil Nash0f9c5512012-06-02 23:12:42 +01002748
2749#include <string>
2750
2751namespace Catch {
2752 class TestCaseInfo;
2753
2754 struct IRunner {
Phil Nasha695eb92012-08-13 07:46:10 +01002755 virtual ~IRunner();
Phil Nash0f9c5512012-06-02 23:12:42 +01002756 };
2757}
2758
2759
Phil Nash371db8b2012-05-21 18:52:09 +01002760#ifdef __OBJC__
2761// #included from: internal/catch_objc.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002762#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01002763
Phil Nash371db8b2012-05-21 18:52:09 +01002764#import <objc/runtime.h>
2765
2766#include <string>
2767
2768// NB. Any general catch headers included here must be included
2769// in catch.hpp first to make sure they are included by the single
2770// header for non obj-usage
Phil Nash81528252011-08-15 09:06:31 +01002771
Phil Nash83224e62011-08-12 18:53:28 +01002772///////////////////////////////////////////////////////////////////////////////
2773// This protocol is really only here for (self) documenting purposes, since
2774// all its methods are optional.
2775@protocol OcFixture
2776
2777@optional
2778
2779-(void) setUp;
2780-(void) tearDown;
2781
2782@end
2783
Phil Nash89d2a3f2012-05-16 15:09:17 +01002784namespace Catch {
Phil Nash83224e62011-08-12 18:53:28 +01002785
Phil Nash5bc030d2012-08-16 18:48:50 +01002786 class OcMethod : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002787
2788 public:
2789 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
2790
2791 virtual void invoke() const {
Phil Nash53c990a2012-03-17 18:20:06 +00002792 id obj = [[m_cls alloc] init];
Phil Nash83224e62011-08-12 18:53:28 +01002793
Phil Nash53c990a2012-03-17 18:20:06 +00002794 performOptionalSelector( obj, @selector(setUp) );
2795 performOptionalSelector( obj, m_sel );
2796 performOptionalSelector( obj, @selector(tearDown) );
Phil Nash83224e62011-08-12 18:53:28 +01002797
Phil Nash53c990a2012-03-17 18:20:06 +00002798 arcSafeRelease( obj );
Phil Nash83224e62011-08-12 18:53:28 +01002799 }
Phil Nash83224e62011-08-12 18:53:28 +01002800 private:
Phil Nash5bc030d2012-08-16 18:48:50 +01002801 virtual ~OcMethod() {}
2802
Phil Nash83224e62011-08-12 18:53:28 +01002803 Class m_cls;
2804 SEL m_sel;
2805 };
2806
Phil Nash89d2a3f2012-05-16 15:09:17 +01002807 namespace Detail{
Phil Nash83224e62011-08-12 18:53:28 +01002808
Phil Nash89d2a3f2012-05-16 15:09:17 +01002809 inline bool startsWith( const std::string& str, const std::string& sub ) {
Phil Nash83224e62011-08-12 18:53:28 +01002810 return str.length() > sub.length() && str.substr( 0, sub.length() ) == sub;
2811 }
2812
Phil Nash89d2a3f2012-05-16 15:09:17 +01002813 inline std::string getAnnotation( Class cls,
2814 const std::string& annotationName,
2815 const std::string& testCaseName ) {
Phil Nash83224e62011-08-12 18:53:28 +01002816 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2817 SEL sel = NSSelectorFromString( selStr );
Phil Nash53c990a2012-03-17 18:20:06 +00002818 arcSafeRelease( selStr );
2819 id value = performOptionalSelector( cls, sel );
2820 if( value )
2821 return [(NSString*)value UTF8String];
Phil Nash83224e62011-08-12 18:53:28 +01002822 return "";
2823 }
2824 }
2825
Phil Nash89d2a3f2012-05-16 15:09:17 +01002826 inline size_t registerTestMethods() {
Phil Nash83224e62011-08-12 18:53:28 +01002827 size_t noTestMethods = 0;
2828 int noClasses = objc_getClassList( NULL, 0 );
2829
Phil Nash861a1e72012-04-28 12:29:52 +01002830 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
Phil Nash53c990a2012-03-17 18:20:06 +00002831 objc_getClassList( classes, noClasses );
Phil Nash83224e62011-08-12 18:53:28 +01002832
Phil Nash89d2a3f2012-05-16 15:09:17 +01002833 for( int c = 0; c < noClasses; c++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01002834 Class cls = classes[c];
2835 {
2836 u_int count;
2837 Method* methods = class_copyMethodList( cls, &count );
Phil Nash7004f4a2012-05-22 08:56:59 +01002838 for( u_int m = 0; m < count ; m++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01002839 SEL selector = method_getName(methods[m]);
2840 std::string methodName = sel_getName(selector);
Phil Nash89d2a3f2012-05-16 15:09:17 +01002841 if( Detail::startsWith( methodName, "Catch_TestCase_" ) ) {
Phil Nash83224e62011-08-12 18:53:28 +01002842 std::string testCaseName = methodName.substr( 15 );
Phil Nash53c990a2012-03-17 18:20:06 +00002843 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
2844 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
Phil Nash83224e62011-08-12 18:53:28 +01002845
Phil Nash3b80af72012-08-09 07:47:30 +01002846 getMutableRegistryHub().registerTest( TestCaseInfo( new OcMethod( cls, selector ), name.c_str(), desc.c_str(), SourceLineInfo() ) );
Phil Nash83224e62011-08-12 18:53:28 +01002847 noTestMethods++;
Phil Nash83224e62011-08-12 18:53:28 +01002848 }
2849 }
2850 free(methods);
2851 }
2852 }
2853 return noTestMethods;
2854 }
Phil Nash78d95a02012-03-04 21:22:36 +00002855
Phil Nash89d2a3f2012-05-16 15:09:17 +01002856 namespace Matchers {
2857 namespace Impl {
2858 namespace NSStringMatchers {
2859
2860 struct StringHolder {
Phil Nash78d95a02012-03-04 21:22:36 +00002861 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
Phil Nash89d2a3f2012-05-16 15:09:17 +01002862 StringHolder() {
Phil Nash53c990a2012-03-17 18:20:06 +00002863 arcSafeRelease( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00002864 }
2865
2866 NSString* m_substr;
2867 };
2868
Phil Nash89d2a3f2012-05-16 15:09:17 +01002869 struct Equals : StringHolder {
Phil Nash8d18d162012-03-14 20:06:14 +00002870 Equals( NSString* substr ) : StringHolder( substr ){}
2871
Phil Nash89d2a3f2012-05-16 15:09:17 +01002872 bool operator()( NSString* str ) const {
Phil Nash8d18d162012-03-14 20:06:14 +00002873 return [str isEqualToString:m_substr];
2874 }
2875
Phil Nash89d2a3f2012-05-16 15:09:17 +01002876 friend std::ostream& operator<<( std::ostream& os, const Equals& matcher ) {
Phil Nash8d18d162012-03-14 20:06:14 +00002877 os << "equals string: " << Catch::toString( matcher.m_substr );
2878 return os;
2879 }
2880 };
2881
Phil Nash89d2a3f2012-05-16 15:09:17 +01002882 struct Contains : StringHolder {
Phil Nash78d95a02012-03-04 21:22:36 +00002883 Contains( NSString* substr ) : StringHolder( substr ){}
2884
Phil Nash89d2a3f2012-05-16 15:09:17 +01002885 bool operator()( NSString* str ) const {
Phil Nash78d95a02012-03-04 21:22:36 +00002886 return [str rangeOfString:m_substr].location != NSNotFound;
2887 }
2888
Phil Nash89d2a3f2012-05-16 15:09:17 +01002889 friend std::ostream& operator<<( std::ostream& os, const Contains& matcher ) {
Phil Nash78d95a02012-03-04 21:22:36 +00002890 os << "contains: " << Catch::toString( matcher.m_substr );
2891 return os;
2892 }
2893 };
2894
Phil Nash89d2a3f2012-05-16 15:09:17 +01002895 struct StartsWith : StringHolder {
Phil Nash78d95a02012-03-04 21:22:36 +00002896 StartsWith( NSString* substr ) : StringHolder( substr ){}
2897
Phil Nash89d2a3f2012-05-16 15:09:17 +01002898 bool operator()( NSString* str ) const {
Phil Nash78d95a02012-03-04 21:22:36 +00002899 return [str rangeOfString:m_substr].location == 0;
2900 }
2901
Phil Nash89d2a3f2012-05-16 15:09:17 +01002902 friend std::ostream& operator<<( std::ostream& os, const StartsWith& matcher ) {
Phil Nash78d95a02012-03-04 21:22:36 +00002903 os << "starts with: " << Catch::toString( matcher.m_substr );
2904 return os;
2905 }
2906 };
Phil Nash89d2a3f2012-05-16 15:09:17 +01002907 struct EndsWith : StringHolder {
Phil Nash78d95a02012-03-04 21:22:36 +00002908 EndsWith( NSString* substr ) : StringHolder( substr ){}
2909
Phil Nash89d2a3f2012-05-16 15:09:17 +01002910 bool operator()( NSString* str ) const {
Phil Nash78d95a02012-03-04 21:22:36 +00002911 return [str rangeOfString:m_substr].location == [str length] - [m_substr length];
2912 }
2913
Phil Nash89d2a3f2012-05-16 15:09:17 +01002914 friend std::ostream& operator<<( std::ostream& os, const EndsWith& matcher ) {
Phil Nash78d95a02012-03-04 21:22:36 +00002915 os << "ends with: " << Catch::toString( matcher.m_substr );
2916 return os;
2917 }
2918 };
2919
2920 } // namespace NSStringMatchers
2921 } // namespace Impl
2922
Phil Nash8d18d162012-03-14 20:06:14 +00002923 inline Impl::NSStringMatchers::Equals
2924 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
2925
Phil Nash78d95a02012-03-04 21:22:36 +00002926 inline Impl::NSStringMatchers::Contains
2927 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00002928
Phil Nash78d95a02012-03-04 21:22:36 +00002929 inline Impl::NSStringMatchers::StartsWith
2930 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00002931
Phil Nash78d95a02012-03-04 21:22:36 +00002932 inline Impl::NSStringMatchers::EndsWith
2933 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
2934
2935 } // namespace Matchers
2936
2937 using namespace Matchers;
2938
2939} // namespace Catch
Phil Nash83224e62011-08-12 18:53:28 +01002940
2941///////////////////////////////////////////////////////////////////////////////
2942#define OC_TEST_CASE( name, desc )\
Phil Nash53c990a2012-03-17 18:20:06 +00002943+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01002944{\
Phil Nash53c990a2012-03-17 18:20:06 +00002945return @ name; \
Phil Nash83224e62011-08-12 18:53:28 +01002946}\
Phil Nash53c990a2012-03-17 18:20:06 +00002947+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01002948{ \
Phil Nash53c990a2012-03-17 18:20:06 +00002949return @ desc; \
Phil Nash83224e62011-08-12 18:53:28 +01002950} \
2951-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
2952
2953#endif
2954
2955#if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER )
Phil Nasha695eb92012-08-13 07:46:10 +01002956// #included from: internal/catch_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04002957#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01002958
2959// Collect all the implementation files together here
2960// These are the equivalent of what would usually be cpp files
2961
Phil Nash5bc030d2012-08-16 18:48:50 +01002962#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01002963#pragma clang diagnostic push
2964#pragma clang diagnostic ignored "-Wweak-vtables"
Phil Nash5bc030d2012-08-16 18:48:50 +01002965#endif
Phil Nasha695eb92012-08-13 07:46:10 +01002966
Phil Nash83224e62011-08-12 18:53:28 +01002967// #included from: catch_runner.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002968#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
Phil Nash83224e62011-08-12 18:53:28 +01002969
Phil Nasha695eb92012-08-13 07:46:10 +01002970// #included from: internal/catch_commandline.hpp
2971#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
2972
Phil Nasha695eb92012-08-13 07:46:10 +01002973namespace Catch {
2974
2975 class Command {
2976 public:
2977 Command(){}
2978
Phil Nashecf934b2012-08-27 21:42:55 +01002979 explicit Command( const std::string& name ) : m_name( name ) {
2980 }
Phil Nasha695eb92012-08-13 07:46:10 +01002981
2982 Command& operator += ( const std::string& arg ) {
2983 m_args.push_back( arg );
2984 return *this;
2985 }
2986 Command& operator += ( const Command& other ) {
2987 std::copy( other.m_args.begin(), other.m_args.end(), std::back_inserter( m_args ) );
2988 if( m_name.empty() )
2989 m_name = other.m_name;
2990 return *this;
2991 }
2992 Command operator + ( const Command& other ) {
2993 Command newCommand( *this );
2994 newCommand += other;
2995 return newCommand;
2996 }
2997
2998 operator SafeBool::type() const {
Phil Nashe571e6f2012-08-24 18:54:56 +01002999 return SafeBool::makeSafe( !m_name.empty() || !m_args.empty() );
Phil Nasha695eb92012-08-13 07:46:10 +01003000 }
3001
3002 std::string name() const { return m_name; }
3003 std::string operator[]( std::size_t i ) const { return m_args[i]; }
3004 std::size_t argsCount() const { return m_args.size(); }
3005
3006 CATCH_ATTRIBUTE_NORETURN
3007 void raiseError( const std::string& message ) const {
3008 std::ostringstream oss;
Phil Nashecf934b2012-08-27 21:42:55 +01003009 if( m_name.empty() )
3010 oss << "Error while parsing " << m_name << ". " << message << ".";
3011 else
3012 oss << "Error while parsing arguments. " << message << ".";
3013
Phil Nasha695eb92012-08-13 07:46:10 +01003014 if( m_args.size() > 0 )
Phil Nashecf934b2012-08-27 21:42:55 +01003015 oss << " Arguments were:";
Phil Nasha695eb92012-08-13 07:46:10 +01003016 for( std::size_t i = 0; i < m_args.size(); ++i )
3017 oss << " " << m_args[i];
3018 throw std::domain_error( oss.str() );
3019 }
3020
3021 private:
3022
3023 std::string m_name;
3024 std::vector<std::string> m_args;
3025 };
3026
3027 class CommandParser {
3028 public:
3029 CommandParser( int argc, char const * const * argv ) : m_argc( static_cast<std::size_t>( argc ) ), m_argv( argv ) {}
3030
Phil Nashe2d215e2012-09-07 17:52:35 +01003031 std::string exeName() const {
Phil Nasha90a88a2012-11-19 19:59:10 +00003032 std::string exeName = m_argv[0];
3033 std::string::size_type pos = exeName.find_last_of( "/\\" );
3034 if( pos != std::string::npos )
3035 exeName = exeName.substr( pos+1 );
3036 return exeName;
Phil Nashe2d215e2012-09-07 17:52:35 +01003037 }
Phil Nasha695eb92012-08-13 07:46:10 +01003038 Command find( const std::string& arg1, const std::string& arg2, const std::string& arg3 ) const {
3039 return find( arg1 ) + find( arg2 ) + find( arg3 );
3040 }
3041
3042 Command find( const std::string& shortArg, const std::string& longArg ) const {
3043 return find( shortArg ) + find( longArg );
3044 }
3045 Command find( const std::string& arg ) const {
Phil Nashecf934b2012-08-27 21:42:55 +01003046 if( arg.empty() )
3047 return getArgs( "", 1 );
3048 else
3049 for( std::size_t i = 1; i < m_argc; ++i )
3050 if( m_argv[i] == arg )
3051 return getArgs( m_argv[i], i+1 );
Phil Nasha695eb92012-08-13 07:46:10 +01003052 return Command();
3053 }
Phil Nashe571e6f2012-08-24 18:54:56 +01003054 Command getDefaultArgs() const {
3055 return getArgs( "", 1 );
3056 }
Phil Nasha695eb92012-08-13 07:46:10 +01003057
3058 private:
Phil Nashe571e6f2012-08-24 18:54:56 +01003059 Command getArgs( const std::string& cmdName, std::size_t from ) const {
3060 Command command( cmdName );
3061 for( std::size_t i = from; i < m_argc && m_argv[i][0] != '-'; ++i )
Phil Nasha695eb92012-08-13 07:46:10 +01003062 command += m_argv[i];
3063 return command;
3064 }
3065
3066 std::size_t m_argc;
3067 char const * const * m_argv;
3068 };
3069
Phil Nashecf934b2012-08-27 21:42:55 +01003070 class OptionParser : public SharedImpl<IShared> {
3071 public:
3072 OptionParser( int minArgs = 0, int maxArgs = 0 )
3073 : m_minArgs( minArgs ), m_maxArgs( maxArgs )
3074 {}
Phil Nasha695eb92012-08-13 07:46:10 +01003075
Phil Nashecf934b2012-08-27 21:42:55 +01003076 virtual ~OptionParser() {}
Phil Nasha695eb92012-08-13 07:46:10 +01003077
Phil Nashecf934b2012-08-27 21:42:55 +01003078 Command find( const CommandParser& parser ) const {
3079 Command cmd;
3080 for( std::vector<std::string>::const_iterator it = m_optionNames.begin();
3081 it != m_optionNames.end();
3082 ++it )
3083 cmd += parser.find( *it );
3084 return cmd;
3085 }
3086
3087 void validateArgs( const Command& args ) const {
3088 if( tooFewArgs( args ) || tooManyArgs( args ) ) {
3089 std::ostringstream oss;
3090 if( m_maxArgs == -1 )
3091 oss <<"Expected at least " << pluralise( static_cast<std::size_t>( m_minArgs ), "argument" );
3092 else if( m_minArgs == m_maxArgs )
3093 oss <<"Expected " << pluralise( static_cast<std::size_t>( m_minArgs ), "argument" );
Phil Nasha695eb92012-08-13 07:46:10 +01003094 else
Phil Nashecf934b2012-08-27 21:42:55 +01003095 oss <<"Expected between " << m_minArgs << " and " << m_maxArgs << " argument";
3096 args.raiseError( oss.str() );
Phil Nasha695eb92012-08-13 07:46:10 +01003097 }
Phil Nashecf934b2012-08-27 21:42:55 +01003098 }
3099
3100 void parseIntoConfig( const CommandParser& parser, ConfigData& config ) {
3101 if( Command cmd = find( parser ) ) {
3102 validateArgs( cmd );
3103 parseIntoConfig( cmd, config );
3104 }
3105 }
3106
3107 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) = 0;
3108 virtual std::string argsSynopsis() const = 0;
3109 virtual std::string optionSummary() const = 0;
Phil Nashe2d215e2012-09-07 17:52:35 +01003110 virtual std::string optionDescription() const { return ""; };
Phil Nashecf934b2012-08-27 21:42:55 +01003111
3112 std::string optionNames() const {
3113 std::string names;
3114 for( std::vector<std::string>::const_iterator it = m_optionNames.begin();
3115 it != m_optionNames.end();
3116 ++it ) {
3117 if( !it->empty() ) {
3118 if( !names.empty() )
3119 names += ", ";
3120 names += *it;
3121 }
3122 else {
3123 names = "[" + names;
3124 }
3125 }
3126 if( names[0] == '[' )
3127 names += "]";
3128 return names;
3129 }
3130
3131 protected:
3132
3133 bool tooFewArgs( const Command& args ) const {
3134 return args.argsCount() < static_cast<std::size_t>( m_minArgs );
3135 }
3136 bool tooManyArgs( const Command& args ) const {
3137 return m_maxArgs >= 0 && args.argsCount() > static_cast<std::size_t>( m_maxArgs );
3138 }
3139 std::vector<std::string> m_optionNames;
3140 int m_minArgs;
3141 int m_maxArgs;
3142 };
3143
3144 namespace Options {
3145
3146 class HelpOptionParser : public OptionParser {
3147 public:
3148 HelpOptionParser() {
3149 m_optionNames.push_back( "-?" );
3150 m_optionNames.push_back( "-h" );
3151 m_optionNames.push_back( "--help" );
3152 }
3153 virtual std::string argsSynopsis() const {
Phil Nash67ec8702012-09-26 18:38:26 +01003154 return "[<option for help on> ...]";
Phil Nashecf934b2012-08-27 21:42:55 +01003155 }
3156 virtual std::string optionSummary() const {
Phil Nash67ec8702012-09-26 18:38:26 +01003157 return "Shows this usage summary, or help on a specific option, or options, if supplied";
Phil Nashe2d215e2012-09-07 17:52:35 +01003158 }
3159 virtual std::string optionDescription() const {
3160 return "";
Phil Nashecf934b2012-08-27 21:42:55 +01003161 }
3162
3163 virtual void parseIntoConfig( const Command&, ConfigData& ) {
3164 // Does not affect config
3165 }
3166 };
3167
3168 class TestCaseOptionParser : public OptionParser {
3169 public:
3170 TestCaseOptionParser() : OptionParser( 1, -1 ) {
3171 m_optionNames.push_back( "-t" );
3172 m_optionNames.push_back( "--test" );
3173 m_optionNames.push_back( "" ); // default option
3174 }
3175 virtual std::string argsSynopsis() const {
3176 return "<testspec> [<testspec>...]";
3177 }
3178 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003179 return "Specifies which test case or cases to run";
3180 }
3181
3182 // Lines are split at the nearest prior space char to the 80 char column.
3183 // Tab chars are removed from the output but their positions are used to align
3184 // subsequently wrapped lines
3185 virtual std::string optionDescription() const {
Phil Nashf7418eb2012-09-09 11:44:30 +01003186 return
3187 "This option allows one ore more test specs to be supplied. Each spec either fully "
3188 "specifies a test case or is a pattern containing wildcards to match a set of test "
3189 "cases. If this option is not provided then all test cases, except those prefixed "
3190 "by './' are run\n"
3191 "\n"
3192 "Specs must be enclosed in \"quotes\" if they contain spaces. If they do not "
3193 "contain spaces the quotes are optional.\n"
3194 "\n"
3195 "Wildcards consist of the * character at the beginning, end, or both and can substitute for "
3196 "any number of any characters (including none)\n"
3197 "\n"
3198 "If spec is prefixed with exclude: or the ~ character then the pattern matches an exclusion. "
3199 "This means that tests matching the pattern are excluded from the set - even if a prior "
Phil Nash799ecf92012-09-24 08:30:13 +01003200 "inclusion spec included them. Subsequent inclusion specs will take precedence, however. "
Phil Nashf7418eb2012-09-09 11:44:30 +01003201 "Inclusions and exclusions are evaluated in left-to-right order.\n"
3202 "\n"
3203 "Examples:\n"
3204 "\n"
3205 " -t thisTestOnly \tMatches the test case called, 'thisTestOnly'\n"
3206 " -t \"this test only\" \tMatches the test case called, 'this test only'\n"
3207 " -t these/* \tMatches all cases starting with 'these/'\n"
3208 " -t exclude:notThis \tMatches all tests except, 'notThis'\n"
3209 " -t ~notThis \tMatches all tests except, 'notThis'\n"
3210 " -t ~*private* \tMatches all tests except those that contain 'private'\n"
3211 " -t a/* ~a/b/* a/b/c \tMatches all tests that start with 'a/', except those "
3212 "that start with 'a/b/', except 'a/b/c', which is included";
Phil Nashecf934b2012-08-27 21:42:55 +01003213 }
3214
3215 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3216 std::string groupName;
3217 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
3218 if( i != 0 )
3219 groupName += " ";
3220 groupName += cmd[i];
3221 }
3222 TestCaseFilters filters( groupName );
Phil Nashe2d215e2012-09-07 17:52:35 +01003223 for( std::size_t i = 0; i < cmd.argsCount(); ++i )
3224 filters.addFilter( TestCaseFilter( cmd[i] ) );
Phil Nashecf934b2012-08-27 21:42:55 +01003225 config.filters.push_back( filters );
3226 }
3227 };
3228
Phil Nash799ecf92012-09-24 08:30:13 +01003229 class TagOptionParser : public OptionParser {
3230 public:
3231 TagOptionParser() : OptionParser( 1, -1 ) {
3232 m_optionNames.push_back( "-g" );
3233 m_optionNames.push_back( "--tag" );
3234 }
3235 virtual std::string argsSynopsis() const {
3236 return "<tagspec> [,<tagspec>...]";
3237 }
3238 virtual std::string optionSummary() const {
3239 return "Matches test cases against tags or tag patterns";
3240 }
3241
3242 // Lines are split at the nearest prior space char to the 80 char column.
3243 // Tab chars are removed from the output but their positions are used to align
3244 // subsequently wrapped lines
3245 virtual std::string optionDescription() const {
3246 return
Phil Nasha1dc7e32012-11-06 19:34:35 +00003247 "This option allows one or more tags or tag patterns to be specified.\n"
3248 "Each tag is enclosed in square brackets. A series of tags form an AND expression "
3249 "wheras a comma seperated sequence forms an OR expression. e.g.:\n\n"
3250 " -g [one][two],[three]\n\n"
3251 "This matches all tests tagged [one] and [two], as well as all tests tagged [three].\n\n"
3252 "Tags can be negated with the ~ character. This removes matching tests from the set. e.g.:\n\n"
3253 " -g [one]~[two]\n\n"
3254 "matches all tests tagged [one], except those also tagged [two]";
Phil Nash799ecf92012-09-24 08:30:13 +01003255 }
3256
3257 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
Phil Nash67ec8702012-09-26 18:38:26 +01003258 std::string groupName;
3259 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
3260 if( i != 0 )
3261 groupName += " ";
3262 groupName += cmd[i];
3263 }
3264 TestCaseFilters filters( groupName );
3265 for( std::size_t i = 0; i < cmd.argsCount(); ++i )
3266 filters.addTags( cmd[i] );
3267 config.filters.push_back( filters );
Phil Nash799ecf92012-09-24 08:30:13 +01003268 }
3269 };
3270
Phil Nashecf934b2012-08-27 21:42:55 +01003271 class ListOptionParser : public OptionParser {
3272 public:
3273 ListOptionParser() : OptionParser( 0, 2 ) {
3274 m_optionNames.push_back( "-l" );
3275 m_optionNames.push_back( "--list" );
3276 }
3277 virtual std::string argsSynopsis() const {
3278 return "[all | tests | reporters [xml]]";
3279 }
3280 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003281 return "Lists available tests or reporters";
3282 }
3283
3284 virtual std::string optionDescription() const {
Phil Nashf7418eb2012-09-09 11:44:30 +01003285 return
3286 "With no arguments this option will list all registered tests - one per line.\n"
3287 "Supplying the xml argument formats the list as an xml document (which may be useful for "
3288 "consumption by other tools).\n"
3289 "Supplying the tests or reporters lists tests or reporters respectively - with descriptions.\n"
3290 "\n"
3291 "Examples:\n"
3292 "\n"
3293 " -l\n"
3294 " -l tests\n"
3295 " -l reporters xml\n"
3296 " -l xml";
Phil Nashecf934b2012-08-27 21:42:55 +01003297 }
3298
3299 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3300 config.listSpec = List::TestNames;
3301 if( cmd.argsCount() >= 1 ) {
3302 if( cmd[0] == "all" )
3303 config.listSpec = List::All;
3304 else if( cmd[0] == "tests" )
3305 config.listSpec = List::Tests;
3306 else if( cmd[0] == "reporters" )
3307 config.listSpec = List::Reports;
3308 else
3309 cmd.raiseError( "Expected [tests] or [reporters]" );
3310 }
3311 if( cmd.argsCount() >= 2 ) {
3312 if( cmd[1] == "xml" )
3313 config.listSpec = static_cast<List::What>( config.listSpec | List::AsXml );
3314 else if( cmd[1] == "text" )
3315 config.listSpec = static_cast<List::What>( config.listSpec | List::AsText );
3316 else
3317 cmd.raiseError( "Expected [xml] or [text]" );
3318 }
3319 }
3320 };
3321
3322 class ReporterOptionParser : public OptionParser {
3323 public:
3324 ReporterOptionParser() : OptionParser( 1, 1 ) {
3325 m_optionNames.push_back( "-r" );
3326 m_optionNames.push_back( "--reporter" );
3327 }
3328 virtual std::string argsSynopsis() const {
3329 return "<reporter name>";
3330 }
3331 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003332 return "Specifies type of reporter";
3333 }
3334
3335 virtual std::string optionDescription() const {
Phil Nashf7418eb2012-09-09 11:44:30 +01003336 return
3337 "A reporter is an object that formats and structures the output of running "
3338 "tests, and potentially summarises the results. By default a basic reporter "
3339 "is used that writes IDE friendly results. CATCH comes bundled with some "
3340 "alternative reporters, but more can be added in client code.\n"
3341 "\n"
3342 "The bundled reporters are:\n"
3343 " -r basic\n"
3344 " -r xml\n"
3345 " -r junit\n"
3346 "\n"
3347 "The JUnit reporter is an xml format that follows the structure of the JUnit "
3348 "XML Report ANT task, as consumed by a number of third-party tools, "
3349 "including Continuous Integration servers such as Jenkins.\n"
3350 "If not otherwise needed, the standard XML reporter is preferred as this is "
3351 "a streaming reporter, whereas the Junit reporter needs to hold all its "
3352 "results until the end so it can write the overall results into attributes "
3353 "of the root node.";
Phil Nashecf934b2012-08-27 21:42:55 +01003354 }
3355
3356 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3357 config.reporter = cmd[0];
3358 }
3359 };
3360
3361 class OutputOptionParser : public OptionParser {
3362 public:
3363 OutputOptionParser() : OptionParser( 1, 1 ) {
3364 m_optionNames.push_back( "-o" );
3365 m_optionNames.push_back( "--out" );
3366 }
3367 virtual std::string argsSynopsis() const {
3368 return "<file name>|<%stream name>";
3369 }
3370 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003371 return "Sends output to a file or stream";
Phil Nashecf934b2012-08-27 21:42:55 +01003372 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003373 virtual std::string optionDescription() const {
3374 return
3375 "Use this option to send all output to a file or a stream. By default output is "
Phil Nash799ecf92012-09-24 08:30:13 +01003376 "sent to stdout (note that uses of stdout and stderr from within test cases are "
Phil Nashf7418eb2012-09-09 11:44:30 +01003377 "redirected and included in the report - so even stderr will effectively end up "
Phil Nash799ecf92012-09-24 08:30:13 +01003378 "on stdout). If the name begins with % it is interpreted as a stream. "
Phil Nashf7418eb2012-09-09 11:44:30 +01003379 "Otherwise it is treated as a filename.\n"
3380 "\n"
3381 "Examples are:\n"
3382 "\n"
3383 " -o filename.txt\n"
3384 " -o \"long filename.txt\"\n"
3385 " -o %stdout\n"
3386 " -o %stderr\n"
3387 " -o %debug \t(The IDE's debug output window - currently only Windows' "
3388 "OutputDebugString is supported).";
3389 }
Phil Nashecf934b2012-08-27 21:42:55 +01003390 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3391 if( cmd[0][0] == '%' )
3392 config.stream = cmd[0].substr( 1 );
Phil Nasha695eb92012-08-13 07:46:10 +01003393 else
Phil Nashecf934b2012-08-27 21:42:55 +01003394 config.outputFilename = cmd[0];
Phil Nasha695eb92012-08-13 07:46:10 +01003395 }
Phil Nashecf934b2012-08-27 21:42:55 +01003396 };
Phil Nasha695eb92012-08-13 07:46:10 +01003397
Phil Nashf7418eb2012-09-09 11:44:30 +01003398 class SuccessOptionParser : public OptionParser {
Phil Nashecf934b2012-08-27 21:42:55 +01003399 public:
Phil Nashf7418eb2012-09-09 11:44:30 +01003400 SuccessOptionParser() {
Phil Nashecf934b2012-08-27 21:42:55 +01003401 m_optionNames.push_back( "-s" );
3402 m_optionNames.push_back( "--success" );
Phil Nash56d5c422012-08-23 20:08:50 +01003403 }
Phil Nashecf934b2012-08-27 21:42:55 +01003404 virtual std::string argsSynopsis() const {
3405 return "";
Phil Nash56d5c422012-08-23 20:08:50 +01003406 }
Phil Nashecf934b2012-08-27 21:42:55 +01003407 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003408 return "Shows results for successful tests";
Phil Nasha695eb92012-08-13 07:46:10 +01003409 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003410 virtual std::string optionDescription() const {
3411 return
3412 "Usually you only want to see reporting for failed tests. Sometimes it's useful "
3413 "to see all the output (especially when you don't trust that that test you just "
Phil Nash799ecf92012-09-24 08:30:13 +01003414 "added worked first time!). To see successful, as well as failing, test results "
Phil Nashf7418eb2012-09-09 11:44:30 +01003415 "just pass this option.";
3416 }
Phil Nash78c92e62012-08-27 21:48:15 +01003417 virtual void parseIntoConfig( const Command&, ConfigData& config ) {
Phil Nashecf934b2012-08-27 21:42:55 +01003418 config.includeWhichResults = Include::SuccessfulResults;
3419 }
3420 };
Phil Nasha695eb92012-08-13 07:46:10 +01003421
Phil Nashecf934b2012-08-27 21:42:55 +01003422 class DebugBreakOptionParser : public OptionParser {
3423 public:
3424 DebugBreakOptionParser() {
3425 m_optionNames.push_back( "-b" );
3426 m_optionNames.push_back( "--break" );
3427 }
3428 virtual std::string argsSynopsis() const {
3429 return "";
3430 }
3431 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003432 return "Breaks into the debugger on failure";
Phil Nashecf934b2012-08-27 21:42:55 +01003433 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003434 virtual std::string optionDescription() const {
3435 return
3436 "In some IDEs (currently XCode and Visual Studio) it is possible for CATCH to "
3437 "break into the debugger on a test failure. This can be very helpful during "
3438 "debug sessions - especially when there is more than one path through a "
3439 "particular test. In addition to the command line option, ensure you have "
3440 "built your code with the DEBUG preprocessor symbol";
3441 }
Phil Nashecf934b2012-08-27 21:42:55 +01003442
Phil Nash78c92e62012-08-27 21:48:15 +01003443 virtual void parseIntoConfig( const Command&, ConfigData& config ) {
Phil Nashecf934b2012-08-27 21:42:55 +01003444 config.shouldDebugBreak = true;
3445 }
3446 };
3447
3448 class NameOptionParser : public OptionParser {
3449 public:
3450 NameOptionParser() : OptionParser( 1, 1 ) {
3451 m_optionNames.push_back( "-n" );
3452 m_optionNames.push_back( "--name" );
3453 }
3454 virtual std::string argsSynopsis() const {
3455 return "<name>";
3456 }
3457 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003458 return "Names a test run";
Phil Nashecf934b2012-08-27 21:42:55 +01003459 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003460 virtual std::string optionDescription() const {
3461 return
3462 "If a name is supplied it will be used by the reporter to provide an overall "
3463 "name for the test run. This can be useful if you are sending to a file, for "
3464 "example, and need to distinguish different test runs - either from different "
3465 "Catch executables or runs of the same executable with different options.\n"
3466 "\n"
3467 "Examples:\n"
3468 "\n"
3469 " -n testRun\n"
3470 " -n \"tests of the widget component\"";
3471 }
Phil Nashecf934b2012-08-27 21:42:55 +01003472
3473 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3474 config.name = cmd[0];
3475 }
3476 };
3477
3478 class AbortOptionParser : public OptionParser {
3479 public:
3480 AbortOptionParser() : OptionParser( 0, 1 ) {
3481 m_optionNames.push_back( "-a" );
3482 m_optionNames.push_back( "--abort" );
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 "Aborts after a certain number of failures";
Phil Nashecf934b2012-08-27 21:42:55 +01003489 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003490 virtual std::string optionDescription() const {
3491 return
3492 "If a REQUIRE assertion fails the test case aborts, but subsequent test cases "
3493 "are still run. If a CHECK assertion fails even the current test case is not "
3494 "aborted.\n"
3495 "\n"
3496 "Sometimes this results in a flood of failure messages and you'd rather just "
3497 "see the first few. Specifying -a or --abort on its own will abort the whole "
3498 "test run on the first failed assertion of any kind. Following it with a "
3499 "number causes it to abort after that number of assertion failures.";
3500 }
Phil Nashecf934b2012-08-27 21:42:55 +01003501
3502 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3503 int threshold = 1;
3504 if( cmd.argsCount() == 1 ) {
3505 std::stringstream ss;
3506 ss << cmd[0];
3507 ss >> threshold;
3508 if( ss.fail() || threshold <= 0 )
3509 cmd.raiseError( "threshold must be a number greater than zero" );
3510 }
3511 config.cutoff = threshold;
3512 }
3513 };
3514
3515 class NoThrowOptionParser : public OptionParser {
3516 public:
3517 NoThrowOptionParser() {
3518 m_optionNames.push_back( "-nt" );
3519 m_optionNames.push_back( "--nothrow" );
3520 }
3521 virtual std::string argsSynopsis() const {
3522 return "";
3523 }
3524 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003525 return "Elides assertions expected to throw";
Phil Nashecf934b2012-08-27 21:42:55 +01003526 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003527 virtual std::string optionDescription() const {
3528 return
3529 "Skips all assertions that test that an exception is thrown, "
3530 "e.g. REQUIRE_THROWS.\n"
3531 "\n"
3532 "These can be a nuisance in certain debugging environments that may break when "
3533 "exceptions are thrown (while this is usually optional for handled exceptions, "
3534 "it can be useful to have enabled if you are trying to track down something "
3535 "unexpected).\n"
3536 "\n"
3537 "When running with this option the throw checking assertions are skipped so "
3538 "as not to contribute additional noise.";
3539 }
Phil Nashecf934b2012-08-27 21:42:55 +01003540
Phil Nash78c92e62012-08-27 21:48:15 +01003541 virtual void parseIntoConfig( const Command&, ConfigData& config ) {
Phil Nashecf934b2012-08-27 21:42:55 +01003542 config.allowThrows = false;
3543 }
3544 };
Phil Nasha70fbe32012-08-31 08:10:36 +01003545
3546 class WarningsOptionParser : public OptionParser {
3547 public:
3548 WarningsOptionParser() : OptionParser( 1, -1 ) {
3549 m_optionNames.push_back( "-w" );
3550 m_optionNames.push_back( "--warnings" );
3551 }
3552 virtual std::string argsSynopsis() const {
3553 return "<warning>";
3554 }
3555 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003556 return "Enable warnings";
Phil Nasha70fbe32012-08-31 08:10:36 +01003557 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003558 virtual std::string optionDescription() const {
3559 return
3560 "Enables the named warnings. If the warnings are violated the test case is "
3561 "failed.\n"
3562 "\n"
3563 "At present only one warning has been provided: NoAssertions. If this warning "
3564 "is enabled then any test case that completes without an assertions (CHECK, "
3565 "REQUIRE etc) being encountered violates the warning.\n"
3566 "\n"
3567 "e.g.:\n"
3568 "\n"
3569 " -w NoAssertions";
3570 }
Phil Nasha70fbe32012-08-31 08:10:36 +01003571
3572 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3573 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
3574 if( cmd[i] == "NoAssertions" )
3575 config.warnings = (ConfigData::WarnAbout::What)( config.warnings | ConfigData::WarnAbout::NoAssertions );
3576 else
3577 cmd.raiseError( "Unrecognised warning: " + cmd[i] );
3578 }
3579 }
3580 };
Phil Nasha695eb92012-08-13 07:46:10 +01003581 }
3582
Phil Nashecf934b2012-08-27 21:42:55 +01003583 class AllOptions
3584 {
3585 public:
3586 typedef std::vector<Ptr<OptionParser> > Parsers;
3587 typedef Parsers::const_iterator const_iterator;
3588 typedef Parsers::const_iterator iterator;
3589
3590 AllOptions() {
Phil Nasha70fbe32012-08-31 08:10:36 +01003591 add<Options::TestCaseOptionParser>(); // Keep this one first
3592
Phil Nash67ec8702012-09-26 18:38:26 +01003593 add<Options::TagOptionParser>();
Phil Nashecf934b2012-08-27 21:42:55 +01003594 add<Options::ListOptionParser>();
3595 add<Options::ReporterOptionParser>();
3596 add<Options::OutputOptionParser>();
Phil Nashf7418eb2012-09-09 11:44:30 +01003597 add<Options::SuccessOptionParser>();
Phil Nashecf934b2012-08-27 21:42:55 +01003598 add<Options::DebugBreakOptionParser>();
3599 add<Options::NameOptionParser>();
3600 add<Options::AbortOptionParser>();
3601 add<Options::NoThrowOptionParser>();
Phil Nasha70fbe32012-08-31 08:10:36 +01003602 add<Options::WarningsOptionParser>();
3603
3604 add<Options::HelpOptionParser>(); // Keep this one last
Phil Nashecf934b2012-08-27 21:42:55 +01003605 }
3606
3607 void parseIntoConfig( const CommandParser& parser, ConfigData& config ) {
Phil Nasha90a88a2012-11-19 19:59:10 +00003608 config.name = parser.exeName();
3609 if( endsWith( config.name, ".exe" ) )
3610 config.name = config.name.substr( 0, config.name.size()-4 );
Phil Nashecf934b2012-08-27 21:42:55 +01003611 for( const_iterator it = m_parsers.begin(); it != m_parsers.end(); ++it )
3612 (*it)->parseIntoConfig( parser, config );
3613 }
3614
3615 const_iterator begin() const {
3616 return m_parsers.begin();
3617 }
3618 const_iterator end() const {
3619 return m_parsers.end();
3620 }
3621 private:
3622
3623 template<typename T>
3624 void add() {
3625 m_parsers.push_back( new T() );
3626 }
3627 Parsers m_parsers;
3628
3629 };
3630
Phil Nasha695eb92012-08-13 07:46:10 +01003631} // end namespace Catch
3632
3633// #included from: internal/catch_list.hpp
3634#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
3635
3636#include <limits>
3637
3638namespace Catch {
Phil Nash56d5c422012-08-23 20:08:50 +01003639 inline bool matchesFilters( const std::vector<TestCaseFilters>& filters, const TestCaseInfo& testCase ) {
3640 std::vector<TestCaseFilters>::const_iterator it = filters.begin();
3641 std::vector<TestCaseFilters>::const_iterator itEnd = filters.end();
3642 for(; it != itEnd; ++it )
3643 if( !it->shouldInclude( testCase ) )
3644 return false;
3645 return true;
3646 }
3647 inline void List( const ConfigData& config ) {
Phil Nasha695eb92012-08-13 07:46:10 +01003648
Phil Nash5bc030d2012-08-16 18:48:50 +01003649 if( config.listSpec & List::Reports ) {
Phil Nasha695eb92012-08-13 07:46:10 +01003650 std::cout << "Available reports:\n";
3651 IReporterRegistry::FactoryMap::const_iterator it = getRegistryHub().getReporterRegistry().getFactories().begin();
3652 IReporterRegistry::FactoryMap::const_iterator itEnd = getRegistryHub().getReporterRegistry().getFactories().end();
3653 for(; it != itEnd; ++it ) {
3654 // !TBD: consider listAs()
3655 std::cout << "\t" << it->first << "\n\t\t'" << it->second->getDescription() << "'\n";
3656 }
3657 std::cout << std::endl;
3658 }
3659
Phil Nash5bc030d2012-08-16 18:48:50 +01003660 if( config.listSpec & List::Tests ) {
Phil Nash56d5c422012-08-23 20:08:50 +01003661 if( config.filters.empty() )
Phil Nash4c97fc52012-08-24 08:23:50 +01003662 std::cout << "All available test cases:\n";
Phil Nash56d5c422012-08-23 20:08:50 +01003663 else
Phil Nash4c97fc52012-08-24 08:23:50 +01003664 std::cout << "Matching test cases:\n";
Phil Nasha695eb92012-08-13 07:46:10 +01003665 std::vector<TestCaseInfo>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin();
3666 std::vector<TestCaseInfo>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end();
Phil Nash4c97fc52012-08-24 08:23:50 +01003667 std::size_t matchedTests = 0;
Phil Nasha695eb92012-08-13 07:46:10 +01003668 for(; it != itEnd; ++it ) {
Phil Nash56d5c422012-08-23 20:08:50 +01003669 if( matchesFilters( config.filters, *it ) ) {
Phil Nash4c97fc52012-08-24 08:23:50 +01003670 matchedTests++;
Phil Nash56d5c422012-08-23 20:08:50 +01003671 // !TBD: consider listAs()
3672 std::cout << "\t" << it->getName() << "\n";
3673 if( ( config.listSpec & List::TestNames ) != List::TestNames )
3674 std::cout << "\t\t '" << it->getDescription() << "'\n";
3675 }
Phil Nasha695eb92012-08-13 07:46:10 +01003676 }
Phil Nash4c97fc52012-08-24 08:23:50 +01003677 if( config.filters.empty() )
3678 std::cout << pluralise( matchedTests, "test case" ) << std::endl;
3679 else
3680 std::cout << pluralise( matchedTests, "matching test case" ) << std::endl;
Phil Nasha695eb92012-08-13 07:46:10 +01003681 }
3682
Phil Nash5bc030d2012-08-16 18:48:50 +01003683 if( ( config.listSpec & List::All ) == 0 ) {
Phil Nash56d5c422012-08-23 20:08:50 +01003684 std::ostringstream oss;
3685 oss << "Unknown list type";
3686 throw std::domain_error( oss.str() );
Phil Nasha695eb92012-08-13 07:46:10 +01003687 }
Phil Nasha695eb92012-08-13 07:46:10 +01003688 }
3689
3690} // end namespace Catch
3691
3692// #included from: internal/catch_runner_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04003693#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003694
3695// #included from: catch_running_test.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04003696#define TWOBLUECUBES_CATCH_RUNNING_TEST_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003697
3698// #included from: catch_section_info.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04003699#define TWOBLUECUBES_CATCH_SECTION_INFO_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003700
3701#include <map>
3702#include <string>
3703
3704namespace Catch {
3705
3706 class SectionInfo {
3707 public:
3708
3709 enum Status {
3710 Root,
3711 Unknown,
3712 Branch,
3713 TestedBranch,
3714 TestedLeaf
3715 };
3716
3717 SectionInfo( SectionInfo* parent )
3718 : m_status( Unknown ),
3719 m_parent( parent )
3720 {}
3721
3722 SectionInfo()
3723 : m_status( Root ),
3724 m_parent( NULL )
3725 {}
3726
3727 ~SectionInfo() {
3728 deleteAllValues( m_subSections );
3729 }
3730
3731 bool shouldRun() const {
3732 return m_status < TestedBranch;
3733 }
3734
3735 bool ran() {
3736 if( m_status < Branch ) {
3737 m_status = TestedLeaf;
3738 return true;
3739 }
3740 return false;
3741 }
3742
Phil Nasha70fbe32012-08-31 08:10:36 +01003743 bool isBranch() const {
3744 return m_status == Branch;
3745 }
3746
Phil Nasha695eb92012-08-13 07:46:10 +01003747 void ranToCompletion() {
3748 if( m_status == Branch && !hasUntestedSections() )
3749 m_status = TestedBranch;
3750 }
3751
3752 SectionInfo* findSubSection( const std::string& name ) {
3753 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.find( name );
3754 return it != m_subSections.end()
3755 ? it->second
3756 : NULL;
3757 }
3758
3759 SectionInfo* addSubSection( const std::string& name ) {
3760 SectionInfo* subSection = new SectionInfo( this );
3761 m_subSections.insert( std::make_pair( name, subSection ) );
3762 m_status = Branch;
3763 return subSection;
3764 }
3765
3766 SectionInfo* getParent() {
3767 return m_parent;
3768 }
3769
3770 bool hasUntestedSections() const {
3771 if( m_status == Unknown )
3772 return true;
3773
3774 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.begin();
3775 std::map<std::string, SectionInfo*>::const_iterator itEnd = m_subSections.end();
3776 for(; it != itEnd; ++it ) {
3777 if( it->second->hasUntestedSections() )
3778 return true;
3779 }
3780 return false;
3781 }
3782
3783 private:
3784 Status m_status;
3785 std::map<std::string, SectionInfo*> m_subSections;
3786 SectionInfo* m_parent;
3787 };
3788}
3789
3790namespace Catch {
3791
3792 class RunningTest {
3793
3794 enum RunStatus {
3795 NothingRun,
3796 EncounteredASection,
3797 RanAtLeastOneSection,
3798 RanToCompletionWithSections,
3799 RanToCompletionWithNoSections
3800 };
3801
3802 public:
3803 explicit RunningTest( const TestCaseInfo* info = NULL )
3804 : m_info( info ),
3805 m_runStatus( RanAtLeastOneSection ),
3806 m_currentSection( &m_rootSection ),
3807 m_changed( false )
3808 {}
3809
3810 bool wasSectionSeen() const {
3811 return m_runStatus == RanAtLeastOneSection ||
3812 m_runStatus == RanToCompletionWithSections;
3813 }
3814
Phil Nasha70fbe32012-08-31 08:10:36 +01003815 bool isBranchSection() const {
3816 return m_currentSection &&
3817 m_currentSection->isBranch();
3818 }
3819
3820 bool hasSections() const {
3821 return m_runStatus == RanAtLeastOneSection ||
3822 m_runStatus == RanToCompletionWithSections ||
3823 m_runStatus == EncounteredASection;
3824 }
3825
Phil Nasha695eb92012-08-13 07:46:10 +01003826 void reset() {
3827 m_runStatus = NothingRun;
3828 m_changed = false;
3829 m_lastSectionToRun = NULL;
3830 }
3831
3832 void ranToCompletion() {
3833 if( m_runStatus == RanAtLeastOneSection ||
3834 m_runStatus == EncounteredASection ) {
3835 m_runStatus = RanToCompletionWithSections;
3836 if( m_lastSectionToRun ) {
3837 m_lastSectionToRun->ranToCompletion();
3838 m_changed = true;
3839 }
3840 }
3841 else {
3842 m_runStatus = RanToCompletionWithNoSections;
3843 }
3844 }
3845
3846 bool addSection( const std::string& name ) {
3847 if( m_runStatus == NothingRun )
3848 m_runStatus = EncounteredASection;
3849
3850 SectionInfo* thisSection = m_currentSection->findSubSection( name );
3851 if( !thisSection ) {
3852 thisSection = m_currentSection->addSubSection( name );
3853 m_changed = true;
3854 }
3855
3856 if( !wasSectionSeen() && thisSection->shouldRun() ) {
3857 m_currentSection = thisSection;
3858 m_lastSectionToRun = NULL;
3859 return true;
3860 }
3861 return false;
3862 }
3863
3864 void endSection( const std::string& ) {
3865 if( m_currentSection->ran() ) {
3866 m_runStatus = RanAtLeastOneSection;
3867 m_changed = true;
3868 }
3869 else if( m_runStatus == EncounteredASection ) {
3870 m_runStatus = RanAtLeastOneSection;
3871 m_lastSectionToRun = m_currentSection;
3872 }
3873 m_currentSection = m_currentSection->getParent();
3874 }
3875
3876 const TestCaseInfo& getTestCaseInfo() const {
3877 return *m_info;
3878 }
3879
3880 bool hasUntestedSections() const {
3881 return m_runStatus == RanAtLeastOneSection ||
3882 ( m_rootSection.hasUntestedSections() && m_changed );
3883 }
3884
3885 private:
3886 const TestCaseInfo* m_info;
3887 RunStatus m_runStatus;
3888 SectionInfo m_rootSection;
3889 SectionInfo* m_currentSection;
3890 SectionInfo* m_lastSectionToRun;
3891 bool m_changed;
3892 };
3893}
3894
3895#include <set>
3896#include <string>
3897
3898namespace Catch {
3899
3900 class StreamRedirect {
3901
3902 public:
3903 StreamRedirect( std::ostream& stream, std::string& targetString )
3904 : m_stream( stream ),
3905 m_prevBuf( stream.rdbuf() ),
3906 m_targetString( targetString )
3907 {
3908 stream.rdbuf( m_oss.rdbuf() );
3909 }
3910
3911 ~StreamRedirect() {
3912 m_targetString += m_oss.str();
3913 m_stream.rdbuf( m_prevBuf );
3914 }
3915
3916 private:
3917 std::ostream& m_stream;
3918 std::streambuf* m_prevBuf;
3919 std::ostringstream m_oss;
3920 std::string& m_targetString;
3921 };
3922
3923 ///////////////////////////////////////////////////////////////////////////
3924
3925 class Runner : public IResultCapture, public IRunner {
3926
3927 Runner( const Runner& );
3928 void operator =( const Runner& );
3929
3930 public:
3931
Phil Nash56d5c422012-08-23 20:08:50 +01003932 explicit Runner( const Config& config, const Ptr<IReporter>& reporter )
Phil Nasha695eb92012-08-13 07:46:10 +01003933 : m_context( getCurrentMutableContext() ),
3934 m_runningTest( NULL ),
3935 m_config( config ),
3936 m_reporter( reporter ),
3937 m_prevRunner( &m_context.getRunner() ),
3938 m_prevResultCapture( &m_context.getResultCapture() ),
3939 m_prevConfig( m_context.getConfig() )
3940 {
3941 m_context.setRunner( this );
3942 m_context.setConfig( &m_config );
3943 m_context.setResultCapture( this );
3944 m_reporter->StartTesting();
3945 }
3946
3947 virtual ~Runner() {
3948 m_reporter->EndTesting( m_totals );
3949 m_context.setRunner( m_prevRunner );
3950 m_context.setConfig( NULL );
3951 m_context.setResultCapture( m_prevResultCapture );
3952 m_context.setConfig( m_prevConfig );
3953 }
3954
Phil Nash56d5c422012-08-23 20:08:50 +01003955 Totals runMatching( const std::string& testSpec ) {
Phil Nasha695eb92012-08-13 07:46:10 +01003956
Phil Nash56d5c422012-08-23 20:08:50 +01003957 std::vector<TestCaseInfo> matchingTests = getRegistryHub().getTestCaseRegistry().getMatchingTestCases( testSpec );
Phil Nash5bc030d2012-08-16 18:48:50 +01003958
3959 Totals totals;
Phil Nash5bc030d2012-08-16 18:48:50 +01003960
Phil Nash56d5c422012-08-23 20:08:50 +01003961 m_reporter->StartGroup( testSpec );
3962
3963 std::vector<TestCaseInfo>::const_iterator it = matchingTests.begin();
3964 std::vector<TestCaseInfo>::const_iterator itEnd = matchingTests.end();
3965 for(; it != itEnd; ++it )
3966 totals += runTest( *it );
3967 // !TBD use std::accumulate?
3968
3969 m_reporter->EndGroup( testSpec, totals );
Phil Nash5bc030d2012-08-16 18:48:50 +01003970 return totals;
3971 }
3972
3973 Totals runTest( const TestCaseInfo& testInfo ) {
Phil Nasha695eb92012-08-13 07:46:10 +01003974 Totals prevTotals = m_totals;
3975
3976 std::string redirectedCout;
3977 std::string redirectedCerr;
3978
3979 m_reporter->StartTestCase( testInfo );
3980
3981 m_runningTest = new RunningTest( &testInfo );
3982
3983 do {
3984 do {
Phil Nasha695eb92012-08-13 07:46:10 +01003985 runCurrentTest( redirectedCout, redirectedCerr );
Phil Nasha695eb92012-08-13 07:46:10 +01003986 }
3987 while( m_runningTest->hasUntestedSections() && !aborting() );
3988 }
3989 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
3990
3991 delete m_runningTest;
3992 m_runningTest = NULL;
3993
3994 Totals deltaTotals = m_totals.delta( prevTotals );
3995 m_totals.testCases += deltaTotals.testCases;
3996 m_reporter->EndTestCase( testInfo, deltaTotals, redirectedCout, redirectedCerr );
Phil Nash5bc030d2012-08-16 18:48:50 +01003997 return deltaTotals;
Phil Nasha695eb92012-08-13 07:46:10 +01003998 }
3999
4000 const Config& config() const {
4001 return m_config;
4002 }
4003
4004 private: // IResultCapture
4005
Phil Nash5efa4bc2012-10-29 20:49:22 +00004006 virtual ResultAction::Value acceptExpression( const ExpressionResultBuilder& assertionResult, const AssertionInfo& assertionInfo ) {
Phil Nash88b70822012-11-04 21:39:38 +00004007 m_lastAssertionInfo = assertionInfo;
4008 return actOnCurrentResult( assertionResult.buildResult( assertionInfo ) );
Phil Nasha695eb92012-08-13 07:46:10 +01004009 }
4010
Phil Nash82acc2c2012-10-28 12:07:17 +00004011 virtual void testEnded( const AssertionResult& result ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004012 if( result.getResultType() == ResultWas::Ok ) {
4013 m_totals.assertions.passed++;
4014 }
Phil Nashd539da92012-11-13 09:44:52 +00004015 else if( !result.isOk() ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004016 m_totals.assertions.failed++;
4017
Phil Nash799ecf92012-09-24 08:30:13 +01004018 {
4019 std::vector<ScopedInfo*>::const_iterator it = m_scopedInfos.begin();
4020 std::vector<ScopedInfo*>::const_iterator itEnd = m_scopedInfos.end();
4021 for(; it != itEnd; ++it )
Phil Nash88b70822012-11-04 21:39:38 +00004022 m_reporter->Result( (*it)->buildResult( m_lastAssertionInfo ) );
Phil Nash799ecf92012-09-24 08:30:13 +01004023 }
4024 {
Phil Nash82acc2c2012-10-28 12:07:17 +00004025 std::vector<AssertionResult>::const_iterator it = m_assertionResults.begin();
4026 std::vector<AssertionResult>::const_iterator itEnd = m_assertionResults.end();
Phil Nash799ecf92012-09-24 08:30:13 +01004027 for(; it != itEnd; ++it )
4028 m_reporter->Result( *it );
4029 }
Phil Nash82acc2c2012-10-28 12:07:17 +00004030 m_assertionResults.clear();
Phil Nasha695eb92012-08-13 07:46:10 +01004031 }
4032
4033 if( result.getResultType() == ResultWas::Info )
Phil Nash82acc2c2012-10-28 12:07:17 +00004034 m_assertionResults.push_back( result );
Phil Nasha695eb92012-08-13 07:46:10 +01004035 else
4036 m_reporter->Result( result );
Phil Nasha90a88a2012-11-19 19:59:10 +00004037
4038 // Reset AssertionInfo
4039 m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after this line}" , m_lastAssertionInfo.resultDisposition );
Phil Nasha695eb92012-08-13 07:46:10 +01004040 }
4041
4042 virtual bool sectionStarted (
4043 const std::string& name,
4044 const std::string& description,
4045 const SourceLineInfo& lineInfo,
4046 Counts& assertions
4047 )
4048 {
4049 std::ostringstream oss;
4050 oss << name << "@" << lineInfo;
4051
4052 if( !m_runningTest->addSection( oss.str() ) )
4053 return false;
4054
Phil Nash88b70822012-11-04 21:39:38 +00004055 m_lastAssertionInfo.lineInfo = lineInfo;
4056
Phil Nasha695eb92012-08-13 07:46:10 +01004057 m_reporter->StartSection( name, description );
4058 assertions = m_totals.assertions;
4059
4060 return true;
4061 }
4062
4063 virtual void sectionEnded( const std::string& name, const Counts& prevAssertions ) {
Phil Nasha70fbe32012-08-31 08:10:36 +01004064 Counts assertions = m_totals.assertions - prevAssertions;
4065 if( assertions.total() == 0 &&
4066 ( m_config.data().warnings & ConfigData::WarnAbout::NoAssertions ) &&
4067 !m_runningTest->isBranchSection() ) {
4068 m_reporter->NoAssertionsInSection( name );
4069 m_totals.assertions.failed++;
4070 assertions.failed++;
4071 }
Phil Nasha695eb92012-08-13 07:46:10 +01004072 m_runningTest->endSection( name );
Phil Nasha70fbe32012-08-31 08:10:36 +01004073 m_reporter->EndSection( name, assertions );
Phil Nasha695eb92012-08-13 07:46:10 +01004074 }
4075
4076 virtual void pushScopedInfo( ScopedInfo* scopedInfo ) {
4077 m_scopedInfos.push_back( scopedInfo );
4078 }
4079
4080 virtual void popScopedInfo( ScopedInfo* scopedInfo ) {
4081 if( m_scopedInfos.back() == scopedInfo )
4082 m_scopedInfos.pop_back();
4083 }
4084
4085 virtual bool shouldDebugBreak() const {
4086 return m_config.shouldDebugBreak();
4087 }
4088
4089 virtual std::string getCurrentTestName() const {
4090 return m_runningTest
4091 ? m_runningTest->getTestCaseInfo().getName()
4092 : "";
4093 }
4094
Phil Nash82acc2c2012-10-28 12:07:17 +00004095 virtual const AssertionResult* getLastResult() const {
Phil Nasha695eb92012-08-13 07:46:10 +01004096 return &m_lastResult;
4097 }
4098
Phil Nash56d5c422012-08-23 20:08:50 +01004099 public:
4100 // !TBD We need to do this another way!
Phil Nasha695eb92012-08-13 07:46:10 +01004101 bool aborting() const {
4102 return m_totals.assertions.failed == static_cast<std::size_t>( m_config.getCutoff() );
4103 }
4104
Phil Nash56d5c422012-08-23 20:08:50 +01004105 private:
4106
Phil Nash88b70822012-11-04 21:39:38 +00004107 ResultAction::Value actOnCurrentResult( const AssertionResult& result ) {
4108 m_lastResult = result;
Phil Nash67305122012-10-09 11:48:55 +01004109 testEnded( m_lastResult );
Phil Nasha695eb92012-08-13 07:46:10 +01004110
Phil Nasha695eb92012-08-13 07:46:10 +01004111 ResultAction::Value action = ResultAction::None;
4112
Phil Nashd539da92012-11-13 09:44:52 +00004113 if( !m_lastResult.isOk() ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004114 action = ResultAction::Failed;
4115 if( shouldDebugBreak() )
4116 action = (ResultAction::Value)( action | ResultAction::Debug );
4117 if( aborting() )
4118 action = (ResultAction::Value)( action | ResultAction::Abort );
4119 }
4120 return action;
4121 }
4122
4123 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
4124 try {
Phil Nashd539da92012-11-13 09:44:52 +00004125 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", m_runningTest->getTestCaseInfo().getLineInfo(), "", ResultDisposition::Normal );
Phil Nasha695eb92012-08-13 07:46:10 +01004126 m_runningTest->reset();
Phil Nasha70fbe32012-08-31 08:10:36 +01004127 Counts prevAssertions = m_totals.assertions;
Phil Nasha695eb92012-08-13 07:46:10 +01004128 if( m_reporter->shouldRedirectStdout() ) {
4129 StreamRedirect coutRedir( std::cout, redirectedCout );
4130 StreamRedirect cerrRedir( std::cerr, redirectedCerr );
4131 m_runningTest->getTestCaseInfo().invoke();
4132 }
4133 else {
4134 m_runningTest->getTestCaseInfo().invoke();
4135 }
Phil Nasha70fbe32012-08-31 08:10:36 +01004136 Counts assertions = m_totals.assertions - prevAssertions;
4137 if( assertions.total() == 0 &&
4138 ( m_config.data().warnings & ConfigData::WarnAbout::NoAssertions ) &&
4139 !m_runningTest->hasSections() ) {
4140 m_totals.assertions.failed++;
4141 m_reporter->NoAssertionsInTestCase( m_runningTest->getTestCaseInfo().getName() );
4142 }
Phil Nasha695eb92012-08-13 07:46:10 +01004143 m_runningTest->ranToCompletion();
4144 }
4145 catch( TestFailureException& ) {
4146 // This just means the test was aborted due to failure
4147 }
4148 catch(...) {
Phil Nash88b70822012-11-04 21:39:38 +00004149 ExpressionResultBuilder exResult( ResultWas::ThrewException );
4150 exResult << translateActiveException();
4151 actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo ) );
Phil Nasha695eb92012-08-13 07:46:10 +01004152 }
Phil Nash82acc2c2012-10-28 12:07:17 +00004153 m_assertionResults.clear();
Phil Nasha695eb92012-08-13 07:46:10 +01004154 }
4155
4156 private:
4157 IMutableContext& m_context;
4158 RunningTest* m_runningTest;
Phil Nash82acc2c2012-10-28 12:07:17 +00004159 AssertionResult m_lastResult;
Phil Nasha695eb92012-08-13 07:46:10 +01004160
4161 const Config& m_config;
4162 Totals m_totals;
4163 Ptr<IReporter> m_reporter;
4164 std::vector<ScopedInfo*> m_scopedInfos;
Phil Nash82acc2c2012-10-28 12:07:17 +00004165 std::vector<AssertionResult> m_assertionResults;
Phil Nasha695eb92012-08-13 07:46:10 +01004166 IRunner* m_prevRunner;
4167 IResultCapture* m_prevResultCapture;
4168 const IConfig* m_prevConfig;
Phil Nash88b70822012-11-04 21:39:38 +00004169 AssertionInfo m_lastAssertionInfo;
Phil Nasha695eb92012-08-13 07:46:10 +01004170 };
4171
4172} // end namespace Catch
4173
Phil Nash7673a302012-11-15 22:15:41 +00004174// #included from: internal/catch_version.h
4175#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
4176
4177namespace Catch {
4178
4179 // Versioning information
4180 struct Version {
4181 const unsigned int MajorVersion;
4182 const unsigned int MinorVersion;
4183 const unsigned int BuildNumber;
4184 const std::string BranchName;
4185 };
4186
4187 extern Version libraryVersion;
4188}
4189
Phil Nash89d1e6c2011-05-24 08:23:02 +01004190#include <fstream>
4191#include <stdlib.h>
4192#include <limits>
4193
Phil Nash89d2a3f2012-05-16 15:09:17 +01004194namespace Catch {
4195
Phil Nash56d5c422012-08-23 20:08:50 +01004196 class Runner2 { // This will become Runner when Runner becomes Context
Phil Nash163088a2012-05-31 19:40:26 +01004197
Phil Nash56d5c422012-08-23 20:08:50 +01004198 public:
4199 Runner2( Config& configWrapper )
4200 : m_configWrapper( configWrapper ),
4201 m_config( configWrapper.data() )
Phil Nash06e959b2012-05-25 08:52:05 +01004202 {
Phil Nash67ec8702012-09-26 18:38:26 +01004203 openStream();
Phil Nash56d5c422012-08-23 20:08:50 +01004204 makeReporter();
4205 }
Phil Nash06e959b2012-05-25 08:52:05 +01004206
Phil Nash56d5c422012-08-23 20:08:50 +01004207 Totals runTests() {
4208
4209 std::vector<TestCaseFilters> filterGroups = m_config.filters;
4210 if( filterGroups.empty() ) {
4211 TestCaseFilters filterGroup( "" );
Phil Nash56d5c422012-08-23 20:08:50 +01004212 filterGroups.push_back( filterGroup );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004213 }
Phil Nash56d5c422012-08-23 20:08:50 +01004214
4215 Runner context( m_configWrapper, m_reporter ); // This Runner will be renamed Context
4216 Totals totals;
4217
4218 std::vector<TestCaseFilters>::const_iterator it = filterGroups.begin();
4219 std::vector<TestCaseFilters>::const_iterator itEnd = filterGroups.end();
Phil Nashe2d215e2012-09-07 17:52:35 +01004220 for(; it != itEnd && !context.aborting(); ++it ) {
Phil Nash56d5c422012-08-23 20:08:50 +01004221 m_reporter->StartGroup( it->getName() );
Phil Nash62b70392012-08-31 18:46:13 +01004222 totals += runTestsForGroup( context, *it );
Phil Nash56d5c422012-08-23 20:08:50 +01004223 if( context.aborting() )
4224 m_reporter->Aborted();
4225 m_reporter->EndGroup( it->getName(), totals );
4226 }
4227 return totals;
4228 }
4229
4230 Totals runTestsForGroup( Runner& context, const TestCaseFilters& filterGroup ) {
4231 Totals totals;
4232 std::vector<TestCaseInfo>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin();
4233 std::vector<TestCaseInfo>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end();
4234 int testsRunForGroup = 0;
4235 for(; it != itEnd; ++it ) {
4236 if( filterGroup.shouldInclude( *it ) ) {
4237 testsRunForGroup++;
4238 if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
4239
4240 if( context.aborting() )
4241 break;
4242
4243 totals += context.runTest( *it );
4244 m_testsAlreadyRun.insert( *it );
4245 }
Phil Nash06e959b2012-05-25 08:52:05 +01004246 }
4247 }
Phil Nash56d5c422012-08-23 20:08:50 +01004248 if( testsRunForGroup == 0 )
4249 std::cerr << "\n[No test cases matched with: " << filterGroup.getName() << "]" << std::endl;
4250 return totals;
4251
Phil Nash89d1e6c2011-05-24 08:23:02 +01004252 }
Phil Nash56d5c422012-08-23 20:08:50 +01004253
4254 private:
Phil Nash67ec8702012-09-26 18:38:26 +01004255 void openStream() {
4256 if( !m_config.stream.empty() )
4257 m_configWrapper.useStream( m_config.stream );
4258
Phil Nash56d5c422012-08-23 20:08:50 +01004259 // Open output file, if specified
4260 if( !m_config.outputFilename.empty() ) {
4261 m_ofs.open( m_config.outputFilename.c_str() );
4262 if( m_ofs.fail() ) {
4263 std::ostringstream oss;
4264 oss << "Unable to open file: '" << m_config.outputFilename << "'";
4265 throw std::domain_error( oss.str() );
4266 }
4267 m_configWrapper.setStreamBuf( m_ofs.rdbuf() );
4268 }
4269 }
4270 void makeReporter() {
4271 std::string reporterName = m_config.reporter.empty()
4272 ? "basic"
4273 : m_config.reporter;
4274
Phil Nasha70fbe32012-08-31 08:10:36 +01004275 ReporterConfig reporterConfig( m_config.name, m_configWrapper.stream(), m_config.includeWhichResults == Include::SuccessfulResults, m_config );
Phil Nash56d5c422012-08-23 20:08:50 +01004276
4277 m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, reporterConfig );
4278 if( !m_reporter ) {
4279 std::ostringstream oss;
4280 oss << "No reporter registered with name: '" << reporterName << "'";
4281 throw std::domain_error( oss.str() );
4282 }
4283 }
4284
4285 private:
4286 Config& m_configWrapper;
4287 const ConfigData& m_config;
4288 std::ofstream m_ofs;
4289 Ptr<IReporter> m_reporter;
4290 std::set<TestCaseInfo> m_testsAlreadyRun;
4291 };
4292
4293 inline int Main( Config& configWrapper ) {
4294 int result = 0;
4295 try
4296 {
4297 Runner2 runner( configWrapper );
4298
4299 const ConfigData& config = configWrapper.data();
4300
4301 // Handle list request
4302 if( config.listSpec != List::None ) {
4303 List( config );
Phil Nash799ecf92012-09-24 08:30:13 +01004304 Catch::cleanUp();
Phil Nash56d5c422012-08-23 20:08:50 +01004305 return 0;
4306 }
4307
4308 result = static_cast<int>( runner.runTests().assertions.failed );
4309
4310 }
4311 catch( std::exception& ex ) {
4312 std::cerr << ex.what() << std::endl;
4313 result = (std::numeric_limits<int>::max)();
4314 }
4315
Phil Nash3b80af72012-08-09 07:47:30 +01004316 Catch::cleanUp();
Phil Nash371db8b2012-05-21 18:52:09 +01004317 return result;
Phil Nash89d1e6c2011-05-24 08:23:02 +01004318 }
4319
Phil Nash163088a2012-05-31 19:40:26 +01004320 inline void showUsage( std::ostream& os ) {
Phil Nashecf934b2012-08-27 21:42:55 +01004321 AllOptions options;
Phil Nashe2d215e2012-09-07 17:52:35 +01004322
Phil Nashecf934b2012-08-27 21:42:55 +01004323 for( AllOptions::const_iterator it = options.begin(); it != options.end(); ++it ) {
4324 OptionParser& opt = **it;
4325 os << " " << opt.optionNames() << " " << opt.argsSynopsis() << "\n";
4326 }
4327 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 +01004328 }
Phil Nashe2d215e2012-09-07 17:52:35 +01004329
4330 inline void addIndent( std::ostream& os, std::size_t indent ) {
4331 while( indent-- > 0 )
4332 os << ' ';
4333 }
4334
4335 inline void recursivelyWrapLine( std::ostream& os, std::string paragraph, std::size_t columns, std::size_t indent ) {
4336 std::size_t width = columns-indent;
4337 std::size_t tab = 0;
4338 std::size_t wrapPoint = width;
4339 for( std::size_t pos = 0; pos < paragraph.size(); ++pos ) {
4340 if( pos == width ) {
4341 addIndent( os, indent );
4342 os << paragraph.substr( 0, wrapPoint ) << "\n";
4343 return recursivelyWrapLine( os, paragraph.substr( wrapPoint+1 ), columns, indent+tab );
4344 }
4345 if( paragraph[pos] == '\t' ) {
4346 tab = pos;
4347 paragraph = paragraph.substr( 0, tab ) + paragraph.substr( tab+1 );
4348 pos--;
4349 }
4350 else if( paragraph[pos] == ' ' ) {
4351 wrapPoint = pos;
4352 }
4353 }
4354 addIndent( os, indent );
4355 os << paragraph << "\n";
4356 }
Phil Nashf7418eb2012-09-09 11:44:30 +01004357
Phil Nashe2d215e2012-09-07 17:52:35 +01004358 inline std::string addLineBreaks( const std::string& str, std::size_t columns, std::size_t indent = 0 ) {
4359 std::ostringstream oss;
4360 std::string::size_type pos = 0;
4361 std::string::size_type newline = str.find_first_of( '\n' );
4362 while( newline != std::string::npos ) {
4363 std::string paragraph = str.substr( pos, newline-pos );
4364 recursivelyWrapLine( oss, paragraph, columns, indent );
4365 pos = newline+1;
4366 newline = str.find_first_of( '\n', pos );
4367 }
Phil Nashf7418eb2012-09-09 11:44:30 +01004368 if( pos != str.size() )
4369 recursivelyWrapLine( oss, str.substr( pos, str.size()-pos ), columns, indent );
4370
Phil Nashe2d215e2012-09-07 17:52:35 +01004371 return oss.str();
4372 }
4373
4374 inline void showHelp( const CommandParser& parser ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01004375 AllOptions options;
4376 Options::HelpOptionParser helpOpt;
4377 bool displayedSpecificOption = false;
4378 for( AllOptions::const_iterator it = options.begin(); it != options.end(); ++it ) {
4379 OptionParser& opt = **it;
4380 if( opt.find( parser ) && opt.optionNames() != helpOpt.optionNames() ) {
4381 displayedSpecificOption = true;
4382 std::cout << "\n" << opt.optionNames() << " " << opt.argsSynopsis() << "\n\n"
4383 << opt.optionSummary() << "\n\n"
4384
4385 << addLineBreaks( opt.optionDescription(), 80, 2 ) << "\n" << std::endl;
4386 }
4387 }
4388
4389 if( !displayedSpecificOption ) {
Phil Nash7673a302012-11-15 22:15:41 +00004390 std::cout << "\nCATCH v" << libraryVersion.MajorVersion << "."
4391 << libraryVersion.MinorVersion << " build "
4392 << libraryVersion.BuildNumber;
4393 if( libraryVersion.BranchName != "master" )
4394 std::cout << " (" << libraryVersion.BranchName << " branch)";
4395
Phil Nasha90a88a2012-11-19 19:59:10 +00004396 std::cout << "\n\n" << parser.exeName() << " is a CATCH host application. Options are as follows:\n\n";
Phil Nashe2d215e2012-09-07 17:52:35 +01004397 showUsage( std::cout );
4398 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01004399 }
4400
Phil Nash89d2a3f2012-05-16 15:09:17 +01004401 inline int Main( int argc, char* const argv[], Config& config ) {
Phil Nash163088a2012-05-31 19:40:26 +01004402
Phil Nashabf27162012-07-05 18:37:58 +01004403 try {
4404 CommandParser parser( argc, argv );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004405
Phil Nashecf934b2012-08-27 21:42:55 +01004406 if( Command cmd = Options::HelpOptionParser().find( parser ) ) {
Phil Nashabf27162012-07-05 18:37:58 +01004407 if( cmd.argsCount() != 0 )
4408 cmd.raiseError( "Does not accept arguments" );
4409
Phil Nashe2d215e2012-09-07 17:52:35 +01004410 showHelp( parser );
Phil Nash3b80af72012-08-09 07:47:30 +01004411 Catch::cleanUp();
Phil Nashabf27162012-07-05 18:37:58 +01004412 return 0;
4413 }
4414
Phil Nashecf934b2012-08-27 21:42:55 +01004415 AllOptions options;
4416
4417 options.parseIntoConfig( parser, config.data() );
Phil Nashabf27162012-07-05 18:37:58 +01004418 }
4419 catch( std::exception& ex ) {
Phil Nash6f220862012-07-23 08:24:52 +01004420 std::cerr << ex.what() << "\n\nUsage: ...\n\n";
Phil Nash163088a2012-05-31 19:40:26 +01004421 showUsage( std::cerr );
Phil Nash3b80af72012-08-09 07:47:30 +01004422 Catch::cleanUp();
Phil Nash89d1e6c2011-05-24 08:23:02 +01004423 return (std::numeric_limits<int>::max)();
4424 }
4425
Phil Nash89d1e6c2011-05-24 08:23:02 +01004426 return Main( config );
4427 }
4428
Phil Nash89d2a3f2012-05-16 15:09:17 +01004429 inline int Main( int argc, char* const argv[] ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01004430 Config config;
Phil Nash371db8b2012-05-21 18:52:09 +01004431// !TBD: This doesn't always work, for some reason
Phil Nash89d1e6c2011-05-24 08:23:02 +01004432// if( isDebuggerActive() )
4433// config.useStream( "debug" );
Phil Nash371db8b2012-05-21 18:52:09 +01004434 return Main( argc, argv, config );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004435 }
4436
4437} // end namespace Catch
4438
Phil Nash3b80af72012-08-09 07:47:30 +01004439// #included from: catch_registry_hub.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004440#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01004441
4442// #included from: catch_test_case_registry_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004443#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01004444
4445#include <vector>
4446#include <set>
4447#include <sstream>
4448#include <iostream>
4449
4450namespace Catch {
4451
4452 class TestRegistry : public ITestCaseRegistry {
4453 public:
4454 TestRegistry() : m_unnamedCount( 0 ) {}
Phil Nasha695eb92012-08-13 07:46:10 +01004455 virtual ~TestRegistry();
Phil Nash3b80af72012-08-09 07:47:30 +01004456
4457 virtual void registerTest( const TestCaseInfo& testInfo ) {
4458 if( testInfo.getName() == "" ) {
4459 std::ostringstream oss;
4460 oss << testInfo.getName() << "unnamed/" << ++m_unnamedCount;
4461 return registerTest( TestCaseInfo( testInfo, oss.str() ) );
4462 }
4463
4464 if( m_functions.find( testInfo ) == m_functions.end() ) {
4465 m_functions.insert( testInfo );
4466 m_functionsInOrder.push_back( testInfo );
Phil Nash5bc030d2012-08-16 18:48:50 +01004467 if( !testInfo.isHidden() )
4468 m_nonHiddenFunctions.push_back( testInfo );
Phil Nash3b80af72012-08-09 07:47:30 +01004469 }
4470 else {
4471 const TestCaseInfo& prev = *m_functions.find( testInfo );
4472 std::cerr << "error: TEST_CASE( \"" << testInfo.getName() << "\" ) already defined.\n"
4473 << "\tFirst seen at " << SourceLineInfo( prev.getLineInfo() ) << "\n"
4474 << "\tRedefined at " << SourceLineInfo( testInfo.getLineInfo() ) << std::endl;
4475 exit(1);
4476 }
4477 }
4478
4479 virtual const std::vector<TestCaseInfo>& getAllTests() const {
4480 return m_functionsInOrder;
4481 }
4482
Phil Nash5bc030d2012-08-16 18:48:50 +01004483 virtual const std::vector<TestCaseInfo>& getAllNonHiddenTests() const {
4484 return m_nonHiddenFunctions;
4485 }
4486
Phil Nash56d5c422012-08-23 20:08:50 +01004487 // !TBD deprecated
Phil Nash3b80af72012-08-09 07:47:30 +01004488 virtual std::vector<TestCaseInfo> getMatchingTestCases( const std::string& rawTestSpec ) const {
Phil Nash5bc030d2012-08-16 18:48:50 +01004489 std::vector<TestCaseInfo> matchingTests;
4490 getMatchingTestCases( rawTestSpec, matchingTests );
4491 return matchingTests;
4492 }
4493
Phil Nash56d5c422012-08-23 20:08:50 +01004494 // !TBD deprecated
Phil Nash5bc030d2012-08-16 18:48:50 +01004495 virtual void getMatchingTestCases( const std::string& rawTestSpec, std::vector<TestCaseInfo>& matchingTestsOut ) const {
Phil Nash56d5c422012-08-23 20:08:50 +01004496 TestCaseFilter filter( rawTestSpec );
Phil Nash5bc030d2012-08-16 18:48:50 +01004497
Phil Nash3b80af72012-08-09 07:47:30 +01004498 std::vector<TestCaseInfo>::const_iterator it = m_functionsInOrder.begin();
4499 std::vector<TestCaseInfo>::const_iterator itEnd = m_functionsInOrder.end();
4500 for(; it != itEnd; ++it ) {
Phil Nash56d5c422012-08-23 20:08:50 +01004501 if( filter.shouldInclude( *it ) ) {
Phil Nash5bc030d2012-08-16 18:48:50 +01004502 matchingTestsOut.push_back( *it );
Phil Nash3b80af72012-08-09 07:47:30 +01004503 }
4504 }
Phil Nash3b80af72012-08-09 07:47:30 +01004505 }
Phil Nash56d5c422012-08-23 20:08:50 +01004506 virtual void getMatchingTestCases( const TestCaseFilters& filters, std::vector<TestCaseInfo>& matchingTestsOut ) const {
4507 std::vector<TestCaseInfo>::const_iterator it = m_functionsInOrder.begin();
4508 std::vector<TestCaseInfo>::const_iterator itEnd = m_functionsInOrder.end();
4509 // !TBD: replace with algorithm
4510 for(; it != itEnd; ++it )
4511 if( filters.shouldInclude( *it ) )
4512 matchingTestsOut.push_back( *it );
4513 }
Phil Nash3b80af72012-08-09 07:47:30 +01004514
4515 private:
4516
4517 std::set<TestCaseInfo> m_functions;
4518 std::vector<TestCaseInfo> m_functionsInOrder;
Phil Nash5bc030d2012-08-16 18:48:50 +01004519 std::vector<TestCaseInfo> m_nonHiddenFunctions;
Phil Nash3b80af72012-08-09 07:47:30 +01004520 size_t m_unnamedCount;
4521 };
4522
4523 ///////////////////////////////////////////////////////////////////////////
4524
Phil Nash5bc030d2012-08-16 18:48:50 +01004525 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
Phil Nash3b80af72012-08-09 07:47:30 +01004526 public:
4527
4528 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
4529
4530 virtual void invoke() const {
4531 m_fun();
4532 }
4533
Phil Nash3b80af72012-08-09 07:47:30 +01004534 private:
Phil Nash5bc030d2012-08-16 18:48:50 +01004535 virtual ~FreeFunctionTestCase();
4536
Phil Nash3b80af72012-08-09 07:47:30 +01004537 TestFunction m_fun;
4538 };
4539
Phil Nash88b70822012-11-04 21:39:38 +00004540 inline std::string extractClassName( const std::string& classOrQualifiedMethodName ) {
4541 std::string className = classOrQualifiedMethodName;
4542 if( className[0] == '&' )
4543 {
4544 std::size_t lastColons = className.rfind( "::" );
4545 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
4546 if( penultimateColons == std::string::npos )
4547 penultimateColons = 1;
4548 className = className.substr( penultimateColons, lastColons-penultimateColons );
4549 }
4550 return className;
4551 }
4552
Phil Nash3b80af72012-08-09 07:47:30 +01004553 ///////////////////////////////////////////////////////////////////////////
4554
4555 AutoReg::AutoReg( TestFunction function,
4556 const char* name,
4557 const char* description,
4558 const SourceLineInfo& lineInfo ) {
Phil Nash88b70822012-11-04 21:39:38 +00004559 registerTestCase( new FreeFunctionTestCase( function ), "global", name, description, lineInfo );
Phil Nash3b80af72012-08-09 07:47:30 +01004560 }
4561
4562 AutoReg::~AutoReg() {}
4563
4564 void AutoReg::registerTestCase( ITestCase* testCase,
Phil Nash88b70822012-11-04 21:39:38 +00004565 const char* classOrQualifiedMethodName,
Phil Nash3b80af72012-08-09 07:47:30 +01004566 const char* name,
4567 const char* description,
4568 const SourceLineInfo& lineInfo ) {
Phil Nash88b70822012-11-04 21:39:38 +00004569
4570 getMutableRegistryHub().registerTest( TestCaseInfo( testCase, extractClassName( classOrQualifiedMethodName ), name, description, lineInfo ) );
Phil Nash3b80af72012-08-09 07:47:30 +01004571 }
4572
4573} // end namespace Catch
4574
4575// #included from: catch_reporter_registry.hpp
4576#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
4577
4578#include <map>
4579
4580namespace Catch {
4581
4582 class ReporterRegistry : public IReporterRegistry {
4583
4584 public:
4585
Phil Nasha695eb92012-08-13 07:46:10 +01004586 virtual ~ReporterRegistry() {
Phil Nash3b80af72012-08-09 07:47:30 +01004587 deleteAllValues( m_factories );
4588 }
4589
4590 virtual IReporter* create( const std::string& name, const ReporterConfig& config ) const {
4591 FactoryMap::const_iterator it = m_factories.find( name );
4592 if( it == m_factories.end() )
4593 return NULL;
4594 return it->second->create( config );
4595 }
4596
4597 void registerReporter( const std::string& name, IReporterFactory* factory ) {
4598 m_factories.insert( std::make_pair( name, factory ) );
4599 }
4600
4601 const FactoryMap& getFactories() const {
4602 return m_factories;
4603 }
4604
4605 private:
4606 FactoryMap m_factories;
4607 };
4608}
4609
4610// #included from: catch_exception_translator_registry.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004611#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01004612
4613#ifdef __OBJC__
4614#import "Foundation/Foundation.h"
4615#endif
4616
4617namespace Catch {
4618
4619 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
4620 public:
4621 ~ExceptionTranslatorRegistry() {
4622 deleteAll( m_translators );
4623 }
4624
4625 virtual void registerTranslator( const IExceptionTranslator* translator ) {
4626 m_translators.push_back( translator );
4627 }
4628
4629 virtual std::string translateActiveException() const {
4630 try {
4631#ifdef __OBJC__
4632 // In Objective-C try objective-c exceptions first
4633 @try {
4634 throw;
4635 }
4636 @catch (NSException *exception) {
4637 return toString( [exception description] );
4638 }
4639#else
4640 throw;
4641#endif
4642 }
4643 catch( std::exception& ex ) {
4644 return ex.what();
4645 }
4646 catch( std::string& msg ) {
4647 return msg;
4648 }
4649 catch( const char* msg ) {
4650 return msg;
4651 }
4652 catch(...) {
4653 return tryTranslators( m_translators.begin() );
4654 }
4655 }
4656
4657 std::string tryTranslators( std::vector<const IExceptionTranslator*>::const_iterator it ) const {
4658 if( it == m_translators.end() )
4659 return "Unknown exception";
4660
4661 try {
4662 return (*it)->translate();
4663 }
4664 catch(...) {
4665 return tryTranslators( it+1 );
4666 }
4667 }
4668
4669 private:
4670 std::vector<const IExceptionTranslator*> m_translators;
4671 };
4672}
4673
4674namespace Catch {
4675
4676 namespace {
4677
4678 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
4679
4680 RegistryHub( const RegistryHub& );
4681 void operator=( const RegistryHub& );
4682
4683 public: // IRegistryHub
4684 RegistryHub() {
4685 }
4686 virtual const IReporterRegistry& getReporterRegistry() const {
4687 return m_reporterRegistry;
4688 }
4689 virtual const ITestCaseRegistry& getTestCaseRegistry() const {
4690 return m_testCaseRegistry;
4691 }
4692 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
4693 return m_exceptionTranslatorRegistry;
4694 }
4695
4696 public: // IMutableRegistryHub
4697 virtual void registerReporter( const std::string& name, IReporterFactory* factory ) {
4698 m_reporterRegistry.registerReporter( name, factory );
4699 }
4700 virtual void registerTest( const TestCaseInfo& testInfo ) {
4701 m_testCaseRegistry.registerTest( testInfo );
4702 }
4703 virtual void registerTranslator( const IExceptionTranslator* translator ) {
4704 m_exceptionTranslatorRegistry.registerTranslator( translator );
4705 }
4706
4707 private:
4708 TestRegistry m_testCaseRegistry;
4709 ReporterRegistry m_reporterRegistry;
4710 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
4711 };
4712
4713 // Single, global, instance
4714 inline RegistryHub*& getTheRegistryHub() {
4715 static RegistryHub* theRegistryHub = NULL;
4716 if( !theRegistryHub )
4717 theRegistryHub = new RegistryHub();
4718 return theRegistryHub;
4719 }
4720 }
4721
4722 IRegistryHub& getRegistryHub() {
4723 return *getTheRegistryHub();
4724 }
4725 IMutableRegistryHub& getMutableRegistryHub() {
4726 return *getTheRegistryHub();
4727 }
4728 void cleanUp() {
4729 delete getTheRegistryHub();
4730 getTheRegistryHub() = NULL;
4731 cleanUpContext();
4732 }
Phil Nash82acc2c2012-10-28 12:07:17 +00004733 std::string translateActiveException() {
4734 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
4735 }
Phil Nash3b80af72012-08-09 07:47:30 +01004736
4737} // end namespace Catch
Matt Wozniskif29c8982012-09-17 01:42:29 -04004738
Phil Nash3b80af72012-08-09 07:47:30 +01004739// #included from: catch_notimplemented_exception.hpp
4740#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
4741
4742#include <ostream>
4743
4744namespace Catch {
4745
4746 NotImplementedException::NotImplementedException( const SourceLineInfo& lineInfo )
4747 : m_lineInfo( lineInfo ) {
4748 std::ostringstream oss;
4749 oss << lineInfo << "function ";
Phil Nash3b80af72012-08-09 07:47:30 +01004750 oss << "not implemented";
4751 m_what = oss.str();
4752 }
4753
4754 const char* NotImplementedException::what() const throw() {
4755 return m_what.c_str();
4756 }
4757
4758} // end namespace Catch
4759
4760// #included from: catch_context_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004761#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01004762
Phil Nash3b80af72012-08-09 07:47:30 +01004763namespace Catch {
4764
4765 class Context : public IMutableContext {
4766
4767 Context() : m_config( NULL ) {}
4768 Context( const Context& );
4769 void operator=( const Context& );
4770
4771 public: // IContext
4772 virtual IResultCapture& getResultCapture() {
4773 return *m_resultCapture;
4774 }
4775 virtual IRunner& getRunner() {
4776 return *m_runner;
4777 }
4778 virtual size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ) {
4779 return getGeneratorsForCurrentTest()
4780 .getGeneratorInfo( fileInfo, totalSize )
4781 .getCurrentIndex();
4782 }
4783 virtual bool advanceGeneratorsForCurrentTest() {
4784 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
4785 return generators && generators->moveNext();
4786 }
4787
4788 virtual const IConfig* getConfig() const {
4789 return m_config;
4790 }
4791
4792 public: // IMutableContext
4793 virtual void setResultCapture( IResultCapture* resultCapture ) {
4794 m_resultCapture = resultCapture;
4795 }
4796 virtual void setRunner( IRunner* runner ) {
4797 m_runner = runner;
4798 }
4799 virtual void setConfig( const IConfig* config ) {
4800 m_config = config;
4801 }
4802
4803 friend IMutableContext& getCurrentMutableContext();
4804
4805 private:
4806 IGeneratorsForTest* findGeneratorsForCurrentTest() {
4807 std::string testName = getResultCapture().getCurrentTestName();
4808
4809 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
4810 m_generatorsByTestName.find( testName );
4811 return it != m_generatorsByTestName.end()
4812 ? it->second
4813 : NULL;
4814 }
4815
4816 IGeneratorsForTest& getGeneratorsForCurrentTest() {
4817 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
4818 if( !generators ) {
4819 std::string testName = getResultCapture().getCurrentTestName();
4820 generators = createGeneratorsForTest();
4821 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
4822 }
4823 return *generators;
4824 }
4825
4826 private:
4827 IRunner* m_runner;
4828 IResultCapture* m_resultCapture;
4829 const IConfig* m_config;
4830 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
4831 };
4832
4833 namespace {
4834 Context* currentContext = NULL;
4835 }
4836 IMutableContext& getCurrentMutableContext() {
4837 if( !currentContext )
4838 currentContext = new Context();
4839 return *currentContext;
4840 }
4841 IContext& getCurrentContext() {
4842 return getCurrentMutableContext();
4843 }
4844
Phil Nash67ec8702012-09-26 18:38:26 +01004845 Stream createStream( const std::string& streamName ) {
4846 if( streamName == "stdout" ) return Stream( std::cout.rdbuf(), false );
4847 if( streamName == "stderr" ) return Stream( std::cerr.rdbuf(), false );
4848 if( streamName == "debug" ) return Stream( new StreamBufImpl<OutputDebugWriter>, true );
Phil Nash3b80af72012-08-09 07:47:30 +01004849
4850 throw std::domain_error( "Unknown stream: " + streamName );
4851 }
4852
4853 void cleanUpContext() {
4854 delete currentContext;
4855 currentContext = NULL;
4856 }
4857}
Matt Wozniskif29c8982012-09-17 01:42:29 -04004858
Phil Nash3b80af72012-08-09 07:47:30 +01004859// #included from: catch_console_colour_impl.hpp
4860#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
4861
Phil Nash56d5c422012-08-23 20:08:50 +01004862// #included from: catch_console_colour.hpp
4863#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
4864
4865namespace Catch {
4866
4867 struct ConsoleColourImpl;
4868
4869 class TextColour : NonCopyable {
4870 public:
4871
4872 enum Colours {
4873 None,
4874
4875 FileName,
4876 ResultError,
4877 ResultSuccess,
4878
4879 Error,
4880 Success,
4881
4882 OriginalExpression,
4883 ReconstructedExpression
4884 };
4885
4886 TextColour( Colours colour = None );
4887 void set( Colours colour );
4888 ~TextColour();
4889
4890 private:
4891 ConsoleColourImpl* m_impl;
4892 };
4893
4894} // end namespace Catch
4895
Phil Nash355b95f2012-10-31 18:04:22 +00004896#if defined( CATCH_CONFIG_USE_ANSI_COLOUR_CODES )
4897
4898#include <unistd.h>
4899
Phil Nash5efa4bc2012-10-29 20:49:22 +00004900namespace Catch {
4901
Phil Nash355b95f2012-10-31 18:04:22 +00004902 // use POSIX/ ANSI console terminal codes
Phil Nash5efa4bc2012-10-29 20:49:22 +00004903 // Implementation contributed by Adam Strzelecki (http://github.com/nanoant)
4904 // https://github.com/philsquared/Catch/pull/131
4905
4906 TextColour::TextColour( Colours colour ) {
4907 if( colour )
4908 set( colour );
4909 }
4910
4911 TextColour::~TextColour() {
4912 set( TextColour::None );
4913 }
4914
Phil Nash355b95f2012-10-31 18:04:22 +00004915 namespace { const char colourEscape = '\033'; }
4916
Phil Nash5efa4bc2012-10-29 20:49:22 +00004917 void TextColour::set( Colours colour ) {
4918 if( isatty( fileno(stdout) ) ) {
4919 switch( colour ) {
4920 case TextColour::FileName:
Phil Nash88b70822012-11-04 21:39:38 +00004921 std::cout << colourEscape << "[0m"; // white/ normal
Phil Nash5efa4bc2012-10-29 20:49:22 +00004922 break;
4923 case TextColour::ResultError:
Phil Nash355b95f2012-10-31 18:04:22 +00004924 std::cout << colourEscape << "[1;31m"; // bold red
Phil Nash5efa4bc2012-10-29 20:49:22 +00004925 break;
4926 case TextColour::ResultSuccess:
Phil Nash355b95f2012-10-31 18:04:22 +00004927 std::cout << colourEscape << "[1;32m"; // bold green
Phil Nash5efa4bc2012-10-29 20:49:22 +00004928 break;
4929 case TextColour::Error:
Phil Nash355b95f2012-10-31 18:04:22 +00004930 std::cout << colourEscape << "[0;31m"; // red
Phil Nash5efa4bc2012-10-29 20:49:22 +00004931 break;
4932 case TextColour::Success:
Phil Nash355b95f2012-10-31 18:04:22 +00004933 std::cout << colourEscape << "[0;32m"; // green
Phil Nash5efa4bc2012-10-29 20:49:22 +00004934 break;
4935 case TextColour::OriginalExpression:
Phil Nash355b95f2012-10-31 18:04:22 +00004936 std::cout << colourEscape << "[0;36m"; // cyan
Phil Nash5efa4bc2012-10-29 20:49:22 +00004937 break;
4938 case TextColour::ReconstructedExpression:
Phil Nash355b95f2012-10-31 18:04:22 +00004939 std::cout << colourEscape << "[0;33m"; // yellow
Phil Nash5efa4bc2012-10-29 20:49:22 +00004940 break;
4941 case TextColour::None:
Phil Nash88b70822012-11-04 21:39:38 +00004942 std::cout << colourEscape << "[0m"; // reset
Phil Nash5efa4bc2012-10-29 20:49:22 +00004943 }
4944 }
4945 }
4946
Phil Nash355b95f2012-10-31 18:04:22 +00004947} // namespace Catch
4948
Phil Nash5efa4bc2012-10-29 20:49:22 +00004949#elif defined ( CATCH_PLATFORM_WINDOWS )
Phil Nash3b80af72012-08-09 07:47:30 +01004950
4951#include <windows.h>
4952
Phil Nash355b95f2012-10-31 18:04:22 +00004953namespace Catch {
4954
Phil Nash3b80af72012-08-09 07:47:30 +01004955 namespace {
4956
4957 WORD mapConsoleColour( TextColour::Colours colour ) {
4958 switch( colour ) {
4959 case TextColour::FileName:
4960 return FOREGROUND_INTENSITY; // greyed out
4961 case TextColour::ResultError:
4962 return FOREGROUND_RED | FOREGROUND_INTENSITY; // bright red
4963 case TextColour::ResultSuccess:
4964 return FOREGROUND_GREEN | FOREGROUND_INTENSITY; // bright green
4965 case TextColour::Error:
4966 return FOREGROUND_RED; // dark red
4967 case TextColour::Success:
4968 return FOREGROUND_GREEN; // dark green
4969 case TextColour::OriginalExpression:
4970 return FOREGROUND_BLUE | FOREGROUND_GREEN; // turquoise
4971 case TextColour::ReconstructedExpression:
4972 return FOREGROUND_RED | FOREGROUND_GREEN; // greeny-yellow
4973 default: return 0;
4974 }
4975 }
4976 }
4977
4978 struct ConsoleColourImpl {
4979
4980 ConsoleColourImpl()
4981 : hStdout( GetStdHandle(STD_OUTPUT_HANDLE) ),
4982 wOldColorAttrs( 0 )
4983 {
4984 GetConsoleScreenBufferInfo( hStdout, &csbiInfo );
4985 wOldColorAttrs = csbiInfo.wAttributes;
4986 }
4987
4988 ~ConsoleColourImpl() {
4989 SetConsoleTextAttribute( hStdout, wOldColorAttrs );
4990 }
4991
4992 void set( TextColour::Colours colour ) {
4993 WORD consoleColour = mapConsoleColour( colour );
4994 if( consoleColour > 0 )
4995 SetConsoleTextAttribute( hStdout, consoleColour );
4996 }
4997
4998 HANDLE hStdout;
4999 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
5000 WORD wOldColorAttrs;
5001 };
5002
5003 TextColour::TextColour( Colours colour )
5004 : m_impl( new ConsoleColourImpl() )
5005 {
5006 if( colour )
5007 m_impl->set( colour );
5008 }
5009
5010 TextColour::~TextColour() {
5011 delete m_impl;
5012 }
5013
5014 void TextColour::set( Colours colour ) {
5015 m_impl->set( colour );
5016 }
5017
Phil Nash355b95f2012-10-31 18:04:22 +00005018} // end namespace Catch
5019
Phil Nash3b80af72012-08-09 07:47:30 +01005020#else
5021
Phil Nash355b95f2012-10-31 18:04:22 +00005022namespace Catch {
5023
Phil Nash3b80af72012-08-09 07:47:30 +01005024 TextColour::TextColour( Colours ){}
5025 TextColour::~TextColour(){}
5026 void TextColour::set( Colours ){}
5027
Phil Nash5efa4bc2012-10-29 20:49:22 +00005028} // end namespace Catch
5029
Phil Nash355b95f2012-10-31 18:04:22 +00005030#endif
5031
Phil Nash3b80af72012-08-09 07:47:30 +01005032// #included from: catch_generators_impl.hpp
5033#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
5034
5035#include <vector>
5036#include <string>
5037#include <map>
5038
5039namespace Catch {
5040
5041 struct GeneratorInfo : IGeneratorInfo {
5042
5043 GeneratorInfo( std::size_t size )
5044 : m_size( size ),
5045 m_currentIndex( 0 )
5046 {}
5047
5048 bool moveNext() {
5049 if( ++m_currentIndex == m_size ) {
5050 m_currentIndex = 0;
5051 return false;
5052 }
5053 return true;
5054 }
5055
5056 std::size_t getCurrentIndex() const {
5057 return m_currentIndex;
5058 }
5059
5060 std::size_t m_size;
5061 std::size_t m_currentIndex;
5062 };
5063
5064 ///////////////////////////////////////////////////////////////////////////
5065
5066 class GeneratorsForTest : public IGeneratorsForTest {
5067
5068 public:
5069 ~GeneratorsForTest() {
5070 deleteAll( m_generatorsInOrder );
5071 }
5072
5073 IGeneratorInfo& getGeneratorInfo( const std::string& fileInfo, std::size_t size ) {
5074 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
5075 if( it == m_generatorsByName.end() ) {
5076 IGeneratorInfo* info = new GeneratorInfo( size );
5077 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
5078 m_generatorsInOrder.push_back( info );
5079 return *info;
5080 }
5081 return *it->second;
5082 }
5083
5084 bool moveNext() {
5085 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
5086 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
5087 for(; it != itEnd; ++it ) {
5088 if( (*it)->moveNext() )
5089 return true;
5090 }
5091 return false;
5092 }
5093
5094 private:
5095 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
5096 std::vector<IGeneratorInfo*> m_generatorsInOrder;
5097 };
5098
5099 IGeneratorsForTest* createGeneratorsForTest()
5100 {
5101 return new GeneratorsForTest();
5102 }
5103
5104} // end namespace Catch
5105
Phil Nash82acc2c2012-10-28 12:07:17 +00005106// #included from: catch_assertionresult.hpp
5107#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01005108
5109namespace Catch {
5110
Phil Nashd539da92012-11-13 09:44:52 +00005111 AssertionInfo::AssertionInfo( const std::string& _macroName,
5112 const SourceLineInfo& _lineInfo,
5113 const std::string& _capturedExpression,
5114 ResultDisposition::Flags _resultDisposition )
5115 : macroName( _macroName ),
5116 lineInfo( _lineInfo ),
5117 capturedExpression( _capturedExpression ),
5118 resultDisposition( _resultDisposition )
5119 {
5120 if( shouldNegate( resultDisposition ) )
5121 capturedExpression = "!" + _capturedExpression;
5122 }
5123
Phil Nash82acc2c2012-10-28 12:07:17 +00005124 AssertionResult::AssertionResult() {}
Phil Nash3b80af72012-08-09 07:47:30 +01005125
Phil Nash82acc2c2012-10-28 12:07:17 +00005126 AssertionResult::AssertionResult( const AssertionInfo& info, const AssertionResultData& data )
5127 : m_info( info ),
5128 m_resultData( data )
5129 {}
Phil Nash3b80af72012-08-09 07:47:30 +01005130
Phil Nash82acc2c2012-10-28 12:07:17 +00005131 AssertionResult::~AssertionResult() {}
Phil Nash3b80af72012-08-09 07:47:30 +01005132
Phil Nashd539da92012-11-13 09:44:52 +00005133 // Result was a success
5134 bool AssertionResult::succeeded() const {
5135 return Catch::isOk( m_resultData.resultType );
5136 }
5137
5138 // Result was a success, or failure is suppressed
5139 bool AssertionResult::isOk() const {
5140 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
Phil Nash3b80af72012-08-09 07:47:30 +01005141 }
5142
Phil Nash82acc2c2012-10-28 12:07:17 +00005143 ResultWas::OfType AssertionResult::getResultType() const {
5144 return m_resultData.resultType;
Phil Nash3b80af72012-08-09 07:47:30 +01005145 }
5146
Phil Nash82acc2c2012-10-28 12:07:17 +00005147 bool AssertionResult::hasExpression() const {
5148 return !m_info.capturedExpression.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01005149 }
5150
Phil Nash82acc2c2012-10-28 12:07:17 +00005151 bool AssertionResult::hasMessage() const {
5152 return !m_resultData.message.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01005153 }
5154
Phil Nash82acc2c2012-10-28 12:07:17 +00005155 std::string AssertionResult::getExpression() const {
5156 return m_info.capturedExpression;
Phil Nash3b80af72012-08-09 07:47:30 +01005157 }
5158
Phil Nash82acc2c2012-10-28 12:07:17 +00005159 bool AssertionResult::hasExpandedExpression() const {
Phil Nash67305122012-10-09 11:48:55 +01005160 return hasExpression() && getExpandedExpression() != getExpression();
Phil Nash3b80af72012-08-09 07:47:30 +01005161 }
5162
Phil Nash82acc2c2012-10-28 12:07:17 +00005163 std::string AssertionResult::getExpandedExpression() const {
5164 return m_resultData.reconstructedExpression;
Phil Nash3b80af72012-08-09 07:47:30 +01005165 }
5166
Phil Nash82acc2c2012-10-28 12:07:17 +00005167 std::string AssertionResult::getMessage() const {
5168 return m_resultData.message;
5169 }
5170 SourceLineInfo AssertionResult::getSourceInfo() const {
5171 return m_info.lineInfo;
Phil Nash3b80af72012-08-09 07:47:30 +01005172 }
5173
Phil Nash82acc2c2012-10-28 12:07:17 +00005174 std::string AssertionResult::getTestMacroName() const {
5175 return m_info.macroName;
Phil Nash3b80af72012-08-09 07:47:30 +01005176 }
5177
5178} // end namespace Catch
5179
Phil Nash82acc2c2012-10-28 12:07:17 +00005180// #included from: catch_expressionresult_builder.hpp
5181#define TWOBLUECUBES_CATCH_EXPRESSIONRESULT_BUILDER_HPP_INCLUDED
5182
5183#include <assert.h>
Phil Nash3b80af72012-08-09 07:47:30 +01005184
5185namespace Catch {
5186
Phil Nash82acc2c2012-10-28 12:07:17 +00005187 ExpressionResultBuilder::ExpressionResultBuilder( ResultWas::OfType resultType ) {
5188 m_data.resultType = resultType;
Phil Nash67305122012-10-09 11:48:55 +01005189 }
Phil Nash82acc2c2012-10-28 12:07:17 +00005190 ExpressionResultBuilder::ExpressionResultBuilder( const ExpressionResultBuilder& other )
5191 : m_data( other.m_data ),
5192 m_exprComponents( other.m_exprComponents )
Phil Nash67305122012-10-09 11:48:55 +01005193 {
Phil Nash82acc2c2012-10-28 12:07:17 +00005194 m_stream << other.m_stream.str();
Phil Nash3b80af72012-08-09 07:47:30 +01005195 }
Phil Nash82acc2c2012-10-28 12:07:17 +00005196 ExpressionResultBuilder& ExpressionResultBuilder::operator=(const ExpressionResultBuilder& other ) {
5197 m_data = other.m_data;
5198 m_exprComponents = other.m_exprComponents;
5199 m_stream.str("");
5200 m_stream << other.m_stream.str();
5201 return *this;
5202 }
5203 ExpressionResultBuilder& ExpressionResultBuilder::setResultType( ResultWas::OfType result ) {
5204 m_data.resultType = result;
5205 return *this;
5206 }
5207 ExpressionResultBuilder& ExpressionResultBuilder::setResultType( bool result ) {
5208 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
5209 return *this;
5210 }
Phil Nashaf1a3212012-11-10 18:46:39 +00005211 ExpressionResultBuilder& ExpressionResultBuilder::endExpression( ResultDisposition::Flags resultDisposition ) {
Phil Nashd539da92012-11-13 09:44:52 +00005212 m_exprComponents.shouldNegate = shouldNegate( resultDisposition );
Phil Nash82acc2c2012-10-28 12:07:17 +00005213 return *this;
5214 }
5215 ExpressionResultBuilder& ExpressionResultBuilder::setLhs( const std::string& lhs ) {
5216 m_exprComponents.lhs = lhs;
5217 return *this;
5218 }
5219 ExpressionResultBuilder& ExpressionResultBuilder::setRhs( const std::string& rhs ) {
5220 m_exprComponents.rhs = rhs;
5221 return *this;
5222 }
5223 ExpressionResultBuilder& ExpressionResultBuilder::setOp( const std::string& op ) {
5224 m_exprComponents.op = op;
5225 return *this;
5226 }
5227 AssertionResult ExpressionResultBuilder::buildResult( const AssertionInfo& info ) const
5228 {
5229 assert( m_data.resultType != ResultWas::Unknown );
Phil Nash3b80af72012-08-09 07:47:30 +01005230
Phil Nash82acc2c2012-10-28 12:07:17 +00005231 AssertionResultData data = m_data;
5232
5233 // Flip bool results if shouldNegate is set
5234 if( m_exprComponents.shouldNegate && data.resultType == ResultWas::Ok )
5235 data.resultType = ResultWas::ExpressionFailed;
5236 else if( m_exprComponents.shouldNegate && data.resultType == ResultWas::ExpressionFailed )
5237 data.resultType = ResultWas::Ok;
5238
5239 data.message = m_stream.str();
5240 data.reconstructedExpression = reconstructExpression( info );
5241 if( m_exprComponents.shouldNegate ) {
5242 if( m_exprComponents.op == "" )
5243 data.reconstructedExpression = "!" + data.reconstructedExpression;
Phil Nash67305122012-10-09 11:48:55 +01005244 else
Phil Nash82acc2c2012-10-28 12:07:17 +00005245 data.reconstructedExpression = "!(" + data.reconstructedExpression + ")";
5246 }
5247 return AssertionResult( info, data );
5248 }
5249 std::string ExpressionResultBuilder::reconstructExpression( const AssertionInfo& info ) const {
5250 if( m_exprComponents.op == "" )
5251 return m_exprComponents.lhs.empty() ? info.capturedExpression : m_exprComponents.op + m_exprComponents.lhs;
5252 else if( m_exprComponents.op == "matches" )
5253 return m_exprComponents.lhs + " " + m_exprComponents.rhs;
5254 else if( m_exprComponents.op != "!" ) {
5255 if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 30 )
5256 return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs;
5257 else if( m_exprComponents.lhs.size() < 70 && m_exprComponents.rhs.size() < 70 )
5258 return "\n\t" + m_exprComponents.lhs + "\n\t" + m_exprComponents.op + "\n\t" + m_exprComponents.rhs;
5259 else
5260 return "\n" + m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs + "\n\n";
Phil Nash67305122012-10-09 11:48:55 +01005261 }
5262 else
Phil Nash82acc2c2012-10-28 12:07:17 +00005263 return "{can't expand - use " + info.macroName + "_FALSE( " + info.capturedExpression.substr(1) + " ) instead of " + info.macroName + "( " + info.capturedExpression + " ) for better diagnostics}";
Phil Nash3b80af72012-08-09 07:47:30 +01005264 }
5265
5266} // end namespace Catch
5267
Phil Nash5bc030d2012-08-16 18:48:50 +01005268// #included from: catch_test_case_info.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005269#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
Phil Nash5bc030d2012-08-16 18:48:50 +01005270
5271namespace Catch {
5272
5273 TestCaseInfo::TestCaseInfo( ITestCase* testCase,
Phil Nash88b70822012-11-04 21:39:38 +00005274 const std::string& className,
5275 const std::string& name,
5276 const std::string& description,
Phil Nash5bc030d2012-08-16 18:48:50 +01005277 const SourceLineInfo& lineInfo )
5278 : m_test( testCase ),
Phil Nash88b70822012-11-04 21:39:38 +00005279 m_className( className ),
Phil Nash5bc030d2012-08-16 18:48:50 +01005280 m_name( name ),
5281 m_description( description ),
Phil Nashfc1baac2012-09-15 17:53:27 +01005282 m_lineInfo( lineInfo ),
5283 m_isHidden( startsWith( name, "./" ) )
5284 {
Phil Nash799ecf92012-09-24 08:30:13 +01005285 TagExtracter( m_tags ).parse( m_description );
Phil Nashfc1baac2012-09-15 17:53:27 +01005286 if( hasTag( "hide" ) )
5287 m_isHidden = true;
5288 }
Phil Nash5bc030d2012-08-16 18:48:50 +01005289
5290 TestCaseInfo::TestCaseInfo()
5291 : m_test( NULL ),
Phil Nash88b70822012-11-04 21:39:38 +00005292 m_className(),
Phil Nash5bc030d2012-08-16 18:48:50 +01005293 m_name(),
Phil Nashfc1baac2012-09-15 17:53:27 +01005294 m_description(),
5295 m_isHidden( false )
Phil Nash5bc030d2012-08-16 18:48:50 +01005296 {}
5297
5298 TestCaseInfo::TestCaseInfo( const TestCaseInfo& other, const std::string& name )
5299 : m_test( other.m_test ),
Phil Nash88b70822012-11-04 21:39:38 +00005300 m_className( other.m_className ),
Phil Nash5bc030d2012-08-16 18:48:50 +01005301 m_name( name ),
5302 m_description( other.m_description ),
Phil Nashfc1baac2012-09-15 17:53:27 +01005303 m_tags( other.m_tags ),
5304 m_lineInfo( other.m_lineInfo ),
5305 m_isHidden( other.m_isHidden )
Phil Nash5bc030d2012-08-16 18:48:50 +01005306 {}
5307
Phil Nashd2ec8492012-08-23 19:48:57 +01005308 TestCaseInfo::TestCaseInfo( const TestCaseInfo& other )
5309 : m_test( other.m_test ),
Phil Nash88b70822012-11-04 21:39:38 +00005310 m_className( other.m_className ),
Phil Nashd2ec8492012-08-23 19:48:57 +01005311 m_name( other.m_name ),
5312 m_description( other.m_description ),
Phil Nashfc1baac2012-09-15 17:53:27 +01005313 m_tags( other.m_tags ),
5314 m_lineInfo( other.m_lineInfo ),
5315 m_isHidden( other.m_isHidden )
Phil Nashd2ec8492012-08-23 19:48:57 +01005316 {}
5317
Phil Nash5bc030d2012-08-16 18:48:50 +01005318 void TestCaseInfo::invoke() const {
5319 m_test->invoke();
5320 }
5321
Phil Nash88b70822012-11-04 21:39:38 +00005322 const std::string& TestCaseInfo::getClassName() const {
5323 return m_className;
5324 }
Phil Nash5bc030d2012-08-16 18:48:50 +01005325 const std::string& TestCaseInfo::getName() const {
5326 return m_name;
5327 }
Phil Nash5bc030d2012-08-16 18:48:50 +01005328 const std::string& TestCaseInfo::getDescription() const {
5329 return m_description;
5330 }
Phil Nash5bc030d2012-08-16 18:48:50 +01005331 const SourceLineInfo& TestCaseInfo::getLineInfo() const {
5332 return m_lineInfo;
5333 }
5334
5335 bool TestCaseInfo::isHidden() const {
Phil Nashfc1baac2012-09-15 17:53:27 +01005336 return m_isHidden;
5337 }
5338
5339 bool TestCaseInfo::hasTag( const std::string& tag ) const {
5340 return m_tags.find( tag ) != m_tags.end();
5341 }
Phil Nash799ecf92012-09-24 08:30:13 +01005342 bool TestCaseInfo::matchesTags( const std::string& tagPattern ) const {
5343 TagExpression exp;
5344 TagExpressionParser( exp ).parse( tagPattern );
5345 return exp.matches( m_tags );
5346 }
Phil Nash67ec8702012-09-26 18:38:26 +01005347 const std::set<std::string>& TestCaseInfo::getTags() const {
Phil Nashfc1baac2012-09-15 17:53:27 +01005348 return m_tags;
Phil Nash5bc030d2012-08-16 18:48:50 +01005349 }
5350
5351 void TestCaseInfo::swap( TestCaseInfo& other ) {
5352 m_test.swap( other.m_test );
Phil Nash88b70822012-11-04 21:39:38 +00005353 m_className.swap( other.m_className );
Phil Nash5bc030d2012-08-16 18:48:50 +01005354 m_name.swap( other.m_name );
5355 m_description.swap( other.m_description );
Phil Nash88b70822012-11-04 21:39:38 +00005356 std::swap( m_lineInfo, other.m_lineInfo );
Phil Nash5bc030d2012-08-16 18:48:50 +01005357 }
5358
5359 bool TestCaseInfo::operator == ( const TestCaseInfo& other ) const {
Phil Nash88b70822012-11-04 21:39:38 +00005360 return m_test.get() == other.m_test.get() &&
5361 m_name == other.m_name &&
5362 m_className == other.m_className;
Phil Nash5bc030d2012-08-16 18:48:50 +01005363 }
5364
5365 bool TestCaseInfo::operator < ( const TestCaseInfo& other ) const {
5366 return m_name < other.m_name;
5367 }
Phil Nashd2ec8492012-08-23 19:48:57 +01005368 TestCaseInfo& TestCaseInfo::operator = ( const TestCaseInfo& other ) {
5369 TestCaseInfo temp( other );
5370 swap( temp );
5371 return *this;
5372 }
Phil Nash799ecf92012-09-24 08:30:13 +01005373
5374} // end namespace Catch
Phil Nash5bc030d2012-08-16 18:48:50 +01005375
Phil Nash7673a302012-11-15 22:15:41 +00005376// #included from: catch_version.hpp
5377#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
5378
5379namespace Catch {
5380
5381 // These numbers are maintained by a script
Phil Nasha90a88a2012-11-19 19:59:10 +00005382 Version libraryVersion = { 0, 9, 5, "integration" };
Phil Nash7673a302012-11-15 22:15:41 +00005383}
5384
Phil Nash56d5c422012-08-23 20:08:50 +01005385// #included from: ../reporters/catch_reporter_basic.hpp
5386#define TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
5387
5388// #included from: ../internal/catch_reporter_registrars.hpp
5389#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
5390
5391namespace Catch {
5392
5393 template<typename T>
5394 class ReporterRegistrar {
5395
5396 class ReporterFactory : public IReporterFactory {
5397
5398 virtual IReporter* create( const ReporterConfig& config ) const {
5399 return new T( config );
5400 }
5401
5402 virtual std::string getDescription() const {
5403 return T::getDescription();
5404 }
5405 };
5406
5407 public:
5408
5409 ReporterRegistrar( const std::string& name ) {
5410 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
5411 }
5412 };
5413}
5414
5415#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
5416 Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name );
5417
5418namespace Catch {
5419
Phil Nash56d5c422012-08-23 20:08:50 +01005420 class BasicReporter : public SharedImpl<IReporter> {
5421
5422 struct SpanInfo {
5423
5424 SpanInfo()
5425 : emitted( false )
5426 {}
5427
5428 SpanInfo( const std::string& spanName )
5429 : name( spanName ),
5430 emitted( false )
5431 {}
5432
5433 SpanInfo( const SpanInfo& other )
5434 : name( other.name ),
5435 emitted( other.emitted )
5436 {}
5437
5438 std::string name;
5439 bool emitted;
5440 };
5441
5442 public:
5443 BasicReporter( const ReporterConfig& config )
5444 : m_config( config ),
5445 m_firstSectionInTestCase( true ),
5446 m_aborted( false )
5447 {}
5448
5449 virtual ~BasicReporter();
5450
5451 static std::string getDescription() {
5452 return "Reports test results as lines of text";
5453 }
5454
5455 private:
5456
5457 void ReportCounts( const std::string& label, const Counts& counts, const std::string& allPrefix = "All " ) {
5458 if( counts.passed )
5459 m_config.stream << counts.failed << " of " << counts.total() << " " << label << "s failed";
5460 else
5461 m_config.stream << ( counts.failed > 1 ? allPrefix : "" ) << pluralise( counts.failed, label ) << " failed";
5462 }
5463
5464 void ReportCounts( const Totals& totals, const std::string& allPrefix = "All " ) {
5465 if( totals.assertions.total() == 0 ) {
5466 m_config.stream << "No tests ran";
5467 }
5468 else if( totals.assertions.failed ) {
5469 TextColour colour( TextColour::ResultError );
5470 ReportCounts( "test case", totals.testCases, allPrefix );
5471 if( totals.testCases.failed > 0 ) {
5472 m_config.stream << " (";
5473 ReportCounts( "assertion", totals.assertions, allPrefix );
5474 m_config.stream << ")";
5475 }
5476 }
5477 else {
5478 TextColour colour( TextColour::ResultSuccess );
5479 m_config.stream << allPrefix << "tests passed ("
5480 << pluralise( totals.assertions.passed, "assertion" ) << " in "
5481 << pluralise( totals.testCases.passed, "test case" ) << ")";
5482 }
5483 }
5484
5485 private: // IReporter
5486
5487 virtual bool shouldRedirectStdout() const {
5488 return false;
5489 }
5490
5491 virtual void StartTesting() {
5492 m_testingSpan = SpanInfo();
5493 }
5494
5495 virtual void Aborted() {
5496 m_aborted = true;
5497 }
5498
5499 virtual void EndTesting( const Totals& totals ) {
5500 // Output the overall test results even if "Started Testing" was not emitted
5501 if( m_aborted ) {
5502 m_config.stream << "\n[Testing aborted. ";
5503 ReportCounts( totals, "The first " );
5504 }
5505 else {
5506 m_config.stream << "\n[Testing completed. ";
5507 ReportCounts( totals );
5508 }
5509 m_config.stream << "]\n" << std::endl;
5510 }
5511
5512 virtual void StartGroup( const std::string& groupName ) {
5513 m_groupSpan = groupName;
5514 }
5515
5516 virtual void EndGroup( const std::string& groupName, const Totals& totals ) {
5517 if( m_groupSpan.emitted && !groupName.empty() ) {
5518 m_config.stream << "[End of group: '" << groupName << "'. ";
5519 ReportCounts( totals );
5520 m_config.stream << "]\n" << std::endl;
5521 m_groupSpan = SpanInfo();
5522 }
5523 }
5524
5525 virtual void StartTestCase( const TestCaseInfo& testInfo ) {
5526 m_testSpan = testInfo.getName();
5527 }
5528
5529 virtual void StartSection( const std::string& sectionName, const std::string& ) {
5530 m_sectionSpans.push_back( SpanInfo( sectionName ) );
5531 }
5532
Phil Nasha70fbe32012-08-31 08:10:36 +01005533 virtual void NoAssertionsInSection( const std::string& sectionName ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01005534 startSpansLazily();
Phil Nasha70fbe32012-08-31 08:10:36 +01005535 TextColour colour( TextColour::ResultError );
5536 m_config.stream << "\nNo assertions in section, '" << sectionName << "'\n" << std::endl;
5537 }
5538 virtual void NoAssertionsInTestCase( const std::string& testName ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01005539 startSpansLazily();
Phil Nasha70fbe32012-08-31 08:10:36 +01005540 TextColour colour( TextColour::ResultError );
5541 m_config.stream << "\nNo assertions in test case, '" << testName << "'\n" << std::endl;
5542 }
5543
Phil Nash56d5c422012-08-23 20:08:50 +01005544 virtual void EndSection( const std::string& sectionName, const Counts& assertions ) {
Phil Nasha70fbe32012-08-31 08:10:36 +01005545
Phil Nash56d5c422012-08-23 20:08:50 +01005546 SpanInfo& sectionSpan = m_sectionSpans.back();
5547 if( sectionSpan.emitted && !sectionSpan.name.empty() ) {
5548 m_config.stream << "[End of section: '" << sectionName << "' ";
5549
5550 if( assertions.failed ) {
5551 TextColour colour( TextColour::ResultError );
5552 ReportCounts( "assertion", assertions);
5553 }
5554 else {
5555 TextColour colour( TextColour::ResultSuccess );
5556 m_config.stream << ( assertions.passed > 1 ? "All " : "" )
5557 << pluralise( assertions.passed, "assertion" ) << " passed" ;
5558 }
5559 m_config.stream << "]\n" << std::endl;
5560 }
5561 m_sectionSpans.pop_back();
5562 }
5563
Phil Nash82acc2c2012-10-28 12:07:17 +00005564 virtual void Result( const AssertionResult& assertionResult ) {
5565 if( !m_config.includeSuccessfulResults && assertionResult.getResultType() == ResultWas::Ok )
Phil Nash56d5c422012-08-23 20:08:50 +01005566 return;
5567
Phil Nashe2d215e2012-09-07 17:52:35 +01005568 startSpansLazily();
Phil Nash56d5c422012-08-23 20:08:50 +01005569
Phil Nash82acc2c2012-10-28 12:07:17 +00005570 if( !assertionResult.getSourceInfo().empty() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01005571 TextColour colour( TextColour::FileName );
Phil Nash82acc2c2012-10-28 12:07:17 +00005572 m_config.stream << assertionResult.getSourceInfo();
Phil Nash56d5c422012-08-23 20:08:50 +01005573 }
5574
Phil Nash82acc2c2012-10-28 12:07:17 +00005575 if( assertionResult.hasExpression() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01005576 TextColour colour( TextColour::OriginalExpression );
Phil Nash82acc2c2012-10-28 12:07:17 +00005577 m_config.stream << assertionResult.getExpression();
Phil Nashd539da92012-11-13 09:44:52 +00005578 if( assertionResult.succeeded() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01005579 TextColour successColour( TextColour::Success );
5580 m_config.stream << " succeeded";
5581 }
5582 else {
5583 TextColour errorColour( TextColour::Error );
5584 m_config.stream << " failed";
Phil Nashd539da92012-11-13 09:44:52 +00005585 if( assertionResult.isOk() ) {
5586 TextColour okAnywayColour( TextColour::Success );
5587 m_config.stream << " - but was ok";
5588 }
Phil Nash56d5c422012-08-23 20:08:50 +01005589 }
5590 }
Phil Nash82acc2c2012-10-28 12:07:17 +00005591 switch( assertionResult.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01005592 case ResultWas::ThrewException:
Phil Nash355b95f2012-10-31 18:04:22 +00005593 {
5594 TextColour colour( TextColour::Error );
5595 if( assertionResult.hasExpression() )
5596 m_config.stream << " with unexpected";
5597 else
5598 m_config.stream << "Unexpected";
5599 m_config.stream << " exception with message: '" << assertionResult.getMessage() << "'";
5600 }
Phil Nash56d5c422012-08-23 20:08:50 +01005601 break;
5602 case ResultWas::DidntThrowException:
Phil Nash355b95f2012-10-31 18:04:22 +00005603 {
5604 TextColour colour( TextColour::Error );
5605 if( assertionResult.hasExpression() )
5606 m_config.stream << " because no exception was thrown where one was expected";
5607 else
5608 m_config.stream << "No exception thrown where one was expected";
5609 }
Phil Nash56d5c422012-08-23 20:08:50 +01005610 break;
5611 case ResultWas::Info:
Phil Nash355b95f2012-10-31 18:04:22 +00005612 {
5613 TextColour colour( TextColour::ReconstructedExpression );
5614 streamVariableLengthText( "info", assertionResult.getMessage() );
5615 }
Phil Nash56d5c422012-08-23 20:08:50 +01005616 break;
5617 case ResultWas::Warning:
Phil Nash355b95f2012-10-31 18:04:22 +00005618 {
5619 TextColour colour( TextColour::ReconstructedExpression );
5620 streamVariableLengthText( "warning", assertionResult.getMessage() );
5621 }
Phil Nash56d5c422012-08-23 20:08:50 +01005622 break;
5623 case ResultWas::ExplicitFailure:
Phil Nash355b95f2012-10-31 18:04:22 +00005624 {
5625 TextColour colour( TextColour::Error );
5626 m_config.stream << "failed with message: '" << assertionResult.getMessage() << "'";
5627 }
Phil Nash56d5c422012-08-23 20:08:50 +01005628 break;
5629 case ResultWas::Unknown: // These cases are here to prevent compiler warnings
5630 case ResultWas::Ok:
5631 case ResultWas::FailureBit:
5632 case ResultWas::ExpressionFailed:
5633 case ResultWas::Exception:
Phil Nash82acc2c2012-10-28 12:07:17 +00005634 if( !assertionResult.hasExpression() ) {
Phil Nashd539da92012-11-13 09:44:52 +00005635 if( assertionResult.succeeded() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01005636 TextColour colour( TextColour::Success );
5637 m_config.stream << " succeeded";
5638 }
5639 else {
5640 TextColour colour( TextColour::Error );
5641 m_config.stream << " failed";
Phil Nashd539da92012-11-13 09:44:52 +00005642 if( assertionResult.isOk() ) {
5643 TextColour okAnywayColour( TextColour::Success );
5644 m_config.stream << " - but was ok";
5645 }
Phil Nash56d5c422012-08-23 20:08:50 +01005646 }
5647 }
5648 break;
5649 }
5650
Phil Nash82acc2c2012-10-28 12:07:17 +00005651 if( assertionResult.hasExpandedExpression() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01005652 m_config.stream << " for: ";
Phil Nash5efa4bc2012-10-29 20:49:22 +00005653 if( assertionResult.getExpandedExpression().size() > 40 ) {
Phil Nash9444bbc2012-10-12 07:58:17 +01005654 m_config.stream << "\n";
Phil Nash5efa4bc2012-10-29 20:49:22 +00005655 if( assertionResult.getExpandedExpression().size() < 70 )
5656 m_config.stream << "\t";
5657 }
Phil Nash56d5c422012-08-23 20:08:50 +01005658 TextColour colour( TextColour::ReconstructedExpression );
Phil Nash82acc2c2012-10-28 12:07:17 +00005659 m_config.stream << assertionResult.getExpandedExpression();
Phil Nash56d5c422012-08-23 20:08:50 +01005660 }
5661 m_config.stream << std::endl;
5662 }
5663
5664 virtual void EndTestCase( const TestCaseInfo& testInfo,
5665 const Totals& totals,
5666 const std::string& stdOut,
5667 const std::string& stdErr ) {
5668 if( !stdOut.empty() ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01005669 startSpansLazily();
Phil Nash56d5c422012-08-23 20:08:50 +01005670 streamVariableLengthText( "stdout", stdOut );
5671 }
5672
5673 if( !stdErr.empty() ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01005674 startSpansLazily();
Phil Nash56d5c422012-08-23 20:08:50 +01005675 streamVariableLengthText( "stderr", stdErr );
5676 }
5677
5678 if( m_testSpan.emitted ) {
5679 m_config.stream << "[Finished: '" << testInfo.getName() << "' ";
5680 ReportCounts( totals );
5681 m_config.stream << "]" << std::endl;
5682 }
5683 }
5684
5685 private: // helpers
5686
Phil Nashe2d215e2012-09-07 17:52:35 +01005687 void startSpansLazily() {
Phil Nash56d5c422012-08-23 20:08:50 +01005688 if( !m_testingSpan.emitted ) {
5689 if( m_config.name.empty() )
5690 m_config.stream << "[Started testing]" << std::endl;
5691 else
5692 m_config.stream << "[Started testing: " << m_config.name << "]" << std::endl;
5693 m_testingSpan.emitted = true;
5694 }
5695
5696 if( !m_groupSpan.emitted && !m_groupSpan.name.empty() ) {
5697 m_config.stream << "[Started group: '" << m_groupSpan.name << "']" << std::endl;
5698 m_groupSpan.emitted = true;
5699 }
5700
5701 if( !m_testSpan.emitted ) {
5702 m_config.stream << std::endl << "[Running: " << m_testSpan.name << "]" << std::endl;
5703 m_testSpan.emitted = true;
5704 }
5705
5706 if( !m_sectionSpans.empty() ) {
5707 SpanInfo& sectionSpan = m_sectionSpans.back();
5708 if( !sectionSpan.emitted && !sectionSpan.name.empty() ) {
5709 if( m_firstSectionInTestCase ) {
5710 m_config.stream << "\n";
5711 m_firstSectionInTestCase = false;
5712 }
5713 std::vector<SpanInfo>::iterator it = m_sectionSpans.begin();
5714 std::vector<SpanInfo>::iterator itEnd = m_sectionSpans.end();
5715 for(; it != itEnd; ++it ) {
5716 SpanInfo& prevSpan = *it;
5717 if( !prevSpan.emitted && !prevSpan.name.empty() ) {
5718 m_config.stream << "[Started section: '" << prevSpan.name << "']" << std::endl;
5719 prevSpan.emitted = true;
5720 }
5721 }
5722 }
5723 }
5724 }
5725
5726 void streamVariableLengthText( const std::string& prefix, const std::string& text ) {
5727 std::string trimmed = trim( text );
5728 if( trimmed.find_first_of( "\r\n" ) == std::string::npos ) {
Phil Nash82acc2c2012-10-28 12:07:17 +00005729 m_config.stream << "[" << prefix << ": " << trimmed << "]";
Phil Nash56d5c422012-08-23 20:08:50 +01005730 }
5731 else {
5732 m_config.stream << "\n[" << prefix << "] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" << trimmed
5733 << "\n[end of " << prefix << "] <<<<<<<<<<<<<<<<<<<<<<<<\n";
5734 }
5735 }
5736
5737 private:
5738 ReporterConfig m_config;
5739 bool m_firstSectionInTestCase;
5740
5741 SpanInfo m_testingSpan;
5742 SpanInfo m_groupSpan;
5743 SpanInfo m_testSpan;
5744 std::vector<SpanInfo> m_sectionSpans;
5745 bool m_aborted;
5746 };
5747
5748} // end namespace Catch
5749
5750// #included from: ../reporters/catch_reporter_xml.hpp
5751#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
5752
5753// #included from: ../internal/catch_xmlwriter.hpp
5754#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
5755
5756#include <sstream>
Phil Nash9e7e63c2012-09-29 20:54:03 +01005757#include <iostream>
Phil Nash56d5c422012-08-23 20:08:50 +01005758#include <string>
5759#include <vector>
5760
5761namespace Catch {
5762
5763 class XmlWriter {
5764 public:
5765
5766 class ScopedElement {
5767 public:
5768 ScopedElement( XmlWriter* writer )
5769 : m_writer( writer )
5770 {}
5771
5772 ScopedElement( const ScopedElement& other )
5773 : m_writer( other.m_writer ){
5774 other.m_writer = NULL;
5775 }
5776
5777 ~ScopedElement() {
5778 if( m_writer )
5779 m_writer->endElement();
5780 }
5781
5782 ScopedElement& writeText( const std::string& text ) {
5783 m_writer->writeText( text );
5784 return *this;
5785 }
5786
5787 template<typename T>
5788 ScopedElement& writeAttribute( const std::string& name, const T& attribute ) {
5789 m_writer->writeAttribute( name, attribute );
5790 return *this;
5791 }
5792
5793 private:
5794 mutable XmlWriter* m_writer;
5795 };
5796
5797 XmlWriter()
5798 : m_tagIsOpen( false ),
5799 m_needsNewline( false ),
5800 m_os( &std::cout )
5801 {}
5802
5803 XmlWriter( std::ostream& os )
5804 : m_tagIsOpen( false ),
5805 m_needsNewline( false ),
5806 m_os( &os )
5807 {}
5808
5809 ~XmlWriter() {
5810 while( !m_tags.empty() )
5811 endElement();
5812 }
5813
5814 XmlWriter& operator = ( const XmlWriter& other ) {
5815 XmlWriter temp( other );
5816 swap( temp );
5817 return *this;
5818 }
5819
5820 void swap( XmlWriter& other ) {
5821 std::swap( m_tagIsOpen, other.m_tagIsOpen );
5822 std::swap( m_needsNewline, other.m_needsNewline );
5823 std::swap( m_tags, other.m_tags );
5824 std::swap( m_indent, other.m_indent );
5825 std::swap( m_os, other.m_os );
5826 }
5827
5828 XmlWriter& startElement( const std::string& name ) {
5829 ensureTagClosed();
5830 newlineIfNecessary();
5831 stream() << m_indent << "<" << name;
5832 m_tags.push_back( name );
5833 m_indent += " ";
5834 m_tagIsOpen = true;
5835 return *this;
5836 }
5837
5838 ScopedElement scopedElement( const std::string& name ) {
5839 ScopedElement scoped( this );
5840 startElement( name );
5841 return scoped;
5842 }
5843
5844 XmlWriter& endElement() {
5845 newlineIfNecessary();
5846 m_indent = m_indent.substr( 0, m_indent.size()-2 );
5847 if( m_tagIsOpen ) {
5848 stream() << "/>\n";
5849 m_tagIsOpen = false;
5850 }
5851 else {
5852 stream() << m_indent << "</" << m_tags.back() << ">\n";
5853 }
5854 m_tags.pop_back();
5855 return *this;
5856 }
5857
5858 XmlWriter& writeAttribute( const std::string& name, const std::string& attribute ) {
5859 if( !name.empty() && !attribute.empty() ) {
5860 stream() << " " << name << "=\"";
5861 writeEncodedText( attribute );
5862 stream() << "\"";
5863 }
5864 return *this;
5865 }
5866
5867 XmlWriter& writeAttribute( const std::string& name, bool attribute ) {
5868 stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
5869 return *this;
5870 }
5871
5872 template<typename T>
5873 XmlWriter& writeAttribute( const std::string& name, const T& attribute ) {
5874 if( !name.empty() )
5875 stream() << " " << name << "=\"" << attribute << "\"";
5876 return *this;
5877 }
5878
5879 XmlWriter& writeText( const std::string& text ) {
5880 if( !text.empty() ){
5881 bool tagWasOpen = m_tagIsOpen;
5882 ensureTagClosed();
5883 if( tagWasOpen )
5884 stream() << m_indent;
5885 writeEncodedText( text );
5886 m_needsNewline = true;
5887 }
5888 return *this;
5889 }
5890
5891 XmlWriter& writeComment( const std::string& text ) {
5892 ensureTagClosed();
5893 stream() << m_indent << "<!--" << text << "-->";
5894 m_needsNewline = true;
5895 return *this;
5896 }
5897
5898 XmlWriter& writeBlankLine() {
5899 ensureTagClosed();
5900 stream() << "\n";
5901 return *this;
5902 }
5903
5904 private:
5905
5906 std::ostream& stream() {
5907 return *m_os;
5908 }
5909
5910 void ensureTagClosed() {
5911 if( m_tagIsOpen ) {
5912 stream() << ">\n";
5913 m_tagIsOpen = false;
5914 }
5915 }
5916
5917 void newlineIfNecessary() {
5918 if( m_needsNewline ) {
5919 stream() << "\n";
5920 m_needsNewline = false;
5921 }
5922 }
5923
5924 void writeEncodedText( const std::string& text ) {
5925 static const char* charsToEncode = "<&\"";
5926 std::string mtext = text;
5927 std::string::size_type pos = mtext.find_first_of( charsToEncode );
5928 while( pos != std::string::npos ) {
5929 stream() << mtext.substr( 0, pos );
5930
5931 switch( mtext[pos] ) {
5932 case '<':
5933 stream() << "&lt;";
5934 break;
5935 case '&':
5936 stream() << "&amp;";
5937 break;
5938 case '\"':
5939 stream() << "&quot;";
5940 break;
5941 }
5942 mtext = mtext.substr( pos+1 );
5943 pos = mtext.find_first_of( charsToEncode );
5944 }
5945 stream() << mtext;
5946 }
5947
5948 bool m_tagIsOpen;
5949 bool m_needsNewline;
5950 std::vector<std::string> m_tags;
5951 std::string m_indent;
5952 std::ostream* m_os;
5953 };
5954
5955}
5956namespace Catch {
5957 class XmlReporter : public SharedImpl<IReporter> {
5958 public:
5959 XmlReporter( const ReporterConfig& config ) : m_config( config ) {}
5960
5961 static std::string getDescription() {
5962 return "Reports test results as an XML document";
5963 }
5964 virtual ~XmlReporter();
5965
5966 private: // IReporter
5967
5968 virtual bool shouldRedirectStdout() const {
5969 return true;
5970 }
5971
5972 virtual void StartTesting() {
5973 m_xml = XmlWriter( m_config.stream );
5974 m_xml.startElement( "Catch" );
5975 if( !m_config.name.empty() )
5976 m_xml.writeAttribute( "name", m_config.name );
5977 }
5978
5979 virtual void EndTesting( const Totals& totals ) {
5980 m_xml.scopedElement( "OverallResults" )
5981 .writeAttribute( "successes", totals.assertions.passed )
5982 .writeAttribute( "failures", totals.assertions.failed );
5983 m_xml.endElement();
5984 }
5985
5986 virtual void StartGroup( const std::string& groupName ) {
5987 m_xml.startElement( "Group" )
5988 .writeAttribute( "name", groupName );
5989 }
5990
5991 virtual void EndGroup( const std::string&, const Totals& totals ) {
5992 m_xml.scopedElement( "OverallResults" )
5993 .writeAttribute( "successes", totals.assertions.passed )
5994 .writeAttribute( "failures", totals.assertions.failed );
5995 m_xml.endElement();
5996 }
5997
5998 virtual void StartSection( const std::string& sectionName, const std::string& description ) {
5999 m_xml.startElement( "Section" )
6000 .writeAttribute( "name", sectionName )
6001 .writeAttribute( "description", description );
6002 }
Phil Nasha70fbe32012-08-31 08:10:36 +01006003 virtual void NoAssertionsInSection( const std::string& ) {}
6004 virtual void NoAssertionsInTestCase( const std::string& ) {}
Phil Nash56d5c422012-08-23 20:08:50 +01006005
6006 virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) {
6007 m_xml.scopedElement( "OverallResults" )
6008 .writeAttribute( "successes", assertions.passed )
6009 .writeAttribute( "failures", assertions.failed );
6010 m_xml.endElement();
6011 }
6012
6013 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) {
6014 m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.getName() );
6015 m_currentTestSuccess = true;
6016 }
6017
Phil Nash82acc2c2012-10-28 12:07:17 +00006018 virtual void Result( const Catch::AssertionResult& assertionResult ) {
6019 if( !m_config.includeSuccessfulResults && assertionResult.getResultType() == ResultWas::Ok )
Phil Nash56d5c422012-08-23 20:08:50 +01006020 return;
6021
Phil Nash82acc2c2012-10-28 12:07:17 +00006022 if( assertionResult.hasExpression() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006023 m_xml.startElement( "Expression" )
Phil Nashd539da92012-11-13 09:44:52 +00006024 .writeAttribute( "success", assertionResult.succeeded() )
Phil Nash82acc2c2012-10-28 12:07:17 +00006025 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
6026 .writeAttribute( "line", assertionResult.getSourceInfo().line );
Phil Nash56d5c422012-08-23 20:08:50 +01006027
6028 m_xml.scopedElement( "Original" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006029 .writeText( assertionResult.getExpression() );
Phil Nash56d5c422012-08-23 20:08:50 +01006030 m_xml.scopedElement( "Expanded" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006031 .writeText( assertionResult.getExpandedExpression() );
Phil Nashd539da92012-11-13 09:44:52 +00006032 m_currentTestSuccess &= assertionResult.succeeded();
Phil Nash56d5c422012-08-23 20:08:50 +01006033 }
6034
Phil Nash82acc2c2012-10-28 12:07:17 +00006035 switch( assertionResult.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006036 case ResultWas::ThrewException:
6037 m_xml.scopedElement( "Exception" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006038 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
6039 .writeAttribute( "line", assertionResult.getSourceInfo().line )
6040 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01006041 m_currentTestSuccess = false;
6042 break;
6043 case ResultWas::Info:
6044 m_xml.scopedElement( "Info" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006045 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01006046 break;
6047 case ResultWas::Warning:
6048 m_xml.scopedElement( "Warning" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006049 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01006050 break;
6051 case ResultWas::ExplicitFailure:
6052 m_xml.scopedElement( "Failure" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006053 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01006054 m_currentTestSuccess = false;
6055 break;
6056 case ResultWas::Unknown:
6057 case ResultWas::Ok:
6058 case ResultWas::FailureBit:
6059 case ResultWas::ExpressionFailed:
6060 case ResultWas::Exception:
6061 case ResultWas::DidntThrowException:
6062 break;
6063 }
Phil Nash82acc2c2012-10-28 12:07:17 +00006064 if( assertionResult.hasExpression() )
Phil Nash56d5c422012-08-23 20:08:50 +01006065 m_xml.endElement();
6066 }
6067
6068 virtual void Aborted() {
6069 // !TBD
6070 }
6071
6072 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) {
6073 m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess );
6074 m_xml.endElement();
6075 }
6076
6077 private:
6078 ReporterConfig m_config;
6079 bool m_currentTestSuccess;
6080 XmlWriter m_xml;
6081 };
6082
6083} // end namespace Catch
6084
6085// #included from: ../reporters/catch_reporter_junit.hpp
6086#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
6087
6088namespace Catch {
6089
6090 class JunitReporter : public SharedImpl<IReporter> {
6091
6092 struct TestStats {
6093 std::string m_element;
6094 std::string m_resultType;
6095 std::string m_message;
6096 std::string m_content;
6097 };
6098
6099 struct TestCaseStats {
6100
Phil Nash88b70822012-11-04 21:39:38 +00006101 TestCaseStats( const std::string& className, const std::string& name )
6102 : m_className( className ),
6103 m_name( name )
6104 {}
Phil Nash56d5c422012-08-23 20:08:50 +01006105
6106 double m_timeInSeconds;
6107 std::string m_status;
6108 std::string m_className;
6109 std::string m_name;
6110 std::vector<TestStats> m_testStats;
6111 };
6112
6113 struct Stats {
6114
6115 Stats( const std::string& name = std::string() )
6116 : m_testsCount( 0 ),
6117 m_failuresCount( 0 ),
6118 m_disabledCount( 0 ),
6119 m_errorsCount( 0 ),
6120 m_timeInSeconds( 0 ),
6121 m_name( name )
6122 {}
6123
6124 std::size_t m_testsCount;
6125 std::size_t m_failuresCount;
6126 std::size_t m_disabledCount;
6127 std::size_t m_errorsCount;
6128 double m_timeInSeconds;
6129 std::string m_name;
6130
6131 std::vector<TestCaseStats> m_testCaseStats;
6132 };
6133
6134 public:
6135 JunitReporter( const ReporterConfig& config )
6136 : m_config( config ),
6137 m_testSuiteStats( "AllTests" ),
6138 m_currentStats( &m_testSuiteStats )
6139 {}
6140 virtual ~JunitReporter();
6141
6142 static std::string getDescription() {
6143 return "Reports test results in an XML format that looks like Ant's junitreport target";
6144 }
6145
6146 private: // IReporter
6147
6148 virtual bool shouldRedirectStdout() const {
6149 return true;
6150 }
6151
6152 virtual void StartTesting(){}
6153
6154 virtual void StartGroup( const std::string& groupName ) {
Phil Nashef60d542012-11-16 08:47:03 +00006155 if( groupName.empty() )
Phil Nasha90a88a2012-11-19 19:59:10 +00006156 m_statsForSuites.push_back( Stats( m_config.name ) );
Phil Nashef60d542012-11-16 08:47:03 +00006157 else
6158 m_statsForSuites.push_back( Stats( groupName ) );
Phil Nash56d5c422012-08-23 20:08:50 +01006159 m_currentStats = &m_statsForSuites.back();
6160 }
6161
6162 virtual void EndGroup( const std::string&, const Totals& totals ) {
6163 m_currentStats->m_testsCount = totals.assertions.total();
6164 m_currentStats = &m_testSuiteStats;
6165 }
6166
6167 virtual void StartSection( const std::string&, const std::string& ){}
6168
Phil Nasha70fbe32012-08-31 08:10:36 +01006169 virtual void NoAssertionsInSection( const std::string& ) {}
6170 virtual void NoAssertionsInTestCase( const std::string& ) {}
6171
6172 virtual void EndSection( const std::string&, const Counts& ) {}
Phil Nash56d5c422012-08-23 20:08:50 +01006173
6174 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) {
Phil Nash88b70822012-11-04 21:39:38 +00006175 m_currentStats->m_testCaseStats.push_back( TestCaseStats( testInfo.getClassName(), testInfo.getName() ) );
Phil Nash56d5c422012-08-23 20:08:50 +01006176 }
6177
Phil Nash82acc2c2012-10-28 12:07:17 +00006178 virtual void Result( const Catch::AssertionResult& assertionResult ) {
6179 if( assertionResult.getResultType() != ResultWas::Ok || m_config.includeSuccessfulResults ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006180 TestCaseStats& testCaseStats = m_currentStats->m_testCaseStats.back();
6181 TestStats stats;
6182 std::ostringstream oss;
Phil Nash82acc2c2012-10-28 12:07:17 +00006183 if( !assertionResult.getMessage().empty() )
6184 oss << assertionResult.getMessage() << " at ";
6185 oss << assertionResult.getSourceInfo();
Phil Nash56d5c422012-08-23 20:08:50 +01006186 stats.m_content = oss.str();
Phil Nash82acc2c2012-10-28 12:07:17 +00006187 stats.m_message = assertionResult.getExpandedExpression();
6188 stats.m_resultType = assertionResult.getTestMacroName();
Phil Nash56d5c422012-08-23 20:08:50 +01006189
Phil Nash82acc2c2012-10-28 12:07:17 +00006190 switch( assertionResult.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006191 case ResultWas::ThrewException:
6192 stats.m_element = "error";
6193 m_currentStats->m_errorsCount++;
6194 break;
6195 case ResultWas::Info:
6196 stats.m_element = "info"; // !TBD ?
6197 break;
6198 case ResultWas::Warning:
6199 stats.m_element = "warning"; // !TBD ?
6200 break;
6201 case ResultWas::ExplicitFailure:
6202 stats.m_element = "failure";
6203 m_currentStats->m_failuresCount++;
6204 break;
6205 case ResultWas::ExpressionFailed:
6206 stats.m_element = "failure";
6207 m_currentStats->m_failuresCount++;
6208 break;
6209 case ResultWas::Ok:
6210 stats.m_element = "success";
6211 break;
6212 case ResultWas::Unknown:
6213 case ResultWas::FailureBit:
6214 case ResultWas::Exception:
6215 case ResultWas::DidntThrowException:
6216 break;
6217 }
6218 testCaseStats.m_testStats.push_back( stats );
6219 }
6220 }
6221
6222 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string& stdOut, const std::string& stdErr ) {
6223 if( !stdOut.empty() )
6224 m_stdOut << stdOut << "\n";
6225 if( !stdErr.empty() )
6226 m_stdErr << stdErr << "\n";
6227 }
6228
6229 virtual void Aborted() {
6230 // !TBD
6231 }
6232
6233 virtual void EndTesting( const Totals& ) {
6234 std::ostream& str = m_config.stream;
6235 {
6236 XmlWriter xml( str );
6237
6238 if( m_statsForSuites.size() > 0 )
6239 xml.startElement( "testsuites" );
6240
6241 std::vector<Stats>::const_iterator it = m_statsForSuites.begin();
6242 std::vector<Stats>::const_iterator itEnd = m_statsForSuites.end();
6243
6244 for(; it != itEnd; ++it ) {
6245 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
6246 xml.writeAttribute( "name", it->m_name );
6247 xml.writeAttribute( "errors", it->m_errorsCount );
6248 xml.writeAttribute( "failures", it->m_failuresCount );
6249 xml.writeAttribute( "tests", it->m_testsCount );
6250 xml.writeAttribute( "hostname", "tbd" );
6251 xml.writeAttribute( "time", "tbd" );
6252 xml.writeAttribute( "timestamp", "tbd" );
6253
6254 OutputTestCases( xml, *it );
6255 }
6256
6257 xml.scopedElement( "system-out" ).writeText( trim( m_stdOut.str() ) );
6258 xml.scopedElement( "system-err" ).writeText( trim( m_stdErr.str() ) );
6259 }
6260 }
6261
6262 void OutputTestCases( XmlWriter& xml, const Stats& stats ) {
6263 std::vector<TestCaseStats>::const_iterator it = stats.m_testCaseStats.begin();
6264 std::vector<TestCaseStats>::const_iterator itEnd = stats.m_testCaseStats.end();
6265 for(; it != itEnd; ++it ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006266
6267 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
6268 xml.writeAttribute( "classname", it->m_className );
6269 xml.writeAttribute( "name", it->m_name );
6270 xml.writeAttribute( "time", "tbd" );
6271
6272 OutputTestResult( xml, *it );
6273 }
6274 }
6275
6276 void OutputTestResult( XmlWriter& xml, const TestCaseStats& stats ) {
6277 std::vector<TestStats>::const_iterator it = stats.m_testStats.begin();
6278 std::vector<TestStats>::const_iterator itEnd = stats.m_testStats.end();
6279 for(; it != itEnd; ++it ) {
6280 if( it->m_element != "success" ) {
6281 XmlWriter::ScopedElement e = xml.scopedElement( it->m_element );
6282
6283 xml.writeAttribute( "message", it->m_message );
6284 xml.writeAttribute( "type", it->m_resultType );
6285 if( !it->m_content.empty() )
6286 xml.writeText( it->m_content );
6287 }
6288 }
6289 }
6290
6291 private:
6292 ReporterConfig m_config;
6293 bool m_currentTestSuccess;
6294
6295 Stats m_testSuiteStats;
6296 Stats* m_currentStats;
6297 std::vector<Stats> m_statsForSuites;
6298 std::ostringstream m_stdOut;
6299 std::ostringstream m_stdErr;
6300 };
6301
6302} // end namespace Catch
6303
Phil Nasha695eb92012-08-13 07:46:10 +01006304namespace Catch {
6305 NonCopyable::~NonCopyable() {}
6306 IShared::~IShared() {}
6307 StreamBufBase::~StreamBufBase() {}
6308 IContext::~IContext() {}
6309 IResultCapture::~IResultCapture() {}
6310 ITestCase::~ITestCase() {}
6311 ITestCaseRegistry::~ITestCaseRegistry() {}
6312 IRegistryHub::~IRegistryHub() {}
6313 IMutableRegistryHub::~IMutableRegistryHub() {}
6314 IExceptionTranslator::~IExceptionTranslator() {}
6315 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
6316 IReporter::~IReporter() {}
6317 IReporterFactory::~IReporterFactory() {}
6318 IReporterRegistry::~IReporterRegistry() {}
6319 BasicReporter::~BasicReporter() {}
6320 IRunner::~IRunner() {}
6321 IMutableContext::~IMutableContext() {}
6322 IConfig::~IConfig() {}
6323 XmlReporter::~XmlReporter() {}
6324 JunitReporter::~JunitReporter() {}
6325 TestRegistry::~TestRegistry() {}
6326 FreeFunctionTestCase::~FreeFunctionTestCase() {}
6327 IGeneratorInfo::~IGeneratorInfo() {}
6328 IGeneratorsForTest::~IGeneratorsForTest() {}
Phil Nash799ecf92012-09-24 08:30:13 +01006329 TagParser::~TagParser() {}
6330 TagExtracter::~TagExtracter() {}
6331 TagExpressionParser::~TagExpressionParser() {}
Phil Nasha695eb92012-08-13 07:46:10 +01006332
Phil Nash9444bbc2012-10-12 07:58:17 +01006333 Matchers::Impl::StdString::Equals::~Equals() {}
6334 Matchers::Impl::StdString::Contains::~Contains() {}
6335 Matchers::Impl::StdString::StartsWith::~StartsWith() {}
6336 Matchers::Impl::StdString::EndsWith::~EndsWith() {}
6337
Phil Nasha695eb92012-08-13 07:46:10 +01006338 void Config::dummy() {}
6339
Phil Nash56d5c422012-08-23 20:08:50 +01006340 INTERNAL_CATCH_REGISTER_REPORTER( "basic", BasicReporter )
6341 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
6342 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
6343
Phil Nasha695eb92012-08-13 07:46:10 +01006344}
6345
Phil Nash5bc030d2012-08-16 18:48:50 +01006346#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01006347#pragma clang diagnostic pop
Phil Nash89d1e6c2011-05-24 08:23:02 +01006348#endif
Matt Wozniskif29c8982012-09-17 01:42:29 -04006349
Phil Nash5bc030d2012-08-16 18:48:50 +01006350#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01006351
6352#ifdef CATCH_CONFIG_MAIN
6353// #included from: internal/catch_default_main.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01006354#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01006355
Phil Nash176eb812012-05-11 08:17:16 +01006356#ifndef __OBJC__
Phil Nash89d1e6c2011-05-24 08:23:02 +01006357
Phil Nash176eb812012-05-11 08:17:16 +01006358// Standard C/C++ main entry point
6359int main (int argc, char * const argv[]) {
6360 return Catch::Main( argc, argv );
6361}
6362
6363#else // __OBJC__
6364
6365// Objective-C entry point
6366int main (int argc, char * const argv[]) {
Phil Nash53c990a2012-03-17 18:20:06 +00006367#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +01006368 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Phil Nash53c990a2012-03-17 18:20:06 +00006369#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01006370
6371 Catch::registerTestMethods();
Phil Nash89d1e6c2011-05-24 08:23:02 +01006372 int result = Catch::Main( argc, (char* const*)argv );
6373
Phil Nash53c990a2012-03-17 18:20:06 +00006374#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +01006375 [pool drain];
Phil Nash53c990a2012-03-17 18:20:06 +00006376#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01006377
Phil Nashdd5b9c22012-02-18 09:58:30 +00006378 return result;
Phil Nash89d1e6c2011-05-24 08:23:02 +01006379}
6380
Phil Nash176eb812012-05-11 08:17:16 +01006381#endif // __OBJC__
6382
Phil Nash89d1e6c2011-05-24 08:23:02 +01006383#endif
6384
Phil Nash89d1e6c2011-05-24 08:23:02 +01006385//////
6386
Phil Nash46bcd4b2012-07-20 18:43:48 +01006387// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
6388#ifdef CATCH_CONFIG_PREFIX_ALL
6389
Phil Nashaf1a3212012-11-10 18:46:39 +00006390#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
6391#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "CATCH_REQUIRE_FALSE" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01006392
Phil Nashaf1a3212012-11-10 18:46:39 +00006393#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" )
6394#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
6395#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01006396
Phil Nashaf1a3212012-11-10 18:46:39 +00006397#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
6398#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CATCH_CHECK_FALSE" )
6399#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" )
6400#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
Phil Nash7717c292012-11-13 09:45:29 +00006401#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01006402
Phil Nashaf1a3212012-11-10 18:46:39 +00006403#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
6404#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
6405#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01006406
Phil Nashaf1a3212012-11-10 18:46:39 +00006407#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
6408#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01006409
Phil Nashaf1a3212012-11-10 18:46:39 +00006410#define CATCH_INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, Catch::ResultDisposition::ContinueOnFailure, "CATCH_INFO" )
6411#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN" )
6412#define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL" )
6413#define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006414#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg, "CATCH_SCOPED_INFO" )
Phil Nashaf1a3212012-11-10 18:46:39 +00006415#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CAPTURE" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006416#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_SCOPED_INFO( #msg " := " << msg, "CATCH_SCOPED_CAPTURE" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01006417
6418#define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
6419
6420#define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
6421#define CATCH_TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
6422#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" )
6423#define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
6424
6425#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
6426
6427#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
6428
Phil Nash46bcd4b2012-07-20 18:43:48 +01006429// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
6430#else
6431
Phil Nashaf1a3212012-11-10 18:46:39 +00006432#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
6433#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "REQUIRE_FALSE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006434
Phil Nashaf1a3212012-11-10 18:46:39 +00006435#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "REQUIRE_THROWS" )
6436#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
6437#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006438
Phil Nashaf1a3212012-11-10 18:46:39 +00006439#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
6440#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CHECK_FALSE" )
6441#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" )
6442#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
Phil Nashd539da92012-11-13 09:44:52 +00006443#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006444
Phil Nashaf1a3212012-11-10 18:46:39 +00006445#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" )
6446#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
6447#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006448
Phil Nashaf1a3212012-11-10 18:46:39 +00006449#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
6450#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
Phil Nash78d95a02012-03-04 21:22:36 +00006451
Phil Nashaf1a3212012-11-10 18:46:39 +00006452#define INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, Catch::ResultDisposition::ContinueOnFailure, "INFO" )
6453#define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN" )
6454#define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL" )
6455#define SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006456#define SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg, "SCOPED_INFO" )
Phil Nashaf1a3212012-11-10 18:46:39 +00006457#define CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, Catch::ResultDisposition::ContinueOnFailure, "CAPTURE" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006458#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_SCOPED_INFO( #msg " := " << msg, "SCOPED_CAPTURE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006459
6460#define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
6461
6462#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
6463#define TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
6464#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01006465#define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006466
6467#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006468
6469#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
6470
Phil Nash46bcd4b2012-07-20 18:43:48 +01006471#endif
6472
6473#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006474
6475using Catch::Detail::Approx;
6476
Phil Nash5bc030d2012-08-16 18:48:50 +01006477#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01006478#pragma clang diagnostic pop
Phil Nash5bc030d2012-08-16 18:48:50 +01006479#endif
Phil Nasha695eb92012-08-13 07:46:10 +01006480
Phil Nashaec1e5e2012-05-09 19:37:51 +01006481#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01006482