blob: 7ea226aca48a03e18ee22c6a5ecdeeac58c4f30e [file] [log] [blame]
Phil Nash89d1e6c2011-05-24 08:23:02 +01001/*
Phil Nash7673a302012-11-15 22:15:41 +00002 * CATCH v0.9 build 1 (integration branch)
3 * Generated: 2012-11-15 22:13:35.214657
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 Nash70c5ef92012-11-13 21:46:01 +0000691 inline bool shouldContinueOnFailure( int flags ) { return flags & ResultDisposition::ContinueOnFailure; }
692 inline bool shouldNegate( int flags ) { return flags & ResultDisposition::NegateResult; }
693 inline bool shouldSuppressFailure( int flags ) { return flags & ResultDisposition::SuppressFail; }
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:
Phil Nashb5b1b1e2012-11-06 19:13:25 +0000942 ExpressionLhs( const 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 {
3032 return m_argv[0];
3033 }
Phil Nasha695eb92012-08-13 07:46:10 +01003034 Command find( const std::string& arg1, const std::string& arg2, const std::string& arg3 ) const {
3035 return find( arg1 ) + find( arg2 ) + find( arg3 );
3036 }
3037
3038 Command find( const std::string& shortArg, const std::string& longArg ) const {
3039 return find( shortArg ) + find( longArg );
3040 }
3041 Command find( const std::string& arg ) const {
Phil Nashecf934b2012-08-27 21:42:55 +01003042 if( arg.empty() )
3043 return getArgs( "", 1 );
3044 else
3045 for( std::size_t i = 1; i < m_argc; ++i )
3046 if( m_argv[i] == arg )
3047 return getArgs( m_argv[i], i+1 );
Phil Nasha695eb92012-08-13 07:46:10 +01003048 return Command();
3049 }
Phil Nashe571e6f2012-08-24 18:54:56 +01003050 Command getDefaultArgs() const {
3051 return getArgs( "", 1 );
3052 }
Phil Nasha695eb92012-08-13 07:46:10 +01003053
3054 private:
Phil Nashe571e6f2012-08-24 18:54:56 +01003055 Command getArgs( const std::string& cmdName, std::size_t from ) const {
3056 Command command( cmdName );
3057 for( std::size_t i = from; i < m_argc && m_argv[i][0] != '-'; ++i )
Phil Nasha695eb92012-08-13 07:46:10 +01003058 command += m_argv[i];
3059 return command;
3060 }
3061
3062 std::size_t m_argc;
3063 char const * const * m_argv;
3064 };
3065
Phil Nashecf934b2012-08-27 21:42:55 +01003066 class OptionParser : public SharedImpl<IShared> {
3067 public:
3068 OptionParser( int minArgs = 0, int maxArgs = 0 )
3069 : m_minArgs( minArgs ), m_maxArgs( maxArgs )
3070 {}
Phil Nasha695eb92012-08-13 07:46:10 +01003071
Phil Nashecf934b2012-08-27 21:42:55 +01003072 virtual ~OptionParser() {}
Phil Nasha695eb92012-08-13 07:46:10 +01003073
Phil Nashecf934b2012-08-27 21:42:55 +01003074 Command find( const CommandParser& parser ) const {
3075 Command cmd;
3076 for( std::vector<std::string>::const_iterator it = m_optionNames.begin();
3077 it != m_optionNames.end();
3078 ++it )
3079 cmd += parser.find( *it );
3080 return cmd;
3081 }
3082
3083 void validateArgs( const Command& args ) const {
3084 if( tooFewArgs( args ) || tooManyArgs( args ) ) {
3085 std::ostringstream oss;
3086 if( m_maxArgs == -1 )
3087 oss <<"Expected at least " << pluralise( static_cast<std::size_t>( m_minArgs ), "argument" );
3088 else if( m_minArgs == m_maxArgs )
3089 oss <<"Expected " << pluralise( static_cast<std::size_t>( m_minArgs ), "argument" );
Phil Nasha695eb92012-08-13 07:46:10 +01003090 else
Phil Nashecf934b2012-08-27 21:42:55 +01003091 oss <<"Expected between " << m_minArgs << " and " << m_maxArgs << " argument";
3092 args.raiseError( oss.str() );
Phil Nasha695eb92012-08-13 07:46:10 +01003093 }
Phil Nashecf934b2012-08-27 21:42:55 +01003094 }
3095
3096 void parseIntoConfig( const CommandParser& parser, ConfigData& config ) {
3097 if( Command cmd = find( parser ) ) {
3098 validateArgs( cmd );
3099 parseIntoConfig( cmd, config );
3100 }
3101 }
3102
3103 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) = 0;
3104 virtual std::string argsSynopsis() const = 0;
3105 virtual std::string optionSummary() const = 0;
Phil Nashe2d215e2012-09-07 17:52:35 +01003106 virtual std::string optionDescription() const { return ""; };
Phil Nashecf934b2012-08-27 21:42:55 +01003107
3108 std::string optionNames() const {
3109 std::string names;
3110 for( std::vector<std::string>::const_iterator it = m_optionNames.begin();
3111 it != m_optionNames.end();
3112 ++it ) {
3113 if( !it->empty() ) {
3114 if( !names.empty() )
3115 names += ", ";
3116 names += *it;
3117 }
3118 else {
3119 names = "[" + names;
3120 }
3121 }
3122 if( names[0] == '[' )
3123 names += "]";
3124 return names;
3125 }
3126
3127 protected:
3128
3129 bool tooFewArgs( const Command& args ) const {
3130 return args.argsCount() < static_cast<std::size_t>( m_minArgs );
3131 }
3132 bool tooManyArgs( const Command& args ) const {
3133 return m_maxArgs >= 0 && args.argsCount() > static_cast<std::size_t>( m_maxArgs );
3134 }
3135 std::vector<std::string> m_optionNames;
3136 int m_minArgs;
3137 int m_maxArgs;
3138 };
3139
3140 namespace Options {
3141
3142 class HelpOptionParser : public OptionParser {
3143 public:
3144 HelpOptionParser() {
3145 m_optionNames.push_back( "-?" );
3146 m_optionNames.push_back( "-h" );
3147 m_optionNames.push_back( "--help" );
3148 }
3149 virtual std::string argsSynopsis() const {
Phil Nash67ec8702012-09-26 18:38:26 +01003150 return "[<option for help on> ...]";
Phil Nashecf934b2012-08-27 21:42:55 +01003151 }
3152 virtual std::string optionSummary() const {
Phil Nash67ec8702012-09-26 18:38:26 +01003153 return "Shows this usage summary, or help on a specific option, or options, if supplied";
Phil Nashe2d215e2012-09-07 17:52:35 +01003154 }
3155 virtual std::string optionDescription() const {
3156 return "";
Phil Nashecf934b2012-08-27 21:42:55 +01003157 }
3158
3159 virtual void parseIntoConfig( const Command&, ConfigData& ) {
3160 // Does not affect config
3161 }
3162 };
3163
3164 class TestCaseOptionParser : public OptionParser {
3165 public:
3166 TestCaseOptionParser() : OptionParser( 1, -1 ) {
3167 m_optionNames.push_back( "-t" );
3168 m_optionNames.push_back( "--test" );
3169 m_optionNames.push_back( "" ); // default option
3170 }
3171 virtual std::string argsSynopsis() const {
3172 return "<testspec> [<testspec>...]";
3173 }
3174 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003175 return "Specifies which test case or cases to run";
3176 }
3177
3178 // Lines are split at the nearest prior space char to the 80 char column.
3179 // Tab chars are removed from the output but their positions are used to align
3180 // subsequently wrapped lines
3181 virtual std::string optionDescription() const {
Phil Nashf7418eb2012-09-09 11:44:30 +01003182 return
3183 "This option allows one ore more test specs to be supplied. Each spec either fully "
3184 "specifies a test case or is a pattern containing wildcards to match a set of test "
3185 "cases. If this option is not provided then all test cases, except those prefixed "
3186 "by './' are run\n"
3187 "\n"
3188 "Specs must be enclosed in \"quotes\" if they contain spaces. If they do not "
3189 "contain spaces the quotes are optional.\n"
3190 "\n"
3191 "Wildcards consist of the * character at the beginning, end, or both and can substitute for "
3192 "any number of any characters (including none)\n"
3193 "\n"
3194 "If spec is prefixed with exclude: or the ~ character then the pattern matches an exclusion. "
3195 "This means that tests matching the pattern are excluded from the set - even if a prior "
Phil Nash799ecf92012-09-24 08:30:13 +01003196 "inclusion spec included them. Subsequent inclusion specs will take precedence, however. "
Phil Nashf7418eb2012-09-09 11:44:30 +01003197 "Inclusions and exclusions are evaluated in left-to-right order.\n"
3198 "\n"
3199 "Examples:\n"
3200 "\n"
3201 " -t thisTestOnly \tMatches the test case called, 'thisTestOnly'\n"
3202 " -t \"this test only\" \tMatches the test case called, 'this test only'\n"
3203 " -t these/* \tMatches all cases starting with 'these/'\n"
3204 " -t exclude:notThis \tMatches all tests except, 'notThis'\n"
3205 " -t ~notThis \tMatches all tests except, 'notThis'\n"
3206 " -t ~*private* \tMatches all tests except those that contain 'private'\n"
3207 " -t a/* ~a/b/* a/b/c \tMatches all tests that start with 'a/', except those "
3208 "that start with 'a/b/', except 'a/b/c', which is included";
Phil Nashecf934b2012-08-27 21:42:55 +01003209 }
3210
3211 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3212 std::string groupName;
3213 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
3214 if( i != 0 )
3215 groupName += " ";
3216 groupName += cmd[i];
3217 }
3218 TestCaseFilters filters( groupName );
Phil Nashe2d215e2012-09-07 17:52:35 +01003219 for( std::size_t i = 0; i < cmd.argsCount(); ++i )
3220 filters.addFilter( TestCaseFilter( cmd[i] ) );
Phil Nashecf934b2012-08-27 21:42:55 +01003221 config.filters.push_back( filters );
3222 }
3223 };
3224
Phil Nash799ecf92012-09-24 08:30:13 +01003225 class TagOptionParser : public OptionParser {
3226 public:
3227 TagOptionParser() : OptionParser( 1, -1 ) {
3228 m_optionNames.push_back( "-g" );
3229 m_optionNames.push_back( "--tag" );
3230 }
3231 virtual std::string argsSynopsis() const {
3232 return "<tagspec> [,<tagspec>...]";
3233 }
3234 virtual std::string optionSummary() const {
3235 return "Matches test cases against tags or tag patterns";
3236 }
3237
3238 // Lines are split at the nearest prior space char to the 80 char column.
3239 // Tab chars are removed from the output but their positions are used to align
3240 // subsequently wrapped lines
3241 virtual std::string optionDescription() const {
3242 return
Phil Nasha1dc7e32012-11-06 19:34:35 +00003243 "This option allows one or more tags or tag patterns to be specified.\n"
3244 "Each tag is enclosed in square brackets. A series of tags form an AND expression "
3245 "wheras a comma seperated sequence forms an OR expression. e.g.:\n\n"
3246 " -g [one][two],[three]\n\n"
3247 "This matches all tests tagged [one] and [two], as well as all tests tagged [three].\n\n"
3248 "Tags can be negated with the ~ character. This removes matching tests from the set. e.g.:\n\n"
3249 " -g [one]~[two]\n\n"
3250 "matches all tests tagged [one], except those also tagged [two]";
Phil Nash799ecf92012-09-24 08:30:13 +01003251 }
3252
3253 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
Phil Nash67ec8702012-09-26 18:38:26 +01003254 std::string groupName;
3255 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
3256 if( i != 0 )
3257 groupName += " ";
3258 groupName += cmd[i];
3259 }
3260 TestCaseFilters filters( groupName );
3261 for( std::size_t i = 0; i < cmd.argsCount(); ++i )
3262 filters.addTags( cmd[i] );
3263 config.filters.push_back( filters );
Phil Nash799ecf92012-09-24 08:30:13 +01003264 }
3265 };
3266
Phil Nashecf934b2012-08-27 21:42:55 +01003267 class ListOptionParser : public OptionParser {
3268 public:
3269 ListOptionParser() : OptionParser( 0, 2 ) {
3270 m_optionNames.push_back( "-l" );
3271 m_optionNames.push_back( "--list" );
3272 }
3273 virtual std::string argsSynopsis() const {
3274 return "[all | tests | reporters [xml]]";
3275 }
3276 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003277 return "Lists available tests or reporters";
3278 }
3279
3280 virtual std::string optionDescription() const {
Phil Nashf7418eb2012-09-09 11:44:30 +01003281 return
3282 "With no arguments this option will list all registered tests - one per line.\n"
3283 "Supplying the xml argument formats the list as an xml document (which may be useful for "
3284 "consumption by other tools).\n"
3285 "Supplying the tests or reporters lists tests or reporters respectively - with descriptions.\n"
3286 "\n"
3287 "Examples:\n"
3288 "\n"
3289 " -l\n"
3290 " -l tests\n"
3291 " -l reporters xml\n"
3292 " -l xml";
Phil Nashecf934b2012-08-27 21:42:55 +01003293 }
3294
3295 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3296 config.listSpec = List::TestNames;
3297 if( cmd.argsCount() >= 1 ) {
3298 if( cmd[0] == "all" )
3299 config.listSpec = List::All;
3300 else if( cmd[0] == "tests" )
3301 config.listSpec = List::Tests;
3302 else if( cmd[0] == "reporters" )
3303 config.listSpec = List::Reports;
3304 else
3305 cmd.raiseError( "Expected [tests] or [reporters]" );
3306 }
3307 if( cmd.argsCount() >= 2 ) {
3308 if( cmd[1] == "xml" )
3309 config.listSpec = static_cast<List::What>( config.listSpec | List::AsXml );
3310 else if( cmd[1] == "text" )
3311 config.listSpec = static_cast<List::What>( config.listSpec | List::AsText );
3312 else
3313 cmd.raiseError( "Expected [xml] or [text]" );
3314 }
3315 }
3316 };
3317
3318 class ReporterOptionParser : public OptionParser {
3319 public:
3320 ReporterOptionParser() : OptionParser( 1, 1 ) {
3321 m_optionNames.push_back( "-r" );
3322 m_optionNames.push_back( "--reporter" );
3323 }
3324 virtual std::string argsSynopsis() const {
3325 return "<reporter name>";
3326 }
3327 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003328 return "Specifies type of reporter";
3329 }
3330
3331 virtual std::string optionDescription() const {
Phil Nashf7418eb2012-09-09 11:44:30 +01003332 return
3333 "A reporter is an object that formats and structures the output of running "
3334 "tests, and potentially summarises the results. By default a basic reporter "
3335 "is used that writes IDE friendly results. CATCH comes bundled with some "
3336 "alternative reporters, but more can be added in client code.\n"
3337 "\n"
3338 "The bundled reporters are:\n"
3339 " -r basic\n"
3340 " -r xml\n"
3341 " -r junit\n"
3342 "\n"
3343 "The JUnit reporter is an xml format that follows the structure of the JUnit "
3344 "XML Report ANT task, as consumed by a number of third-party tools, "
3345 "including Continuous Integration servers such as Jenkins.\n"
3346 "If not otherwise needed, the standard XML reporter is preferred as this is "
3347 "a streaming reporter, whereas the Junit reporter needs to hold all its "
3348 "results until the end so it can write the overall results into attributes "
3349 "of the root node.";
Phil Nashecf934b2012-08-27 21:42:55 +01003350 }
3351
3352 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3353 config.reporter = cmd[0];
3354 }
3355 };
3356
3357 class OutputOptionParser : public OptionParser {
3358 public:
3359 OutputOptionParser() : OptionParser( 1, 1 ) {
3360 m_optionNames.push_back( "-o" );
3361 m_optionNames.push_back( "--out" );
3362 }
3363 virtual std::string argsSynopsis() const {
3364 return "<file name>|<%stream name>";
3365 }
3366 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003367 return "Sends output to a file or stream";
Phil Nashecf934b2012-08-27 21:42:55 +01003368 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003369 virtual std::string optionDescription() const {
3370 return
3371 "Use this option to send all output to a file or a stream. By default output is "
Phil Nash799ecf92012-09-24 08:30:13 +01003372 "sent to stdout (note that uses of stdout and stderr from within test cases are "
Phil Nashf7418eb2012-09-09 11:44:30 +01003373 "redirected and included in the report - so even stderr will effectively end up "
Phil Nash799ecf92012-09-24 08:30:13 +01003374 "on stdout). If the name begins with % it is interpreted as a stream. "
Phil Nashf7418eb2012-09-09 11:44:30 +01003375 "Otherwise it is treated as a filename.\n"
3376 "\n"
3377 "Examples are:\n"
3378 "\n"
3379 " -o filename.txt\n"
3380 " -o \"long filename.txt\"\n"
3381 " -o %stdout\n"
3382 " -o %stderr\n"
3383 " -o %debug \t(The IDE's debug output window - currently only Windows' "
3384 "OutputDebugString is supported).";
3385 }
Phil Nashecf934b2012-08-27 21:42:55 +01003386 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3387 if( cmd[0][0] == '%' )
3388 config.stream = cmd[0].substr( 1 );
Phil Nasha695eb92012-08-13 07:46:10 +01003389 else
Phil Nashecf934b2012-08-27 21:42:55 +01003390 config.outputFilename = cmd[0];
Phil Nasha695eb92012-08-13 07:46:10 +01003391 }
Phil Nashecf934b2012-08-27 21:42:55 +01003392 };
Phil Nasha695eb92012-08-13 07:46:10 +01003393
Phil Nashf7418eb2012-09-09 11:44:30 +01003394 class SuccessOptionParser : public OptionParser {
Phil Nashecf934b2012-08-27 21:42:55 +01003395 public:
Phil Nashf7418eb2012-09-09 11:44:30 +01003396 SuccessOptionParser() {
Phil Nashecf934b2012-08-27 21:42:55 +01003397 m_optionNames.push_back( "-s" );
3398 m_optionNames.push_back( "--success" );
Phil Nash56d5c422012-08-23 20:08:50 +01003399 }
Phil Nashecf934b2012-08-27 21:42:55 +01003400 virtual std::string argsSynopsis() const {
3401 return "";
Phil Nash56d5c422012-08-23 20:08:50 +01003402 }
Phil Nashecf934b2012-08-27 21:42:55 +01003403 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003404 return "Shows results for successful tests";
Phil Nasha695eb92012-08-13 07:46:10 +01003405 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003406 virtual std::string optionDescription() const {
3407 return
3408 "Usually you only want to see reporting for failed tests. Sometimes it's useful "
3409 "to see all the output (especially when you don't trust that that test you just "
Phil Nash799ecf92012-09-24 08:30:13 +01003410 "added worked first time!). To see successful, as well as failing, test results "
Phil Nashf7418eb2012-09-09 11:44:30 +01003411 "just pass this option.";
3412 }
Phil Nash78c92e62012-08-27 21:48:15 +01003413 virtual void parseIntoConfig( const Command&, ConfigData& config ) {
Phil Nashecf934b2012-08-27 21:42:55 +01003414 config.includeWhichResults = Include::SuccessfulResults;
3415 }
3416 };
Phil Nasha695eb92012-08-13 07:46:10 +01003417
Phil Nashecf934b2012-08-27 21:42:55 +01003418 class DebugBreakOptionParser : public OptionParser {
3419 public:
3420 DebugBreakOptionParser() {
3421 m_optionNames.push_back( "-b" );
3422 m_optionNames.push_back( "--break" );
3423 }
3424 virtual std::string argsSynopsis() const {
3425 return "";
3426 }
3427 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003428 return "Breaks into the debugger on failure";
Phil Nashecf934b2012-08-27 21:42:55 +01003429 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003430 virtual std::string optionDescription() const {
3431 return
3432 "In some IDEs (currently XCode and Visual Studio) it is possible for CATCH to "
3433 "break into the debugger on a test failure. This can be very helpful during "
3434 "debug sessions - especially when there is more than one path through a "
3435 "particular test. In addition to the command line option, ensure you have "
3436 "built your code with the DEBUG preprocessor symbol";
3437 }
Phil Nashecf934b2012-08-27 21:42:55 +01003438
Phil Nash78c92e62012-08-27 21:48:15 +01003439 virtual void parseIntoConfig( const Command&, ConfigData& config ) {
Phil Nashecf934b2012-08-27 21:42:55 +01003440 config.shouldDebugBreak = true;
3441 }
3442 };
3443
3444 class NameOptionParser : public OptionParser {
3445 public:
3446 NameOptionParser() : OptionParser( 1, 1 ) {
3447 m_optionNames.push_back( "-n" );
3448 m_optionNames.push_back( "--name" );
3449 }
3450 virtual std::string argsSynopsis() const {
3451 return "<name>";
3452 }
3453 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003454 return "Names a test run";
Phil Nashecf934b2012-08-27 21:42:55 +01003455 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003456 virtual std::string optionDescription() const {
3457 return
3458 "If a name is supplied it will be used by the reporter to provide an overall "
3459 "name for the test run. This can be useful if you are sending to a file, for "
3460 "example, and need to distinguish different test runs - either from different "
3461 "Catch executables or runs of the same executable with different options.\n"
3462 "\n"
3463 "Examples:\n"
3464 "\n"
3465 " -n testRun\n"
3466 " -n \"tests of the widget component\"";
3467 }
Phil Nashecf934b2012-08-27 21:42:55 +01003468
3469 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3470 config.name = cmd[0];
3471 }
3472 };
3473
3474 class AbortOptionParser : public OptionParser {
3475 public:
3476 AbortOptionParser() : OptionParser( 0, 1 ) {
3477 m_optionNames.push_back( "-a" );
3478 m_optionNames.push_back( "--abort" );
3479 }
3480 virtual std::string argsSynopsis() const {
3481 return "[#]";
3482 }
3483 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003484 return "Aborts after a certain number of failures";
Phil Nashecf934b2012-08-27 21:42:55 +01003485 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003486 virtual std::string optionDescription() const {
3487 return
3488 "If a REQUIRE assertion fails the test case aborts, but subsequent test cases "
3489 "are still run. If a CHECK assertion fails even the current test case is not "
3490 "aborted.\n"
3491 "\n"
3492 "Sometimes this results in a flood of failure messages and you'd rather just "
3493 "see the first few. Specifying -a or --abort on its own will abort the whole "
3494 "test run on the first failed assertion of any kind. Following it with a "
3495 "number causes it to abort after that number of assertion failures.";
3496 }
Phil Nashecf934b2012-08-27 21:42:55 +01003497
3498 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3499 int threshold = 1;
3500 if( cmd.argsCount() == 1 ) {
3501 std::stringstream ss;
3502 ss << cmd[0];
3503 ss >> threshold;
3504 if( ss.fail() || threshold <= 0 )
3505 cmd.raiseError( "threshold must be a number greater than zero" );
3506 }
3507 config.cutoff = threshold;
3508 }
3509 };
3510
3511 class NoThrowOptionParser : public OptionParser {
3512 public:
3513 NoThrowOptionParser() {
3514 m_optionNames.push_back( "-nt" );
3515 m_optionNames.push_back( "--nothrow" );
3516 }
3517 virtual std::string argsSynopsis() const {
3518 return "";
3519 }
3520 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003521 return "Elides assertions expected to throw";
Phil Nashecf934b2012-08-27 21:42:55 +01003522 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003523 virtual std::string optionDescription() const {
3524 return
3525 "Skips all assertions that test that an exception is thrown, "
3526 "e.g. REQUIRE_THROWS.\n"
3527 "\n"
3528 "These can be a nuisance in certain debugging environments that may break when "
3529 "exceptions are thrown (while this is usually optional for handled exceptions, "
3530 "it can be useful to have enabled if you are trying to track down something "
3531 "unexpected).\n"
3532 "\n"
3533 "When running with this option the throw checking assertions are skipped so "
3534 "as not to contribute additional noise.";
3535 }
Phil Nashecf934b2012-08-27 21:42:55 +01003536
Phil Nash78c92e62012-08-27 21:48:15 +01003537 virtual void parseIntoConfig( const Command&, ConfigData& config ) {
Phil Nashecf934b2012-08-27 21:42:55 +01003538 config.allowThrows = false;
3539 }
3540 };
Phil Nasha70fbe32012-08-31 08:10:36 +01003541
3542 class WarningsOptionParser : public OptionParser {
3543 public:
3544 WarningsOptionParser() : OptionParser( 1, -1 ) {
3545 m_optionNames.push_back( "-w" );
3546 m_optionNames.push_back( "--warnings" );
3547 }
3548 virtual std::string argsSynopsis() const {
3549 return "<warning>";
3550 }
3551 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003552 return "Enable warnings";
Phil Nasha70fbe32012-08-31 08:10:36 +01003553 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003554 virtual std::string optionDescription() const {
3555 return
3556 "Enables the named warnings. If the warnings are violated the test case is "
3557 "failed.\n"
3558 "\n"
3559 "At present only one warning has been provided: NoAssertions. If this warning "
3560 "is enabled then any test case that completes without an assertions (CHECK, "
3561 "REQUIRE etc) being encountered violates the warning.\n"
3562 "\n"
3563 "e.g.:\n"
3564 "\n"
3565 " -w NoAssertions";
3566 }
Phil Nasha70fbe32012-08-31 08:10:36 +01003567
3568 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3569 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
3570 if( cmd[i] == "NoAssertions" )
3571 config.warnings = (ConfigData::WarnAbout::What)( config.warnings | ConfigData::WarnAbout::NoAssertions );
3572 else
3573 cmd.raiseError( "Unrecognised warning: " + cmd[i] );
3574 }
3575 }
3576 };
Phil Nasha695eb92012-08-13 07:46:10 +01003577 }
3578
Phil Nashecf934b2012-08-27 21:42:55 +01003579 class AllOptions
3580 {
3581 public:
3582 typedef std::vector<Ptr<OptionParser> > Parsers;
3583 typedef Parsers::const_iterator const_iterator;
3584 typedef Parsers::const_iterator iterator;
3585
3586 AllOptions() {
Phil Nasha70fbe32012-08-31 08:10:36 +01003587 add<Options::TestCaseOptionParser>(); // Keep this one first
3588
Phil Nash67ec8702012-09-26 18:38:26 +01003589 add<Options::TagOptionParser>();
Phil Nashecf934b2012-08-27 21:42:55 +01003590 add<Options::ListOptionParser>();
3591 add<Options::ReporterOptionParser>();
3592 add<Options::OutputOptionParser>();
Phil Nashf7418eb2012-09-09 11:44:30 +01003593 add<Options::SuccessOptionParser>();
Phil Nashecf934b2012-08-27 21:42:55 +01003594 add<Options::DebugBreakOptionParser>();
3595 add<Options::NameOptionParser>();
3596 add<Options::AbortOptionParser>();
3597 add<Options::NoThrowOptionParser>();
Phil Nasha70fbe32012-08-31 08:10:36 +01003598 add<Options::WarningsOptionParser>();
3599
3600 add<Options::HelpOptionParser>(); // Keep this one last
Phil Nashecf934b2012-08-27 21:42:55 +01003601 }
3602
3603 void parseIntoConfig( const CommandParser& parser, ConfigData& config ) {
3604 for( const_iterator it = m_parsers.begin(); it != m_parsers.end(); ++it )
3605 (*it)->parseIntoConfig( parser, config );
3606 }
3607
3608 const_iterator begin() const {
3609 return m_parsers.begin();
3610 }
3611 const_iterator end() const {
3612 return m_parsers.end();
3613 }
3614 private:
3615
3616 template<typename T>
3617 void add() {
3618 m_parsers.push_back( new T() );
3619 }
3620 Parsers m_parsers;
3621
3622 };
3623
Phil Nasha695eb92012-08-13 07:46:10 +01003624} // end namespace Catch
3625
3626// #included from: internal/catch_list.hpp
3627#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
3628
3629#include <limits>
3630
3631namespace Catch {
Phil Nash56d5c422012-08-23 20:08:50 +01003632 inline bool matchesFilters( const std::vector<TestCaseFilters>& filters, const TestCaseInfo& testCase ) {
3633 std::vector<TestCaseFilters>::const_iterator it = filters.begin();
3634 std::vector<TestCaseFilters>::const_iterator itEnd = filters.end();
3635 for(; it != itEnd; ++it )
3636 if( !it->shouldInclude( testCase ) )
3637 return false;
3638 return true;
3639 }
3640 inline void List( const ConfigData& config ) {
Phil Nasha695eb92012-08-13 07:46:10 +01003641
Phil Nash5bc030d2012-08-16 18:48:50 +01003642 if( config.listSpec & List::Reports ) {
Phil Nasha695eb92012-08-13 07:46:10 +01003643 std::cout << "Available reports:\n";
3644 IReporterRegistry::FactoryMap::const_iterator it = getRegistryHub().getReporterRegistry().getFactories().begin();
3645 IReporterRegistry::FactoryMap::const_iterator itEnd = getRegistryHub().getReporterRegistry().getFactories().end();
3646 for(; it != itEnd; ++it ) {
3647 // !TBD: consider listAs()
3648 std::cout << "\t" << it->first << "\n\t\t'" << it->second->getDescription() << "'\n";
3649 }
3650 std::cout << std::endl;
3651 }
3652
Phil Nash5bc030d2012-08-16 18:48:50 +01003653 if( config.listSpec & List::Tests ) {
Phil Nash56d5c422012-08-23 20:08:50 +01003654 if( config.filters.empty() )
Phil Nash4c97fc52012-08-24 08:23:50 +01003655 std::cout << "All available test cases:\n";
Phil Nash56d5c422012-08-23 20:08:50 +01003656 else
Phil Nash4c97fc52012-08-24 08:23:50 +01003657 std::cout << "Matching test cases:\n";
Phil Nasha695eb92012-08-13 07:46:10 +01003658 std::vector<TestCaseInfo>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin();
3659 std::vector<TestCaseInfo>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end();
Phil Nash4c97fc52012-08-24 08:23:50 +01003660 std::size_t matchedTests = 0;
Phil Nasha695eb92012-08-13 07:46:10 +01003661 for(; it != itEnd; ++it ) {
Phil Nash56d5c422012-08-23 20:08:50 +01003662 if( matchesFilters( config.filters, *it ) ) {
Phil Nash4c97fc52012-08-24 08:23:50 +01003663 matchedTests++;
Phil Nash56d5c422012-08-23 20:08:50 +01003664 // !TBD: consider listAs()
3665 std::cout << "\t" << it->getName() << "\n";
3666 if( ( config.listSpec & List::TestNames ) != List::TestNames )
3667 std::cout << "\t\t '" << it->getDescription() << "'\n";
3668 }
Phil Nasha695eb92012-08-13 07:46:10 +01003669 }
Phil Nash4c97fc52012-08-24 08:23:50 +01003670 if( config.filters.empty() )
3671 std::cout << pluralise( matchedTests, "test case" ) << std::endl;
3672 else
3673 std::cout << pluralise( matchedTests, "matching test case" ) << std::endl;
Phil Nasha695eb92012-08-13 07:46:10 +01003674 }
3675
Phil Nash5bc030d2012-08-16 18:48:50 +01003676 if( ( config.listSpec & List::All ) == 0 ) {
Phil Nash56d5c422012-08-23 20:08:50 +01003677 std::ostringstream oss;
3678 oss << "Unknown list type";
3679 throw std::domain_error( oss.str() );
Phil Nasha695eb92012-08-13 07:46:10 +01003680 }
Phil Nasha695eb92012-08-13 07:46:10 +01003681 }
3682
3683} // end namespace Catch
3684
3685// #included from: internal/catch_runner_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04003686#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003687
3688// #included from: catch_running_test.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04003689#define TWOBLUECUBES_CATCH_RUNNING_TEST_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003690
3691// #included from: catch_section_info.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04003692#define TWOBLUECUBES_CATCH_SECTION_INFO_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003693
3694#include <map>
3695#include <string>
3696
3697namespace Catch {
3698
3699 class SectionInfo {
3700 public:
3701
3702 enum Status {
3703 Root,
3704 Unknown,
3705 Branch,
3706 TestedBranch,
3707 TestedLeaf
3708 };
3709
3710 SectionInfo( SectionInfo* parent )
3711 : m_status( Unknown ),
3712 m_parent( parent )
3713 {}
3714
3715 SectionInfo()
3716 : m_status( Root ),
3717 m_parent( NULL )
3718 {}
3719
3720 ~SectionInfo() {
3721 deleteAllValues( m_subSections );
3722 }
3723
3724 bool shouldRun() const {
3725 return m_status < TestedBranch;
3726 }
3727
3728 bool ran() {
3729 if( m_status < Branch ) {
3730 m_status = TestedLeaf;
3731 return true;
3732 }
3733 return false;
3734 }
3735
Phil Nasha70fbe32012-08-31 08:10:36 +01003736 bool isBranch() const {
3737 return m_status == Branch;
3738 }
3739
Phil Nasha695eb92012-08-13 07:46:10 +01003740 void ranToCompletion() {
3741 if( m_status == Branch && !hasUntestedSections() )
3742 m_status = TestedBranch;
3743 }
3744
3745 SectionInfo* findSubSection( const std::string& name ) {
3746 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.find( name );
3747 return it != m_subSections.end()
3748 ? it->second
3749 : NULL;
3750 }
3751
3752 SectionInfo* addSubSection( const std::string& name ) {
3753 SectionInfo* subSection = new SectionInfo( this );
3754 m_subSections.insert( std::make_pair( name, subSection ) );
3755 m_status = Branch;
3756 return subSection;
3757 }
3758
3759 SectionInfo* getParent() {
3760 return m_parent;
3761 }
3762
3763 bool hasUntestedSections() const {
3764 if( m_status == Unknown )
3765 return true;
3766
3767 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.begin();
3768 std::map<std::string, SectionInfo*>::const_iterator itEnd = m_subSections.end();
3769 for(; it != itEnd; ++it ) {
3770 if( it->second->hasUntestedSections() )
3771 return true;
3772 }
3773 return false;
3774 }
3775
3776 private:
3777 Status m_status;
3778 std::map<std::string, SectionInfo*> m_subSections;
3779 SectionInfo* m_parent;
3780 };
3781}
3782
3783namespace Catch {
3784
3785 class RunningTest {
3786
3787 enum RunStatus {
3788 NothingRun,
3789 EncounteredASection,
3790 RanAtLeastOneSection,
3791 RanToCompletionWithSections,
3792 RanToCompletionWithNoSections
3793 };
3794
3795 public:
3796 explicit RunningTest( const TestCaseInfo* info = NULL )
3797 : m_info( info ),
3798 m_runStatus( RanAtLeastOneSection ),
3799 m_currentSection( &m_rootSection ),
3800 m_changed( false )
3801 {}
3802
3803 bool wasSectionSeen() const {
3804 return m_runStatus == RanAtLeastOneSection ||
3805 m_runStatus == RanToCompletionWithSections;
3806 }
3807
Phil Nasha70fbe32012-08-31 08:10:36 +01003808 bool isBranchSection() const {
3809 return m_currentSection &&
3810 m_currentSection->isBranch();
3811 }
3812
3813 bool hasSections() const {
3814 return m_runStatus == RanAtLeastOneSection ||
3815 m_runStatus == RanToCompletionWithSections ||
3816 m_runStatus == EncounteredASection;
3817 }
3818
Phil Nasha695eb92012-08-13 07:46:10 +01003819 void reset() {
3820 m_runStatus = NothingRun;
3821 m_changed = false;
3822 m_lastSectionToRun = NULL;
3823 }
3824
3825 void ranToCompletion() {
3826 if( m_runStatus == RanAtLeastOneSection ||
3827 m_runStatus == EncounteredASection ) {
3828 m_runStatus = RanToCompletionWithSections;
3829 if( m_lastSectionToRun ) {
3830 m_lastSectionToRun->ranToCompletion();
3831 m_changed = true;
3832 }
3833 }
3834 else {
3835 m_runStatus = RanToCompletionWithNoSections;
3836 }
3837 }
3838
3839 bool addSection( const std::string& name ) {
3840 if( m_runStatus == NothingRun )
3841 m_runStatus = EncounteredASection;
3842
3843 SectionInfo* thisSection = m_currentSection->findSubSection( name );
3844 if( !thisSection ) {
3845 thisSection = m_currentSection->addSubSection( name );
3846 m_changed = true;
3847 }
3848
3849 if( !wasSectionSeen() && thisSection->shouldRun() ) {
3850 m_currentSection = thisSection;
3851 m_lastSectionToRun = NULL;
3852 return true;
3853 }
3854 return false;
3855 }
3856
3857 void endSection( const std::string& ) {
3858 if( m_currentSection->ran() ) {
3859 m_runStatus = RanAtLeastOneSection;
3860 m_changed = true;
3861 }
3862 else if( m_runStatus == EncounteredASection ) {
3863 m_runStatus = RanAtLeastOneSection;
3864 m_lastSectionToRun = m_currentSection;
3865 }
3866 m_currentSection = m_currentSection->getParent();
3867 }
3868
3869 const TestCaseInfo& getTestCaseInfo() const {
3870 return *m_info;
3871 }
3872
3873 bool hasUntestedSections() const {
3874 return m_runStatus == RanAtLeastOneSection ||
3875 ( m_rootSection.hasUntestedSections() && m_changed );
3876 }
3877
3878 private:
3879 const TestCaseInfo* m_info;
3880 RunStatus m_runStatus;
3881 SectionInfo m_rootSection;
3882 SectionInfo* m_currentSection;
3883 SectionInfo* m_lastSectionToRun;
3884 bool m_changed;
3885 };
3886}
3887
3888#include <set>
3889#include <string>
3890
3891namespace Catch {
3892
3893 class StreamRedirect {
3894
3895 public:
3896 StreamRedirect( std::ostream& stream, std::string& targetString )
3897 : m_stream( stream ),
3898 m_prevBuf( stream.rdbuf() ),
3899 m_targetString( targetString )
3900 {
3901 stream.rdbuf( m_oss.rdbuf() );
3902 }
3903
3904 ~StreamRedirect() {
3905 m_targetString += m_oss.str();
3906 m_stream.rdbuf( m_prevBuf );
3907 }
3908
3909 private:
3910 std::ostream& m_stream;
3911 std::streambuf* m_prevBuf;
3912 std::ostringstream m_oss;
3913 std::string& m_targetString;
3914 };
3915
3916 ///////////////////////////////////////////////////////////////////////////
3917
3918 class Runner : public IResultCapture, public IRunner {
3919
3920 Runner( const Runner& );
3921 void operator =( const Runner& );
3922
3923 public:
3924
Phil Nash56d5c422012-08-23 20:08:50 +01003925 explicit Runner( const Config& config, const Ptr<IReporter>& reporter )
Phil Nasha695eb92012-08-13 07:46:10 +01003926 : m_context( getCurrentMutableContext() ),
3927 m_runningTest( NULL ),
3928 m_config( config ),
3929 m_reporter( reporter ),
3930 m_prevRunner( &m_context.getRunner() ),
3931 m_prevResultCapture( &m_context.getResultCapture() ),
3932 m_prevConfig( m_context.getConfig() )
3933 {
3934 m_context.setRunner( this );
3935 m_context.setConfig( &m_config );
3936 m_context.setResultCapture( this );
3937 m_reporter->StartTesting();
3938 }
3939
3940 virtual ~Runner() {
3941 m_reporter->EndTesting( m_totals );
3942 m_context.setRunner( m_prevRunner );
3943 m_context.setConfig( NULL );
3944 m_context.setResultCapture( m_prevResultCapture );
3945 m_context.setConfig( m_prevConfig );
3946 }
3947
Phil Nash56d5c422012-08-23 20:08:50 +01003948 Totals runMatching( const std::string& testSpec ) {
Phil Nasha695eb92012-08-13 07:46:10 +01003949
Phil Nash56d5c422012-08-23 20:08:50 +01003950 std::vector<TestCaseInfo> matchingTests = getRegistryHub().getTestCaseRegistry().getMatchingTestCases( testSpec );
Phil Nash5bc030d2012-08-16 18:48:50 +01003951
3952 Totals totals;
Phil Nash5bc030d2012-08-16 18:48:50 +01003953
Phil Nash56d5c422012-08-23 20:08:50 +01003954 m_reporter->StartGroup( testSpec );
3955
3956 std::vector<TestCaseInfo>::const_iterator it = matchingTests.begin();
3957 std::vector<TestCaseInfo>::const_iterator itEnd = matchingTests.end();
3958 for(; it != itEnd; ++it )
3959 totals += runTest( *it );
3960 // !TBD use std::accumulate?
3961
3962 m_reporter->EndGroup( testSpec, totals );
Phil Nash5bc030d2012-08-16 18:48:50 +01003963 return totals;
3964 }
3965
3966 Totals runTest( const TestCaseInfo& testInfo ) {
Phil Nasha695eb92012-08-13 07:46:10 +01003967 Totals prevTotals = m_totals;
3968
3969 std::string redirectedCout;
3970 std::string redirectedCerr;
3971
3972 m_reporter->StartTestCase( testInfo );
3973
3974 m_runningTest = new RunningTest( &testInfo );
3975
3976 do {
3977 do {
Phil Nasha695eb92012-08-13 07:46:10 +01003978 runCurrentTest( redirectedCout, redirectedCerr );
Phil Nasha695eb92012-08-13 07:46:10 +01003979 }
3980 while( m_runningTest->hasUntestedSections() && !aborting() );
3981 }
3982 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
3983
3984 delete m_runningTest;
3985 m_runningTest = NULL;
3986
3987 Totals deltaTotals = m_totals.delta( prevTotals );
3988 m_totals.testCases += deltaTotals.testCases;
3989 m_reporter->EndTestCase( testInfo, deltaTotals, redirectedCout, redirectedCerr );
Phil Nash5bc030d2012-08-16 18:48:50 +01003990 return deltaTotals;
Phil Nasha695eb92012-08-13 07:46:10 +01003991 }
3992
3993 const Config& config() const {
3994 return m_config;
3995 }
3996
3997 private: // IResultCapture
3998
Phil Nash5efa4bc2012-10-29 20:49:22 +00003999 virtual ResultAction::Value acceptExpression( const ExpressionResultBuilder& assertionResult, const AssertionInfo& assertionInfo ) {
Phil Nash88b70822012-11-04 21:39:38 +00004000 m_lastAssertionInfo = assertionInfo;
4001 return actOnCurrentResult( assertionResult.buildResult( assertionInfo ) );
Phil Nasha695eb92012-08-13 07:46:10 +01004002 }
4003
Phil Nash82acc2c2012-10-28 12:07:17 +00004004 virtual void testEnded( const AssertionResult& result ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004005 if( result.getResultType() == ResultWas::Ok ) {
4006 m_totals.assertions.passed++;
4007 }
Phil Nashd539da92012-11-13 09:44:52 +00004008 else if( !result.isOk() ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004009 m_totals.assertions.failed++;
4010
Phil Nash799ecf92012-09-24 08:30:13 +01004011 {
4012 std::vector<ScopedInfo*>::const_iterator it = m_scopedInfos.begin();
4013 std::vector<ScopedInfo*>::const_iterator itEnd = m_scopedInfos.end();
4014 for(; it != itEnd; ++it )
Phil Nash88b70822012-11-04 21:39:38 +00004015 m_reporter->Result( (*it)->buildResult( m_lastAssertionInfo ) );
Phil Nash799ecf92012-09-24 08:30:13 +01004016 }
4017 {
Phil Nash82acc2c2012-10-28 12:07:17 +00004018 std::vector<AssertionResult>::const_iterator it = m_assertionResults.begin();
4019 std::vector<AssertionResult>::const_iterator itEnd = m_assertionResults.end();
Phil Nash799ecf92012-09-24 08:30:13 +01004020 for(; it != itEnd; ++it )
4021 m_reporter->Result( *it );
4022 }
Phil Nash82acc2c2012-10-28 12:07:17 +00004023 m_assertionResults.clear();
Phil Nasha695eb92012-08-13 07:46:10 +01004024 }
4025
4026 if( result.getResultType() == ResultWas::Info )
Phil Nash82acc2c2012-10-28 12:07:17 +00004027 m_assertionResults.push_back( result );
Phil Nasha695eb92012-08-13 07:46:10 +01004028 else
4029 m_reporter->Result( result );
4030 }
4031
4032 virtual bool sectionStarted (
4033 const std::string& name,
4034 const std::string& description,
4035 const SourceLineInfo& lineInfo,
4036 Counts& assertions
4037 )
4038 {
4039 std::ostringstream oss;
4040 oss << name << "@" << lineInfo;
4041
4042 if( !m_runningTest->addSection( oss.str() ) )
4043 return false;
4044
Phil Nash88b70822012-11-04 21:39:38 +00004045 m_lastAssertionInfo.lineInfo = lineInfo;
4046
Phil Nasha695eb92012-08-13 07:46:10 +01004047 m_reporter->StartSection( name, description );
4048 assertions = m_totals.assertions;
4049
4050 return true;
4051 }
4052
4053 virtual void sectionEnded( const std::string& name, const Counts& prevAssertions ) {
Phil Nasha70fbe32012-08-31 08:10:36 +01004054 Counts assertions = m_totals.assertions - prevAssertions;
4055 if( assertions.total() == 0 &&
4056 ( m_config.data().warnings & ConfigData::WarnAbout::NoAssertions ) &&
4057 !m_runningTest->isBranchSection() ) {
4058 m_reporter->NoAssertionsInSection( name );
4059 m_totals.assertions.failed++;
4060 assertions.failed++;
4061 }
Phil Nasha695eb92012-08-13 07:46:10 +01004062 m_runningTest->endSection( name );
Phil Nasha70fbe32012-08-31 08:10:36 +01004063 m_reporter->EndSection( name, assertions );
Phil Nasha695eb92012-08-13 07:46:10 +01004064 }
4065
4066 virtual void pushScopedInfo( ScopedInfo* scopedInfo ) {
4067 m_scopedInfos.push_back( scopedInfo );
4068 }
4069
4070 virtual void popScopedInfo( ScopedInfo* scopedInfo ) {
4071 if( m_scopedInfos.back() == scopedInfo )
4072 m_scopedInfos.pop_back();
4073 }
4074
4075 virtual bool shouldDebugBreak() const {
4076 return m_config.shouldDebugBreak();
4077 }
4078
4079 virtual std::string getCurrentTestName() const {
4080 return m_runningTest
4081 ? m_runningTest->getTestCaseInfo().getName()
4082 : "";
4083 }
4084
Phil Nash82acc2c2012-10-28 12:07:17 +00004085 virtual const AssertionResult* getLastResult() const {
Phil Nasha695eb92012-08-13 07:46:10 +01004086 return &m_lastResult;
4087 }
4088
Phil Nash56d5c422012-08-23 20:08:50 +01004089 public:
4090 // !TBD We need to do this another way!
Phil Nasha695eb92012-08-13 07:46:10 +01004091 bool aborting() const {
4092 return m_totals.assertions.failed == static_cast<std::size_t>( m_config.getCutoff() );
4093 }
4094
Phil Nash56d5c422012-08-23 20:08:50 +01004095 private:
4096
Phil Nash88b70822012-11-04 21:39:38 +00004097 ResultAction::Value actOnCurrentResult( const AssertionResult& result ) {
4098 m_lastResult = result;
Phil Nash67305122012-10-09 11:48:55 +01004099 testEnded( m_lastResult );
Phil Nasha695eb92012-08-13 07:46:10 +01004100
Phil Nasha695eb92012-08-13 07:46:10 +01004101 ResultAction::Value action = ResultAction::None;
4102
Phil Nashd539da92012-11-13 09:44:52 +00004103 if( !m_lastResult.isOk() ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004104 action = ResultAction::Failed;
4105 if( shouldDebugBreak() )
4106 action = (ResultAction::Value)( action | ResultAction::Debug );
4107 if( aborting() )
4108 action = (ResultAction::Value)( action | ResultAction::Abort );
4109 }
4110 return action;
4111 }
4112
4113 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
4114 try {
Phil Nashd539da92012-11-13 09:44:52 +00004115 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", m_runningTest->getTestCaseInfo().getLineInfo(), "", ResultDisposition::Normal );
Phil Nasha695eb92012-08-13 07:46:10 +01004116 m_runningTest->reset();
Phil Nasha70fbe32012-08-31 08:10:36 +01004117 Counts prevAssertions = m_totals.assertions;
Phil Nasha695eb92012-08-13 07:46:10 +01004118 if( m_reporter->shouldRedirectStdout() ) {
4119 StreamRedirect coutRedir( std::cout, redirectedCout );
4120 StreamRedirect cerrRedir( std::cerr, redirectedCerr );
4121 m_runningTest->getTestCaseInfo().invoke();
4122 }
4123 else {
4124 m_runningTest->getTestCaseInfo().invoke();
4125 }
Phil Nasha70fbe32012-08-31 08:10:36 +01004126 Counts assertions = m_totals.assertions - prevAssertions;
4127 if( assertions.total() == 0 &&
4128 ( m_config.data().warnings & ConfigData::WarnAbout::NoAssertions ) &&
4129 !m_runningTest->hasSections() ) {
4130 m_totals.assertions.failed++;
4131 m_reporter->NoAssertionsInTestCase( m_runningTest->getTestCaseInfo().getName() );
4132 }
Phil Nasha695eb92012-08-13 07:46:10 +01004133 m_runningTest->ranToCompletion();
4134 }
4135 catch( TestFailureException& ) {
4136 // This just means the test was aborted due to failure
4137 }
4138 catch(...) {
Phil Nash88b70822012-11-04 21:39:38 +00004139 ExpressionResultBuilder exResult( ResultWas::ThrewException );
4140 exResult << translateActiveException();
4141 actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo ) );
Phil Nasha695eb92012-08-13 07:46:10 +01004142 }
Phil Nash82acc2c2012-10-28 12:07:17 +00004143 m_assertionResults.clear();
Phil Nasha695eb92012-08-13 07:46:10 +01004144 }
4145
4146 private:
4147 IMutableContext& m_context;
4148 RunningTest* m_runningTest;
Phil Nash82acc2c2012-10-28 12:07:17 +00004149 AssertionResult m_lastResult;
Phil Nasha695eb92012-08-13 07:46:10 +01004150
4151 const Config& m_config;
4152 Totals m_totals;
4153 Ptr<IReporter> m_reporter;
4154 std::vector<ScopedInfo*> m_scopedInfos;
Phil Nash82acc2c2012-10-28 12:07:17 +00004155 std::vector<AssertionResult> m_assertionResults;
Phil Nasha695eb92012-08-13 07:46:10 +01004156 IRunner* m_prevRunner;
4157 IResultCapture* m_prevResultCapture;
4158 const IConfig* m_prevConfig;
Phil Nash88b70822012-11-04 21:39:38 +00004159 AssertionInfo m_lastAssertionInfo;
Phil Nasha695eb92012-08-13 07:46:10 +01004160 };
4161
4162} // end namespace Catch
4163
Phil Nash7673a302012-11-15 22:15:41 +00004164// #included from: internal/catch_version.h
4165#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
4166
4167namespace Catch {
4168
4169 // Versioning information
4170 struct Version {
4171 const unsigned int MajorVersion;
4172 const unsigned int MinorVersion;
4173 const unsigned int BuildNumber;
4174 const std::string BranchName;
4175 };
4176
4177 extern Version libraryVersion;
4178}
4179
Phil Nash89d1e6c2011-05-24 08:23:02 +01004180#include <fstream>
4181#include <stdlib.h>
4182#include <limits>
4183
Phil Nash89d2a3f2012-05-16 15:09:17 +01004184namespace Catch {
4185
Phil Nash56d5c422012-08-23 20:08:50 +01004186 class Runner2 { // This will become Runner when Runner becomes Context
Phil Nash163088a2012-05-31 19:40:26 +01004187
Phil Nash56d5c422012-08-23 20:08:50 +01004188 public:
4189 Runner2( Config& configWrapper )
4190 : m_configWrapper( configWrapper ),
4191 m_config( configWrapper.data() )
Phil Nash06e959b2012-05-25 08:52:05 +01004192 {
Phil Nash67ec8702012-09-26 18:38:26 +01004193 openStream();
Phil Nash56d5c422012-08-23 20:08:50 +01004194 makeReporter();
4195 }
Phil Nash06e959b2012-05-25 08:52:05 +01004196
Phil Nash56d5c422012-08-23 20:08:50 +01004197 Totals runTests() {
4198
4199 std::vector<TestCaseFilters> filterGroups = m_config.filters;
4200 if( filterGroups.empty() ) {
4201 TestCaseFilters filterGroup( "" );
Phil Nash56d5c422012-08-23 20:08:50 +01004202 filterGroups.push_back( filterGroup );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004203 }
Phil Nash56d5c422012-08-23 20:08:50 +01004204
4205 Runner context( m_configWrapper, m_reporter ); // This Runner will be renamed Context
4206 Totals totals;
4207
4208 std::vector<TestCaseFilters>::const_iterator it = filterGroups.begin();
4209 std::vector<TestCaseFilters>::const_iterator itEnd = filterGroups.end();
Phil Nashe2d215e2012-09-07 17:52:35 +01004210 for(; it != itEnd && !context.aborting(); ++it ) {
Phil Nash56d5c422012-08-23 20:08:50 +01004211 m_reporter->StartGroup( it->getName() );
Phil Nash62b70392012-08-31 18:46:13 +01004212 totals += runTestsForGroup( context, *it );
Phil Nash56d5c422012-08-23 20:08:50 +01004213 if( context.aborting() )
4214 m_reporter->Aborted();
4215 m_reporter->EndGroup( it->getName(), totals );
4216 }
4217 return totals;
4218 }
4219
4220 Totals runTestsForGroup( Runner& context, const TestCaseFilters& filterGroup ) {
4221 Totals totals;
4222 std::vector<TestCaseInfo>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin();
4223 std::vector<TestCaseInfo>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end();
4224 int testsRunForGroup = 0;
4225 for(; it != itEnd; ++it ) {
4226 if( filterGroup.shouldInclude( *it ) ) {
4227 testsRunForGroup++;
4228 if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
4229
4230 if( context.aborting() )
4231 break;
4232
4233 totals += context.runTest( *it );
4234 m_testsAlreadyRun.insert( *it );
4235 }
Phil Nash06e959b2012-05-25 08:52:05 +01004236 }
4237 }
Phil Nash56d5c422012-08-23 20:08:50 +01004238 if( testsRunForGroup == 0 )
4239 std::cerr << "\n[No test cases matched with: " << filterGroup.getName() << "]" << std::endl;
4240 return totals;
4241
Phil Nash89d1e6c2011-05-24 08:23:02 +01004242 }
Phil Nash56d5c422012-08-23 20:08:50 +01004243
4244 private:
Phil Nash67ec8702012-09-26 18:38:26 +01004245 void openStream() {
4246 if( !m_config.stream.empty() )
4247 m_configWrapper.useStream( m_config.stream );
4248
Phil Nash56d5c422012-08-23 20:08:50 +01004249 // Open output file, if specified
4250 if( !m_config.outputFilename.empty() ) {
4251 m_ofs.open( m_config.outputFilename.c_str() );
4252 if( m_ofs.fail() ) {
4253 std::ostringstream oss;
4254 oss << "Unable to open file: '" << m_config.outputFilename << "'";
4255 throw std::domain_error( oss.str() );
4256 }
4257 m_configWrapper.setStreamBuf( m_ofs.rdbuf() );
4258 }
4259 }
4260 void makeReporter() {
4261 std::string reporterName = m_config.reporter.empty()
4262 ? "basic"
4263 : m_config.reporter;
4264
Phil Nasha70fbe32012-08-31 08:10:36 +01004265 ReporterConfig reporterConfig( m_config.name, m_configWrapper.stream(), m_config.includeWhichResults == Include::SuccessfulResults, m_config );
Phil Nash56d5c422012-08-23 20:08:50 +01004266
4267 m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, reporterConfig );
4268 if( !m_reporter ) {
4269 std::ostringstream oss;
4270 oss << "No reporter registered with name: '" << reporterName << "'";
4271 throw std::domain_error( oss.str() );
4272 }
4273 }
4274
4275 private:
4276 Config& m_configWrapper;
4277 const ConfigData& m_config;
4278 std::ofstream m_ofs;
4279 Ptr<IReporter> m_reporter;
4280 std::set<TestCaseInfo> m_testsAlreadyRun;
4281 };
4282
4283 inline int Main( Config& configWrapper ) {
4284 int result = 0;
4285 try
4286 {
4287 Runner2 runner( configWrapper );
4288
4289 const ConfigData& config = configWrapper.data();
4290
4291 // Handle list request
4292 if( config.listSpec != List::None ) {
4293 List( config );
Phil Nash799ecf92012-09-24 08:30:13 +01004294 Catch::cleanUp();
Phil Nash56d5c422012-08-23 20:08:50 +01004295 return 0;
4296 }
4297
4298 result = static_cast<int>( runner.runTests().assertions.failed );
4299
4300 }
4301 catch( std::exception& ex ) {
4302 std::cerr << ex.what() << std::endl;
4303 result = (std::numeric_limits<int>::max)();
4304 }
4305
Phil Nash3b80af72012-08-09 07:47:30 +01004306 Catch::cleanUp();
Phil Nash371db8b2012-05-21 18:52:09 +01004307 return result;
Phil Nash89d1e6c2011-05-24 08:23:02 +01004308 }
4309
Phil Nash163088a2012-05-31 19:40:26 +01004310 inline void showUsage( std::ostream& os ) {
Phil Nashecf934b2012-08-27 21:42:55 +01004311 AllOptions options;
Phil Nashe2d215e2012-09-07 17:52:35 +01004312
Phil Nashecf934b2012-08-27 21:42:55 +01004313 for( AllOptions::const_iterator it = options.begin(); it != options.end(); ++it ) {
4314 OptionParser& opt = **it;
4315 os << " " << opt.optionNames() << " " << opt.argsSynopsis() << "\n";
4316 }
4317 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 +01004318 }
Phil Nashe2d215e2012-09-07 17:52:35 +01004319
4320 inline void addIndent( std::ostream& os, std::size_t indent ) {
4321 while( indent-- > 0 )
4322 os << ' ';
4323 }
4324
4325 inline void recursivelyWrapLine( std::ostream& os, std::string paragraph, std::size_t columns, std::size_t indent ) {
4326 std::size_t width = columns-indent;
4327 std::size_t tab = 0;
4328 std::size_t wrapPoint = width;
4329 for( std::size_t pos = 0; pos < paragraph.size(); ++pos ) {
4330 if( pos == width ) {
4331 addIndent( os, indent );
4332 os << paragraph.substr( 0, wrapPoint ) << "\n";
4333 return recursivelyWrapLine( os, paragraph.substr( wrapPoint+1 ), columns, indent+tab );
4334 }
4335 if( paragraph[pos] == '\t' ) {
4336 tab = pos;
4337 paragraph = paragraph.substr( 0, tab ) + paragraph.substr( tab+1 );
4338 pos--;
4339 }
4340 else if( paragraph[pos] == ' ' ) {
4341 wrapPoint = pos;
4342 }
4343 }
4344 addIndent( os, indent );
4345 os << paragraph << "\n";
4346 }
Phil Nashf7418eb2012-09-09 11:44:30 +01004347
Phil Nashe2d215e2012-09-07 17:52:35 +01004348 inline std::string addLineBreaks( const std::string& str, std::size_t columns, std::size_t indent = 0 ) {
4349 std::ostringstream oss;
4350 std::string::size_type pos = 0;
4351 std::string::size_type newline = str.find_first_of( '\n' );
4352 while( newline != std::string::npos ) {
4353 std::string paragraph = str.substr( pos, newline-pos );
4354 recursivelyWrapLine( oss, paragraph, columns, indent );
4355 pos = newline+1;
4356 newline = str.find_first_of( '\n', pos );
4357 }
Phil Nashf7418eb2012-09-09 11:44:30 +01004358 if( pos != str.size() )
4359 recursivelyWrapLine( oss, str.substr( pos, str.size()-pos ), columns, indent );
4360
Phil Nashe2d215e2012-09-07 17:52:35 +01004361 return oss.str();
4362 }
4363
4364 inline void showHelp( const CommandParser& parser ) {
4365 std::string exeName = parser.exeName();
Phil Nash89d1e6c2011-05-24 08:23:02 +01004366 std::string::size_type pos = exeName.find_last_of( "/\\" );
Phil Nash89d2a3f2012-05-16 15:09:17 +01004367 if( pos != std::string::npos ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01004368 exeName = exeName.substr( pos+1 );
4369 }
4370
Phil Nashe2d215e2012-09-07 17:52:35 +01004371 AllOptions options;
4372 Options::HelpOptionParser helpOpt;
4373 bool displayedSpecificOption = false;
4374 for( AllOptions::const_iterator it = options.begin(); it != options.end(); ++it ) {
4375 OptionParser& opt = **it;
4376 if( opt.find( parser ) && opt.optionNames() != helpOpt.optionNames() ) {
4377 displayedSpecificOption = true;
4378 std::cout << "\n" << opt.optionNames() << " " << opt.argsSynopsis() << "\n\n"
4379 << opt.optionSummary() << "\n\n"
4380
4381 << addLineBreaks( opt.optionDescription(), 80, 2 ) << "\n" << std::endl;
4382 }
4383 }
4384
4385 if( !displayedSpecificOption ) {
Phil Nash7673a302012-11-15 22:15:41 +00004386 std::cout << "\nCATCH v" << libraryVersion.MajorVersion << "."
4387 << libraryVersion.MinorVersion << " build "
4388 << libraryVersion.BuildNumber;
4389 if( libraryVersion.BranchName != "master" )
4390 std::cout << " (" << libraryVersion.BranchName << " branch)";
4391
4392 std::cout << "\n\n" << exeName << " is a CATCH host application. Options are as follows:\n\n";
Phil Nashe2d215e2012-09-07 17:52:35 +01004393 showUsage( std::cout );
4394 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01004395 }
4396
Phil Nash89d2a3f2012-05-16 15:09:17 +01004397 inline int Main( int argc, char* const argv[], Config& config ) {
Phil Nash163088a2012-05-31 19:40:26 +01004398
Phil Nashabf27162012-07-05 18:37:58 +01004399 try {
4400 CommandParser parser( argc, argv );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004401
Phil Nashecf934b2012-08-27 21:42:55 +01004402 if( Command cmd = Options::HelpOptionParser().find( parser ) ) {
Phil Nashabf27162012-07-05 18:37:58 +01004403 if( cmd.argsCount() != 0 )
4404 cmd.raiseError( "Does not accept arguments" );
4405
Phil Nashe2d215e2012-09-07 17:52:35 +01004406 showHelp( parser );
Phil Nash3b80af72012-08-09 07:47:30 +01004407 Catch::cleanUp();
Phil Nashabf27162012-07-05 18:37:58 +01004408 return 0;
4409 }
4410
Phil Nashecf934b2012-08-27 21:42:55 +01004411 AllOptions options;
4412
4413 options.parseIntoConfig( parser, config.data() );
Phil Nashabf27162012-07-05 18:37:58 +01004414 }
4415 catch( std::exception& ex ) {
Phil Nash6f220862012-07-23 08:24:52 +01004416 std::cerr << ex.what() << "\n\nUsage: ...\n\n";
Phil Nash163088a2012-05-31 19:40:26 +01004417 showUsage( std::cerr );
Phil Nash3b80af72012-08-09 07:47:30 +01004418 Catch::cleanUp();
Phil Nash89d1e6c2011-05-24 08:23:02 +01004419 return (std::numeric_limits<int>::max)();
4420 }
4421
Phil Nash89d1e6c2011-05-24 08:23:02 +01004422 return Main( config );
4423 }
4424
Phil Nash89d2a3f2012-05-16 15:09:17 +01004425 inline int Main( int argc, char* const argv[] ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01004426 Config config;
Phil Nash371db8b2012-05-21 18:52:09 +01004427// !TBD: This doesn't always work, for some reason
Phil Nash89d1e6c2011-05-24 08:23:02 +01004428// if( isDebuggerActive() )
4429// config.useStream( "debug" );
Phil Nash371db8b2012-05-21 18:52:09 +01004430 return Main( argc, argv, config );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004431 }
4432
4433} // end namespace Catch
4434
Phil Nash3b80af72012-08-09 07:47:30 +01004435// #included from: catch_registry_hub.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004436#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01004437
4438// #included from: catch_test_case_registry_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004439#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01004440
4441#include <vector>
4442#include <set>
4443#include <sstream>
4444#include <iostream>
4445
4446namespace Catch {
4447
4448 class TestRegistry : public ITestCaseRegistry {
4449 public:
4450 TestRegistry() : m_unnamedCount( 0 ) {}
Phil Nasha695eb92012-08-13 07:46:10 +01004451 virtual ~TestRegistry();
Phil Nash3b80af72012-08-09 07:47:30 +01004452
4453 virtual void registerTest( const TestCaseInfo& testInfo ) {
4454 if( testInfo.getName() == "" ) {
4455 std::ostringstream oss;
4456 oss << testInfo.getName() << "unnamed/" << ++m_unnamedCount;
4457 return registerTest( TestCaseInfo( testInfo, oss.str() ) );
4458 }
4459
4460 if( m_functions.find( testInfo ) == m_functions.end() ) {
4461 m_functions.insert( testInfo );
4462 m_functionsInOrder.push_back( testInfo );
Phil Nash5bc030d2012-08-16 18:48:50 +01004463 if( !testInfo.isHidden() )
4464 m_nonHiddenFunctions.push_back( testInfo );
Phil Nash3b80af72012-08-09 07:47:30 +01004465 }
4466 else {
4467 const TestCaseInfo& prev = *m_functions.find( testInfo );
4468 std::cerr << "error: TEST_CASE( \"" << testInfo.getName() << "\" ) already defined.\n"
4469 << "\tFirst seen at " << SourceLineInfo( prev.getLineInfo() ) << "\n"
4470 << "\tRedefined at " << SourceLineInfo( testInfo.getLineInfo() ) << std::endl;
4471 exit(1);
4472 }
4473 }
4474
4475 virtual const std::vector<TestCaseInfo>& getAllTests() const {
4476 return m_functionsInOrder;
4477 }
4478
Phil Nash5bc030d2012-08-16 18:48:50 +01004479 virtual const std::vector<TestCaseInfo>& getAllNonHiddenTests() const {
4480 return m_nonHiddenFunctions;
4481 }
4482
Phil Nash56d5c422012-08-23 20:08:50 +01004483 // !TBD deprecated
Phil Nash3b80af72012-08-09 07:47:30 +01004484 virtual std::vector<TestCaseInfo> getMatchingTestCases( const std::string& rawTestSpec ) const {
Phil Nash5bc030d2012-08-16 18:48:50 +01004485 std::vector<TestCaseInfo> matchingTests;
4486 getMatchingTestCases( rawTestSpec, matchingTests );
4487 return matchingTests;
4488 }
4489
Phil Nash56d5c422012-08-23 20:08:50 +01004490 // !TBD deprecated
Phil Nash5bc030d2012-08-16 18:48:50 +01004491 virtual void getMatchingTestCases( const std::string& rawTestSpec, std::vector<TestCaseInfo>& matchingTestsOut ) const {
Phil Nash56d5c422012-08-23 20:08:50 +01004492 TestCaseFilter filter( rawTestSpec );
Phil Nash5bc030d2012-08-16 18:48:50 +01004493
Phil Nash3b80af72012-08-09 07:47:30 +01004494 std::vector<TestCaseInfo>::const_iterator it = m_functionsInOrder.begin();
4495 std::vector<TestCaseInfo>::const_iterator itEnd = m_functionsInOrder.end();
4496 for(; it != itEnd; ++it ) {
Phil Nash56d5c422012-08-23 20:08:50 +01004497 if( filter.shouldInclude( *it ) ) {
Phil Nash5bc030d2012-08-16 18:48:50 +01004498 matchingTestsOut.push_back( *it );
Phil Nash3b80af72012-08-09 07:47:30 +01004499 }
4500 }
Phil Nash3b80af72012-08-09 07:47:30 +01004501 }
Phil Nash56d5c422012-08-23 20:08:50 +01004502 virtual void getMatchingTestCases( const TestCaseFilters& filters, std::vector<TestCaseInfo>& matchingTestsOut ) const {
4503 std::vector<TestCaseInfo>::const_iterator it = m_functionsInOrder.begin();
4504 std::vector<TestCaseInfo>::const_iterator itEnd = m_functionsInOrder.end();
4505 // !TBD: replace with algorithm
4506 for(; it != itEnd; ++it )
4507 if( filters.shouldInclude( *it ) )
4508 matchingTestsOut.push_back( *it );
4509 }
Phil Nash3b80af72012-08-09 07:47:30 +01004510
4511 private:
4512
4513 std::set<TestCaseInfo> m_functions;
4514 std::vector<TestCaseInfo> m_functionsInOrder;
Phil Nash5bc030d2012-08-16 18:48:50 +01004515 std::vector<TestCaseInfo> m_nonHiddenFunctions;
Phil Nash3b80af72012-08-09 07:47:30 +01004516 size_t m_unnamedCount;
4517 };
4518
4519 ///////////////////////////////////////////////////////////////////////////
4520
Phil Nash5bc030d2012-08-16 18:48:50 +01004521 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
Phil Nash3b80af72012-08-09 07:47:30 +01004522 public:
4523
4524 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
4525
4526 virtual void invoke() const {
4527 m_fun();
4528 }
4529
Phil Nash3b80af72012-08-09 07:47:30 +01004530 private:
Phil Nash5bc030d2012-08-16 18:48:50 +01004531 virtual ~FreeFunctionTestCase();
4532
Phil Nash3b80af72012-08-09 07:47:30 +01004533 TestFunction m_fun;
4534 };
4535
Phil Nash88b70822012-11-04 21:39:38 +00004536 inline std::string extractClassName( const std::string& classOrQualifiedMethodName ) {
4537 std::string className = classOrQualifiedMethodName;
4538 if( className[0] == '&' )
4539 {
4540 std::size_t lastColons = className.rfind( "::" );
4541 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
4542 if( penultimateColons == std::string::npos )
4543 penultimateColons = 1;
4544 className = className.substr( penultimateColons, lastColons-penultimateColons );
4545 }
4546 return className;
4547 }
4548
Phil Nash3b80af72012-08-09 07:47:30 +01004549 ///////////////////////////////////////////////////////////////////////////
4550
4551 AutoReg::AutoReg( TestFunction function,
4552 const char* name,
4553 const char* description,
4554 const SourceLineInfo& lineInfo ) {
Phil Nash88b70822012-11-04 21:39:38 +00004555 registerTestCase( new FreeFunctionTestCase( function ), "global", name, description, lineInfo );
Phil Nash3b80af72012-08-09 07:47:30 +01004556 }
4557
4558 AutoReg::~AutoReg() {}
4559
4560 void AutoReg::registerTestCase( ITestCase* testCase,
Phil Nash88b70822012-11-04 21:39:38 +00004561 const char* classOrQualifiedMethodName,
Phil Nash3b80af72012-08-09 07:47:30 +01004562 const char* name,
4563 const char* description,
4564 const SourceLineInfo& lineInfo ) {
Phil Nash88b70822012-11-04 21:39:38 +00004565
4566 getMutableRegistryHub().registerTest( TestCaseInfo( testCase, extractClassName( classOrQualifiedMethodName ), name, description, lineInfo ) );
Phil Nash3b80af72012-08-09 07:47:30 +01004567 }
4568
4569} // end namespace Catch
4570
4571// #included from: catch_reporter_registry.hpp
4572#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
4573
4574#include <map>
4575
4576namespace Catch {
4577
4578 class ReporterRegistry : public IReporterRegistry {
4579
4580 public:
4581
Phil Nasha695eb92012-08-13 07:46:10 +01004582 virtual ~ReporterRegistry() {
Phil Nash3b80af72012-08-09 07:47:30 +01004583 deleteAllValues( m_factories );
4584 }
4585
4586 virtual IReporter* create( const std::string& name, const ReporterConfig& config ) const {
4587 FactoryMap::const_iterator it = m_factories.find( name );
4588 if( it == m_factories.end() )
4589 return NULL;
4590 return it->second->create( config );
4591 }
4592
4593 void registerReporter( const std::string& name, IReporterFactory* factory ) {
4594 m_factories.insert( std::make_pair( name, factory ) );
4595 }
4596
4597 const FactoryMap& getFactories() const {
4598 return m_factories;
4599 }
4600
4601 private:
4602 FactoryMap m_factories;
4603 };
4604}
4605
4606// #included from: catch_exception_translator_registry.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004607#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01004608
4609#ifdef __OBJC__
4610#import "Foundation/Foundation.h"
4611#endif
4612
4613namespace Catch {
4614
4615 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
4616 public:
4617 ~ExceptionTranslatorRegistry() {
4618 deleteAll( m_translators );
4619 }
4620
4621 virtual void registerTranslator( const IExceptionTranslator* translator ) {
4622 m_translators.push_back( translator );
4623 }
4624
4625 virtual std::string translateActiveException() const {
4626 try {
4627#ifdef __OBJC__
4628 // In Objective-C try objective-c exceptions first
4629 @try {
4630 throw;
4631 }
4632 @catch (NSException *exception) {
4633 return toString( [exception description] );
4634 }
4635#else
4636 throw;
4637#endif
4638 }
4639 catch( std::exception& ex ) {
4640 return ex.what();
4641 }
4642 catch( std::string& msg ) {
4643 return msg;
4644 }
4645 catch( const char* msg ) {
4646 return msg;
4647 }
4648 catch(...) {
4649 return tryTranslators( m_translators.begin() );
4650 }
4651 }
4652
4653 std::string tryTranslators( std::vector<const IExceptionTranslator*>::const_iterator it ) const {
4654 if( it == m_translators.end() )
4655 return "Unknown exception";
4656
4657 try {
4658 return (*it)->translate();
4659 }
4660 catch(...) {
4661 return tryTranslators( it+1 );
4662 }
4663 }
4664
4665 private:
4666 std::vector<const IExceptionTranslator*> m_translators;
4667 };
4668}
4669
4670namespace Catch {
4671
4672 namespace {
4673
4674 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
4675
4676 RegistryHub( const RegistryHub& );
4677 void operator=( const RegistryHub& );
4678
4679 public: // IRegistryHub
4680 RegistryHub() {
4681 }
4682 virtual const IReporterRegistry& getReporterRegistry() const {
4683 return m_reporterRegistry;
4684 }
4685 virtual const ITestCaseRegistry& getTestCaseRegistry() const {
4686 return m_testCaseRegistry;
4687 }
4688 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
4689 return m_exceptionTranslatorRegistry;
4690 }
4691
4692 public: // IMutableRegistryHub
4693 virtual void registerReporter( const std::string& name, IReporterFactory* factory ) {
4694 m_reporterRegistry.registerReporter( name, factory );
4695 }
4696 virtual void registerTest( const TestCaseInfo& testInfo ) {
4697 m_testCaseRegistry.registerTest( testInfo );
4698 }
4699 virtual void registerTranslator( const IExceptionTranslator* translator ) {
4700 m_exceptionTranslatorRegistry.registerTranslator( translator );
4701 }
4702
4703 private:
4704 TestRegistry m_testCaseRegistry;
4705 ReporterRegistry m_reporterRegistry;
4706 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
4707 };
4708
4709 // Single, global, instance
4710 inline RegistryHub*& getTheRegistryHub() {
4711 static RegistryHub* theRegistryHub = NULL;
4712 if( !theRegistryHub )
4713 theRegistryHub = new RegistryHub();
4714 return theRegistryHub;
4715 }
4716 }
4717
4718 IRegistryHub& getRegistryHub() {
4719 return *getTheRegistryHub();
4720 }
4721 IMutableRegistryHub& getMutableRegistryHub() {
4722 return *getTheRegistryHub();
4723 }
4724 void cleanUp() {
4725 delete getTheRegistryHub();
4726 getTheRegistryHub() = NULL;
4727 cleanUpContext();
4728 }
Phil Nash82acc2c2012-10-28 12:07:17 +00004729 std::string translateActiveException() {
4730 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
4731 }
Phil Nash3b80af72012-08-09 07:47:30 +01004732
4733} // end namespace Catch
Matt Wozniskif29c8982012-09-17 01:42:29 -04004734
Phil Nash3b80af72012-08-09 07:47:30 +01004735// #included from: catch_notimplemented_exception.hpp
4736#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
4737
4738#include <ostream>
4739
4740namespace Catch {
4741
4742 NotImplementedException::NotImplementedException( const SourceLineInfo& lineInfo )
4743 : m_lineInfo( lineInfo ) {
4744 std::ostringstream oss;
4745 oss << lineInfo << "function ";
Phil Nash3b80af72012-08-09 07:47:30 +01004746 oss << "not implemented";
4747 m_what = oss.str();
4748 }
4749
4750 const char* NotImplementedException::what() const throw() {
4751 return m_what.c_str();
4752 }
4753
4754} // end namespace Catch
4755
4756// #included from: catch_context_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004757#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01004758
Phil Nash3b80af72012-08-09 07:47:30 +01004759namespace Catch {
4760
4761 class Context : public IMutableContext {
4762
4763 Context() : m_config( NULL ) {}
4764 Context( const Context& );
4765 void operator=( const Context& );
4766
4767 public: // IContext
4768 virtual IResultCapture& getResultCapture() {
4769 return *m_resultCapture;
4770 }
4771 virtual IRunner& getRunner() {
4772 return *m_runner;
4773 }
4774 virtual size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ) {
4775 return getGeneratorsForCurrentTest()
4776 .getGeneratorInfo( fileInfo, totalSize )
4777 .getCurrentIndex();
4778 }
4779 virtual bool advanceGeneratorsForCurrentTest() {
4780 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
4781 return generators && generators->moveNext();
4782 }
4783
4784 virtual const IConfig* getConfig() const {
4785 return m_config;
4786 }
4787
4788 public: // IMutableContext
4789 virtual void setResultCapture( IResultCapture* resultCapture ) {
4790 m_resultCapture = resultCapture;
4791 }
4792 virtual void setRunner( IRunner* runner ) {
4793 m_runner = runner;
4794 }
4795 virtual void setConfig( const IConfig* config ) {
4796 m_config = config;
4797 }
4798
4799 friend IMutableContext& getCurrentMutableContext();
4800
4801 private:
4802 IGeneratorsForTest* findGeneratorsForCurrentTest() {
4803 std::string testName = getResultCapture().getCurrentTestName();
4804
4805 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
4806 m_generatorsByTestName.find( testName );
4807 return it != m_generatorsByTestName.end()
4808 ? it->second
4809 : NULL;
4810 }
4811
4812 IGeneratorsForTest& getGeneratorsForCurrentTest() {
4813 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
4814 if( !generators ) {
4815 std::string testName = getResultCapture().getCurrentTestName();
4816 generators = createGeneratorsForTest();
4817 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
4818 }
4819 return *generators;
4820 }
4821
4822 private:
4823 IRunner* m_runner;
4824 IResultCapture* m_resultCapture;
4825 const IConfig* m_config;
4826 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
4827 };
4828
4829 namespace {
4830 Context* currentContext = NULL;
4831 }
4832 IMutableContext& getCurrentMutableContext() {
4833 if( !currentContext )
4834 currentContext = new Context();
4835 return *currentContext;
4836 }
4837 IContext& getCurrentContext() {
4838 return getCurrentMutableContext();
4839 }
4840
Phil Nash67ec8702012-09-26 18:38:26 +01004841 Stream createStream( const std::string& streamName ) {
4842 if( streamName == "stdout" ) return Stream( std::cout.rdbuf(), false );
4843 if( streamName == "stderr" ) return Stream( std::cerr.rdbuf(), false );
4844 if( streamName == "debug" ) return Stream( new StreamBufImpl<OutputDebugWriter>, true );
Phil Nash3b80af72012-08-09 07:47:30 +01004845
4846 throw std::domain_error( "Unknown stream: " + streamName );
4847 }
4848
4849 void cleanUpContext() {
4850 delete currentContext;
4851 currentContext = NULL;
4852 }
4853}
Matt Wozniskif29c8982012-09-17 01:42:29 -04004854
Phil Nash3b80af72012-08-09 07:47:30 +01004855// #included from: catch_console_colour_impl.hpp
4856#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
4857
Phil Nash56d5c422012-08-23 20:08:50 +01004858// #included from: catch_console_colour.hpp
4859#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
4860
4861namespace Catch {
4862
4863 struct ConsoleColourImpl;
4864
4865 class TextColour : NonCopyable {
4866 public:
4867
4868 enum Colours {
4869 None,
4870
4871 FileName,
4872 ResultError,
4873 ResultSuccess,
4874
4875 Error,
4876 Success,
4877
4878 OriginalExpression,
4879 ReconstructedExpression
4880 };
4881
4882 TextColour( Colours colour = None );
4883 void set( Colours colour );
4884 ~TextColour();
4885
4886 private:
4887 ConsoleColourImpl* m_impl;
4888 };
4889
4890} // end namespace Catch
4891
Phil Nash355b95f2012-10-31 18:04:22 +00004892#if defined( CATCH_CONFIG_USE_ANSI_COLOUR_CODES )
4893
4894#include <unistd.h>
4895
Phil Nash5efa4bc2012-10-29 20:49:22 +00004896namespace Catch {
4897
Phil Nash355b95f2012-10-31 18:04:22 +00004898 // use POSIX/ ANSI console terminal codes
Phil Nash5efa4bc2012-10-29 20:49:22 +00004899 // Implementation contributed by Adam Strzelecki (http://github.com/nanoant)
4900 // https://github.com/philsquared/Catch/pull/131
4901
4902 TextColour::TextColour( Colours colour ) {
4903 if( colour )
4904 set( colour );
4905 }
4906
4907 TextColour::~TextColour() {
4908 set( TextColour::None );
4909 }
4910
Phil Nash355b95f2012-10-31 18:04:22 +00004911 namespace { const char colourEscape = '\033'; }
4912
Phil Nash5efa4bc2012-10-29 20:49:22 +00004913 void TextColour::set( Colours colour ) {
4914 if( isatty( fileno(stdout) ) ) {
4915 switch( colour ) {
4916 case TextColour::FileName:
Phil Nash88b70822012-11-04 21:39:38 +00004917 std::cout << colourEscape << "[0m"; // white/ normal
Phil Nash5efa4bc2012-10-29 20:49:22 +00004918 break;
4919 case TextColour::ResultError:
Phil Nash355b95f2012-10-31 18:04:22 +00004920 std::cout << colourEscape << "[1;31m"; // bold red
Phil Nash5efa4bc2012-10-29 20:49:22 +00004921 break;
4922 case TextColour::ResultSuccess:
Phil Nash355b95f2012-10-31 18:04:22 +00004923 std::cout << colourEscape << "[1;32m"; // bold green
Phil Nash5efa4bc2012-10-29 20:49:22 +00004924 break;
4925 case TextColour::Error:
Phil Nash355b95f2012-10-31 18:04:22 +00004926 std::cout << colourEscape << "[0;31m"; // red
Phil Nash5efa4bc2012-10-29 20:49:22 +00004927 break;
4928 case TextColour::Success:
Phil Nash355b95f2012-10-31 18:04:22 +00004929 std::cout << colourEscape << "[0;32m"; // green
Phil Nash5efa4bc2012-10-29 20:49:22 +00004930 break;
4931 case TextColour::OriginalExpression:
Phil Nash355b95f2012-10-31 18:04:22 +00004932 std::cout << colourEscape << "[0;36m"; // cyan
Phil Nash5efa4bc2012-10-29 20:49:22 +00004933 break;
4934 case TextColour::ReconstructedExpression:
Phil Nash355b95f2012-10-31 18:04:22 +00004935 std::cout << colourEscape << "[0;33m"; // yellow
Phil Nash5efa4bc2012-10-29 20:49:22 +00004936 break;
4937 case TextColour::None:
Phil Nash88b70822012-11-04 21:39:38 +00004938 std::cout << colourEscape << "[0m"; // reset
Phil Nash5efa4bc2012-10-29 20:49:22 +00004939 }
4940 }
4941 }
4942
Phil Nash355b95f2012-10-31 18:04:22 +00004943} // namespace Catch
4944
Phil Nash5efa4bc2012-10-29 20:49:22 +00004945#elif defined ( CATCH_PLATFORM_WINDOWS )
Phil Nash3b80af72012-08-09 07:47:30 +01004946
4947#include <windows.h>
4948
Phil Nash355b95f2012-10-31 18:04:22 +00004949namespace Catch {
4950
Phil Nash3b80af72012-08-09 07:47:30 +01004951 namespace {
4952
4953 WORD mapConsoleColour( TextColour::Colours colour ) {
4954 switch( colour ) {
4955 case TextColour::FileName:
4956 return FOREGROUND_INTENSITY; // greyed out
4957 case TextColour::ResultError:
4958 return FOREGROUND_RED | FOREGROUND_INTENSITY; // bright red
4959 case TextColour::ResultSuccess:
4960 return FOREGROUND_GREEN | FOREGROUND_INTENSITY; // bright green
4961 case TextColour::Error:
4962 return FOREGROUND_RED; // dark red
4963 case TextColour::Success:
4964 return FOREGROUND_GREEN; // dark green
4965 case TextColour::OriginalExpression:
4966 return FOREGROUND_BLUE | FOREGROUND_GREEN; // turquoise
4967 case TextColour::ReconstructedExpression:
4968 return FOREGROUND_RED | FOREGROUND_GREEN; // greeny-yellow
4969 default: return 0;
4970 }
4971 }
4972 }
4973
4974 struct ConsoleColourImpl {
4975
4976 ConsoleColourImpl()
4977 : hStdout( GetStdHandle(STD_OUTPUT_HANDLE) ),
4978 wOldColorAttrs( 0 )
4979 {
4980 GetConsoleScreenBufferInfo( hStdout, &csbiInfo );
4981 wOldColorAttrs = csbiInfo.wAttributes;
4982 }
4983
4984 ~ConsoleColourImpl() {
4985 SetConsoleTextAttribute( hStdout, wOldColorAttrs );
4986 }
4987
4988 void set( TextColour::Colours colour ) {
4989 WORD consoleColour = mapConsoleColour( colour );
4990 if( consoleColour > 0 )
4991 SetConsoleTextAttribute( hStdout, consoleColour );
4992 }
4993
4994 HANDLE hStdout;
4995 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
4996 WORD wOldColorAttrs;
4997 };
4998
4999 TextColour::TextColour( Colours colour )
5000 : m_impl( new ConsoleColourImpl() )
5001 {
5002 if( colour )
5003 m_impl->set( colour );
5004 }
5005
5006 TextColour::~TextColour() {
5007 delete m_impl;
5008 }
5009
5010 void TextColour::set( Colours colour ) {
5011 m_impl->set( colour );
5012 }
5013
Phil Nash355b95f2012-10-31 18:04:22 +00005014} // end namespace Catch
5015
Phil Nash3b80af72012-08-09 07:47:30 +01005016#else
5017
Phil Nash355b95f2012-10-31 18:04:22 +00005018namespace Catch {
5019
Phil Nash3b80af72012-08-09 07:47:30 +01005020 TextColour::TextColour( Colours ){}
5021 TextColour::~TextColour(){}
5022 void TextColour::set( Colours ){}
5023
Phil Nash5efa4bc2012-10-29 20:49:22 +00005024} // end namespace Catch
5025
Phil Nash355b95f2012-10-31 18:04:22 +00005026#endif
5027
Phil Nash3b80af72012-08-09 07:47:30 +01005028// #included from: catch_generators_impl.hpp
5029#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
5030
5031#include <vector>
5032#include <string>
5033#include <map>
5034
5035namespace Catch {
5036
5037 struct GeneratorInfo : IGeneratorInfo {
5038
5039 GeneratorInfo( std::size_t size )
5040 : m_size( size ),
5041 m_currentIndex( 0 )
5042 {}
5043
5044 bool moveNext() {
5045 if( ++m_currentIndex == m_size ) {
5046 m_currentIndex = 0;
5047 return false;
5048 }
5049 return true;
5050 }
5051
5052 std::size_t getCurrentIndex() const {
5053 return m_currentIndex;
5054 }
5055
5056 std::size_t m_size;
5057 std::size_t m_currentIndex;
5058 };
5059
5060 ///////////////////////////////////////////////////////////////////////////
5061
5062 class GeneratorsForTest : public IGeneratorsForTest {
5063
5064 public:
5065 ~GeneratorsForTest() {
5066 deleteAll( m_generatorsInOrder );
5067 }
5068
5069 IGeneratorInfo& getGeneratorInfo( const std::string& fileInfo, std::size_t size ) {
5070 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
5071 if( it == m_generatorsByName.end() ) {
5072 IGeneratorInfo* info = new GeneratorInfo( size );
5073 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
5074 m_generatorsInOrder.push_back( info );
5075 return *info;
5076 }
5077 return *it->second;
5078 }
5079
5080 bool moveNext() {
5081 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
5082 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
5083 for(; it != itEnd; ++it ) {
5084 if( (*it)->moveNext() )
5085 return true;
5086 }
5087 return false;
5088 }
5089
5090 private:
5091 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
5092 std::vector<IGeneratorInfo*> m_generatorsInOrder;
5093 };
5094
5095 IGeneratorsForTest* createGeneratorsForTest()
5096 {
5097 return new GeneratorsForTest();
5098 }
5099
5100} // end namespace Catch
5101
Phil Nash82acc2c2012-10-28 12:07:17 +00005102// #included from: catch_assertionresult.hpp
5103#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01005104
5105namespace Catch {
5106
Phil Nashd539da92012-11-13 09:44:52 +00005107 AssertionInfo::AssertionInfo( const std::string& _macroName,
5108 const SourceLineInfo& _lineInfo,
5109 const std::string& _capturedExpression,
5110 ResultDisposition::Flags _resultDisposition )
5111 : macroName( _macroName ),
5112 lineInfo( _lineInfo ),
5113 capturedExpression( _capturedExpression ),
5114 resultDisposition( _resultDisposition )
5115 {
5116 if( shouldNegate( resultDisposition ) )
5117 capturedExpression = "!" + _capturedExpression;
5118 }
5119
Phil Nash82acc2c2012-10-28 12:07:17 +00005120 AssertionResult::AssertionResult() {}
Phil Nash3b80af72012-08-09 07:47:30 +01005121
Phil Nash82acc2c2012-10-28 12:07:17 +00005122 AssertionResult::AssertionResult( const AssertionInfo& info, const AssertionResultData& data )
5123 : m_info( info ),
5124 m_resultData( data )
5125 {}
Phil Nash3b80af72012-08-09 07:47:30 +01005126
Phil Nash82acc2c2012-10-28 12:07:17 +00005127 AssertionResult::~AssertionResult() {}
Phil Nash3b80af72012-08-09 07:47:30 +01005128
Phil Nashd539da92012-11-13 09:44:52 +00005129 // Result was a success
5130 bool AssertionResult::succeeded() const {
5131 return Catch::isOk( m_resultData.resultType );
5132 }
5133
5134 // Result was a success, or failure is suppressed
5135 bool AssertionResult::isOk() const {
5136 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
Phil Nash3b80af72012-08-09 07:47:30 +01005137 }
5138
Phil Nash82acc2c2012-10-28 12:07:17 +00005139 ResultWas::OfType AssertionResult::getResultType() const {
5140 return m_resultData.resultType;
Phil Nash3b80af72012-08-09 07:47:30 +01005141 }
5142
Phil Nash82acc2c2012-10-28 12:07:17 +00005143 bool AssertionResult::hasExpression() const {
5144 return !m_info.capturedExpression.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01005145 }
5146
Phil Nash82acc2c2012-10-28 12:07:17 +00005147 bool AssertionResult::hasMessage() const {
5148 return !m_resultData.message.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01005149 }
5150
Phil Nash82acc2c2012-10-28 12:07:17 +00005151 std::string AssertionResult::getExpression() const {
5152 return m_info.capturedExpression;
Phil Nash3b80af72012-08-09 07:47:30 +01005153 }
5154
Phil Nash82acc2c2012-10-28 12:07:17 +00005155 bool AssertionResult::hasExpandedExpression() const {
Phil Nash67305122012-10-09 11:48:55 +01005156 return hasExpression() && getExpandedExpression() != getExpression();
Phil Nash3b80af72012-08-09 07:47:30 +01005157 }
5158
Phil Nash82acc2c2012-10-28 12:07:17 +00005159 std::string AssertionResult::getExpandedExpression() const {
5160 return m_resultData.reconstructedExpression;
Phil Nash3b80af72012-08-09 07:47:30 +01005161 }
5162
Phil Nash82acc2c2012-10-28 12:07:17 +00005163 std::string AssertionResult::getMessage() const {
5164 return m_resultData.message;
5165 }
5166 SourceLineInfo AssertionResult::getSourceInfo() const {
5167 return m_info.lineInfo;
Phil Nash3b80af72012-08-09 07:47:30 +01005168 }
5169
Phil Nash82acc2c2012-10-28 12:07:17 +00005170 std::string AssertionResult::getTestMacroName() const {
5171 return m_info.macroName;
Phil Nash3b80af72012-08-09 07:47:30 +01005172 }
5173
5174} // end namespace Catch
5175
Phil Nash82acc2c2012-10-28 12:07:17 +00005176// #included from: catch_expressionresult_builder.hpp
5177#define TWOBLUECUBES_CATCH_EXPRESSIONRESULT_BUILDER_HPP_INCLUDED
5178
5179#include <assert.h>
Phil Nash3b80af72012-08-09 07:47:30 +01005180
5181namespace Catch {
5182
Phil Nash82acc2c2012-10-28 12:07:17 +00005183 ExpressionResultBuilder::ExpressionResultBuilder( ResultWas::OfType resultType ) {
5184 m_data.resultType = resultType;
Phil Nash67305122012-10-09 11:48:55 +01005185 }
Phil Nash82acc2c2012-10-28 12:07:17 +00005186 ExpressionResultBuilder::ExpressionResultBuilder( const ExpressionResultBuilder& other )
5187 : m_data( other.m_data ),
5188 m_exprComponents( other.m_exprComponents )
Phil Nash67305122012-10-09 11:48:55 +01005189 {
Phil Nash82acc2c2012-10-28 12:07:17 +00005190 m_stream << other.m_stream.str();
Phil Nash3b80af72012-08-09 07:47:30 +01005191 }
Phil Nash82acc2c2012-10-28 12:07:17 +00005192 ExpressionResultBuilder& ExpressionResultBuilder::operator=(const ExpressionResultBuilder& other ) {
5193 m_data = other.m_data;
5194 m_exprComponents = other.m_exprComponents;
5195 m_stream.str("");
5196 m_stream << other.m_stream.str();
5197 return *this;
5198 }
5199 ExpressionResultBuilder& ExpressionResultBuilder::setResultType( ResultWas::OfType result ) {
5200 m_data.resultType = result;
5201 return *this;
5202 }
5203 ExpressionResultBuilder& ExpressionResultBuilder::setResultType( bool result ) {
5204 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
5205 return *this;
5206 }
Phil Nashaf1a3212012-11-10 18:46:39 +00005207 ExpressionResultBuilder& ExpressionResultBuilder::endExpression( ResultDisposition::Flags resultDisposition ) {
Phil Nashd539da92012-11-13 09:44:52 +00005208 m_exprComponents.shouldNegate = shouldNegate( resultDisposition );
Phil Nash82acc2c2012-10-28 12:07:17 +00005209 return *this;
5210 }
5211 ExpressionResultBuilder& ExpressionResultBuilder::setLhs( const std::string& lhs ) {
5212 m_exprComponents.lhs = lhs;
5213 return *this;
5214 }
5215 ExpressionResultBuilder& ExpressionResultBuilder::setRhs( const std::string& rhs ) {
5216 m_exprComponents.rhs = rhs;
5217 return *this;
5218 }
5219 ExpressionResultBuilder& ExpressionResultBuilder::setOp( const std::string& op ) {
5220 m_exprComponents.op = op;
5221 return *this;
5222 }
5223 AssertionResult ExpressionResultBuilder::buildResult( const AssertionInfo& info ) const
5224 {
5225 assert( m_data.resultType != ResultWas::Unknown );
Phil Nash3b80af72012-08-09 07:47:30 +01005226
Phil Nash82acc2c2012-10-28 12:07:17 +00005227 AssertionResultData data = m_data;
5228
5229 // Flip bool results if shouldNegate is set
5230 if( m_exprComponents.shouldNegate && data.resultType == ResultWas::Ok )
5231 data.resultType = ResultWas::ExpressionFailed;
5232 else if( m_exprComponents.shouldNegate && data.resultType == ResultWas::ExpressionFailed )
5233 data.resultType = ResultWas::Ok;
5234
5235 data.message = m_stream.str();
5236 data.reconstructedExpression = reconstructExpression( info );
5237 if( m_exprComponents.shouldNegate ) {
5238 if( m_exprComponents.op == "" )
5239 data.reconstructedExpression = "!" + data.reconstructedExpression;
Phil Nash67305122012-10-09 11:48:55 +01005240 else
Phil Nash82acc2c2012-10-28 12:07:17 +00005241 data.reconstructedExpression = "!(" + data.reconstructedExpression + ")";
5242 }
5243 return AssertionResult( info, data );
5244 }
5245 std::string ExpressionResultBuilder::reconstructExpression( const AssertionInfo& info ) const {
5246 if( m_exprComponents.op == "" )
5247 return m_exprComponents.lhs.empty() ? info.capturedExpression : m_exprComponents.op + m_exprComponents.lhs;
5248 else if( m_exprComponents.op == "matches" )
5249 return m_exprComponents.lhs + " " + m_exprComponents.rhs;
5250 else if( m_exprComponents.op != "!" ) {
5251 if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 30 )
5252 return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs;
5253 else if( m_exprComponents.lhs.size() < 70 && m_exprComponents.rhs.size() < 70 )
5254 return "\n\t" + m_exprComponents.lhs + "\n\t" + m_exprComponents.op + "\n\t" + m_exprComponents.rhs;
5255 else
5256 return "\n" + m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs + "\n\n";
Phil Nash67305122012-10-09 11:48:55 +01005257 }
5258 else
Phil Nash82acc2c2012-10-28 12:07:17 +00005259 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 +01005260 }
5261
5262} // end namespace Catch
5263
Phil Nash5bc030d2012-08-16 18:48:50 +01005264// #included from: catch_test_case_info.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005265#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
Phil Nash5bc030d2012-08-16 18:48:50 +01005266
5267namespace Catch {
5268
5269 TestCaseInfo::TestCaseInfo( ITestCase* testCase,
Phil Nash88b70822012-11-04 21:39:38 +00005270 const std::string& className,
5271 const std::string& name,
5272 const std::string& description,
Phil Nash5bc030d2012-08-16 18:48:50 +01005273 const SourceLineInfo& lineInfo )
5274 : m_test( testCase ),
Phil Nash88b70822012-11-04 21:39:38 +00005275 m_className( className ),
Phil Nash5bc030d2012-08-16 18:48:50 +01005276 m_name( name ),
5277 m_description( description ),
Phil Nashfc1baac2012-09-15 17:53:27 +01005278 m_lineInfo( lineInfo ),
5279 m_isHidden( startsWith( name, "./" ) )
5280 {
Phil Nash799ecf92012-09-24 08:30:13 +01005281 TagExtracter( m_tags ).parse( m_description );
Phil Nashfc1baac2012-09-15 17:53:27 +01005282 if( hasTag( "hide" ) )
5283 m_isHidden = true;
5284 }
Phil Nash5bc030d2012-08-16 18:48:50 +01005285
5286 TestCaseInfo::TestCaseInfo()
5287 : m_test( NULL ),
Phil Nash88b70822012-11-04 21:39:38 +00005288 m_className(),
Phil Nash5bc030d2012-08-16 18:48:50 +01005289 m_name(),
Phil Nashfc1baac2012-09-15 17:53:27 +01005290 m_description(),
5291 m_isHidden( false )
Phil Nash5bc030d2012-08-16 18:48:50 +01005292 {}
5293
5294 TestCaseInfo::TestCaseInfo( const TestCaseInfo& other, const std::string& name )
5295 : m_test( other.m_test ),
Phil Nash88b70822012-11-04 21:39:38 +00005296 m_className( other.m_className ),
Phil Nash5bc030d2012-08-16 18:48:50 +01005297 m_name( name ),
5298 m_description( other.m_description ),
Phil Nashfc1baac2012-09-15 17:53:27 +01005299 m_tags( other.m_tags ),
5300 m_lineInfo( other.m_lineInfo ),
5301 m_isHidden( other.m_isHidden )
Phil Nash5bc030d2012-08-16 18:48:50 +01005302 {}
5303
Phil Nashd2ec8492012-08-23 19:48:57 +01005304 TestCaseInfo::TestCaseInfo( const TestCaseInfo& other )
5305 : m_test( other.m_test ),
Phil Nash88b70822012-11-04 21:39:38 +00005306 m_className( other.m_className ),
Phil Nashd2ec8492012-08-23 19:48:57 +01005307 m_name( other.m_name ),
5308 m_description( other.m_description ),
Phil Nashfc1baac2012-09-15 17:53:27 +01005309 m_tags( other.m_tags ),
5310 m_lineInfo( other.m_lineInfo ),
5311 m_isHidden( other.m_isHidden )
Phil Nashd2ec8492012-08-23 19:48:57 +01005312 {}
5313
Phil Nash5bc030d2012-08-16 18:48:50 +01005314 void TestCaseInfo::invoke() const {
5315 m_test->invoke();
5316 }
5317
Phil Nash88b70822012-11-04 21:39:38 +00005318 const std::string& TestCaseInfo::getClassName() const {
5319 return m_className;
5320 }
Phil Nash5bc030d2012-08-16 18:48:50 +01005321 const std::string& TestCaseInfo::getName() const {
5322 return m_name;
5323 }
Phil Nash5bc030d2012-08-16 18:48:50 +01005324 const std::string& TestCaseInfo::getDescription() const {
5325 return m_description;
5326 }
Phil Nash5bc030d2012-08-16 18:48:50 +01005327 const SourceLineInfo& TestCaseInfo::getLineInfo() const {
5328 return m_lineInfo;
5329 }
5330
5331 bool TestCaseInfo::isHidden() const {
Phil Nashfc1baac2012-09-15 17:53:27 +01005332 return m_isHidden;
5333 }
5334
5335 bool TestCaseInfo::hasTag( const std::string& tag ) const {
5336 return m_tags.find( tag ) != m_tags.end();
5337 }
Phil Nash799ecf92012-09-24 08:30:13 +01005338 bool TestCaseInfo::matchesTags( const std::string& tagPattern ) const {
5339 TagExpression exp;
5340 TagExpressionParser( exp ).parse( tagPattern );
5341 return exp.matches( m_tags );
5342 }
Phil Nash67ec8702012-09-26 18:38:26 +01005343 const std::set<std::string>& TestCaseInfo::getTags() const {
Phil Nashfc1baac2012-09-15 17:53:27 +01005344 return m_tags;
Phil Nash5bc030d2012-08-16 18:48:50 +01005345 }
5346
5347 void TestCaseInfo::swap( TestCaseInfo& other ) {
5348 m_test.swap( other.m_test );
Phil Nash88b70822012-11-04 21:39:38 +00005349 m_className.swap( other.m_className );
Phil Nash5bc030d2012-08-16 18:48:50 +01005350 m_name.swap( other.m_name );
5351 m_description.swap( other.m_description );
Phil Nash88b70822012-11-04 21:39:38 +00005352 std::swap( m_lineInfo, other.m_lineInfo );
Phil Nash5bc030d2012-08-16 18:48:50 +01005353 }
5354
5355 bool TestCaseInfo::operator == ( const TestCaseInfo& other ) const {
Phil Nash88b70822012-11-04 21:39:38 +00005356 return m_test.get() == other.m_test.get() &&
5357 m_name == other.m_name &&
5358 m_className == other.m_className;
Phil Nash5bc030d2012-08-16 18:48:50 +01005359 }
5360
5361 bool TestCaseInfo::operator < ( const TestCaseInfo& other ) const {
5362 return m_name < other.m_name;
5363 }
Phil Nashd2ec8492012-08-23 19:48:57 +01005364 TestCaseInfo& TestCaseInfo::operator = ( const TestCaseInfo& other ) {
5365 TestCaseInfo temp( other );
5366 swap( temp );
5367 return *this;
5368 }
Phil Nash799ecf92012-09-24 08:30:13 +01005369
5370} // end namespace Catch
Phil Nash5bc030d2012-08-16 18:48:50 +01005371
Phil Nash7673a302012-11-15 22:15:41 +00005372// #included from: catch_version.hpp
5373#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
5374
5375namespace Catch {
5376
5377 // These numbers are maintained by a script
5378 Version libraryVersion = { 0, 9, 1, "integration" };
5379}
5380
Phil Nash56d5c422012-08-23 20:08:50 +01005381// #included from: ../reporters/catch_reporter_basic.hpp
5382#define TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
5383
5384// #included from: ../internal/catch_reporter_registrars.hpp
5385#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
5386
5387namespace Catch {
5388
5389 template<typename T>
5390 class ReporterRegistrar {
5391
5392 class ReporterFactory : public IReporterFactory {
5393
5394 virtual IReporter* create( const ReporterConfig& config ) const {
5395 return new T( config );
5396 }
5397
5398 virtual std::string getDescription() const {
5399 return T::getDescription();
5400 }
5401 };
5402
5403 public:
5404
5405 ReporterRegistrar( const std::string& name ) {
5406 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
5407 }
5408 };
5409}
5410
5411#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
5412 Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name );
5413
5414namespace Catch {
5415
Phil Nash56d5c422012-08-23 20:08:50 +01005416 class BasicReporter : public SharedImpl<IReporter> {
5417
5418 struct SpanInfo {
5419
5420 SpanInfo()
5421 : emitted( false )
5422 {}
5423
5424 SpanInfo( const std::string& spanName )
5425 : name( spanName ),
5426 emitted( false )
5427 {}
5428
5429 SpanInfo( const SpanInfo& other )
5430 : name( other.name ),
5431 emitted( other.emitted )
5432 {}
5433
5434 std::string name;
5435 bool emitted;
5436 };
5437
5438 public:
5439 BasicReporter( const ReporterConfig& config )
5440 : m_config( config ),
5441 m_firstSectionInTestCase( true ),
5442 m_aborted( false )
5443 {}
5444
5445 virtual ~BasicReporter();
5446
5447 static std::string getDescription() {
5448 return "Reports test results as lines of text";
5449 }
5450
5451 private:
5452
5453 void ReportCounts( const std::string& label, const Counts& counts, const std::string& allPrefix = "All " ) {
5454 if( counts.passed )
5455 m_config.stream << counts.failed << " of " << counts.total() << " " << label << "s failed";
5456 else
5457 m_config.stream << ( counts.failed > 1 ? allPrefix : "" ) << pluralise( counts.failed, label ) << " failed";
5458 }
5459
5460 void ReportCounts( const Totals& totals, const std::string& allPrefix = "All " ) {
5461 if( totals.assertions.total() == 0 ) {
5462 m_config.stream << "No tests ran";
5463 }
5464 else if( totals.assertions.failed ) {
5465 TextColour colour( TextColour::ResultError );
5466 ReportCounts( "test case", totals.testCases, allPrefix );
5467 if( totals.testCases.failed > 0 ) {
5468 m_config.stream << " (";
5469 ReportCounts( "assertion", totals.assertions, allPrefix );
5470 m_config.stream << ")";
5471 }
5472 }
5473 else {
5474 TextColour colour( TextColour::ResultSuccess );
5475 m_config.stream << allPrefix << "tests passed ("
5476 << pluralise( totals.assertions.passed, "assertion" ) << " in "
5477 << pluralise( totals.testCases.passed, "test case" ) << ")";
5478 }
5479 }
5480
5481 private: // IReporter
5482
5483 virtual bool shouldRedirectStdout() const {
5484 return false;
5485 }
5486
5487 virtual void StartTesting() {
5488 m_testingSpan = SpanInfo();
5489 }
5490
5491 virtual void Aborted() {
5492 m_aborted = true;
5493 }
5494
5495 virtual void EndTesting( const Totals& totals ) {
5496 // Output the overall test results even if "Started Testing" was not emitted
5497 if( m_aborted ) {
5498 m_config.stream << "\n[Testing aborted. ";
5499 ReportCounts( totals, "The first " );
5500 }
5501 else {
5502 m_config.stream << "\n[Testing completed. ";
5503 ReportCounts( totals );
5504 }
5505 m_config.stream << "]\n" << std::endl;
5506 }
5507
5508 virtual void StartGroup( const std::string& groupName ) {
5509 m_groupSpan = groupName;
5510 }
5511
5512 virtual void EndGroup( const std::string& groupName, const Totals& totals ) {
5513 if( m_groupSpan.emitted && !groupName.empty() ) {
5514 m_config.stream << "[End of group: '" << groupName << "'. ";
5515 ReportCounts( totals );
5516 m_config.stream << "]\n" << std::endl;
5517 m_groupSpan = SpanInfo();
5518 }
5519 }
5520
5521 virtual void StartTestCase( const TestCaseInfo& testInfo ) {
5522 m_testSpan = testInfo.getName();
5523 }
5524
5525 virtual void StartSection( const std::string& sectionName, const std::string& ) {
5526 m_sectionSpans.push_back( SpanInfo( sectionName ) );
5527 }
5528
Phil Nasha70fbe32012-08-31 08:10:36 +01005529 virtual void NoAssertionsInSection( const std::string& sectionName ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01005530 startSpansLazily();
Phil Nasha70fbe32012-08-31 08:10:36 +01005531 TextColour colour( TextColour::ResultError );
5532 m_config.stream << "\nNo assertions in section, '" << sectionName << "'\n" << std::endl;
5533 }
5534 virtual void NoAssertionsInTestCase( const std::string& testName ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01005535 startSpansLazily();
Phil Nasha70fbe32012-08-31 08:10:36 +01005536 TextColour colour( TextColour::ResultError );
5537 m_config.stream << "\nNo assertions in test case, '" << testName << "'\n" << std::endl;
5538 }
5539
Phil Nash56d5c422012-08-23 20:08:50 +01005540 virtual void EndSection( const std::string& sectionName, const Counts& assertions ) {
Phil Nasha70fbe32012-08-31 08:10:36 +01005541
Phil Nash56d5c422012-08-23 20:08:50 +01005542 SpanInfo& sectionSpan = m_sectionSpans.back();
5543 if( sectionSpan.emitted && !sectionSpan.name.empty() ) {
5544 m_config.stream << "[End of section: '" << sectionName << "' ";
5545
5546 if( assertions.failed ) {
5547 TextColour colour( TextColour::ResultError );
5548 ReportCounts( "assertion", assertions);
5549 }
5550 else {
5551 TextColour colour( TextColour::ResultSuccess );
5552 m_config.stream << ( assertions.passed > 1 ? "All " : "" )
5553 << pluralise( assertions.passed, "assertion" ) << " passed" ;
5554 }
5555 m_config.stream << "]\n" << std::endl;
5556 }
5557 m_sectionSpans.pop_back();
5558 }
5559
Phil Nash82acc2c2012-10-28 12:07:17 +00005560 virtual void Result( const AssertionResult& assertionResult ) {
5561 if( !m_config.includeSuccessfulResults && assertionResult.getResultType() == ResultWas::Ok )
Phil Nash56d5c422012-08-23 20:08:50 +01005562 return;
5563
Phil Nashe2d215e2012-09-07 17:52:35 +01005564 startSpansLazily();
Phil Nash56d5c422012-08-23 20:08:50 +01005565
Phil Nash82acc2c2012-10-28 12:07:17 +00005566 if( !assertionResult.getSourceInfo().empty() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01005567 TextColour colour( TextColour::FileName );
Phil Nash82acc2c2012-10-28 12:07:17 +00005568 m_config.stream << assertionResult.getSourceInfo();
Phil Nash56d5c422012-08-23 20:08:50 +01005569 }
5570
Phil Nash82acc2c2012-10-28 12:07:17 +00005571 if( assertionResult.hasExpression() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01005572 TextColour colour( TextColour::OriginalExpression );
Phil Nash82acc2c2012-10-28 12:07:17 +00005573 m_config.stream << assertionResult.getExpression();
Phil Nashd539da92012-11-13 09:44:52 +00005574 if( assertionResult.succeeded() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01005575 TextColour successColour( TextColour::Success );
5576 m_config.stream << " succeeded";
5577 }
5578 else {
5579 TextColour errorColour( TextColour::Error );
5580 m_config.stream << " failed";
Phil Nashd539da92012-11-13 09:44:52 +00005581 if( assertionResult.isOk() ) {
5582 TextColour okAnywayColour( TextColour::Success );
5583 m_config.stream << " - but was ok";
5584 }
Phil Nash56d5c422012-08-23 20:08:50 +01005585 }
5586 }
Phil Nash82acc2c2012-10-28 12:07:17 +00005587 switch( assertionResult.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01005588 case ResultWas::ThrewException:
Phil Nash355b95f2012-10-31 18:04:22 +00005589 {
5590 TextColour colour( TextColour::Error );
5591 if( assertionResult.hasExpression() )
5592 m_config.stream << " with unexpected";
5593 else
5594 m_config.stream << "Unexpected";
5595 m_config.stream << " exception with message: '" << assertionResult.getMessage() << "'";
5596 }
Phil Nash56d5c422012-08-23 20:08:50 +01005597 break;
5598 case ResultWas::DidntThrowException:
Phil Nash355b95f2012-10-31 18:04:22 +00005599 {
5600 TextColour colour( TextColour::Error );
5601 if( assertionResult.hasExpression() )
5602 m_config.stream << " because no exception was thrown where one was expected";
5603 else
5604 m_config.stream << "No exception thrown where one was expected";
5605 }
Phil Nash56d5c422012-08-23 20:08:50 +01005606 break;
5607 case ResultWas::Info:
Phil Nash355b95f2012-10-31 18:04:22 +00005608 {
5609 TextColour colour( TextColour::ReconstructedExpression );
5610 streamVariableLengthText( "info", assertionResult.getMessage() );
5611 }
Phil Nash56d5c422012-08-23 20:08:50 +01005612 break;
5613 case ResultWas::Warning:
Phil Nash355b95f2012-10-31 18:04:22 +00005614 {
5615 TextColour colour( TextColour::ReconstructedExpression );
5616 streamVariableLengthText( "warning", assertionResult.getMessage() );
5617 }
Phil Nash56d5c422012-08-23 20:08:50 +01005618 break;
5619 case ResultWas::ExplicitFailure:
Phil Nash355b95f2012-10-31 18:04:22 +00005620 {
5621 TextColour colour( TextColour::Error );
5622 m_config.stream << "failed with message: '" << assertionResult.getMessage() << "'";
5623 }
Phil Nash56d5c422012-08-23 20:08:50 +01005624 break;
5625 case ResultWas::Unknown: // These cases are here to prevent compiler warnings
5626 case ResultWas::Ok:
5627 case ResultWas::FailureBit:
5628 case ResultWas::ExpressionFailed:
5629 case ResultWas::Exception:
Phil Nash82acc2c2012-10-28 12:07:17 +00005630 if( !assertionResult.hasExpression() ) {
Phil Nashd539da92012-11-13 09:44:52 +00005631 if( assertionResult.succeeded() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01005632 TextColour colour( TextColour::Success );
5633 m_config.stream << " succeeded";
5634 }
5635 else {
5636 TextColour colour( TextColour::Error );
5637 m_config.stream << " failed";
Phil Nashd539da92012-11-13 09:44:52 +00005638 if( assertionResult.isOk() ) {
5639 TextColour okAnywayColour( TextColour::Success );
5640 m_config.stream << " - but was ok";
5641 }
Phil Nash56d5c422012-08-23 20:08:50 +01005642 }
5643 }
5644 break;
5645 }
5646
Phil Nash82acc2c2012-10-28 12:07:17 +00005647 if( assertionResult.hasExpandedExpression() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01005648 m_config.stream << " for: ";
Phil Nash5efa4bc2012-10-29 20:49:22 +00005649 if( assertionResult.getExpandedExpression().size() > 40 ) {
Phil Nash9444bbc2012-10-12 07:58:17 +01005650 m_config.stream << "\n";
Phil Nash5efa4bc2012-10-29 20:49:22 +00005651 if( assertionResult.getExpandedExpression().size() < 70 )
5652 m_config.stream << "\t";
5653 }
Phil Nash56d5c422012-08-23 20:08:50 +01005654 TextColour colour( TextColour::ReconstructedExpression );
Phil Nash82acc2c2012-10-28 12:07:17 +00005655 m_config.stream << assertionResult.getExpandedExpression();
Phil Nash56d5c422012-08-23 20:08:50 +01005656 }
5657 m_config.stream << std::endl;
5658 }
5659
5660 virtual void EndTestCase( const TestCaseInfo& testInfo,
5661 const Totals& totals,
5662 const std::string& stdOut,
5663 const std::string& stdErr ) {
5664 if( !stdOut.empty() ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01005665 startSpansLazily();
Phil Nash56d5c422012-08-23 20:08:50 +01005666 streamVariableLengthText( "stdout", stdOut );
5667 }
5668
5669 if( !stdErr.empty() ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01005670 startSpansLazily();
Phil Nash56d5c422012-08-23 20:08:50 +01005671 streamVariableLengthText( "stderr", stdErr );
5672 }
5673
5674 if( m_testSpan.emitted ) {
5675 m_config.stream << "[Finished: '" << testInfo.getName() << "' ";
5676 ReportCounts( totals );
5677 m_config.stream << "]" << std::endl;
5678 }
5679 }
5680
5681 private: // helpers
5682
Phil Nashe2d215e2012-09-07 17:52:35 +01005683 void startSpansLazily() {
Phil Nash56d5c422012-08-23 20:08:50 +01005684 if( !m_testingSpan.emitted ) {
5685 if( m_config.name.empty() )
5686 m_config.stream << "[Started testing]" << std::endl;
5687 else
5688 m_config.stream << "[Started testing: " << m_config.name << "]" << std::endl;
5689 m_testingSpan.emitted = true;
5690 }
5691
5692 if( !m_groupSpan.emitted && !m_groupSpan.name.empty() ) {
5693 m_config.stream << "[Started group: '" << m_groupSpan.name << "']" << std::endl;
5694 m_groupSpan.emitted = true;
5695 }
5696
5697 if( !m_testSpan.emitted ) {
5698 m_config.stream << std::endl << "[Running: " << m_testSpan.name << "]" << std::endl;
5699 m_testSpan.emitted = true;
5700 }
5701
5702 if( !m_sectionSpans.empty() ) {
5703 SpanInfo& sectionSpan = m_sectionSpans.back();
5704 if( !sectionSpan.emitted && !sectionSpan.name.empty() ) {
5705 if( m_firstSectionInTestCase ) {
5706 m_config.stream << "\n";
5707 m_firstSectionInTestCase = false;
5708 }
5709 std::vector<SpanInfo>::iterator it = m_sectionSpans.begin();
5710 std::vector<SpanInfo>::iterator itEnd = m_sectionSpans.end();
5711 for(; it != itEnd; ++it ) {
5712 SpanInfo& prevSpan = *it;
5713 if( !prevSpan.emitted && !prevSpan.name.empty() ) {
5714 m_config.stream << "[Started section: '" << prevSpan.name << "']" << std::endl;
5715 prevSpan.emitted = true;
5716 }
5717 }
5718 }
5719 }
5720 }
5721
5722 void streamVariableLengthText( const std::string& prefix, const std::string& text ) {
5723 std::string trimmed = trim( text );
5724 if( trimmed.find_first_of( "\r\n" ) == std::string::npos ) {
Phil Nash82acc2c2012-10-28 12:07:17 +00005725 m_config.stream << "[" << prefix << ": " << trimmed << "]";
Phil Nash56d5c422012-08-23 20:08:50 +01005726 }
5727 else {
5728 m_config.stream << "\n[" << prefix << "] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" << trimmed
5729 << "\n[end of " << prefix << "] <<<<<<<<<<<<<<<<<<<<<<<<\n";
5730 }
5731 }
5732
5733 private:
5734 ReporterConfig m_config;
5735 bool m_firstSectionInTestCase;
5736
5737 SpanInfo m_testingSpan;
5738 SpanInfo m_groupSpan;
5739 SpanInfo m_testSpan;
5740 std::vector<SpanInfo> m_sectionSpans;
5741 bool m_aborted;
5742 };
5743
5744} // end namespace Catch
5745
5746// #included from: ../reporters/catch_reporter_xml.hpp
5747#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
5748
5749// #included from: ../internal/catch_xmlwriter.hpp
5750#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
5751
5752#include <sstream>
Phil Nash9e7e63c2012-09-29 20:54:03 +01005753#include <iostream>
Phil Nash56d5c422012-08-23 20:08:50 +01005754#include <string>
5755#include <vector>
5756
5757namespace Catch {
5758
5759 class XmlWriter {
5760 public:
5761
5762 class ScopedElement {
5763 public:
5764 ScopedElement( XmlWriter* writer )
5765 : m_writer( writer )
5766 {}
5767
5768 ScopedElement( const ScopedElement& other )
5769 : m_writer( other.m_writer ){
5770 other.m_writer = NULL;
5771 }
5772
5773 ~ScopedElement() {
5774 if( m_writer )
5775 m_writer->endElement();
5776 }
5777
5778 ScopedElement& writeText( const std::string& text ) {
5779 m_writer->writeText( text );
5780 return *this;
5781 }
5782
5783 template<typename T>
5784 ScopedElement& writeAttribute( const std::string& name, const T& attribute ) {
5785 m_writer->writeAttribute( name, attribute );
5786 return *this;
5787 }
5788
5789 private:
5790 mutable XmlWriter* m_writer;
5791 };
5792
5793 XmlWriter()
5794 : m_tagIsOpen( false ),
5795 m_needsNewline( false ),
5796 m_os( &std::cout )
5797 {}
5798
5799 XmlWriter( std::ostream& os )
5800 : m_tagIsOpen( false ),
5801 m_needsNewline( false ),
5802 m_os( &os )
5803 {}
5804
5805 ~XmlWriter() {
5806 while( !m_tags.empty() )
5807 endElement();
5808 }
5809
5810 XmlWriter& operator = ( const XmlWriter& other ) {
5811 XmlWriter temp( other );
5812 swap( temp );
5813 return *this;
5814 }
5815
5816 void swap( XmlWriter& other ) {
5817 std::swap( m_tagIsOpen, other.m_tagIsOpen );
5818 std::swap( m_needsNewline, other.m_needsNewline );
5819 std::swap( m_tags, other.m_tags );
5820 std::swap( m_indent, other.m_indent );
5821 std::swap( m_os, other.m_os );
5822 }
5823
5824 XmlWriter& startElement( const std::string& name ) {
5825 ensureTagClosed();
5826 newlineIfNecessary();
5827 stream() << m_indent << "<" << name;
5828 m_tags.push_back( name );
5829 m_indent += " ";
5830 m_tagIsOpen = true;
5831 return *this;
5832 }
5833
5834 ScopedElement scopedElement( const std::string& name ) {
5835 ScopedElement scoped( this );
5836 startElement( name );
5837 return scoped;
5838 }
5839
5840 XmlWriter& endElement() {
5841 newlineIfNecessary();
5842 m_indent = m_indent.substr( 0, m_indent.size()-2 );
5843 if( m_tagIsOpen ) {
5844 stream() << "/>\n";
5845 m_tagIsOpen = false;
5846 }
5847 else {
5848 stream() << m_indent << "</" << m_tags.back() << ">\n";
5849 }
5850 m_tags.pop_back();
5851 return *this;
5852 }
5853
5854 XmlWriter& writeAttribute( const std::string& name, const std::string& attribute ) {
5855 if( !name.empty() && !attribute.empty() ) {
5856 stream() << " " << name << "=\"";
5857 writeEncodedText( attribute );
5858 stream() << "\"";
5859 }
5860 return *this;
5861 }
5862
5863 XmlWriter& writeAttribute( const std::string& name, bool attribute ) {
5864 stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
5865 return *this;
5866 }
5867
5868 template<typename T>
5869 XmlWriter& writeAttribute( const std::string& name, const T& attribute ) {
5870 if( !name.empty() )
5871 stream() << " " << name << "=\"" << attribute << "\"";
5872 return *this;
5873 }
5874
5875 XmlWriter& writeText( const std::string& text ) {
5876 if( !text.empty() ){
5877 bool tagWasOpen = m_tagIsOpen;
5878 ensureTagClosed();
5879 if( tagWasOpen )
5880 stream() << m_indent;
5881 writeEncodedText( text );
5882 m_needsNewline = true;
5883 }
5884 return *this;
5885 }
5886
5887 XmlWriter& writeComment( const std::string& text ) {
5888 ensureTagClosed();
5889 stream() << m_indent << "<!--" << text << "-->";
5890 m_needsNewline = true;
5891 return *this;
5892 }
5893
5894 XmlWriter& writeBlankLine() {
5895 ensureTagClosed();
5896 stream() << "\n";
5897 return *this;
5898 }
5899
5900 private:
5901
5902 std::ostream& stream() {
5903 return *m_os;
5904 }
5905
5906 void ensureTagClosed() {
5907 if( m_tagIsOpen ) {
5908 stream() << ">\n";
5909 m_tagIsOpen = false;
5910 }
5911 }
5912
5913 void newlineIfNecessary() {
5914 if( m_needsNewline ) {
5915 stream() << "\n";
5916 m_needsNewline = false;
5917 }
5918 }
5919
5920 void writeEncodedText( const std::string& text ) {
5921 static const char* charsToEncode = "<&\"";
5922 std::string mtext = text;
5923 std::string::size_type pos = mtext.find_first_of( charsToEncode );
5924 while( pos != std::string::npos ) {
5925 stream() << mtext.substr( 0, pos );
5926
5927 switch( mtext[pos] ) {
5928 case '<':
5929 stream() << "&lt;";
5930 break;
5931 case '&':
5932 stream() << "&amp;";
5933 break;
5934 case '\"':
5935 stream() << "&quot;";
5936 break;
5937 }
5938 mtext = mtext.substr( pos+1 );
5939 pos = mtext.find_first_of( charsToEncode );
5940 }
5941 stream() << mtext;
5942 }
5943
5944 bool m_tagIsOpen;
5945 bool m_needsNewline;
5946 std::vector<std::string> m_tags;
5947 std::string m_indent;
5948 std::ostream* m_os;
5949 };
5950
5951}
5952namespace Catch {
5953 class XmlReporter : public SharedImpl<IReporter> {
5954 public:
5955 XmlReporter( const ReporterConfig& config ) : m_config( config ) {}
5956
5957 static std::string getDescription() {
5958 return "Reports test results as an XML document";
5959 }
5960 virtual ~XmlReporter();
5961
5962 private: // IReporter
5963
5964 virtual bool shouldRedirectStdout() const {
5965 return true;
5966 }
5967
5968 virtual void StartTesting() {
5969 m_xml = XmlWriter( m_config.stream );
5970 m_xml.startElement( "Catch" );
5971 if( !m_config.name.empty() )
5972 m_xml.writeAttribute( "name", m_config.name );
5973 }
5974
5975 virtual void EndTesting( const Totals& totals ) {
5976 m_xml.scopedElement( "OverallResults" )
5977 .writeAttribute( "successes", totals.assertions.passed )
5978 .writeAttribute( "failures", totals.assertions.failed );
5979 m_xml.endElement();
5980 }
5981
5982 virtual void StartGroup( const std::string& groupName ) {
5983 m_xml.startElement( "Group" )
5984 .writeAttribute( "name", groupName );
5985 }
5986
5987 virtual void EndGroup( const std::string&, const Totals& totals ) {
5988 m_xml.scopedElement( "OverallResults" )
5989 .writeAttribute( "successes", totals.assertions.passed )
5990 .writeAttribute( "failures", totals.assertions.failed );
5991 m_xml.endElement();
5992 }
5993
5994 virtual void StartSection( const std::string& sectionName, const std::string& description ) {
5995 m_xml.startElement( "Section" )
5996 .writeAttribute( "name", sectionName )
5997 .writeAttribute( "description", description );
5998 }
Phil Nasha70fbe32012-08-31 08:10:36 +01005999 virtual void NoAssertionsInSection( const std::string& ) {}
6000 virtual void NoAssertionsInTestCase( const std::string& ) {}
Phil Nash56d5c422012-08-23 20:08:50 +01006001
6002 virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) {
6003 m_xml.scopedElement( "OverallResults" )
6004 .writeAttribute( "successes", assertions.passed )
6005 .writeAttribute( "failures", assertions.failed );
6006 m_xml.endElement();
6007 }
6008
6009 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) {
6010 m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.getName() );
6011 m_currentTestSuccess = true;
6012 }
6013
Phil Nash82acc2c2012-10-28 12:07:17 +00006014 virtual void Result( const Catch::AssertionResult& assertionResult ) {
6015 if( !m_config.includeSuccessfulResults && assertionResult.getResultType() == ResultWas::Ok )
Phil Nash56d5c422012-08-23 20:08:50 +01006016 return;
6017
Phil Nash82acc2c2012-10-28 12:07:17 +00006018 if( assertionResult.hasExpression() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006019 m_xml.startElement( "Expression" )
Phil Nashd539da92012-11-13 09:44:52 +00006020 .writeAttribute( "success", assertionResult.succeeded() )
Phil Nash82acc2c2012-10-28 12:07:17 +00006021 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
6022 .writeAttribute( "line", assertionResult.getSourceInfo().line );
Phil Nash56d5c422012-08-23 20:08:50 +01006023
6024 m_xml.scopedElement( "Original" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006025 .writeText( assertionResult.getExpression() );
Phil Nash56d5c422012-08-23 20:08:50 +01006026 m_xml.scopedElement( "Expanded" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006027 .writeText( assertionResult.getExpandedExpression() );
Phil Nashd539da92012-11-13 09:44:52 +00006028 m_currentTestSuccess &= assertionResult.succeeded();
Phil Nash56d5c422012-08-23 20:08:50 +01006029 }
6030
Phil Nash82acc2c2012-10-28 12:07:17 +00006031 switch( assertionResult.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006032 case ResultWas::ThrewException:
6033 m_xml.scopedElement( "Exception" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006034 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
6035 .writeAttribute( "line", assertionResult.getSourceInfo().line )
6036 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01006037 m_currentTestSuccess = false;
6038 break;
6039 case ResultWas::Info:
6040 m_xml.scopedElement( "Info" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006041 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01006042 break;
6043 case ResultWas::Warning:
6044 m_xml.scopedElement( "Warning" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006045 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01006046 break;
6047 case ResultWas::ExplicitFailure:
6048 m_xml.scopedElement( "Failure" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006049 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01006050 m_currentTestSuccess = false;
6051 break;
6052 case ResultWas::Unknown:
6053 case ResultWas::Ok:
6054 case ResultWas::FailureBit:
6055 case ResultWas::ExpressionFailed:
6056 case ResultWas::Exception:
6057 case ResultWas::DidntThrowException:
6058 break;
6059 }
Phil Nash82acc2c2012-10-28 12:07:17 +00006060 if( assertionResult.hasExpression() )
Phil Nash56d5c422012-08-23 20:08:50 +01006061 m_xml.endElement();
6062 }
6063
6064 virtual void Aborted() {
6065 // !TBD
6066 }
6067
6068 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) {
6069 m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess );
6070 m_xml.endElement();
6071 }
6072
6073 private:
6074 ReporterConfig m_config;
6075 bool m_currentTestSuccess;
6076 XmlWriter m_xml;
6077 };
6078
6079} // end namespace Catch
6080
6081// #included from: ../reporters/catch_reporter_junit.hpp
6082#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
6083
6084namespace Catch {
6085
6086 class JunitReporter : public SharedImpl<IReporter> {
6087
6088 struct TestStats {
6089 std::string m_element;
6090 std::string m_resultType;
6091 std::string m_message;
6092 std::string m_content;
6093 };
6094
6095 struct TestCaseStats {
6096
Phil Nash88b70822012-11-04 21:39:38 +00006097 TestCaseStats( const std::string& className, const std::string& name )
6098 : m_className( className ),
6099 m_name( name )
6100 {}
Phil Nash56d5c422012-08-23 20:08:50 +01006101
6102 double m_timeInSeconds;
6103 std::string m_status;
6104 std::string m_className;
6105 std::string m_name;
6106 std::vector<TestStats> m_testStats;
6107 };
6108
6109 struct Stats {
6110
6111 Stats( const std::string& name = std::string() )
6112 : m_testsCount( 0 ),
6113 m_failuresCount( 0 ),
6114 m_disabledCount( 0 ),
6115 m_errorsCount( 0 ),
6116 m_timeInSeconds( 0 ),
6117 m_name( name )
6118 {}
6119
6120 std::size_t m_testsCount;
6121 std::size_t m_failuresCount;
6122 std::size_t m_disabledCount;
6123 std::size_t m_errorsCount;
6124 double m_timeInSeconds;
6125 std::string m_name;
6126
6127 std::vector<TestCaseStats> m_testCaseStats;
6128 };
6129
6130 public:
6131 JunitReporter( const ReporterConfig& config )
6132 : m_config( config ),
6133 m_testSuiteStats( "AllTests" ),
6134 m_currentStats( &m_testSuiteStats )
6135 {}
6136 virtual ~JunitReporter();
6137
6138 static std::string getDescription() {
6139 return "Reports test results in an XML format that looks like Ant's junitreport target";
6140 }
6141
6142 private: // IReporter
6143
6144 virtual bool shouldRedirectStdout() const {
6145 return true;
6146 }
6147
6148 virtual void StartTesting(){}
6149
6150 virtual void StartGroup( const std::string& groupName ) {
6151 m_statsForSuites.push_back( Stats( groupName ) );
6152 m_currentStats = &m_statsForSuites.back();
6153 }
6154
6155 virtual void EndGroup( const std::string&, const Totals& totals ) {
6156 m_currentStats->m_testsCount = totals.assertions.total();
6157 m_currentStats = &m_testSuiteStats;
6158 }
6159
6160 virtual void StartSection( const std::string&, const std::string& ){}
6161
Phil Nasha70fbe32012-08-31 08:10:36 +01006162 virtual void NoAssertionsInSection( const std::string& ) {}
6163 virtual void NoAssertionsInTestCase( const std::string& ) {}
6164
6165 virtual void EndSection( const std::string&, const Counts& ) {}
Phil Nash56d5c422012-08-23 20:08:50 +01006166
6167 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) {
Phil Nash88b70822012-11-04 21:39:38 +00006168 m_currentStats->m_testCaseStats.push_back( TestCaseStats( testInfo.getClassName(), testInfo.getName() ) );
Phil Nash56d5c422012-08-23 20:08:50 +01006169 }
6170
Phil Nash82acc2c2012-10-28 12:07:17 +00006171 virtual void Result( const Catch::AssertionResult& assertionResult ) {
6172 if( assertionResult.getResultType() != ResultWas::Ok || m_config.includeSuccessfulResults ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006173 TestCaseStats& testCaseStats = m_currentStats->m_testCaseStats.back();
6174 TestStats stats;
6175 std::ostringstream oss;
Phil Nash82acc2c2012-10-28 12:07:17 +00006176 if( !assertionResult.getMessage().empty() )
6177 oss << assertionResult.getMessage() << " at ";
6178 oss << assertionResult.getSourceInfo();
Phil Nash56d5c422012-08-23 20:08:50 +01006179 stats.m_content = oss.str();
Phil Nash82acc2c2012-10-28 12:07:17 +00006180 stats.m_message = assertionResult.getExpandedExpression();
6181 stats.m_resultType = assertionResult.getTestMacroName();
Phil Nash56d5c422012-08-23 20:08:50 +01006182
Phil Nash82acc2c2012-10-28 12:07:17 +00006183 switch( assertionResult.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006184 case ResultWas::ThrewException:
6185 stats.m_element = "error";
6186 m_currentStats->m_errorsCount++;
6187 break;
6188 case ResultWas::Info:
6189 stats.m_element = "info"; // !TBD ?
6190 break;
6191 case ResultWas::Warning:
6192 stats.m_element = "warning"; // !TBD ?
6193 break;
6194 case ResultWas::ExplicitFailure:
6195 stats.m_element = "failure";
6196 m_currentStats->m_failuresCount++;
6197 break;
6198 case ResultWas::ExpressionFailed:
6199 stats.m_element = "failure";
6200 m_currentStats->m_failuresCount++;
6201 break;
6202 case ResultWas::Ok:
6203 stats.m_element = "success";
6204 break;
6205 case ResultWas::Unknown:
6206 case ResultWas::FailureBit:
6207 case ResultWas::Exception:
6208 case ResultWas::DidntThrowException:
6209 break;
6210 }
6211 testCaseStats.m_testStats.push_back( stats );
6212 }
6213 }
6214
6215 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string& stdOut, const std::string& stdErr ) {
6216 if( !stdOut.empty() )
6217 m_stdOut << stdOut << "\n";
6218 if( !stdErr.empty() )
6219 m_stdErr << stdErr << "\n";
6220 }
6221
6222 virtual void Aborted() {
6223 // !TBD
6224 }
6225
6226 virtual void EndTesting( const Totals& ) {
6227 std::ostream& str = m_config.stream;
6228 {
6229 XmlWriter xml( str );
6230
6231 if( m_statsForSuites.size() > 0 )
6232 xml.startElement( "testsuites" );
6233
6234 std::vector<Stats>::const_iterator it = m_statsForSuites.begin();
6235 std::vector<Stats>::const_iterator itEnd = m_statsForSuites.end();
6236
6237 for(; it != itEnd; ++it ) {
6238 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
6239 xml.writeAttribute( "name", it->m_name );
6240 xml.writeAttribute( "errors", it->m_errorsCount );
6241 xml.writeAttribute( "failures", it->m_failuresCount );
6242 xml.writeAttribute( "tests", it->m_testsCount );
6243 xml.writeAttribute( "hostname", "tbd" );
6244 xml.writeAttribute( "time", "tbd" );
6245 xml.writeAttribute( "timestamp", "tbd" );
6246
6247 OutputTestCases( xml, *it );
6248 }
6249
6250 xml.scopedElement( "system-out" ).writeText( trim( m_stdOut.str() ) );
6251 xml.scopedElement( "system-err" ).writeText( trim( m_stdErr.str() ) );
6252 }
6253 }
6254
6255 void OutputTestCases( XmlWriter& xml, const Stats& stats ) {
6256 std::vector<TestCaseStats>::const_iterator it = stats.m_testCaseStats.begin();
6257 std::vector<TestCaseStats>::const_iterator itEnd = stats.m_testCaseStats.end();
6258 for(; it != itEnd; ++it ) {
6259 xml.writeBlankLine();
6260 xml.writeComment( "Test case" );
6261
6262 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
6263 xml.writeAttribute( "classname", it->m_className );
6264 xml.writeAttribute( "name", it->m_name );
6265 xml.writeAttribute( "time", "tbd" );
6266
6267 OutputTestResult( xml, *it );
6268 }
6269 }
6270
6271 void OutputTestResult( XmlWriter& xml, const TestCaseStats& stats ) {
6272 std::vector<TestStats>::const_iterator it = stats.m_testStats.begin();
6273 std::vector<TestStats>::const_iterator itEnd = stats.m_testStats.end();
6274 for(; it != itEnd; ++it ) {
6275 if( it->m_element != "success" ) {
6276 XmlWriter::ScopedElement e = xml.scopedElement( it->m_element );
6277
6278 xml.writeAttribute( "message", it->m_message );
6279 xml.writeAttribute( "type", it->m_resultType );
6280 if( !it->m_content.empty() )
6281 xml.writeText( it->m_content );
6282 }
6283 }
6284 }
6285
6286 private:
6287 ReporterConfig m_config;
6288 bool m_currentTestSuccess;
6289
6290 Stats m_testSuiteStats;
6291 Stats* m_currentStats;
6292 std::vector<Stats> m_statsForSuites;
6293 std::ostringstream m_stdOut;
6294 std::ostringstream m_stdErr;
6295 };
6296
6297} // end namespace Catch
6298
Phil Nasha695eb92012-08-13 07:46:10 +01006299namespace Catch {
6300 NonCopyable::~NonCopyable() {}
6301 IShared::~IShared() {}
6302 StreamBufBase::~StreamBufBase() {}
6303 IContext::~IContext() {}
6304 IResultCapture::~IResultCapture() {}
6305 ITestCase::~ITestCase() {}
6306 ITestCaseRegistry::~ITestCaseRegistry() {}
6307 IRegistryHub::~IRegistryHub() {}
6308 IMutableRegistryHub::~IMutableRegistryHub() {}
6309 IExceptionTranslator::~IExceptionTranslator() {}
6310 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
6311 IReporter::~IReporter() {}
6312 IReporterFactory::~IReporterFactory() {}
6313 IReporterRegistry::~IReporterRegistry() {}
6314 BasicReporter::~BasicReporter() {}
6315 IRunner::~IRunner() {}
6316 IMutableContext::~IMutableContext() {}
6317 IConfig::~IConfig() {}
6318 XmlReporter::~XmlReporter() {}
6319 JunitReporter::~JunitReporter() {}
6320 TestRegistry::~TestRegistry() {}
6321 FreeFunctionTestCase::~FreeFunctionTestCase() {}
6322 IGeneratorInfo::~IGeneratorInfo() {}
6323 IGeneratorsForTest::~IGeneratorsForTest() {}
Phil Nash799ecf92012-09-24 08:30:13 +01006324 TagParser::~TagParser() {}
6325 TagExtracter::~TagExtracter() {}
6326 TagExpressionParser::~TagExpressionParser() {}
Phil Nasha695eb92012-08-13 07:46:10 +01006327
Phil Nash9444bbc2012-10-12 07:58:17 +01006328 Matchers::Impl::StdString::Equals::~Equals() {}
6329 Matchers::Impl::StdString::Contains::~Contains() {}
6330 Matchers::Impl::StdString::StartsWith::~StartsWith() {}
6331 Matchers::Impl::StdString::EndsWith::~EndsWith() {}
6332
Phil Nasha695eb92012-08-13 07:46:10 +01006333 void Config::dummy() {}
6334
Phil Nash56d5c422012-08-23 20:08:50 +01006335 INTERNAL_CATCH_REGISTER_REPORTER( "basic", BasicReporter )
6336 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
6337 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
6338
Phil Nasha695eb92012-08-13 07:46:10 +01006339}
6340
Phil Nash5bc030d2012-08-16 18:48:50 +01006341#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01006342#pragma clang diagnostic pop
Phil Nash89d1e6c2011-05-24 08:23:02 +01006343#endif
Matt Wozniskif29c8982012-09-17 01:42:29 -04006344
Phil Nash5bc030d2012-08-16 18:48:50 +01006345#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01006346
6347#ifdef CATCH_CONFIG_MAIN
6348// #included from: internal/catch_default_main.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01006349#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01006350
Phil Nash176eb812012-05-11 08:17:16 +01006351#ifndef __OBJC__
Phil Nash89d1e6c2011-05-24 08:23:02 +01006352
Phil Nash176eb812012-05-11 08:17:16 +01006353// Standard C/C++ main entry point
6354int main (int argc, char * const argv[]) {
6355 return Catch::Main( argc, argv );
6356}
6357
6358#else // __OBJC__
6359
6360// Objective-C entry point
6361int main (int argc, char * const argv[]) {
Phil Nash53c990a2012-03-17 18:20:06 +00006362#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +01006363 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Phil Nash53c990a2012-03-17 18:20:06 +00006364#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01006365
6366 Catch::registerTestMethods();
Phil Nash89d1e6c2011-05-24 08:23:02 +01006367 int result = Catch::Main( argc, (char* const*)argv );
6368
Phil Nash53c990a2012-03-17 18:20:06 +00006369#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +01006370 [pool drain];
Phil Nash53c990a2012-03-17 18:20:06 +00006371#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01006372
Phil Nashdd5b9c22012-02-18 09:58:30 +00006373 return result;
Phil Nash89d1e6c2011-05-24 08:23:02 +01006374}
6375
Phil Nash176eb812012-05-11 08:17:16 +01006376#endif // __OBJC__
6377
Phil Nash89d1e6c2011-05-24 08:23:02 +01006378#endif
6379
Phil Nash89d1e6c2011-05-24 08:23:02 +01006380//////
6381
Phil Nash46bcd4b2012-07-20 18:43:48 +01006382// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
6383#ifdef CATCH_CONFIG_PREFIX_ALL
6384
Phil Nashaf1a3212012-11-10 18:46:39 +00006385#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
6386#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 +01006387
Phil Nashaf1a3212012-11-10 18:46:39 +00006388#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" )
6389#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
6390#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01006391
Phil Nashaf1a3212012-11-10 18:46:39 +00006392#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
6393#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CATCH_CHECK_FALSE" )
6394#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" )
6395#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
Phil Nash7717c292012-11-13 09:45:29 +00006396#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 +01006397
Phil Nashaf1a3212012-11-10 18:46:39 +00006398#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
6399#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
6400#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01006401
Phil Nashaf1a3212012-11-10 18:46:39 +00006402#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
6403#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01006404
Phil Nashaf1a3212012-11-10 18:46:39 +00006405#define CATCH_INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, Catch::ResultDisposition::ContinueOnFailure, "CATCH_INFO" )
6406#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN" )
6407#define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL" )
6408#define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006409#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg, "CATCH_SCOPED_INFO" )
Phil Nashaf1a3212012-11-10 18:46:39 +00006410#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CAPTURE" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006411#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_SCOPED_INFO( #msg " := " << msg, "CATCH_SCOPED_CAPTURE" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01006412
6413#define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
6414
6415#define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
6416#define CATCH_TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
6417#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" )
6418#define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
6419
6420#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
6421
6422#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
6423
Phil Nash46bcd4b2012-07-20 18:43:48 +01006424// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
6425#else
6426
Phil Nashaf1a3212012-11-10 18:46:39 +00006427#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
6428#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "REQUIRE_FALSE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006429
Phil Nashaf1a3212012-11-10 18:46:39 +00006430#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "REQUIRE_THROWS" )
6431#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
6432#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006433
Phil Nashaf1a3212012-11-10 18:46:39 +00006434#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
6435#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CHECK_FALSE" )
6436#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" )
6437#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
Phil Nashd539da92012-11-13 09:44:52 +00006438#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006439
Phil Nashaf1a3212012-11-10 18:46:39 +00006440#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" )
6441#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
6442#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006443
Phil Nashaf1a3212012-11-10 18:46:39 +00006444#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
6445#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
Phil Nash78d95a02012-03-04 21:22:36 +00006446
Phil Nashaf1a3212012-11-10 18:46:39 +00006447#define INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, Catch::ResultDisposition::ContinueOnFailure, "INFO" )
6448#define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN" )
6449#define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL" )
6450#define SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006451#define SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg, "SCOPED_INFO" )
Phil Nashaf1a3212012-11-10 18:46:39 +00006452#define CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, Catch::ResultDisposition::ContinueOnFailure, "CAPTURE" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006453#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_SCOPED_INFO( #msg " := " << msg, "SCOPED_CAPTURE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006454
6455#define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
6456
6457#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
6458#define TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
6459#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01006460#define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006461
6462#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006463
6464#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
6465
Phil Nash46bcd4b2012-07-20 18:43:48 +01006466#endif
6467
6468#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006469
6470using Catch::Detail::Approx;
6471
Phil Nash5bc030d2012-08-16 18:48:50 +01006472#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01006473#pragma clang diagnostic pop
Phil Nash5bc030d2012-08-16 18:48:50 +01006474#endif
Phil Nasha695eb92012-08-13 07:46:10 +01006475
Phil Nashaec1e5e2012-05-09 19:37:51 +01006476#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01006477