blob: e8f2dcf113bc15e6341c9ca9875496c77160ebda [file] [log] [blame]
Phil Nash89d1e6c2011-05-24 08:23:02 +01001/*
Phil Nashf7378ee2013-09-07 12:07:38 +01002 * CATCH v1.0 build 9 (master branch)
3 * Generated: 2013-09-07 12:04:25.989589
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 Nashce612bf2012-11-01 08:27:09 +000017#pragma clang diagnostic ignored "-Wglobal-constructors"
Phil Nash93906752013-03-16 20:21:51 +000018#pragma clang diagnostic ignored "-Wvariadic-macros"
Phil Nash5bc030d2012-08-16 18:48:50 +010019
Phil Nasha695eb92012-08-13 07:46:10 +010020#pragma clang diagnostic push
21#pragma clang diagnostic ignored "-Wpadded"
Phil Nash5bc030d2012-08-16 18:48:50 +010022#endif
Phil Nasha695eb92012-08-13 07:46:10 +010023
Phil Nash3b80af72012-08-09 07:47:30 +010024// #included from: internal/catch_notimplemented_exception.h
25#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010026
Phil Nash89d1e6c2011-05-24 08:23:02 +010027// #included from: catch_common.h
Phil Nash3b80af72012-08-09 07:47:30 +010028#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010029
Phil Nash89d1e6c2011-05-24 08:23:02 +010030#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
31#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
32#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
33
34#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
35#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
36
Phil Nash89d1e6c2011-05-24 08:23:02 +010037#include <sstream>
38#include <stdexcept>
39#include <algorithm>
40
Phil Nash8defc712013-04-24 19:10:02 +010041// #included from: catch_compiler_capabilities.h
42#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
43
44// Much of the following code is based on Boost (1.53)
45
46////////////////////////////////////////////////////////////////////////////////
47// Borland
48#ifdef __BORLANDC__
49
50#if (__BORLANDC__ > 0x582 )
51//#define CATCH_CONFIG_SFINAE // Not confirmed
52#endif
53
54#endif // __BORLANDC__
55
56////////////////////////////////////////////////////////////////////////////////
57// EDG
58#ifdef __EDG_VERSION__
59
60#if (__EDG_VERSION__ > 238 )
61//#define CATCH_CONFIG_SFINAE // Not confirmed
62#endif
63
64#endif // __EDG_VERSION__
65
66////////////////////////////////////////////////////////////////////////////////
67// Digital Mars
68#ifdef __DMC__
69
70#if (__DMC__ > 0x840 )
71//#define CATCH_CONFIG_SFINAE // Not confirmed
72#endif
73
74#endif // __DMC__
75
76////////////////////////////////////////////////////////////////////////////////
77// GCC
78#ifdef __GNUC__
79
80#if __GNUC__ < 3
81
82#if (__GNUC_MINOR__ >= 96 )
83//#define CATCH_CONFIG_SFINAE
84#endif
85
86#elif __GNUC__ >= 3
87
88// #define CATCH_CONFIG_SFINAE // Taking this out completely for now
89
90#endif // __GNUC__ < 3
91
92#endif // __GNUC__
93
94////////////////////////////////////////////////////////////////////////////////
95// Visual C++
96#ifdef _MSC_VER
97
98#if (_MSC_VER >= 1310 ) // (VC++ 7.0+)
99//#define CATCH_CONFIG_SFINAE // Not confirmed
100#endif
101
102#endif // _MSC_VER
103
104// Use variadic macros if the compiler supports them
105#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
106 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
107 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
108 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
Phil Nash786959d2013-06-07 19:07:50 +0100109
110#ifndef CATCH_CONFIG_NO_VARIADIC_MACROS
111#define CATCH_CONFIG_VARIADIC_MACROS
112#endif
113
Phil Nash8defc712013-04-24 19:10:02 +0100114#endif
115
Phil Nash89d2a3f2012-05-16 15:09:17 +0100116namespace Catch {
117
Phil Nasha04981b2013-03-08 09:30:25 +0000118 class NonCopyable {
Phil Nash8defc712013-04-24 19:10:02 +0100119 NonCopyable( NonCopyable const& );
120 void operator = ( NonCopyable const& );
Phil Nasha04981b2013-03-08 09:30:25 +0000121 protected:
122 NonCopyable() {}
123 virtual ~NonCopyable();
124 };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100125
Phil Nash163088a2012-05-31 19:40:26 +0100126 class SafeBool {
127 public:
128 typedef void (SafeBool::*type)() const;
129
130 static type makeSafe( bool value ) {
131 return value ? &SafeBool::trueValue : 0;
132 }
133 private:
134 void trueValue() const {}
135 };
136
Phil Nash89d1e6c2011-05-24 08:23:02 +0100137 template<typename ContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +0100138 inline void deleteAll( ContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100139 typename ContainerT::const_iterator it = container.begin();
140 typename ContainerT::const_iterator itEnd = container.end();
141 for(; it != itEnd; ++it )
Phil Nash89d1e6c2011-05-24 08:23:02 +0100142 delete *it;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100143 }
144 template<typename AssociativeContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +0100145 inline void deleteAllValues( AssociativeContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100146 typename AssociativeContainerT::const_iterator it = container.begin();
147 typename AssociativeContainerT::const_iterator itEnd = container.end();
148 for(; it != itEnd; ++it )
Phil Nash89d1e6c2011-05-24 08:23:02 +0100149 delete it->second;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100150 }
151
152 template<typename ContainerT, typename Function>
Phil Nashd31737f2012-05-09 19:04:00 +0100153 inline void forEach( ContainerT& container, Function function ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100154 std::for_each( container.begin(), container.end(), function );
155 }
156
157 template<typename ContainerT, typename Function>
Phil Nash8defc712013-04-24 19:10:02 +0100158 inline void forEach( ContainerT const& container, Function function ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100159 std::for_each( container.begin(), container.end(), function );
160 }
161
Phil Nash8defc712013-04-24 19:10:02 +0100162 inline bool startsWith( std::string const& s, std::string const& prefix ) {
Phil Nash56d5c422012-08-23 20:08:50 +0100163 return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
164 }
Phil Nash8defc712013-04-24 19:10:02 +0100165 inline bool endsWith( std::string const& s, std::string const& suffix ) {
Phil Nash4c97fc52012-08-24 08:23:50 +0100166 return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
167 }
Phil Nash8defc712013-04-24 19:10:02 +0100168 inline bool contains( std::string const& s, std::string const& infix ) {
Phil Nash4c97fc52012-08-24 08:23:50 +0100169 return s.find( infix ) != std::string::npos;
170 }
Phil Nashdd26e882013-03-25 09:25:31 +0000171 inline void toLowerInPlace( std::string& s ) {
Phil Nash6d56d712013-03-12 18:49:37 +0000172 std::transform( s.begin(), s.end(), s.begin(), ::tolower );
173 }
Phil Nashdd26e882013-03-25 09:25:31 +0000174 inline std::string toLower( std::string const& s ) {
175 std::string lc = s;
176 toLowerInPlace( lc );
177 return lc;
178 }
Phil Nash4c97fc52012-08-24 08:23:50 +0100179
180 struct pluralise {
Phil Nash8defc712013-04-24 19:10:02 +0100181 pluralise( std::size_t count, std::string const& label )
Phil Nash4c97fc52012-08-24 08:23:50 +0100182 : m_count( count ),
183 m_label( label )
184 {}
185
Phil Nash8defc712013-04-24 19:10:02 +0100186 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
Phil Nash4c97fc52012-08-24 08:23:50 +0100187 os << pluraliser.m_count << " " << pluraliser.m_label;
188 if( pluraliser.m_count != 1 )
Phil Nash90a35942012-11-13 22:04:29 +0000189 os << "s";
Phil Nash4c97fc52012-08-24 08:23:50 +0100190 return os;
191 }
192
193 std::size_t m_count;
194 std::string m_label;
195 };
Phil Nash56d5c422012-08-23 20:08:50 +0100196
Phil Nash89d2a3f2012-05-16 15:09:17 +0100197 struct SourceLineInfo {
198
Phil Nashd31737f2012-05-09 19:04:00 +0100199 SourceLineInfo() : line( 0 ){}
Phil Nash8defc712013-04-24 19:10:02 +0100200 SourceLineInfo( std::string const& _file, std::size_t _line )
Phil Nash62179662012-05-11 19:06:43 +0100201 : file( _file ),
202 line( _line )
Phil Nash6e0f58d2012-02-15 18:37:21 +0000203 {}
Phil Nash8defc712013-04-24 19:10:02 +0100204 SourceLineInfo( SourceLineInfo const& other )
Phil Nashd31737f2012-05-09 19:04:00 +0100205 : file( other.file ),
206 line( other.line )
207 {}
Phil Nashce612bf2012-11-01 08:27:09 +0000208 bool empty() const {
209 return file.empty();
210 }
Phil Nashaa7123b2013-08-15 19:01:00 +0100211 bool operator == ( SourceLineInfo const& other ) const {
212 return line == other.line && file == other.file;
213 }
Phil Nash6e0f58d2012-02-15 18:37:21 +0000214 std::string file;
215 std::size_t line;
216 };
217
Phil Nash8defc712013-04-24 19:10:02 +0100218 inline std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
Phil Nash6e0f58d2012-02-15 18:37:21 +0000219#ifndef __GNUG__
Phil Nash5c7d3d72013-04-01 11:27:10 +0100220 os << info.file << "(" << info.line << ")";
Phil Nash6e0f58d2012-02-15 18:37:21 +0000221#else
Phil Nash2e7d9662013-01-16 09:44:43 +0000222 os << info.file << ":" << info.line;
Phil Nash6e0f58d2012-02-15 18:37:21 +0000223#endif
224 return os;
225 }
226
Phil Nash8defc712013-04-24 19:10:02 +0100227 // This is just here to avoid compiler warnings with macro constants and boolean literals
228 inline bool isTrue( bool value ){ return value; }
229
230 inline void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100231 std::ostringstream oss;
Phil Nash2e7d9662013-01-16 09:44:43 +0000232 oss << locationInfo << ": Internal Catch error: '" << message << "'";
Phil Nash8defc712013-04-24 19:10:02 +0100233 if( isTrue( true ))
234 throw std::logic_error( oss.str() );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100235 }
236}
237
Phil Nasha695eb92012-08-13 07:46:10 +0100238#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
239#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100240
Phil Nash3b80af72012-08-09 07:47:30 +0100241#include <ostream>
242
243namespace Catch {
244
245 class NotImplementedException : public std::exception
246 {
247 public:
Phil Nash8defc712013-04-24 19:10:02 +0100248 NotImplementedException( SourceLineInfo const& lineInfo );
Phil Nash3b80af72012-08-09 07:47:30 +0100249
250 virtual ~NotImplementedException() throw() {}
251
252 virtual const char* what() const throw();
253
254 private:
255 std::string m_what;
256 SourceLineInfo m_lineInfo;
257 };
258
259} // end namespace Catch
260
261///////////////////////////////////////////////////////////////////////////////
262#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
263
264// #included from: internal/catch_context.h
265#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
266
Phil Nasha70fbe32012-08-31 08:10:36 +0100267// #included from: catch_interfaces_generators.h
268#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +0100269
Phil Nasha70fbe32012-08-31 08:10:36 +0100270#include <string>
Phil Nashf7299fc2012-02-25 09:39:45 +0000271
Phil Nash89d2a3f2012-05-16 15:09:17 +0100272namespace Catch {
273
Phil Nasha70fbe32012-08-31 08:10:36 +0100274 struct IGeneratorInfo {
275 virtual ~IGeneratorInfo();
276 virtual bool moveNext() = 0;
277 virtual std::size_t getCurrentIndex() const = 0;
Phil Nashf7299fc2012-02-25 09:39:45 +0000278 };
279
Phil Nasha70fbe32012-08-31 08:10:36 +0100280 struct IGeneratorsForTest {
281 virtual ~IGeneratorsForTest();
Phil Nash89d2a3f2012-05-16 15:09:17 +0100282
Phil Nash8defc712013-04-24 19:10:02 +0100283 virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +0100284 virtual bool moveNext() = 0;
Phil Nashf7299fc2012-02-25 09:39:45 +0000285 };
Phil Nasha70fbe32012-08-31 08:10:36 +0100286
287 IGeneratorsForTest* createGeneratorsForTest();
288
289} // end namespace Catch
290
Phil Nash49e6d532012-05-05 19:35:35 +0100291// #included from: catch_ptr.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100292#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
Phil Nash49e6d532012-05-05 19:35:35 +0100293
Phil Nash37186a12013-03-13 12:19:30 +0000294#ifdef __clang__
295#pragma clang diagnostic push
296#pragma clang diagnostic ignored "-Wpadded"
297#endif
298
Phil Nash89d2a3f2012-05-16 15:09:17 +0100299namespace Catch {
300
Phil Nash49e6d532012-05-05 19:35:35 +0100301 // An intrusive reference counting smart pointer.
302 // T must implement addRef() and release() methods
303 // typically implementing the IShared interface
304 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100305 class Ptr {
Phil Nash49e6d532012-05-05 19:35:35 +0100306 public:
307 Ptr() : m_p( NULL ){}
308 Ptr( T* p ) : m_p( p ){
Phil Nash61756972012-07-28 20:37:07 +0100309 if( m_p )
310 m_p->addRef();
Phil Nash49e6d532012-05-05 19:35:35 +0100311 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000312 Ptr( Ptr const& other ) : m_p( other.m_p ){
Phil Nash61756972012-07-28 20:37:07 +0100313 if( m_p )
314 m_p->addRef();
Phil Nash49e6d532012-05-05 19:35:35 +0100315 }
316 ~Ptr(){
317 if( m_p )
318 m_p->release();
319 }
Phil Nashff03cdf2012-12-06 08:44:51 +0000320 void reset() {
321 if( m_p )
322 m_p->release();
323 m_p = NULL;
324 }
Phil Nash49e6d532012-05-05 19:35:35 +0100325 Ptr& operator = ( T* p ){
326 Ptr temp( p );
327 swap( temp );
328 return *this;
329 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000330 Ptr& operator = ( Ptr const& other ){
Phil Nash49e6d532012-05-05 19:35:35 +0100331 Ptr temp( other );
332 swap( temp );
333 return *this;
334 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000335 void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
336 T* get() { return m_p; }
337 const T* get() const{ return m_p; }
338 T& operator*() const { return *m_p; }
339 T* operator->() const { return m_p; }
340 bool operator !() const { return m_p == NULL; }
Phil Nashff03cdf2012-12-06 08:44:51 +0000341 operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); }
Phil Nash49e6d532012-05-05 19:35:35 +0100342
343 private:
344 T* m_p;
345 };
346
347 struct IShared : NonCopyable {
Phil Nasha695eb92012-08-13 07:46:10 +0100348 virtual ~IShared();
Phil Nasha1fbfea2012-12-01 23:57:18 +0000349 virtual void addRef() const = 0;
350 virtual void release() const = 0;
Phil Nash49e6d532012-05-05 19:35:35 +0100351 };
352
Phil Nasha1fbfea2012-12-01 23:57:18 +0000353 template<typename T = IShared>
Phil Nash49e6d532012-05-05 19:35:35 +0100354 struct SharedImpl : T {
355
356 SharedImpl() : m_rc( 0 ){}
357
Phil Nasha1fbfea2012-12-01 23:57:18 +0000358 virtual void addRef() const {
Phil Nash49e6d532012-05-05 19:35:35 +0100359 ++m_rc;
360 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000361 virtual void release() const {
Phil Nash49e6d532012-05-05 19:35:35 +0100362 if( --m_rc == 0 )
363 delete this;
364 }
365
Phil Nasha1fbfea2012-12-01 23:57:18 +0000366 mutable unsigned int m_rc;
Phil Nash49e6d532012-05-05 19:35:35 +0100367 };
368
369} // end namespace Catch
370
Phil Nash37186a12013-03-13 12:19:30 +0000371#ifdef __clang__
372#pragma clang diagnostic pop
373#endif
374
Phil Nash786959d2013-06-07 19:07:50 +0100375#include <memory>
376#include <vector>
377#include <stdlib.h>
378
379namespace Catch {
380
381 class TestCase;
382 class Stream;
383 struct IResultCapture;
384 struct IRunner;
385 struct IGeneratorsForTest;
386 struct IConfig;
387
388 struct IContext
389 {
390 virtual ~IContext();
391
392 virtual IResultCapture& getResultCapture() = 0;
393 virtual IRunner& getRunner() = 0;
394 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
395 virtual bool advanceGeneratorsForCurrentTest() = 0;
396 virtual Ptr<IConfig const> getConfig() const = 0;
397 };
398
399 struct IMutableContext : IContext
400 {
401 virtual ~IMutableContext();
402 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
403 virtual void setRunner( IRunner* runner ) = 0;
404 virtual void setConfig( Ptr<IConfig const> const& config ) = 0;
405 };
406
407 IContext& getCurrentContext();
408 IMutableContext& getCurrentMutableContext();
409 void cleanUpContext();
410 Stream createStream( std::string const& streamName );
411
412}
413
414// #included from: internal/catch_test_registry.hpp
415#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
416
417// #included from: catch_interfaces_testcase.h
418#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
419
Phil Nash0f9c5512012-06-02 23:12:42 +0100420#include <vector>
421
422namespace Catch {
Phil Nash56d5c422012-08-23 20:08:50 +0100423
424 class TestCaseFilters;
425
Phil Nash5bc030d2012-08-16 18:48:50 +0100426 struct ITestCase : IShared {
Phil Nash0f9c5512012-06-02 23:12:42 +0100427 virtual void invoke () const = 0;
Phil Nash5bc030d2012-08-16 18:48:50 +0100428 protected:
429 virtual ~ITestCase();
Phil Nash0f9c5512012-06-02 23:12:42 +0100430 };
431
Phil Nasha1fbfea2012-12-01 23:57:18 +0000432 class TestCase;
Phil Nash0f9c5512012-06-02 23:12:42 +0100433
434 struct ITestCaseRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +0100435 virtual ~ITestCaseRegistry();
Phil Nash8defc712013-04-24 19:10:02 +0100436 virtual std::vector<TestCase> const& getAllTests() const = 0;
437 virtual std::vector<TestCase> getMatchingTestCases( std::string const& rawTestSpec ) const = 0;
Phil Nash0f9c5512012-06-02 23:12:42 +0100438 };
439}
440
Phil Nash89d2a3f2012-05-16 15:09:17 +0100441namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100442
443template<typename C>
Phil Nash5bc030d2012-08-16 18:48:50 +0100444class MethodTestCase : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +0100445
Phil Nash176eb812012-05-11 08:17:16 +0100446public:
447 MethodTestCase( void (C::*method)() ) : m_method( method ) {}
Phil Nash89d1e6c2011-05-24 08:23:02 +0100448
Phil Nash176eb812012-05-11 08:17:16 +0100449 virtual void invoke() const {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100450 C obj;
451 (obj.*m_method)();
452 }
453
Phil Nash89d1e6c2011-05-24 08:23:02 +0100454private:
Phil Nash5bc030d2012-08-16 18:48:50 +0100455 virtual ~MethodTestCase() {}
456
Phil Nash89d1e6c2011-05-24 08:23:02 +0100457 void (C::*m_method)();
458};
459
460typedef void(*TestFunction)();
461
Phil Nash93906752013-03-16 20:21:51 +0000462struct NameAndDesc {
463 NameAndDesc( const char* _name = "", const char* _description= "" )
464 : name( _name ), description( _description )
465 {}
466
467 const char* name;
468 const char* description;
469};
470
Phil Nash89d2a3f2012-05-16 15:09:17 +0100471struct AutoReg {
472
Phil Nash176eb812012-05-11 08:17:16 +0100473 AutoReg( TestFunction function,
Phil Nash93906752013-03-16 20:21:51 +0000474 SourceLineInfo const& lineInfo,
475 NameAndDesc const& nameAndDesc );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100476
Phil Nash89d1e6c2011-05-24 08:23:02 +0100477 template<typename C>
Phil Nash176eb812012-05-11 08:17:16 +0100478 AutoReg( void (C::*method)(),
Phil Nash93906752013-03-16 20:21:51 +0000479 char const* className,
480 NameAndDesc const& nameAndDesc,
481 SourceLineInfo const& lineInfo ) {
482 registerTestCase( new MethodTestCase<C>( method ),
483 className,
484 nameAndDesc,
485 lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100486 }
487
Phil Nash176eb812012-05-11 08:17:16 +0100488 void registerTestCase( ITestCase* testCase,
Phil Nash93906752013-03-16 20:21:51 +0000489 char const* className,
490 NameAndDesc const& nameAndDesc,
491 SourceLineInfo const& lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100492
Phil Nash176eb812012-05-11 08:17:16 +0100493 ~AutoReg();
Phil Nash89d1e6c2011-05-24 08:23:02 +0100494
495private:
Phil Nash8defc712013-04-24 19:10:02 +0100496 AutoReg( AutoReg const& );
497 void operator= ( AutoReg const& );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100498};
499
500} // end namespace Catch
501
Phil Nash93906752013-03-16 20:21:51 +0000502#ifdef CATCH_CONFIG_VARIADIC_MACROS
503 ///////////////////////////////////////////////////////////////////////////////
504 #define INTERNAL_CATCH_TESTCASE( ... ) \
Phil Nash786959d2013-06-07 19:07:50 +0100505 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
506 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
507 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100508
Phil Nash93906752013-03-16 20:21:51 +0000509 ///////////////////////////////////////////////////////////////////////////////
Phil Nash93906752013-03-16 20:21:51 +0000510 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
511 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100512
Phil Nash93906752013-03-16 20:21:51 +0000513 ///////////////////////////////////////////////////////////////////////////////
Phil Nash786959d2013-06-07 19:07:50 +0100514 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
Phil Nash93906752013-03-16 20:21:51 +0000515 namespace{ \
Phil Nash786959d2013-06-07 19:07:50 +0100516 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
Phil Nash93906752013-03-16 20:21:51 +0000517 void test(); \
518 }; \
Phil Nash786959d2013-06-07 19:07:50 +0100519 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
Phil Nash93906752013-03-16 20:21:51 +0000520 } \
Phil Nash786959d2013-06-07 19:07:50 +0100521 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100522
Phil Nash93906752013-03-16 20:21:51 +0000523#else
524 ///////////////////////////////////////////////////////////////////////////////
525 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
Phil Nash786959d2013-06-07 19:07:50 +0100526 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
527 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
528 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
Phil Nash93906752013-03-16 20:21:51 +0000529
530 ///////////////////////////////////////////////////////////////////////////////
Phil Nash93906752013-03-16 20:21:51 +0000531 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
532 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
533
534 ///////////////////////////////////////////////////////////////////////////////
Phil Nash786959d2013-06-07 19:07:50 +0100535 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
Phil Nash93906752013-03-16 20:21:51 +0000536 namespace{ \
Phil Nash786959d2013-06-07 19:07:50 +0100537 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
Phil Nash93906752013-03-16 20:21:51 +0000538 void test(); \
539 }; \
Phil Nash786959d2013-06-07 19:07:50 +0100540 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
Phil Nash93906752013-03-16 20:21:51 +0000541 } \
Phil Nash786959d2013-06-07 19:07:50 +0100542 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
Phil Nash93906752013-03-16 20:21:51 +0000543
544#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +0100545
546// #included from: internal/catch_capture.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100547#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100548
Phil Nashce612bf2012-11-01 08:27:09 +0000549// #included from: catch_expression_decomposer.hpp
550#define TWOBLUECUBES_CATCH_EXPRESSION_DECOMPOSER_HPP_INCLUDED
Phil Nash89d2a3f2012-05-16 15:09:17 +0100551
Phil Nashce612bf2012-11-01 08:27:09 +0000552// #included from: catch_expression_lhs.hpp
553#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
Phil Nash176eb812012-05-11 08:17:16 +0100554
Phil Nashce612bf2012-11-01 08:27:09 +0000555// #included from: catch_expressionresult_builder.h
556#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_BUILDER_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +0100557
Phil Nashd31737f2012-05-09 19:04:00 +0100558// #included from: catch_tostring.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100559#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +0100560
Phil Nash19279252013-04-20 21:07:32 +0100561// #included from: catch_sfinae.hpp
562#define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED
563
564// Try to detect if the current compiler supports SFINAE
Phil Nash19279252013-04-20 21:07:32 +0100565
Phil Nash19279252013-04-20 21:07:32 +0100566namespace Catch {
567
568 struct TrueType {
569 static const bool value = true;
570 typedef void Enable;
571 char sizer[1];
572 };
573 struct FalseType {
574 static const bool value = false;
575 typedef void Disable;
576 char sizer[2];
577 };
578
Phil Nash471eba22013-04-22 18:55:12 +0100579#ifdef CATCH_CONFIG_SFINAE
Phil Nashdd520442013-04-20 23:20:05 +0100580
Phil Nash19279252013-04-20 21:07:32 +0100581 template<bool> struct NotABooleanExpression;
582
583 template<bool c> struct If : NotABooleanExpression<c> {};
584 template<> struct If<true> : TrueType {};
585 template<> struct If<false> : FalseType {};
586
587 template<int size> struct SizedIf;
588 template<> struct SizedIf<sizeof(TrueType)> : TrueType {};
589 template<> struct SizedIf<sizeof(FalseType)> : FalseType {};
590
Phil Nash471eba22013-04-22 18:55:12 +0100591#endif // CATCH_CONFIG_SFINAE
Phil Nash19279252013-04-20 21:07:32 +0100592
Phil Nashdd520442013-04-20 23:20:05 +0100593} // end namespace Catch
594
Phil Nashd31737f2012-05-09 19:04:00 +0100595#include <sstream>
Phil Nash767f1582013-03-04 12:19:15 +0100596#include <iomanip>
597#include <limits>
Phil Nashd31737f2012-05-09 19:04:00 +0100598
Phil Nash0dc9e432012-08-01 08:17:07 +0100599#ifdef __OBJC__
600// #included from: catch_objc_arc.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100601#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
Phil Nash0dc9e432012-08-01 08:17:07 +0100602
603#import <Foundation/Foundation.h>
604
605#ifdef __has_feature
606#define CATCH_ARC_ENABLED __has_feature(objc_arc)
607#else
608#define CATCH_ARC_ENABLED 0
609#endif
610
611void arcSafeRelease( NSObject* obj );
612id performOptionalSelector( id obj, SEL sel );
613
614#if !CATCH_ARC_ENABLED
615inline void arcSafeRelease( NSObject* obj ) {
616 [obj release];
617}
618inline id performOptionalSelector( id obj, SEL sel ) {
619 if( [obj respondsToSelector: sel] )
620 return [obj performSelector: sel];
621 return nil;
622}
623#define CATCH_UNSAFE_UNRETAINED
624#define CATCH_ARC_STRONG
625#else
626inline void arcSafeRelease( NSObject* ){}
627inline id performOptionalSelector( id obj, SEL sel ) {
Phil Nash5bc030d2012-08-16 18:48:50 +0100628#ifdef __clang__
Phil Nash0dc9e432012-08-01 08:17:07 +0100629#pragma clang diagnostic push
630#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
Phil Nash5bc030d2012-08-16 18:48:50 +0100631#endif
Phil Nash0dc9e432012-08-01 08:17:07 +0100632 if( [obj respondsToSelector: sel] )
633 return [obj performSelector: sel];
Phil Nash5bc030d2012-08-16 18:48:50 +0100634#ifdef __clang__
Phil Nash0dc9e432012-08-01 08:17:07 +0100635#pragma clang diagnostic pop
Phil Nash5bc030d2012-08-16 18:48:50 +0100636#endif
Phil Nash0dc9e432012-08-01 08:17:07 +0100637 return nil;
638}
639#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
640#define CATCH_ARC_STRONG __strong
641#endif
642
643#endif
644
Phil Nash89d2a3f2012-05-16 15:09:17 +0100645namespace Catch {
646namespace Detail {
647
Phil Nashdd520442013-04-20 23:20:05 +0100648// SFINAE is currently disabled by default for all compilers.
649// If the non SFINAE version of IsStreamInsertable is ambiguous for you
Phil Nash471eba22013-04-22 18:55:12 +0100650// and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE
651#ifdef CATCH_CONFIG_SFINAE
Phil Nashdd520442013-04-20 23:20:05 +0100652
Phil Nash19279252013-04-20 21:07:32 +0100653 template<typename T>
654 class IsStreamInsertableHelper {
655 template<int N> struct TrueIfSizeable : TrueType {};
656
657 template<typename T2>
658 static TrueIfSizeable<sizeof((*(std::ostream*)0) << *((T2 const*)0))> dummy(T2*);
659 static FalseType dummy(...);
660
661 public:
662 typedef SizedIf<sizeof(dummy((T*)0))> type;
Phil Nashd31737f2012-05-09 19:04:00 +0100663 };
664
Phil Nash19279252013-04-20 21:07:32 +0100665 template<typename T>
666 struct IsStreamInsertable : IsStreamInsertableHelper<T>::type {};
667
Phil Nash19279252013-04-20 21:07:32 +0100668#else
669
Phil Nashdd520442013-04-20 23:20:05 +0100670 struct BorgType {
671 template<typename T> BorgType( T const& );
672 };
Phil Nashd31737f2012-05-09 19:04:00 +0100673
Phil Nashdd520442013-04-20 23:20:05 +0100674 TrueType& testStreamable( std::ostream& );
675 FalseType testStreamable( FalseType );
676
677 FalseType operator<<( std::ostream const&, BorgType const& );
Phil Nashd31737f2012-05-09 19:04:00 +0100678
679 template<typename T>
Phil Nashdd520442013-04-20 23:20:05 +0100680 struct IsStreamInsertable {
681 static std::ostream &s;
Phil Nash8defc712013-04-24 19:10:02 +0100682 static T const&t;
Phil Nashdd520442013-04-20 23:20:05 +0100683 enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
684 };
Phil Nashd31737f2012-05-09 19:04:00 +0100685
Phil Nashdd520442013-04-20 23:20:05 +0100686#endif
687
688 template<bool C>
689 struct StringMakerBase {
690 template<typename T>
691 static std::string convert( T const& ) { return "{?}"; }
692 };
693
694 template<>
695 struct StringMakerBase<true> {
696 template<typename T>
697 static std::string convert( T const& _value ) {
698 std::ostringstream oss;
699 oss << _value;
700 return oss.str();
701 }
Phil Nashd31737f2012-05-09 19:04:00 +0100702 };
703
Phil Nash767f1582013-03-04 12:19:15 +0100704} // end namespace Detail
Phil Nashd31737f2012-05-09 19:04:00 +0100705
Phil Nash767f1582013-03-04 12:19:15 +0100706template<typename T>
Phil Nashdd520442013-04-20 23:20:05 +0100707struct StringMaker :
708 Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
Phil Nash19279252013-04-20 21:07:32 +0100709
Phil Nash767f1582013-03-04 12:19:15 +0100710template<typename T>
711struct StringMaker<T*> {
Phil Nash503d5d02013-07-03 08:25:11 +0100712 template<typename U>
713 static std::string convert( U* p ) {
Phil Nashd31737f2012-05-09 19:04:00 +0100714 if( !p )
715 return INTERNAL_CATCH_STRINGIFY( NULL );
716 std::ostringstream oss;
717 oss << p;
718 return oss.str();
719 }
Phil Nash767f1582013-03-04 12:19:15 +0100720};
Phil Nashd31737f2012-05-09 19:04:00 +0100721
Phil Nash767f1582013-03-04 12:19:15 +0100722template<typename T>
723struct StringMaker<std::vector<T> > {
724 static std::string convert( std::vector<T> const& v ) {
Phil Nashd31737f2012-05-09 19:04:00 +0100725 std::ostringstream oss;
Phil Nash767f1582013-03-04 12:19:15 +0100726 oss << "{ ";
727 for( std::size_t i = 0; i < v.size(); ++ i ) {
Phil Nash19279252013-04-20 21:07:32 +0100728 oss << toString( v[i] );
Phil Nash767f1582013-03-04 12:19:15 +0100729 if( i < v.size() - 1 )
730 oss << ", ";
731 }
732 oss << " }";
Phil Nashd31737f2012-05-09 19:04:00 +0100733 return oss.str();
734 }
Phil Nash767f1582013-03-04 12:19:15 +0100735};
Phil Nashd31737f2012-05-09 19:04:00 +0100736
Phil Nash767f1582013-03-04 12:19:15 +0100737namespace Detail {
738 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +0100739 inline std::string makeString( T const& value ) {
Phil Nash767f1582013-03-04 12:19:15 +0100740 return StringMaker<T>::convert( value );
741 }
Phil Nashd31737f2012-05-09 19:04:00 +0100742} // end namespace Detail
743
744/// \brief converts any type to a string
745///
746/// The default template forwards on to ostringstream - except when an
747/// ostringstream overload does not exist - in which case it attempts to detect
748/// that and writes {?}.
749/// Overload (not specialise) this template for custom typs that you don't want
750/// to provide an ostream overload for.
751template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +0100752std::string toString( T const& value ) {
Phil Nash767f1582013-03-04 12:19:15 +0100753 return StringMaker<T>::convert( value );
Phil Nashd31737f2012-05-09 19:04:00 +0100754}
755
756// Built in overloads
757
Phil Nash8defc712013-04-24 19:10:02 +0100758inline std::string toString( std::string const& value ) {
Phil Nashd31737f2012-05-09 19:04:00 +0100759 return "\"" + value + "\"";
760}
761
Phil Nash8defc712013-04-24 19:10:02 +0100762inline std::string toString( std::wstring const& value ) {
Phil Nashd31737f2012-05-09 19:04:00 +0100763 std::ostringstream oss;
764 oss << "\"";
765 for(size_t i = 0; i < value.size(); ++i )
766 oss << static_cast<char>( value[i] <= 0xff ? value[i] : '?');
767 oss << "\"";
768 return oss.str();
769}
770
771inline std::string toString( const char* const value ) {
772 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
773}
774
775inline std::string toString( char* const value ) {
776 return Catch::toString( static_cast<const char*>( value ) );
777}
778
779inline std::string toString( int value ) {
780 std::ostringstream oss;
781 oss << value;
782 return oss.str();
783}
784
785inline std::string toString( unsigned long value ) {
786 std::ostringstream oss;
787 if( value > 8192 )
788 oss << "0x" << std::hex << value;
789 else
790 oss << value;
791 return oss.str();
792}
793
794inline std::string toString( unsigned int value ) {
Phil Nash62179662012-05-11 19:06:43 +0100795 return toString( static_cast<unsigned long>( value ) );
Phil Nashd31737f2012-05-09 19:04:00 +0100796}
797
798inline std::string toString( const double value ) {
799 std::ostringstream oss;
Phil Nashaa7123b2013-08-15 19:01:00 +0100800 oss << std::setprecision( 10 )
801 << std::fixed
Phil Nash767f1582013-03-04 12:19:15 +0100802 << value;
Phil Nashaa7123b2013-08-15 19:01:00 +0100803 std::string d = oss.str();
804 std::size_t i = d.find_last_not_of( '0' );
805 if( i != std::string::npos && i != d.size()-1 ) {
806 if( d[i] == '.' )
807 i++;
808 d = d.substr( 0, i+1 );
809 }
810 return d;
Phil Nashd31737f2012-05-09 19:04:00 +0100811}
812
813inline std::string toString( bool value ) {
814 return value ? "true" : "false";
815}
816
Phil Nash78372d02012-06-06 08:06:40 +0100817inline std::string toString( char value ) {
818 return value < ' '
Phil Nashcf5ced52012-12-14 07:50:08 +0000819 ? toString( static_cast<unsigned int>( value ) )
Phil Nash78372d02012-06-06 08:06:40 +0100820 : Detail::makeString( value );
821}
822
823inline std::string toString( signed char value ) {
824 return toString( static_cast<char>( value ) );
825}
826
Phil Nashcf5ced52012-12-14 07:50:08 +0000827inline std::string toString( unsigned char value ) {
828 return toString( static_cast<char>( value ) );
829}
830
Phil Nash176eb812012-05-11 08:17:16 +0100831#ifdef CATCH_CONFIG_CPP11_NULLPTR
Phil Nash06e959b2012-05-25 08:52:05 +0100832inline std::string toString( std::nullptr_t ) {
Phil Nash176eb812012-05-11 08:17:16 +0100833 return "nullptr";
834}
835#endif
836
Phil Nash0dc9e432012-08-01 08:17:07 +0100837#ifdef __OBJC__
Phil Nash0dc9e432012-08-01 08:17:07 +0100838 inline std::string toString( NSString const * const& nsstring ) {
Phil Nash6d56d712013-03-12 18:49:37 +0000839 if( !nsstring )
840 return "nil";
Phil Nash0dc9e432012-08-01 08:17:07 +0100841 return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
842 }
843 inline std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
Phil Nash6d56d712013-03-12 18:49:37 +0000844 if( !nsstring )
845 return "nil";
Phil Nash0dc9e432012-08-01 08:17:07 +0100846 return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
847 }
848 inline std::string toString( NSObject* const& nsObject ) {
849 return toString( [nsObject description] );
850 }
851#endif
852
Phil Nashd31737f2012-05-09 19:04:00 +0100853} // end namespace Catch
854
Phil Nashce612bf2012-11-01 08:27:09 +0000855// #included from: catch_assertionresult.h
856#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100857
Phil Nash89d1e6c2011-05-24 08:23:02 +0100858#include <string>
859// #included from: catch_result_type.h
Phil Nash3b80af72012-08-09 07:47:30 +0100860#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100861
Phil Nash89d2a3f2012-05-16 15:09:17 +0100862namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100863
Phil Nash90a35942012-11-13 22:04:29 +0000864 // ResultWas::OfType enum
865 struct ResultWas { enum OfType {
866 Unknown = -1,
867 Ok = 0,
868 Info = 1,
869 Warning = 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100870
Phil Nash90a35942012-11-13 22:04:29 +0000871 FailureBit = 0x10,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100872
Phil Nash90a35942012-11-13 22:04:29 +0000873 ExpressionFailed = FailureBit | 1,
874 ExplicitFailure = FailureBit | 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100875
Phil Nash90a35942012-11-13 22:04:29 +0000876 Exception = 0x100 | FailureBit,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100877
Phil Nash90a35942012-11-13 22:04:29 +0000878 ThrewException = Exception | 1,
879 DidntThrowException = Exception | 2
Phil Nash89d1e6c2011-05-24 08:23:02 +0100880
Phil Nash90a35942012-11-13 22:04:29 +0000881 }; };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100882
Phil Nash90a35942012-11-13 22:04:29 +0000883 inline bool isOk( ResultWas::OfType resultType ) {
884 return ( resultType & ResultWas::FailureBit ) == 0;
885 }
Phil Nasha2773812013-02-02 20:37:58 +0000886 inline bool isJustInfo( int flags ) {
887 return flags == ResultWas::Info;
888 }
Phil Nash67305122012-10-09 11:48:55 +0100889
Phil Nash90a35942012-11-13 22:04:29 +0000890 // ResultAction::Value enum
891 struct ResultAction { enum Value {
892 None,
893 Failed = 1, // Failure - but no debug break if Debug bit not set
894 Debug = 2, // If this bit is set, invoke the debugger
895 Abort = 4 // Test run should abort
896 }; };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100897
Phil Nash90a35942012-11-13 22:04:29 +0000898 // ResultDisposition::Flags enum
899 struct ResultDisposition { enum Flags {
900 Normal = 0x00,
901
902 ContinueOnFailure = 0x01, // Failures fail test, but execution continues
903 NegateResult = 0x02, // Prefix expressiom with !
904 SuppressFail = 0x04 // Failures are reported but do not fail the test
905 }; };
906
907 inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
908 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
909 }
910
Phil Nash3e2e3182012-11-17 10:49:24 +0000911 inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
912 inline bool shouldNegate( int flags ) { return ( flags & ResultDisposition::NegateResult ) != 0; }
913 inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
Phil Nash90a35942012-11-13 22:04:29 +0000914
915} // end namespace Catch
Phil Nash89d1e6c2011-05-24 08:23:02 +0100916
917
Phil Nash89d2a3f2012-05-16 15:09:17 +0100918namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100919
Phil Nashce612bf2012-11-01 08:27:09 +0000920 struct AssertionInfo
Phil Nash67305122012-10-09 11:48:55 +0100921 {
Phil Nashce612bf2012-11-01 08:27:09 +0000922 AssertionInfo() {}
Phil Nash8defc712013-04-24 19:10:02 +0100923 AssertionInfo( std::string const& _macroName,
924 SourceLineInfo const& _lineInfo,
925 std::string const& _capturedExpression,
Phil Nash90a35942012-11-13 22:04:29 +0000926 ResultDisposition::Flags _resultDisposition );
Phil Nash67305122012-10-09 11:48:55 +0100927
928 std::string macroName;
929 SourceLineInfo lineInfo;
930 std::string capturedExpression;
Phil Nash90a35942012-11-13 22:04:29 +0000931 ResultDisposition::Flags resultDisposition;
Phil Nashce612bf2012-11-01 08:27:09 +0000932 };
933
934 struct AssertionResultData
935 {
936 AssertionResultData() : resultType( ResultWas::Unknown ) {}
937
Phil Nash67305122012-10-09 11:48:55 +0100938 std::string reconstructedExpression;
939 std::string message;
940 ResultWas::OfType resultType;
941 };
942
Phil Nashce612bf2012-11-01 08:27:09 +0000943 class AssertionResult {
Phil Nash89d2a3f2012-05-16 15:09:17 +0100944 public:
Phil Nashce612bf2012-11-01 08:27:09 +0000945 AssertionResult();
Phil Nash8defc712013-04-24 19:10:02 +0100946 AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
Phil Nashce612bf2012-11-01 08:27:09 +0000947 ~AssertionResult();
Phil Nash89d1e6c2011-05-24 08:23:02 +0100948
Phil Nash90a35942012-11-13 22:04:29 +0000949 bool isOk() const;
950 bool succeeded() const;
Phil Nash3b80af72012-08-09 07:47:30 +0100951 ResultWas::OfType getResultType() const;
952 bool hasExpression() const;
953 bool hasMessage() const;
954 std::string getExpression() const;
Phil Nash786959d2013-06-07 19:07:50 +0100955 std::string getExpressionInMacro() const;
Phil Nash3b80af72012-08-09 07:47:30 +0100956 bool hasExpandedExpression() const;
957 std::string getExpandedExpression() const;
958 std::string getMessage() const;
Phil Nashce612bf2012-11-01 08:27:09 +0000959 SourceLineInfo getSourceInfo() const;
Phil Nash3b80af72012-08-09 07:47:30 +0100960 std::string getTestMacroName() const;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100961
962 protected:
Phil Nashce612bf2012-11-01 08:27:09 +0000963 AssertionInfo m_info;
964 AssertionResultData m_resultData;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100965 };
966
967} // end namespace Catch
968
Phil Nash89d1e6c2011-05-24 08:23:02 +0100969// #included from: catch_evaluate.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100970#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100971
Phil Nashdd26e882013-03-25 09:25:31 +0000972#ifdef _MSC_VER
973#pragma warning(push)
974#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
975#endif
976
Phil Nash89d2a3f2012-05-16 15:09:17 +0100977namespace Catch {
978namespace Internal {
979
980 enum Operator {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100981 IsEqualTo,
982 IsNotEqualTo,
983 IsLessThan,
984 IsGreaterThan,
985 IsLessThanOrEqualTo,
986 IsGreaterThanOrEqualTo
987 };
988
Phil Nash371db8b2012-05-21 18:52:09 +0100989 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
990 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
991 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
992 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
993 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
994 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
995 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100996
Phil Nash471eba22013-04-22 18:55:12 +0100997 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +0100998 inline T& opCast(T const& t) { return const_cast<T&>(t); }
Phil Nash471eba22013-04-22 18:55:12 +0100999
1000// nullptr_t support based on pull request #154 from Konstantin Baumann
1001#ifdef CATCH_CONFIG_CPP11_NULLPTR
1002 inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
1003#endif // CATCH_CONFIG_CPP11_NULLPTR
1004
Phil Nash89d1e6c2011-05-24 08:23:02 +01001005 // So the compare overloads can be operator agnostic we convey the operator as a template
1006 // enum, which is used to specialise an Evaluator for doing the comparison.
1007 template<typename T1, typename T2, Operator Op>
1008 class Evaluator{};
1009
1010 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001011 struct Evaluator<T1, T2, IsEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001012 static bool evaluate( T1 const& lhs, T2 const& rhs) {
Phil Nash471eba22013-04-22 18:55:12 +01001013 return opCast( lhs ) == opCast( rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001014 }
1015 };
1016 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001017 struct Evaluator<T1, T2, IsNotEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001018 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nash471eba22013-04-22 18:55:12 +01001019 return opCast( lhs ) != opCast( rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001020 }
1021 };
1022 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001023 struct Evaluator<T1, T2, IsLessThan> {
Phil Nash8defc712013-04-24 19:10:02 +01001024 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nash471eba22013-04-22 18:55:12 +01001025 return opCast( lhs ) < opCast( rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001026 }
1027 };
1028 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001029 struct Evaluator<T1, T2, IsGreaterThan> {
Phil Nash8defc712013-04-24 19:10:02 +01001030 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nash471eba22013-04-22 18:55:12 +01001031 return opCast( lhs ) > opCast( rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001032 }
1033 };
1034 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001035 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001036 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nash471eba22013-04-22 18:55:12 +01001037 return opCast( lhs ) >= opCast( rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001038 }
1039 };
1040 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001041 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001042 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nash471eba22013-04-22 18:55:12 +01001043 return opCast( lhs ) <= opCast( rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001044 }
1045 };
1046
1047 template<Operator Op, typename T1, typename T2>
Phil Nash8defc712013-04-24 19:10:02 +01001048 bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001049 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1050 }
1051
Phil Nash90a35942012-11-13 22:04:29 +00001052 // This level of indirection allows us to specialise for integer types
1053 // to avoid signed/ unsigned warnings
1054
Phil Nash89d1e6c2011-05-24 08:23:02 +01001055 // "base" overload
1056 template<Operator Op, typename T1, typename T2>
Phil Nash8defc712013-04-24 19:10:02 +01001057 bool compare( T1 const& lhs, T2 const& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001058 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1059 }
1060
1061 // unsigned X to int
Phil Nash89d2a3f2012-05-16 15:09:17 +01001062 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001063 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1064 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001065 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001066 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1067 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001068 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001069 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1070 }
1071
1072 // unsigned X to long
Phil Nash89d2a3f2012-05-16 15:09:17 +01001073 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001074 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1075 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001076 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001077 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1078 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001079 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001080 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1081 }
1082
1083 // int to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +01001084 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001085 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1086 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001087 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001088 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1089 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001090 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001091 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1092 }
1093
1094 // long to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +01001095 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -03001096 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001097 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001098 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -03001099 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001100 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001101 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -03001102 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001103 }
1104
Phil Nash06e959b2012-05-25 08:52:05 +01001105 // pointer to long (when comparing against NULL)
Phil Nash90a35942012-11-13 22:04:29 +00001106 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001107 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
Phil Nash6f1543b2012-05-07 19:46:19 +01001108 }
Phil Nash90a35942012-11-13 22:04:29 +00001109 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
Phil Nash6f1543b2012-05-07 19:46:19 +01001110 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001111 }
1112
Phil Nash06e959b2012-05-25 08:52:05 +01001113 // pointer to int (when comparing against NULL)
Phil Nash90a35942012-11-13 22:04:29 +00001114 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
Phil Nash06e959b2012-05-25 08:52:05 +01001115 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1116 }
Phil Nash90a35942012-11-13 22:04:29 +00001117 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
Phil Nash06e959b2012-05-25 08:52:05 +01001118 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1119 }
1120
Phil Nash471eba22013-04-22 18:55:12 +01001121#ifdef CATCH_CONFIG_CPP11_NULLPTR
1122 // pointer to nullptr_t (when comparing against nullptr)
1123 template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
1124 return Evaluator<T*, T*, Op>::evaluate( NULL, rhs );
1125 }
1126 template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
1127 return Evaluator<T*, T*, Op>::evaluate( lhs, NULL );
1128 }
1129#endif // CATCH_CONFIG_CPP11_NULLPTR
1130
Phil Nash89d1e6c2011-05-24 08:23:02 +01001131} // end of namespace Internal
1132} // end of namespace Catch
1133
Phil Nashdd26e882013-03-25 09:25:31 +00001134#ifdef _MSC_VER
1135#pragma warning(pop)
1136#endif
1137
Phil Nash89d2a3f2012-05-16 15:09:17 +01001138namespace Catch {
Phil Nashf51d3162011-12-28 10:37:31 +00001139
Phil Nashcd688302013-06-29 12:11:32 +01001140struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
1141
Phil Nashce612bf2012-11-01 08:27:09 +00001142// Wraps the (stringised versions of) the lhs, operator and rhs of an expression - as well as
1143// the result of evaluating it. This is used to build an AssertionResult object
1144class ExpressionResultBuilder {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001145public:
1146
Phil Nashce612bf2012-11-01 08:27:09 +00001147 ExpressionResultBuilder( ResultWas::OfType resultType = ResultWas::Unknown );
Phil Nash8defc712013-04-24 19:10:02 +01001148 ExpressionResultBuilder( ExpressionResultBuilder const& other );
1149 ExpressionResultBuilder& operator=(ExpressionResultBuilder const& other );
Phil Nashd31737f2012-05-09 19:04:00 +01001150
Phil Nashce612bf2012-11-01 08:27:09 +00001151 ExpressionResultBuilder& setResultType( ResultWas::OfType result );
1152 ExpressionResultBuilder& setResultType( bool result );
Phil Nash8defc712013-04-24 19:10:02 +01001153 ExpressionResultBuilder& setLhs( std::string const& lhs );
1154 ExpressionResultBuilder& setRhs( std::string const& rhs );
1155 ExpressionResultBuilder& setOp( std::string const& op );
Phil Nash78d95a02012-03-04 21:22:36 +00001156
Phil Nash90a35942012-11-13 22:04:29 +00001157 ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition );
Phil Nash67305122012-10-09 11:48:55 +01001158
Phil Nashce612bf2012-11-01 08:27:09 +00001159 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01001160 ExpressionResultBuilder& operator << ( T const& value ) {
Phil Nashce612bf2012-11-01 08:27:09 +00001161 m_stream << value;
1162 return *this;
Phil Nash67305122012-10-09 11:48:55 +01001163 }
1164
Phil Nash8defc712013-04-24 19:10:02 +01001165 std::string reconstructExpression( AssertionInfo const& info ) const;
Phil Nashce612bf2012-11-01 08:27:09 +00001166
Phil Nash8defc712013-04-24 19:10:02 +01001167 AssertionResult buildResult( AssertionInfo const& info ) const;
Phil Nashce612bf2012-11-01 08:27:09 +00001168
Phil Nashcd688302013-06-29 12:11:32 +01001169 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
1170 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
1171
Phil Nash89d1e6c2011-05-24 08:23:02 +01001172private:
Phil Nashce612bf2012-11-01 08:27:09 +00001173 AssertionResultData m_data;
1174 struct ExprComponents {
1175 ExprComponents() : shouldNegate( false ) {}
1176 bool shouldNegate;
1177 std::string lhs, rhs, op;
1178 } m_exprComponents;
1179 std::ostringstream m_stream;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001180};
1181
Phil Nashd31737f2012-05-09 19:04:00 +01001182} // end namespace Catch
1183
Phil Nash89d2a3f2012-05-16 15:09:17 +01001184namespace Catch {
Phil Nash176eb812012-05-11 08:17:16 +01001185
Phil Nashce612bf2012-11-01 08:27:09 +00001186// Wraps the LHS of an expression and captures the operator and RHS (if any) - wrapping them all
1187// in an ExpressionResultBuilder object
Phil Nash176eb812012-05-11 08:17:16 +01001188template<typename T>
Phil Nashce612bf2012-11-01 08:27:09 +00001189class ExpressionLhs {
Phil Nash8defc712013-04-24 19:10:02 +01001190 void operator = ( ExpressionLhs const& );
Phil Nash176eb812012-05-11 08:17:16 +01001191
1192public:
Wichert Akkermanfec10532012-11-16 10:47:33 +01001193 ExpressionLhs( T lhs ) : m_lhs( lhs ) {}
Phil Nash176eb812012-05-11 08:17:16 +01001194
1195 template<typename RhsT>
Phil Nash8defc712013-04-24 19:10:02 +01001196 ExpressionResultBuilder& operator == ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001197 return captureExpression<Internal::IsEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001198 }
1199
1200 template<typename RhsT>
Phil Nash8defc712013-04-24 19:10:02 +01001201 ExpressionResultBuilder& operator != ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001202 return captureExpression<Internal::IsNotEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001203 }
1204
1205 template<typename RhsT>
Phil Nash8defc712013-04-24 19:10:02 +01001206 ExpressionResultBuilder& operator < ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001207 return captureExpression<Internal::IsLessThan>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001208 }
1209
1210 template<typename RhsT>
Phil Nash8defc712013-04-24 19:10:02 +01001211 ExpressionResultBuilder& operator > ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001212 return captureExpression<Internal::IsGreaterThan>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001213 }
1214
1215 template<typename RhsT>
Phil Nash8defc712013-04-24 19:10:02 +01001216 ExpressionResultBuilder& operator <= ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001217 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001218 }
1219
1220 template<typename RhsT>
Phil Nash8defc712013-04-24 19:10:02 +01001221 ExpressionResultBuilder& operator >= ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001222 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001223 }
1224
Phil Nashce612bf2012-11-01 08:27:09 +00001225 ExpressionResultBuilder& operator == ( bool rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001226 return captureExpression<Internal::IsEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001227 }
1228
Phil Nashce612bf2012-11-01 08:27:09 +00001229 ExpressionResultBuilder& operator != ( bool rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001230 return captureExpression<Internal::IsNotEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001231 }
1232
Phil Nash90a35942012-11-13 22:04:29 +00001233 ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition ) {
Phil Nashce612bf2012-11-01 08:27:09 +00001234 bool value = m_lhs ? true : false;
1235 return m_result
1236 .setLhs( Catch::toString( value ) )
1237 .setResultType( value )
Phil Nash90a35942012-11-13 22:04:29 +00001238 .endExpression( resultDisposition );
Phil Nash176eb812012-05-11 08:17:16 +01001239 }
1240
Phil Nashce612bf2012-11-01 08:27:09 +00001241 // Only simple binary expressions are allowed on the LHS.
1242 // If more complex compositions are required then place the sub expression in parentheses
Phil Nash8defc712013-04-24 19:10:02 +01001243 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& );
1244 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& );
1245 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& );
1246 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& );
Phil Nashcd688302013-06-29 12:11:32 +01001247 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
1248 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
Phil Nash176eb812012-05-11 08:17:16 +01001249
1250private:
Phil Nash9902ac92012-10-09 20:58:33 +01001251 template<Internal::Operator Op, typename RhsT>
Phil Nash8defc712013-04-24 19:10:02 +01001252 ExpressionResultBuilder& captureExpression( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001253 return m_result
Phil Nashce612bf2012-11-01 08:27:09 +00001254 .setResultType( Internal::compare<Op>( m_lhs, rhs ) )
1255 .setLhs( Catch::toString( m_lhs ) )
Phil Nash9902ac92012-10-09 20:58:33 +01001256 .setRhs( Catch::toString( rhs ) )
1257 .setOp( Internal::OperatorTraits<Op>::getName() );
1258 }
1259
1260private:
Phil Nashce612bf2012-11-01 08:27:09 +00001261 ExpressionResultBuilder m_result;
Phil Nash176eb812012-05-11 08:17:16 +01001262 T m_lhs;
1263};
1264
Phil Nash176eb812012-05-11 08:17:16 +01001265} // end namespace Catch
1266
Phil Nash89d2a3f2012-05-16 15:09:17 +01001267namespace Catch {
1268
Phil Nashce612bf2012-11-01 08:27:09 +00001269// Captures the LHS of the expression and wraps it in an Expression Lhs object
1270class ExpressionDecomposer {
Phil Nash89d2a3f2012-05-16 15:09:17 +01001271public:
1272
Phil Nash89d2a3f2012-05-16 15:09:17 +01001273 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01001274 ExpressionLhs<T const&> operator->* ( T const& operand ) {
1275 return ExpressionLhs<T const&>( operand );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001276 }
1277
Phil Nashce612bf2012-11-01 08:27:09 +00001278 ExpressionLhs<bool> operator->* ( bool value ) {
1279 return ExpressionLhs<bool>( value );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001280 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001281};
1282
1283} // end namespace Catch
1284
Phil Nasha2773812013-02-02 20:37:58 +00001285// #included from: catch_message.h
1286#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
1287
1288#include <string>
1289
1290namespace Catch {
1291
1292 struct MessageInfo {
1293 MessageInfo( std::string const& _macroName,
1294 SourceLineInfo const& _lineInfo,
1295 ResultWas::OfType _type );
1296
1297 std::string macroName;
1298 SourceLineInfo lineInfo;
1299 ResultWas::OfType type;
1300 std::string message;
1301 unsigned int sequence;
1302
1303 bool operator == ( MessageInfo const& other ) const {
1304 return sequence == other.sequence;
1305 }
1306 bool operator < ( MessageInfo const& other ) const {
1307 return sequence < other.sequence;
1308 }
1309 private:
1310 static unsigned int globalCount;
1311 };
1312
Phil Nashb5fd5a62013-06-28 17:09:57 +01001313 struct MessageBuilder {
1314 MessageBuilder( std::string const& macroName,
1315 SourceLineInfo const& lineInfo,
1316 ResultWas::OfType type )
1317 : m_info( macroName, lineInfo, type )
1318 {}
Phil Nasha2773812013-02-02 20:37:58 +00001319
1320 template<typename T>
Phil Nashb5fd5a62013-06-28 17:09:57 +01001321 MessageBuilder& operator << ( T const& value ) {
1322 m_stream << value;
Phil Nasha2773812013-02-02 20:37:58 +00001323 return *this;
1324 }
Phil Nashb5fd5a62013-06-28 17:09:57 +01001325
1326 MessageInfo m_info;
1327 std::ostringstream m_stream;
Phil Nasha2773812013-02-02 20:37:58 +00001328 };
1329
Phil Nashb5fd5a62013-06-28 17:09:57 +01001330 class ScopedMessage {
Phil Nasha2773812013-02-02 20:37:58 +00001331 public:
Phil Nashb5fd5a62013-06-28 17:09:57 +01001332 ScopedMessage( MessageBuilder const& builder );
1333 ~ScopedMessage();
1334
1335 MessageInfo m_info;
Phil Nasha2773812013-02-02 20:37:58 +00001336 };
1337
1338} // end namespace Catch
1339
Phil Nashd31737f2012-05-09 19:04:00 +01001340// #included from: catch_interfaces_capture.h
Phil Nash3b80af72012-08-09 07:47:30 +01001341#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01001342
Phil Nashd31737f2012-05-09 19:04:00 +01001343#include <string>
Phil Nasha70fbe32012-08-31 08:10:36 +01001344// #included from: catch_totals.hpp
1345#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
1346
Phil Nash9e7e63c2012-09-29 20:54:03 +01001347#include <cstddef>
1348
Phil Nasha70fbe32012-08-31 08:10:36 +01001349namespace Catch {
1350
1351 struct Counts {
1352 Counts() : passed( 0 ), failed( 0 ) {}
1353
Phil Nash8defc712013-04-24 19:10:02 +01001354 Counts operator - ( Counts const& other ) const {
Phil Nasha70fbe32012-08-31 08:10:36 +01001355 Counts diff;
1356 diff.passed = passed - other.passed;
1357 diff.failed = failed - other.failed;
1358 return diff;
1359 }
Phil Nash8defc712013-04-24 19:10:02 +01001360 Counts& operator += ( Counts const& other ) {
Phil Nasha70fbe32012-08-31 08:10:36 +01001361 passed += other.passed;
1362 failed += other.failed;
1363 return *this;
1364 }
1365
1366 std::size_t total() const {
1367 return passed + failed;
1368 }
1369
1370 std::size_t passed;
1371 std::size_t failed;
1372 };
1373
1374 struct Totals {
1375
Phil Nash8defc712013-04-24 19:10:02 +01001376 Totals operator - ( Totals const& other ) const {
Phil Nasha70fbe32012-08-31 08:10:36 +01001377 Totals diff;
1378 diff.assertions = assertions - other.assertions;
1379 diff.testCases = testCases - other.testCases;
1380 return diff;
1381 }
1382
Phil Nash8defc712013-04-24 19:10:02 +01001383 Totals delta( Totals const& prevTotals ) const {
Phil Nasha70fbe32012-08-31 08:10:36 +01001384 Totals diff = *this - prevTotals;
1385 if( diff.assertions.failed > 0 )
1386 ++diff.testCases.failed;
1387 else
1388 ++diff.testCases.passed;
1389 return diff;
1390 }
1391
Phil Nash8defc712013-04-24 19:10:02 +01001392 Totals& operator += ( Totals const& other ) {
Phil Nasha70fbe32012-08-31 08:10:36 +01001393 assertions += other.assertions;
1394 testCases += other.testCases;
1395 return *this;
1396 }
1397
1398 Counts assertions;
1399 Counts testCases;
1400 };
1401}
1402
Phil Nashd31737f2012-05-09 19:04:00 +01001403
Phil Nash89d2a3f2012-05-16 15:09:17 +01001404namespace Catch {
1405
Phil Nasha1fbfea2012-12-01 23:57:18 +00001406 class TestCase;
Phil Nashce612bf2012-11-01 08:27:09 +00001407 class ExpressionResultBuilder;
1408 class AssertionResult;
1409 struct AssertionInfo;
Phil Nasha1fbfea2012-12-01 23:57:18 +00001410 struct SectionInfo;
Phil Nashb5fd5a62013-06-28 17:09:57 +01001411 struct MessageInfo;
Phil Nasha2773812013-02-02 20:37:58 +00001412 class ScopedMessageBuilder;
Phil Nashd31737f2012-05-09 19:04:00 +01001413
Phil Nash89d2a3f2012-05-16 15:09:17 +01001414 struct IResultCapture {
Phil Nashd31737f2012-05-09 19:04:00 +01001415
Phil Nasha695eb92012-08-13 07:46:10 +01001416 virtual ~IResultCapture();
Phil Nashd31737f2012-05-09 19:04:00 +01001417
Phil Nasha2773812013-02-02 20:37:58 +00001418 virtual void assertionEnded( AssertionResult const& result ) = 0;
Phil Nasha1fbfea2012-12-01 23:57:18 +00001419 virtual bool sectionStarted( SectionInfo const& sectionInfo,
Phil Nash89d2a3f2012-05-16 15:09:17 +01001420 Counts& assertions ) = 0;
Phil Nashaa7123b2013-08-15 19:01:00 +01001421 virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0;
Phil Nashb5fd5a62013-06-28 17:09:57 +01001422 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
1423 virtual void popScopedMessage( MessageInfo const& message ) = 0;
Phil Nasha2773812013-02-02 20:37:58 +00001424
Phil Nash89d2a3f2012-05-16 15:09:17 +01001425 virtual bool shouldDebugBreak() const = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001426
Phil Nasha1fbfea2012-12-01 23:57:18 +00001427 virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001428
Phil Nash89d2a3f2012-05-16 15:09:17 +01001429 virtual std::string getCurrentTestName() const = 0;
Phil Nashce612bf2012-11-01 08:27:09 +00001430 virtual const AssertionResult* getLastResult() const = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001431 };
1432}
1433
1434// #included from: catch_debugger.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01001435#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01001436
Phil Nashd31737f2012-05-09 19:04:00 +01001437#include <iostream>
1438
Phil Nash04a33642013-08-16 19:09:09 +01001439// #included from: catch_platform.h
1440#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
1441
Phil Nashd31737f2012-05-09 19:04:00 +01001442#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
1443#define CATCH_PLATFORM_MAC
1444#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
1445#define CATCH_PLATFORM_IPHONE
Phil Nash04a33642013-08-16 19:09:09 +01001446#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
Phil Nashd31737f2012-05-09 19:04:00 +01001447#define CATCH_PLATFORM_WINDOWS
1448#endif
1449
1450#ifdef CATCH_PLATFORM_MAC
1451
1452 #include <assert.h>
1453 #include <stdbool.h>
1454 #include <sys/types.h>
1455 #include <unistd.h>
1456 #include <sys/sysctl.h>
1457
Phil Nash89d2a3f2012-05-16 15:09:17 +01001458 namespace Catch{
1459
Phil Nashd31737f2012-05-09 19:04:00 +01001460 // The following function is taken directly from the following technical note:
1461 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
1462
Phil Nashd31737f2012-05-09 19:04:00 +01001463 // Returns true if the current process is being debugged (either
1464 // running under the debugger or has a debugger attached post facto).
Phil Nash89d2a3f2012-05-16 15:09:17 +01001465 inline bool isDebuggerActive(){
1466
Phil Nashd31737f2012-05-09 19:04:00 +01001467 int junk;
1468 int mib[4];
1469 struct kinfo_proc info;
1470 size_t size;
1471
1472 // Initialize the flags so that, if sysctl fails for some bizarre
1473 // reason, we get a predictable result.
1474
1475 info.kp_proc.p_flag = 0;
1476
1477 // Initialize mib, which tells sysctl the info we want, in this case
1478 // we're looking for information about a specific process ID.
1479
1480 mib[0] = CTL_KERN;
1481 mib[1] = KERN_PROC;
1482 mib[2] = KERN_PROC_PID;
1483 mib[3] = getpid();
1484
1485 // Call sysctl.
1486
1487 size = sizeof(info);
1488 junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
1489 assert(junk == 0);
1490
1491 // We're being debugged if the P_TRACED flag is set.
1492
1493 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
1494 }
1495 }
1496
1497 // The following code snippet taken from:
1498 // http://cocoawithlove.com/2008/03/break-into-debugger.html
1499 #ifdef DEBUG
1500 #if defined(__ppc64__) || defined(__ppc__)
1501 #define BreakIntoDebugger() \
Phil Nash89d2a3f2012-05-16 15:09:17 +01001502 if( Catch::isDebuggerActive() ) { \
Phil Nashd31737f2012-05-09 19:04:00 +01001503 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
1504 : : : "memory","r0","r3","r4" ); \
1505 }
1506 #else
1507 #define BreakIntoDebugger() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
1508 #endif
1509 #else
1510 inline void BreakIntoDebugger(){}
1511 #endif
1512
1513#elif defined(_MSC_VER)
1514 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
1515 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { __debugbreak(); }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001516 inline bool isDebuggerActive() {
Phil Nashd31737f2012-05-09 19:04:00 +01001517 return IsDebuggerPresent() != 0;
1518 }
Phil Nash176eb812012-05-11 08:17:16 +01001519#elif defined(__MINGW32__)
1520 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
1521 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
1522 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { DebugBreak(); }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001523 inline bool isDebuggerActive() {
Phil Nash176eb812012-05-11 08:17:16 +01001524 return IsDebuggerPresent() != 0;
1525 }
Phil Nashd31737f2012-05-09 19:04:00 +01001526#else
Phil Nasha04981b2013-03-08 09:30:25 +00001527 inline void BreakIntoDebugger(){}
1528 inline bool isDebuggerActive() { return false; }
Phil Nashd31737f2012-05-09 19:04:00 +01001529#endif
1530
1531#ifdef CATCH_PLATFORM_WINDOWS
1532extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
Phil Nash8defc712013-04-24 19:10:02 +01001533inline void writeToDebugConsole( std::string const& text ) {
Phil Nashd31737f2012-05-09 19:04:00 +01001534 ::OutputDebugStringA( text.c_str() );
1535}
1536#else
Phil Nash8defc712013-04-24 19:10:02 +01001537inline void writeToDebugConsole( std::string const& text ) {
Phil Nashd31737f2012-05-09 19:04:00 +01001538 // !TBD: Need a version for Mac/ XCode and other IDEs
1539 std::cout << text;
1540}
1541#endif // CATCH_PLATFORM_WINDOWS
1542
Phil Nash3b80af72012-08-09 07:47:30 +01001543// #included from: catch_interfaces_registry_hub.h
1544#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
1545
Phil Nasha70fbe32012-08-31 08:10:36 +01001546// #included from: catch_interfaces_reporter.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04001547#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001548
1549// #included from: catch_config.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04001550#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001551
1552// #included from: catch_test_spec.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04001553#define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001554
1555// #included from: catch_test_case_info.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04001556#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001557
1558#include <string>
Phil Nashfc1baac2012-09-15 17:53:27 +01001559#include <set>
Phil Nasha70fbe32012-08-31 08:10:36 +01001560
Phil Nash37186a12013-03-13 12:19:30 +00001561#ifdef __clang__
1562#pragma clang diagnostic push
1563#pragma clang diagnostic ignored "-Wpadded"
1564#endif
1565
Phil Nasha70fbe32012-08-31 08:10:36 +01001566namespace Catch {
1567
1568 struct ITestCase;
1569
Phil Nasha1fbfea2012-12-01 23:57:18 +00001570 struct TestCaseInfo {
Phil Nash8defc712013-04-24 19:10:02 +01001571 TestCaseInfo( std::string const& _name,
1572 std::string const& _className,
1573 std::string const& _description,
1574 std::set<std::string> const& _tags,
Phil Nasha1fbfea2012-12-01 23:57:18 +00001575 bool _isHidden,
Phil Nash8defc712013-04-24 19:10:02 +01001576 SourceLineInfo const& _lineInfo );
Phil Nasha70fbe32012-08-31 08:10:36 +01001577
Phil Nash8defc712013-04-24 19:10:02 +01001578 TestCaseInfo( TestCaseInfo const& other );
Phil Nasha70fbe32012-08-31 08:10:36 +01001579
Phil Nasha1fbfea2012-12-01 23:57:18 +00001580 std::string name;
1581 std::string className;
1582 std::string description;
1583 std::set<std::string> tags;
Phil Nash38f7eef2013-03-29 13:44:33 +00001584 std::string tagsAsString;
Phil Nasha1fbfea2012-12-01 23:57:18 +00001585 SourceLineInfo lineInfo;
Phil Nashff03cdf2012-12-06 08:44:51 +00001586 bool isHidden;
Phil Nasha1fbfea2012-12-01 23:57:18 +00001587 };
1588
1589 class TestCase : protected TestCaseInfo {
Phil Nasha70fbe32012-08-31 08:10:36 +01001590 public:
Phil Nasha70fbe32012-08-31 08:10:36 +01001591
Phil Nash8defc712013-04-24 19:10:02 +01001592 TestCase( ITestCase* testCase, TestCaseInfo const& info );
1593 TestCase( TestCase const& other );
Phil Nasha70fbe32012-08-31 08:10:36 +01001594
Phil Nash8defc712013-04-24 19:10:02 +01001595 TestCase withName( std::string const& _newName ) const;
Phil Nasha70fbe32012-08-31 08:10:36 +01001596
1597 void invoke() const;
Phil Nash90a35942012-11-13 22:04:29 +00001598
Phil Nash8defc712013-04-24 19:10:02 +01001599 TestCaseInfo const& getTestCaseInfo() const;
Phil Nasha70fbe32012-08-31 08:10:36 +01001600
Phil Nasha70fbe32012-08-31 08:10:36 +01001601 bool isHidden() const;
Phil Nash8defc712013-04-24 19:10:02 +01001602 bool hasTag( std::string const& tag ) const;
1603 bool matchesTags( std::string const& tagPattern ) const;
1604 std::set<std::string> const& getTags() const;
Phil Nasha70fbe32012-08-31 08:10:36 +01001605
Phil Nasha1fbfea2012-12-01 23:57:18 +00001606 void swap( TestCase& other );
Phil Nash8defc712013-04-24 19:10:02 +01001607 bool operator == ( TestCase const& other ) const;
1608 bool operator < ( TestCase const& other ) const;
1609 TestCase& operator = ( TestCase const& other );
Phil Nasha70fbe32012-08-31 08:10:36 +01001610
1611 private:
Phil Nasha1fbfea2012-12-01 23:57:18 +00001612 Ptr<ITestCase> test;
Phil Nasha70fbe32012-08-31 08:10:36 +01001613 };
Phil Nasha1fbfea2012-12-01 23:57:18 +00001614
1615 TestCase makeTestCase( ITestCase* testCase,
Phil Nash8defc712013-04-24 19:10:02 +01001616 std::string const& className,
1617 std::string const& name,
1618 std::string const& description,
1619 SourceLineInfo const& lineInfo );
Phil Nasha70fbe32012-08-31 08:10:36 +01001620}
1621
Phil Nash37186a12013-03-13 12:19:30 +00001622#ifdef __clang__
1623#pragma clang diagnostic pop
1624#endif
1625
Phil Nash67ec8702012-09-26 18:38:26 +01001626// #included from: catch_tags.hpp
1627#define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED
1628
1629#include <string>
1630#include <set>
1631#include <map>
1632#include <vector>
1633
1634#ifdef __clang__
1635#pragma clang diagnostic ignored "-Wpadded"
1636#endif
1637
1638namespace Catch {
1639 class TagParser {
1640 public:
1641 virtual ~TagParser();
1642
Phil Nash8defc712013-04-24 19:10:02 +01001643 void parse( std::string const& str ) {
Phil Nash67ec8702012-09-26 18:38:26 +01001644 std::size_t pos = 0;
1645 while( pos < str.size() ) {
1646 char c = str[pos];
1647 if( c == '[' ) {
1648 std::size_t end = str.find_first_of( ']', pos );
1649 if( end != std::string::npos ) {
1650 acceptTag( str.substr( pos+1, end-pos-1 ) );
1651 pos = end+1;
1652 }
1653 else {
1654 acceptChar( c );
1655 pos++;
1656 }
1657 }
1658 else {
1659 acceptChar( c );
1660 pos++;
1661 }
1662 }
1663 endParse();
1664 }
1665
1666 protected:
Phil Nash8defc712013-04-24 19:10:02 +01001667 virtual void acceptTag( std::string const& tag ) = 0;
Phil Nash67ec8702012-09-26 18:38:26 +01001668 virtual void acceptChar( char c ) = 0;
1669 virtual void endParse() {}
1670
1671 private:
1672 };
1673
1674 class TagExtracter : public TagParser {
1675 public:
1676
1677 TagExtracter( std::set<std::string>& tags )
1678 : m_tags( tags )
1679 {}
1680 virtual ~TagExtracter();
1681
1682 void parse( std::string& description ) {
1683 TagParser::parse( description );
1684 description = m_remainder;
1685 }
1686
1687 private:
Phil Nash8defc712013-04-24 19:10:02 +01001688 virtual void acceptTag( std::string const& tag ) {
Phil Nashdd26e882013-03-25 09:25:31 +00001689 m_tags.insert( toLower( tag ) );
Phil Nash67ec8702012-09-26 18:38:26 +01001690 }
1691 virtual void acceptChar( char c ) {
1692 m_remainder += c;
1693 }
1694
Phil Nash8defc712013-04-24 19:10:02 +01001695 TagExtracter& operator=(TagExtracter const&);
Phil Nashe0a40e22012-11-01 08:28:26 +00001696
Phil Nash67ec8702012-09-26 18:38:26 +01001697 std::set<std::string>& m_tags;
1698 std::string m_remainder;
1699 };
1700
1701 class Tag {
1702 public:
1703 Tag()
Phil Nash90a35942012-11-13 22:04:29 +00001704 : m_isNegated( false )
Phil Nash67ec8702012-09-26 18:38:26 +01001705 {}
1706
Phil Nash8defc712013-04-24 19:10:02 +01001707 Tag( std::string const& name, bool isNegated )
Phil Nash67ec8702012-09-26 18:38:26 +01001708 : m_name( name ),
Phil Nash90a35942012-11-13 22:04:29 +00001709 m_isNegated( isNegated )
Phil Nash67ec8702012-09-26 18:38:26 +01001710 {}
1711
1712 std::string getName() const {
1713 return m_name;
1714 }
1715 bool isNegated() const {
1716 return m_isNegated;
1717 }
1718
1719 bool operator ! () const {
1720 return m_name.empty();
1721 }
1722
1723 private:
1724 std::string m_name;
1725 bool m_isNegated;
1726 };
1727
1728 class TagSet {
1729 typedef std::map<std::string, Tag> TagMap;
1730 public:
Phil Nash8defc712013-04-24 19:10:02 +01001731 void add( Tag const& tag ) {
Phil Nashdd26e882013-03-25 09:25:31 +00001732 m_tags.insert( std::make_pair( toLower( tag.getName() ), tag ) );
Phil Nash67ec8702012-09-26 18:38:26 +01001733 }
1734
Phil Nash67ec8702012-09-26 18:38:26 +01001735 bool empty() const {
1736 return m_tags.empty();
1737 }
1738
Phil Nash8defc712013-04-24 19:10:02 +01001739 bool matches( std::set<std::string> const& tags ) const {
Phil Nash67ec8702012-09-26 18:38:26 +01001740 TagMap::const_iterator it = m_tags.begin();
1741 TagMap::const_iterator itEnd = m_tags.end();
1742 for(; it != itEnd; ++it ) {
1743 bool found = tags.find( it->first ) != tags.end();
1744 if( found == it->second.isNegated() )
1745 return false;
1746 }
1747 return true;
1748 }
1749
1750 private:
1751 TagMap m_tags;
1752 };
1753
1754 class TagExpression {
1755 public:
Phil Nash8defc712013-04-24 19:10:02 +01001756 bool matches( std::set<std::string> const& tags ) const {
Phil Nash67ec8702012-09-26 18:38:26 +01001757 std::vector<TagSet>::const_iterator it = m_tagSets.begin();
1758 std::vector<TagSet>::const_iterator itEnd = m_tagSets.end();
1759 for(; it != itEnd; ++it )
1760 if( it->matches( tags ) )
1761 return true;
1762 return false;
1763 }
1764
1765 private:
1766 friend class TagExpressionParser;
1767
1768 std::vector<TagSet> m_tagSets;
1769 };
1770
1771 class TagExpressionParser : public TagParser {
1772 public:
1773 TagExpressionParser( TagExpression& exp )
1774 : m_isNegated( false ),
1775 m_exp( exp )
1776 {}
1777
1778 ~TagExpressionParser();
1779
1780 private:
Phil Nash8defc712013-04-24 19:10:02 +01001781 virtual void acceptTag( std::string const& tag ) {
Phil Nash67ec8702012-09-26 18:38:26 +01001782 m_currentTagSet.add( Tag( tag, m_isNegated ) );
1783 m_isNegated = false;
1784 }
1785 virtual void acceptChar( char c ) {
1786 switch( c ) {
1787 case '~':
1788 m_isNegated = true;
1789 break;
1790 case ',':
1791 m_exp.m_tagSets.push_back( m_currentTagSet );
1792 break;
1793 }
1794 }
1795 virtual void endParse() {
1796 if( !m_currentTagSet.empty() )
1797 m_exp.m_tagSets.push_back( m_currentTagSet );
1798 }
1799
Phil Nash8defc712013-04-24 19:10:02 +01001800 TagExpressionParser& operator=(TagExpressionParser const&);
Phil Nashe0a40e22012-11-01 08:28:26 +00001801
Phil Nash67ec8702012-09-26 18:38:26 +01001802 bool m_isNegated;
1803 TagSet m_currentTagSet;
1804 TagExpression& m_exp;
1805 };
1806
1807} // end namespace Catch
1808
Phil Nasha70fbe32012-08-31 08:10:36 +01001809#include <string>
1810#include <vector>
1811
1812namespace Catch {
1813
1814 struct IfFilterMatches{ enum DoWhat {
Phil Nashe2d215e2012-09-07 17:52:35 +01001815 AutoDetectBehaviour,
Phil Nasha70fbe32012-08-31 08:10:36 +01001816 IncludeTests,
1817 ExcludeTests
1818 }; };
1819
1820 class TestCaseFilter {
1821 enum WildcardPosition {
1822 NoWildcard = 0,
1823 WildcardAtStart = 1,
1824 WildcardAtEnd = 2,
1825 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
1826 };
1827
1828 public:
Phil Nash8defc712013-04-24 19:10:02 +01001829 TestCaseFilter( std::string const& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::AutoDetectBehaviour )
Phil Nashdd26e882013-03-25 09:25:31 +00001830 : m_stringToMatch( toLower( testSpec ) ),
Phil Nasha70fbe32012-08-31 08:10:36 +01001831 m_filterType( matchBehaviour ),
1832 m_wildcardPosition( NoWildcard )
1833 {
Phil Nashe2d215e2012-09-07 17:52:35 +01001834 if( m_filterType == IfFilterMatches::AutoDetectBehaviour ) {
1835 if( startsWith( m_stringToMatch, "exclude:" ) ) {
1836 m_stringToMatch = m_stringToMatch.substr( 8 );
1837 m_filterType = IfFilterMatches::ExcludeTests;
1838 }
1839 else if( startsWith( m_stringToMatch, "~" ) ) {
1840 m_stringToMatch = m_stringToMatch.substr( 1 );
1841 m_filterType = IfFilterMatches::ExcludeTests;
1842 }
1843 else {
1844 m_filterType = IfFilterMatches::IncludeTests;
1845 }
1846 }
1847
Phil Nashbd7f7972013-03-21 09:00:24 +00001848 if( startsWith( m_stringToMatch, "*" ) ) {
Phil Nasha70fbe32012-08-31 08:10:36 +01001849 m_stringToMatch = m_stringToMatch.substr( 1 );
1850 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtStart );
1851 }
Phil Nashbd7f7972013-03-21 09:00:24 +00001852 if( endsWith( m_stringToMatch, "*" ) ) {
Phil Nasha70fbe32012-08-31 08:10:36 +01001853 m_stringToMatch = m_stringToMatch.substr( 0, m_stringToMatch.size()-1 );
1854 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtEnd );
1855 }
1856 }
1857
1858 IfFilterMatches::DoWhat getFilterType() const {
1859 return m_filterType;
1860 }
1861
Phil Nash8defc712013-04-24 19:10:02 +01001862 bool shouldInclude( TestCase const& testCase ) const {
Phil Nasha70fbe32012-08-31 08:10:36 +01001863 return isMatch( testCase ) == (m_filterType == IfFilterMatches::IncludeTests);
1864 }
1865 private:
1866
1867#ifdef __clang__
1868#pragma clang diagnostic push
1869#pragma clang diagnostic ignored "-Wunreachable-code"
1870#endif
1871
Phil Nash8defc712013-04-24 19:10:02 +01001872 bool isMatch( TestCase const& testCase ) const {
Phil Nash6d56d712013-03-12 18:49:37 +00001873 std::string name = testCase.getTestCaseInfo().name;
Phil Nashdd26e882013-03-25 09:25:31 +00001874 toLowerInPlace( name );
Phil Nasha70fbe32012-08-31 08:10:36 +01001875
1876 switch( m_wildcardPosition ) {
1877 case NoWildcard:
1878 return m_stringToMatch == name;
1879 case WildcardAtStart:
1880 return endsWith( name, m_stringToMatch );
1881 case WildcardAtEnd:
1882 return startsWith( name, m_stringToMatch );
1883 case WildcardAtBothEnds:
1884 return contains( name, m_stringToMatch );
1885 }
1886 throw std::logic_error( "Unhandled wildcard type" );
1887 }
1888
1889#ifdef __clang__
1890#pragma clang diagnostic pop
1891#endif
1892
1893 std::string m_stringToMatch;
1894 IfFilterMatches::DoWhat m_filterType;
1895 WildcardPosition m_wildcardPosition;
1896 };
1897
1898 class TestCaseFilters {
1899 public:
Phil Nash8defc712013-04-24 19:10:02 +01001900 TestCaseFilters( std::string const& name ) : m_name( name ) {}
Phil Nasha70fbe32012-08-31 08:10:36 +01001901
1902 std::string getName() const {
1903 return m_name;
1904 }
1905
Phil Nash8defc712013-04-24 19:10:02 +01001906 void addFilter( TestCaseFilter const& filter ) {
Phil Nasha70fbe32012-08-31 08:10:36 +01001907 if( filter.getFilterType() == IfFilterMatches::ExcludeTests )
1908 m_exclusionFilters.push_back( filter );
1909 else
1910 m_inclusionFilters.push_back( filter );
1911 }
1912
Phil Nash8defc712013-04-24 19:10:02 +01001913 void addTags( std::string const& tagPattern ) {
Phil Nash67ec8702012-09-26 18:38:26 +01001914 TagExpression exp;
1915 TagExpressionParser( exp ).parse( tagPattern );
1916
1917 m_tagExpressions.push_back( exp );
1918 }
1919
Phil Nash8defc712013-04-24 19:10:02 +01001920 bool shouldInclude( TestCase const& testCase ) const {
Phil Nash67ec8702012-09-26 18:38:26 +01001921 if( !m_tagExpressions.empty() ) {
1922 std::vector<TagExpression>::const_iterator it = m_tagExpressions.begin();
1923 std::vector<TagExpression>::const_iterator itEnd = m_tagExpressions.end();
1924 for(; it != itEnd; ++it )
1925 if( it->matches( testCase.getTags() ) )
1926 break;
1927 if( it == itEnd )
1928 return false;
1929 }
1930
Phil Nasha70fbe32012-08-31 08:10:36 +01001931 if( !m_inclusionFilters.empty() ) {
1932 std::vector<TestCaseFilter>::const_iterator it = m_inclusionFilters.begin();
1933 std::vector<TestCaseFilter>::const_iterator itEnd = m_inclusionFilters.end();
1934 for(; it != itEnd; ++it )
1935 if( it->shouldInclude( testCase ) )
1936 break;
1937 if( it == itEnd )
1938 return false;
1939 }
Phil Nash67ec8702012-09-26 18:38:26 +01001940 else if( m_exclusionFilters.empty() && m_tagExpressions.empty() ) {
Phil Nashfc1baac2012-09-15 17:53:27 +01001941 return !testCase.isHidden();
1942 }
1943
Phil Nasha70fbe32012-08-31 08:10:36 +01001944 std::vector<TestCaseFilter>::const_iterator it = m_exclusionFilters.begin();
1945 std::vector<TestCaseFilter>::const_iterator itEnd = m_exclusionFilters.end();
1946 for(; it != itEnd; ++it )
1947 if( !it->shouldInclude( testCase ) )
1948 return false;
1949 return true;
1950 }
1951 private:
Phil Nash67ec8702012-09-26 18:38:26 +01001952 std::vector<TagExpression> m_tagExpressions;
Phil Nasha70fbe32012-08-31 08:10:36 +01001953 std::vector<TestCaseFilter> m_inclusionFilters;
1954 std::vector<TestCaseFilter> m_exclusionFilters;
1955 std::string m_name;
1956 };
1957
1958}
1959
1960// #included from: catch_interfaces_config.h
1961#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
1962
Phil Nash786959d2013-06-07 19:07:50 +01001963#include <iostream>
1964#include <string>
1965
Phil Nasha70fbe32012-08-31 08:10:36 +01001966namespace Catch {
1967
Phil Nashaa7123b2013-08-15 19:01:00 +01001968 struct Verbosity { enum Level {
1969 NoOutput = 0,
1970 Quiet,
1971 Normal
1972 }; };
1973
1974 struct WarnAbout { enum What {
1975 Nothing = 0x00,
1976 NoAssertions = 0x01
1977 }; };
1978
1979 struct ShowDurations { enum OrNot {
1980 DefaultForReporter,
1981 Always,
1982 Never
1983 }; };
1984
Phil Nash786959d2013-06-07 19:07:50 +01001985 struct IConfig : IShared {
Phil Nasha70fbe32012-08-31 08:10:36 +01001986
1987 virtual ~IConfig();
1988
1989 virtual bool allowThrows() const = 0;
Phil Nash786959d2013-06-07 19:07:50 +01001990 virtual std::ostream& stream() const = 0;
1991 virtual std::string name() const = 0;
1992 virtual bool includeSuccessfulResults() const = 0;
1993 virtual bool shouldDebugBreak() const = 0;
1994 virtual bool warnAboutMissingAssertions() const = 0;
1995 virtual int abortAfter() const = 0;
Phil Nashaa7123b2013-08-15 19:01:00 +01001996 virtual ShowDurations::OrNot showDurations() const = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +01001997 };
1998}
1999
Phil Nash67ec8702012-09-26 18:38:26 +01002000// #included from: catch_stream.hpp
2001#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
2002
Phil Nash9e7e63c2012-09-29 20:54:03 +01002003// #included from: catch_streambuf.h
2004#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
2005
2006#include <streambuf>
2007
2008namespace Catch {
2009
2010 class StreamBufBase : public std::streambuf {
2011 public:
Phil Nashad7445d2013-07-02 08:49:29 +01002012 virtual ~StreamBufBase() throw();
Phil Nash9e7e63c2012-09-29 20:54:03 +01002013 };
2014}
2015
Phil Nash67ec8702012-09-26 18:38:26 +01002016#include <stdexcept>
2017#include <cstdio>
2018
2019namespace Catch {
2020
2021 template<typename WriterF, size_t bufferSize=256>
2022 class StreamBufImpl : public StreamBufBase {
2023 char data[bufferSize];
2024 WriterF m_writer;
2025
2026 public:
2027 StreamBufImpl() {
2028 setp( data, data + sizeof(data) );
2029 }
2030
Phil Nashad7445d2013-07-02 08:49:29 +01002031 ~StreamBufImpl() throw() {
Phil Nash67ec8702012-09-26 18:38:26 +01002032 sync();
2033 }
2034
2035 private:
Phil Nasha04981b2013-03-08 09:30:25 +00002036 int overflow( int c ) {
Phil Nash67ec8702012-09-26 18:38:26 +01002037 sync();
2038
2039 if( c != EOF ) {
2040 if( pbase() == epptr() )
2041 m_writer( std::string( 1, static_cast<char>( c ) ) );
2042 else
2043 sputc( static_cast<char>( c ) );
2044 }
2045 return 0;
2046 }
2047
Phil Nasha04981b2013-03-08 09:30:25 +00002048 int sync() {
Phil Nash67ec8702012-09-26 18:38:26 +01002049 if( pbase() != pptr() ) {
2050 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
2051 setp( pbase(), epptr() );
2052 }
2053 return 0;
2054 }
2055 };
2056
2057 ///////////////////////////////////////////////////////////////////////////
2058
2059 struct OutputDebugWriter {
2060
Phil Nash8defc712013-04-24 19:10:02 +01002061 void operator()( std::string const&str ) {
Phil Nash67ec8702012-09-26 18:38:26 +01002062 writeToDebugConsole( str );
2063 }
2064 };
2065
2066 class Stream {
2067 public:
2068 Stream()
2069 : streamBuf( NULL ), isOwned( false )
2070 {}
2071
2072 Stream( std::streambuf* _streamBuf, bool _isOwned )
2073 : streamBuf( _streamBuf ), isOwned( _isOwned )
2074 {}
2075
2076 void release() {
2077 if( isOwned ) {
2078 delete streamBuf;
2079 streamBuf = NULL;
2080 isOwned = false;
2081 }
2082 }
2083
2084 std::streambuf* streamBuf;
2085
2086 private:
2087 bool isOwned;
2088 };
2089}
2090
Phil Nasha70fbe32012-08-31 08:10:36 +01002091#include <memory>
2092#include <vector>
2093#include <string>
2094#include <iostream>
2095
Phil Nashe4756452013-01-26 20:18:30 +00002096#ifndef CATCH_CONFIG_CONSOLE_WIDTH
2097#define CATCH_CONFIG_CONSOLE_WIDTH 80
2098#endif
2099
Phil Nasha70fbe32012-08-31 08:10:36 +01002100namespace Catch {
2101
Phil Nasha70fbe32012-08-31 08:10:36 +01002102 struct ConfigData {
2103
Phil Nasha70fbe32012-08-31 08:10:36 +01002104 ConfigData()
Phil Nash786959d2013-06-07 19:07:50 +01002105 : listTests( false ),
2106 listTags( false ),
2107 listReporters( false ),
2108 showSuccessfulTests( false ),
Phil Nasha70fbe32012-08-31 08:10:36 +01002109 shouldDebugBreak( false ),
Phil Nash786959d2013-06-07 19:07:50 +01002110 noThrow( false ),
2111 showHelp( false ),
2112 abortAfter( -1 ),
2113 verbosity( Verbosity::Normal ),
Phil Nashaa7123b2013-08-15 19:01:00 +01002114 warnings( WarnAbout::Nothing ),
2115 showDurations( ShowDurations::DefaultForReporter )
Phil Nasha70fbe32012-08-31 08:10:36 +01002116 {}
2117
Phil Nash786959d2013-06-07 19:07:50 +01002118 bool listTests;
2119 bool listTags;
2120 bool listReporters;
2121
2122 bool showSuccessfulTests;
Phil Nasha70fbe32012-08-31 08:10:36 +01002123 bool shouldDebugBreak;
Phil Nash786959d2013-06-07 19:07:50 +01002124 bool noThrow;
2125 bool showHelp;
2126
2127 int abortAfter;
2128
2129 Verbosity::Level verbosity;
Phil Nasha70fbe32012-08-31 08:10:36 +01002130 WarnAbout::What warnings;
Phil Nashaa7123b2013-08-15 19:01:00 +01002131 ShowDurations::OrNot showDurations;
Phil Nash786959d2013-06-07 19:07:50 +01002132
2133 std::string reporterName;
2134 std::string outputFilename;
2135 std::string name;
2136 std::string processName;
2137
2138 std::vector<std::string> testsOrTags;
Phil Nasha70fbe32012-08-31 08:10:36 +01002139 };
2140
Phil Nash786959d2013-06-07 19:07:50 +01002141 class Config : public SharedImpl<IConfig> {
Phil Nasha70fbe32012-08-31 08:10:36 +01002142 private:
Phil Nash8defc712013-04-24 19:10:02 +01002143 Config( Config const& other );
2144 Config& operator = ( Config const& other );
Phil Nasha70fbe32012-08-31 08:10:36 +01002145 virtual void dummy();
2146 public:
2147
2148 Config()
Phil Nash67ec8702012-09-26 18:38:26 +01002149 : m_os( std::cout.rdbuf() )
Phil Nasha70fbe32012-08-31 08:10:36 +01002150 {}
2151
Phil Nash8defc712013-04-24 19:10:02 +01002152 Config( ConfigData const& data )
Phil Nasha70fbe32012-08-31 08:10:36 +01002153 : m_data( data ),
Phil Nasha70fbe32012-08-31 08:10:36 +01002154 m_os( std::cout.rdbuf() )
Phil Nash786959d2013-06-07 19:07:50 +01002155 {
2156 if( !data.testsOrTags.empty() ) {
2157 std::string groupName;
2158 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) {
2159 if( i != 0 )
2160 groupName += " ";
2161 groupName += data.testsOrTags[i];
2162 }
2163 TestCaseFilters filters( groupName );
2164 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) {
2165 std::string filter = data.testsOrTags[i];
2166 if( startsWith( filter, "[" ) || startsWith( filter, "~[" ) )
2167 filters.addTags( filter );
2168 else
2169 filters.addFilter( TestCaseFilter( filter ) );
2170 }
2171 m_filterSets.push_back( filters );
2172 }
2173 }
Phil Nasha70fbe32012-08-31 08:10:36 +01002174
2175 virtual ~Config() {
2176 m_os.rdbuf( std::cout.rdbuf() );
Phil Nash67ec8702012-09-26 18:38:26 +01002177 m_stream.release();
Phil Nasha70fbe32012-08-31 08:10:36 +01002178 }
2179
Phil Nash8defc712013-04-24 19:10:02 +01002180 void setFilename( std::string const& filename ) {
Phil Nasha70fbe32012-08-31 08:10:36 +01002181 m_data.outputFilename = filename;
2182 }
2183
Phil Nash8defc712013-04-24 19:10:02 +01002184 std::string const& getFilename() const {
Phil Nasha70fbe32012-08-31 08:10:36 +01002185 return m_data.outputFilename ;
2186 }
2187
Phil Nash786959d2013-06-07 19:07:50 +01002188 bool listTests() const { return m_data.listTests; }
2189 bool listTags() const { return m_data.listTags; }
2190 bool listReporters() const { return m_data.listReporters; }
Phil Nasha70fbe32012-08-31 08:10:36 +01002191
Phil Nash786959d2013-06-07 19:07:50 +01002192 std::string getProcessName() const {
2193 return m_data.processName;
Phil Nasha70fbe32012-08-31 08:10:36 +01002194 }
2195
2196 bool shouldDebugBreak() const {
2197 return m_data.shouldDebugBreak;
2198 }
2199
Phil Nasha70fbe32012-08-31 08:10:36 +01002200 void setStreamBuf( std::streambuf* buf ) {
2201 m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
2202 }
2203
Phil Nash8defc712013-04-24 19:10:02 +01002204 void useStream( std::string const& streamName ) {
Phil Nash67ec8702012-09-26 18:38:26 +01002205 Stream stream = createStream( streamName );
2206 setStreamBuf( stream.streamBuf );
2207 m_stream.release();
2208 m_stream = stream;
Phil Nasha70fbe32012-08-31 08:10:36 +01002209 }
2210
Phil Nash786959d2013-06-07 19:07:50 +01002211 std::string getReporterName() const { return m_data.reporterName; }
2212
Phil Nash8defc712013-04-24 19:10:02 +01002213 void addTestSpec( std::string const& testSpec ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01002214 TestCaseFilters filters( testSpec );
2215 filters.addFilter( TestCaseFilter( testSpec ) );
Phil Nash786959d2013-06-07 19:07:50 +01002216 m_filterSets.push_back( filters );
Phil Nashe2d215e2012-09-07 17:52:35 +01002217 }
2218
Phil Nash786959d2013-06-07 19:07:50 +01002219 int abortAfter() const {
2220 return m_data.abortAfter;
Phil Nasha70fbe32012-08-31 08:10:36 +01002221 }
2222
Phil Nash786959d2013-06-07 19:07:50 +01002223 std::vector<TestCaseFilters> const& filters() const {
2224 return m_filterSets;
Phil Nasha70fbe32012-08-31 08:10:36 +01002225 }
2226
Phil Nash786959d2013-06-07 19:07:50 +01002227 bool showHelp() const { return m_data.showHelp; }
Phil Nasha70fbe32012-08-31 08:10:36 +01002228
Phil Nash786959d2013-06-07 19:07:50 +01002229 // IConfig interface
2230 virtual bool allowThrows() const { return !m_data.noThrow; }
2231 virtual std::ostream& stream() const { return m_os; }
2232 virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
2233 virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
Phil Nashaa7123b2013-08-15 19:01:00 +01002234 virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
2235 virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
Phil Nasha70fbe32012-08-31 08:10:36 +01002236
2237 private:
2238 ConfigData m_data;
2239
Phil Nash67ec8702012-09-26 18:38:26 +01002240 Stream m_stream;
Phil Nasha70fbe32012-08-31 08:10:36 +01002241 mutable std::ostream m_os;
Phil Nash786959d2013-06-07 19:07:50 +01002242 std::vector<TestCaseFilters> m_filterSets;
Phil Nasha70fbe32012-08-31 08:10:36 +01002243 };
2244
2245} // end namespace Catch
2246
Phil Nashff03cdf2012-12-06 08:44:51 +00002247// #included from: catch_option.hpp
2248#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
2249
2250namespace Catch {
2251
2252 // An optional type
2253 template<typename T>
2254 class Option {
2255 public:
2256 Option() : nullableValue( NULL ) {}
2257 Option( T const& _value )
2258 : nullableValue( new( storage ) T( _value ) )
2259 {}
2260 Option( Option const& _other )
2261 : nullableValue( _other ? new( storage ) T( *_other ) : NULL )
2262 {}
2263
2264 ~Option() {
2265 reset();
2266 }
2267
2268 Option& operator= ( Option const& _other ) {
2269 reset();
2270 if( _other )
2271 nullableValue = new( storage ) T( *_other );
2272 return *this;
2273 }
Phil Nash8a52a392013-07-25 08:12:03 +01002274 Option& operator = ( T const& _value ) {
2275 reset();
2276 nullableValue = new( storage ) T( _value );
2277 return *this;
2278 }
Phil Nashff03cdf2012-12-06 08:44:51 +00002279
2280 void reset() {
2281 if( nullableValue )
2282 nullableValue->~T();
2283 nullableValue = NULL;
2284 }
Phil Nash8a52a392013-07-25 08:12:03 +01002285
Phil Nashff03cdf2012-12-06 08:44:51 +00002286 T& operator*() { return *nullableValue; }
Phil Nash8defc712013-04-24 19:10:02 +01002287 T const& operator*() const { return *nullableValue; }
Phil Nashff03cdf2012-12-06 08:44:51 +00002288 T* operator->() { return nullableValue; }
2289 const T* operator->() const { return nullableValue; }
2290
Phil Nash786959d2013-06-07 19:07:50 +01002291 T valueOr( T const& defaultValue ) const {
2292 return nullableValue ? *nullableValue : defaultValue;
2293 }
2294
Phil Nashff03cdf2012-12-06 08:44:51 +00002295 bool some() const { return nullableValue != NULL; }
2296 bool none() const { return nullableValue == NULL; }
2297
2298 bool operator !() const { return nullableValue == NULL; }
2299 operator SafeBool::type() const {
2300 return SafeBool::makeSafe( some() );
2301 }
2302
2303 private:
2304 T* nullableValue;
2305 char storage[sizeof(T)];
Phil Nasha70fbe32012-08-31 08:10:36 +01002306 };
2307
2308} // end namespace Catch
2309
2310#include <string>
2311#include <ostream>
2312#include <map>
Phil Nash357d6542013-08-16 08:01:16 +01002313#include <assert.h>
Phil Nasha70fbe32012-08-31 08:10:36 +01002314
2315namespace Catch
2316{
Phil Nasha1fbfea2012-12-01 23:57:18 +00002317 struct ReporterConfig {
Phil Nash786959d2013-06-07 19:07:50 +01002318 explicit ReporterConfig( Ptr<IConfig> const& _fullConfig )
2319 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
2320
2321 ReporterConfig( Ptr<IConfig> const& _fullConfig, std::ostream& _stream )
Phil Nasha1fbfea2012-12-01 23:57:18 +00002322 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
2323
Phil Nash786959d2013-06-07 19:07:50 +01002324 std::ostream& stream() const { return *m_stream; }
2325 Ptr<IConfig> fullConfig() const { return m_fullConfig; }
Phil Nasha1fbfea2012-12-01 23:57:18 +00002326
2327 private:
2328 std::ostream* m_stream;
Phil Nash786959d2013-06-07 19:07:50 +01002329 Ptr<IConfig> m_fullConfig;
Phil Nasha1fbfea2012-12-01 23:57:18 +00002330 };
2331
2332 struct ReporterPreferences {
2333 ReporterPreferences()
2334 : shouldRedirectStdOut( false )
Phil Nasha70fbe32012-08-31 08:10:36 +01002335 {}
2336
Phil Nasha1fbfea2012-12-01 23:57:18 +00002337 bool shouldRedirectStdOut;
2338 };
2339
Phil Nashaa7123b2013-08-15 19:01:00 +01002340 template<typename T>
2341 struct LazyStat : Option<T> {
2342 LazyStat() : used( false ) {}
2343 LazyStat& operator=( T const& _value ) {
2344 Option<T>::operator=( _value );
2345 used = false;
2346 return *this;
2347 }
2348 void reset() {
2349 Option<T>::reset();
2350 used = false;
2351 }
2352 bool used;
2353 };
2354
Phil Nasha1fbfea2012-12-01 23:57:18 +00002355 struct TestRunInfo {
2356 TestRunInfo( std::string const& _name ) : name( _name ) {}
2357 std::string name;
2358 };
2359 struct GroupInfo {
Phil Nash2e7d9662013-01-16 09:44:43 +00002360 GroupInfo( std::string const& _name,
2361 std::size_t _groupIndex,
2362 std::size_t _groupsCount )
2363 : name( _name ),
2364 groupIndex( _groupIndex ),
2365 groupsCounts( _groupsCount )
Phil Nash799ecf92012-09-24 08:30:13 +01002366 {}
2367
Phil Nasha70fbe32012-08-31 08:10:36 +01002368 std::string name;
Phil Nash2e7d9662013-01-16 09:44:43 +00002369 std::size_t groupIndex;
2370 std::size_t groupsCounts;
Phil Nasha70fbe32012-08-31 08:10:36 +01002371 };
2372
Phil Nasha1fbfea2012-12-01 23:57:18 +00002373 struct SectionInfo {
2374 SectionInfo( std::string const& _name,
2375 std::string const& _description,
2376 SourceLineInfo const& _lineInfo )
2377 : name( _name ),
2378 description( _description ),
2379 lineInfo( _lineInfo )
Phil Nasha70fbe32012-08-31 08:10:36 +01002380 {}
Phil Nasha70fbe32012-08-31 08:10:36 +01002381
Phil Nasha70fbe32012-08-31 08:10:36 +01002382 std::string name;
Phil Nasha1fbfea2012-12-01 23:57:18 +00002383 std::string description;
2384 SourceLineInfo lineInfo;
Phil Nasha70fbe32012-08-31 08:10:36 +01002385 };
2386
Phil Nash2e7d9662013-01-16 09:44:43 +00002387 struct AssertionStats {
Phil Nasha1fbfea2012-12-01 23:57:18 +00002388 AssertionStats( AssertionResult const& _assertionResult,
Phil Nasha2773812013-02-02 20:37:58 +00002389 std::vector<MessageInfo> const& _infoMessages,
Phil Nasha1fbfea2012-12-01 23:57:18 +00002390 Totals const& _totals )
2391 : assertionResult( _assertionResult ),
Phil Nasha2773812013-02-02 20:37:58 +00002392 infoMessages( _infoMessages ),
Phil Nasha1fbfea2012-12-01 23:57:18 +00002393 totals( _totals )
Phil Nasha2773812013-02-02 20:37:58 +00002394 {
2395 if( assertionResult.hasMessage() ) {
2396 // Copy message into messages list.
2397 // !TBD This should have been done earlier, somewhere
2398 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
2399 builder << assertionResult.getMessage();
Phil Nashb5fd5a62013-06-28 17:09:57 +01002400 builder.m_info.message = builder.m_stream.str();
2401
2402 infoMessages.push_back( builder.m_info );
Phil Nasha2773812013-02-02 20:37:58 +00002403 }
2404 }
Phil Nasha1fbfea2012-12-01 23:57:18 +00002405 virtual ~AssertionStats();
Phil Nasha70fbe32012-08-31 08:10:36 +01002406
Phil Nasha1fbfea2012-12-01 23:57:18 +00002407 AssertionResult assertionResult;
Phil Nasha2773812013-02-02 20:37:58 +00002408 std::vector<MessageInfo> infoMessages;
Phil Nasha1fbfea2012-12-01 23:57:18 +00002409 Totals totals;
2410 };
2411
Phil Nash2e7d9662013-01-16 09:44:43 +00002412 struct SectionStats {
Phil Nasha1fbfea2012-12-01 23:57:18 +00002413 SectionStats( SectionInfo const& _sectionInfo,
2414 Counts const& _assertions,
Phil Nashaa7123b2013-08-15 19:01:00 +01002415 double _durationInSeconds,
Phil Nasha1fbfea2012-12-01 23:57:18 +00002416 bool _missingAssertions )
2417 : sectionInfo( _sectionInfo ),
2418 assertions( _assertions ),
Phil Nashaa7123b2013-08-15 19:01:00 +01002419 durationInSeconds( _durationInSeconds ),
Phil Nasha1fbfea2012-12-01 23:57:18 +00002420 missingAssertions( _missingAssertions )
2421 {}
2422 virtual ~SectionStats();
2423
2424 SectionInfo sectionInfo;
2425 Counts assertions;
Phil Nashaa7123b2013-08-15 19:01:00 +01002426 double durationInSeconds;
Phil Nasha1fbfea2012-12-01 23:57:18 +00002427 bool missingAssertions;
2428 };
2429
Phil Nash2e7d9662013-01-16 09:44:43 +00002430 struct TestCaseStats {
Phil Nasha1fbfea2012-12-01 23:57:18 +00002431 TestCaseStats( TestCaseInfo const& _testInfo,
2432 Totals const& _totals,
2433 std::string const& _stdOut,
2434 std::string const& _stdErr,
Phil Nasha1fbfea2012-12-01 23:57:18 +00002435 bool _aborting )
2436 : testInfo( _testInfo ),
2437 totals( _totals ),
2438 stdOut( _stdOut ),
2439 stdErr( _stdErr ),
Phil Nasha1fbfea2012-12-01 23:57:18 +00002440 aborting( _aborting )
2441 {}
2442 virtual ~TestCaseStats();
2443
2444 TestCaseInfo testInfo;
2445 Totals totals;
2446 std::string stdOut;
2447 std::string stdErr;
Phil Nasha1fbfea2012-12-01 23:57:18 +00002448 bool aborting;
2449 };
2450
Phil Nash2e7d9662013-01-16 09:44:43 +00002451 struct TestGroupStats {
Phil Nasha1fbfea2012-12-01 23:57:18 +00002452 TestGroupStats( GroupInfo const& _groupInfo,
2453 Totals const& _totals,
2454 bool _aborting )
2455 : groupInfo( _groupInfo ),
2456 totals( _totals ),
2457 aborting( _aborting )
2458 {}
Phil Nash2e7d9662013-01-16 09:44:43 +00002459 TestGroupStats( GroupInfo const& _groupInfo )
2460 : groupInfo( _groupInfo ),
2461 aborting( false )
2462 {}
Phil Nasha1fbfea2012-12-01 23:57:18 +00002463 virtual ~TestGroupStats();
2464
2465 GroupInfo groupInfo;
2466 Totals totals;
2467 bool aborting;
2468 };
2469
Phil Nash2e7d9662013-01-16 09:44:43 +00002470 struct TestRunStats {
Phil Nasha1fbfea2012-12-01 23:57:18 +00002471 TestRunStats( TestRunInfo const& _runInfo,
2472 Totals const& _totals,
2473 bool _aborting )
2474 : runInfo( _runInfo ),
2475 totals( _totals ),
2476 aborting( _aborting )
2477 {}
Phil Nash2e7d9662013-01-16 09:44:43 +00002478 TestRunStats( TestRunStats const& _other )
2479 : runInfo( _other.runInfo ),
2480 totals( _other.totals ),
2481 aborting( _other.aborting )
2482 {}
Phil Nasha1fbfea2012-12-01 23:57:18 +00002483 virtual ~TestRunStats();
2484
2485 TestRunInfo runInfo;
2486 Totals totals;
2487 bool aborting;
2488 };
2489
Phil Nasha1fbfea2012-12-01 23:57:18 +00002490 struct IStreamingReporter : IShared {
2491 virtual ~IStreamingReporter();
Phil Nashff03cdf2012-12-06 08:44:51 +00002492
Phil Nash2e7d9662013-01-16 09:44:43 +00002493 // Implementing class must also provide the following static method:
Phil Nashff03cdf2012-12-06 08:44:51 +00002494 // static std::string getDescription();
2495
Phil Nasha1fbfea2012-12-01 23:57:18 +00002496 virtual ReporterPreferences getPreferences() const = 0;
2497
Phil Nash37186a12013-03-13 12:19:30 +00002498 virtual void noMatchingTestCases( std::string const& spec ) = 0;
2499
Phil Nasha1fbfea2012-12-01 23:57:18 +00002500 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
2501 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
2502
2503 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
2504 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
2505
2506 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
2507
Phil Nashb5fd5a62013-06-28 17:09:57 +01002508 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
Phil Nash2e7d9662013-01-16 09:44:43 +00002509 virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
2510 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
2511 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
2512 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
Phil Nasha1fbfea2012-12-01 23:57:18 +00002513 };
Phil Nashff03cdf2012-12-06 08:44:51 +00002514
Phil Nash2e7d9662013-01-16 09:44:43 +00002515 struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
2516
2517 StreamingReporterBase( ReporterConfig const& _config )
Phil Nash786959d2013-06-07 19:07:50 +01002518 : m_config( _config.fullConfig() ),
Phil Nashbcad0932012-12-10 08:54:57 +00002519 stream( _config.stream() )
Phil Nashff03cdf2012-12-06 08:44:51 +00002520 {}
2521
Phil Nash2e7d9662013-01-16 09:44:43 +00002522 virtual ~StreamingReporterBase();
Phil Nashff03cdf2012-12-06 08:44:51 +00002523
Phil Nash37186a12013-03-13 12:19:30 +00002524 virtual void noMatchingTestCases( std::string const& ) {}
2525
Phil Nashff03cdf2012-12-06 08:44:51 +00002526 virtual void testRunStarting( TestRunInfo const& _testRunInfo ) {
Phil Nashaa7123b2013-08-15 19:01:00 +01002527 currentTestRunInfo = _testRunInfo;
Phil Nashff03cdf2012-12-06 08:44:51 +00002528 }
2529 virtual void testGroupStarting( GroupInfo const& _groupInfo ) {
Phil Nashaa7123b2013-08-15 19:01:00 +01002530 currentGroupInfo = _groupInfo;
Phil Nashff03cdf2012-12-06 08:44:51 +00002531 }
2532
2533 virtual void testCaseStarting( TestCaseInfo const& _testInfo ) {
Phil Nashaa7123b2013-08-15 19:01:00 +01002534 currentTestCaseInfo = _testInfo;
Phil Nashff03cdf2012-12-06 08:44:51 +00002535 }
2536 virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
Phil Nashaa7123b2013-08-15 19:01:00 +01002537 m_sectionStack.push_back( _sectionInfo );
Phil Nashff03cdf2012-12-06 08:44:51 +00002538 }
2539
Phil Nash2e7d9662013-01-16 09:44:43 +00002540 virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) {
Phil Nashaa7123b2013-08-15 19:01:00 +01002541 m_sectionStack.pop_back();
Phil Nashff03cdf2012-12-06 08:44:51 +00002542 }
Phil Nash2e7d9662013-01-16 09:44:43 +00002543 virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) {
Phil Nashaa7123b2013-08-15 19:01:00 +01002544 currentTestCaseInfo.reset();
2545 assert( m_sectionStack.empty() );
Phil Nashff03cdf2012-12-06 08:44:51 +00002546 }
Phil Nash2e7d9662013-01-16 09:44:43 +00002547 virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) {
Phil Nashaa7123b2013-08-15 19:01:00 +01002548 currentGroupInfo.reset();
Phil Nashff03cdf2012-12-06 08:44:51 +00002549 }
Phil Nash2e7d9662013-01-16 09:44:43 +00002550 virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) {
Phil Nashaa7123b2013-08-15 19:01:00 +01002551 currentTestCaseInfo.reset();
2552 currentGroupInfo.reset();
2553 currentTestRunInfo.reset();
Phil Nashff03cdf2012-12-06 08:44:51 +00002554 }
2555
Phil Nash786959d2013-06-07 19:07:50 +01002556 Ptr<IConfig> m_config;
Phil Nash2e7d9662013-01-16 09:44:43 +00002557 std::ostream& stream;
Phil Nashe4756452013-01-26 20:18:30 +00002558
Phil Nashaa7123b2013-08-15 19:01:00 +01002559 LazyStat<TestRunInfo> currentTestRunInfo;
2560 LazyStat<GroupInfo> currentGroupInfo;
2561 LazyStat<TestCaseInfo> currentTestCaseInfo;
2562
2563 std::vector<SectionInfo> m_sectionStack;
Phil Nash2e7d9662013-01-16 09:44:43 +00002564 };
2565
Phil Nashaa7123b2013-08-15 19:01:00 +01002566 struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
2567 template<typename T, typename ChildNodeT>
2568 struct Node : SharedImpl<> {
2569 explicit Node( T const& _value ) : value( _value ) {}
2570 virtual ~Node() {}
Phil Nash2e7d9662013-01-16 09:44:43 +00002571
Phil Nashaa7123b2013-08-15 19:01:00 +01002572 typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
2573 T value;
2574 ChildNodes children;
2575 };
2576 struct SectionNode : SharedImpl<> {
2577 explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {}
2578 virtual ~SectionNode();
Phil Nash2e7d9662013-01-16 09:44:43 +00002579
Phil Nashaa7123b2013-08-15 19:01:00 +01002580 bool operator == ( SectionNode const& other ) const {
2581 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
2582 }
2583 bool operator == ( Ptr<SectionNode> const& other ) const {
2584 return operator==( *other );
2585 }
Phil Nash2e7d9662013-01-16 09:44:43 +00002586
Phil Nashaa7123b2013-08-15 19:01:00 +01002587 SectionStats stats;
2588 typedef std::vector<Ptr<SectionNode> > ChildSections;
2589 typedef std::vector<AssertionStats> Assertions;
2590 ChildSections childSections;
2591 Assertions assertions;
2592 std::string stdOut;
2593 std::string stdErr;
2594 };
2595 friend bool operator == ( Ptr<SectionNode> const& node, SectionInfo const& other ) {
2596 return node->stats.sectionInfo.lineInfo == other.lineInfo;
2597 }
Phil Nash2e7d9662013-01-16 09:44:43 +00002598
Phil Nashaa7123b2013-08-15 19:01:00 +01002599 typedef Node<TestCaseStats, SectionNode> TestCaseNode;
2600 typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
2601 typedef Node<TestRunStats, TestGroupNode> TestRunNode;
2602
2603 CumulativeReporterBase( ReporterConfig const& _config )
2604 : m_config( _config.fullConfig() ),
2605 stream( _config.stream() )
2606 {}
2607 ~CumulativeReporterBase();
2608
2609 virtual void testRunStarting( TestRunInfo const& ) {}
2610 virtual void testGroupStarting( GroupInfo const& ) {}
2611
2612 virtual void testCaseStarting( TestCaseInfo const& ) {}
2613
2614 virtual void sectionStarting( SectionInfo const& sectionInfo ) {
2615 SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
2616 Ptr<SectionNode> node;
2617 if( m_sectionStack.empty() ) {
2618 if( !m_rootSection )
2619 m_rootSection = new SectionNode( incompleteStats );
2620 node = m_rootSection;
2621 }
2622 else {
2623 SectionNode& parentNode = *m_sectionStack.back();
2624 SectionNode::ChildSections::const_iterator it =
2625 std::find( parentNode.childSections.begin(), parentNode.childSections.end(), sectionInfo );
2626 if( it == parentNode.childSections.end() ) {
2627 node = new SectionNode( incompleteStats );
2628 parentNode.childSections.push_back( node );
2629 }
2630 else
2631 node = *it;
2632 }
2633 m_sectionStack.push_back( node );
2634 m_deepestSection = node;
2635 }
2636
2637 virtual void assertionStarting( AssertionInfo const& ) {}
2638
2639 virtual bool assertionEnded( AssertionStats const& assertionStats ) {
2640 assert( !m_sectionStack.empty() );
2641 SectionNode& sectionNode = *m_sectionStack.back();
2642 sectionNode.assertions.push_back( assertionStats );
2643 return true;
2644 }
2645 virtual void sectionEnded( SectionStats const& sectionStats ) {
2646 assert( !m_sectionStack.empty() );
2647 SectionNode& node = *m_sectionStack.back();
2648 node.stats = sectionStats;
2649 m_sectionStack.pop_back();
2650 }
2651 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
2652 Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
2653 assert( m_sectionStack.size() == 0 );
2654 node->children.push_back( m_rootSection );
2655 m_testCases.push_back( node );
2656 m_rootSection.reset();
2657
2658 assert( m_deepestSection );
2659 m_deepestSection->stdOut = testCaseStats.stdOut;
2660 m_deepestSection->stdErr = testCaseStats.stdErr;
2661 }
2662 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
2663 Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
2664 node->children.swap( m_testCases );
2665 m_testGroups.push_back( node );
2666 }
2667 virtual void testRunEnded( TestRunStats const& testRunStats ) {
2668 Ptr<TestRunNode> node = new TestRunNode( testRunStats );
2669 node->children.swap( m_testGroups );
2670 m_testRuns.push_back( node );
2671 testRunEnded();
2672 }
2673 virtual void testRunEnded() = 0;
2674
2675 Ptr<IConfig> m_config;
2676 std::ostream& stream;
2677 std::vector<AssertionStats> m_assertions;
2678 std::vector<std::vector<Ptr<SectionNode> > > m_sections;
2679 std::vector<Ptr<TestCaseNode> > m_testCases;
2680 std::vector<Ptr<TestGroupNode> > m_testGroups;
2681
2682 std::vector<Ptr<TestRunNode> > m_testRuns;
2683
2684 Ptr<SectionNode> m_rootSection;
2685 Ptr<SectionNode> m_deepestSection;
2686 std::vector<Ptr<SectionNode> > m_sectionStack;
2687
Phil Nash2e7d9662013-01-16 09:44:43 +00002688 };
2689
Phil Nasha1fbfea2012-12-01 23:57:18 +00002690 // Deprecated
Phil Nasha70fbe32012-08-31 08:10:36 +01002691 struct IReporter : IShared {
2692 virtual ~IReporter();
Phil Nashce612bf2012-11-01 08:27:09 +00002693
Phil Nasha70fbe32012-08-31 08:10:36 +01002694 virtual bool shouldRedirectStdout() const = 0;
Phil Nashce612bf2012-11-01 08:27:09 +00002695
Phil Nasha70fbe32012-08-31 08:10:36 +01002696 virtual void StartTesting() = 0;
Phil Nasha1fbfea2012-12-01 23:57:18 +00002697 virtual void EndTesting( Totals const& totals ) = 0;
2698 virtual void StartGroup( std::string const& groupName ) = 0;
2699 virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
2700 virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
2701 virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
2702 virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
Phil Nash8defc712013-04-24 19:10:02 +01002703 virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
Phil Nasha1fbfea2012-12-01 23:57:18 +00002704 virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
2705 virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +01002706 virtual void Aborted() = 0;
Phil Nash8defc712013-04-24 19:10:02 +01002707 virtual void Result( AssertionResult const& result ) = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +01002708 };
2709
2710 struct IReporterFactory {
2711 virtual ~IReporterFactory();
Phil Nasha1fbfea2012-12-01 23:57:18 +00002712 virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +01002713 virtual std::string getDescription() const = 0;
2714 };
2715
2716 struct IReporterRegistry {
2717 typedef std::map<std::string, IReporterFactory*> FactoryMap;
2718
2719 virtual ~IReporterRegistry();
Phil Nash786959d2013-06-07 19:07:50 +01002720 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const = 0;
Phil Nash8defc712013-04-24 19:10:02 +01002721 virtual FactoryMap const& getFactories() const = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +01002722 };
2723
Phil Nasha1fbfea2012-12-01 23:57:18 +00002724 inline std::string trim( std::string const& str ) {
Phil Nashaa7123b2013-08-15 19:01:00 +01002725 static char const* whitespaceChars = "\n\r\t ";
2726 std::string::size_type start = str.find_first_not_of( whitespaceChars );
2727 std::string::size_type end = str.find_last_not_of( whitespaceChars );
Phil Nasha70fbe32012-08-31 08:10:36 +01002728
2729 return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
2730 }
2731}
2732
Phil Nash3b80af72012-08-09 07:47:30 +01002733#include <vector>
Phil Nash3b80af72012-08-09 07:47:30 +01002734
2735namespace Catch {
2736
Phil Nasha1fbfea2012-12-01 23:57:18 +00002737 class TestCase;
Phil Nash3b80af72012-08-09 07:47:30 +01002738 struct ITestCaseRegistry;
2739 struct IExceptionTranslatorRegistry;
2740 struct IExceptionTranslator;
2741
2742 struct IRegistryHub {
Phil Nasha695eb92012-08-13 07:46:10 +01002743 virtual ~IRegistryHub();
Phil Nash3b80af72012-08-09 07:47:30 +01002744
Phil Nash8defc712013-04-24 19:10:02 +01002745 virtual IReporterRegistry const& getReporterRegistry() const = 0;
2746 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
Phil Nash3b80af72012-08-09 07:47:30 +01002747 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
2748 };
2749
2750 struct IMutableRegistryHub {
Phil Nasha695eb92012-08-13 07:46:10 +01002751 virtual ~IMutableRegistryHub();
Phil Nash8defc712013-04-24 19:10:02 +01002752 virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0;
2753 virtual void registerTest( TestCase const& testInfo ) = 0;
Phil Nash3b80af72012-08-09 07:47:30 +01002754 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
2755 };
2756
2757 IRegistryHub& getRegistryHub();
2758 IMutableRegistryHub& getMutableRegistryHub();
2759 void cleanUp();
Phil Nashce612bf2012-11-01 08:27:09 +00002760 std::string translateActiveException();
2761
Phil Nash3b80af72012-08-09 07:47:30 +01002762}
2763
Phil Nashce612bf2012-11-01 08:27:09 +00002764#include <ostream>
2765
2766namespace Catch {
2767
2768 inline IResultCapture& getResultCapture() {
2769 return getCurrentContext().getResultCapture();
2770 }
2771
2772 template<typename MatcherT>
Phil Nash8defc712013-04-24 19:10:02 +01002773 ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher,
2774 std::string const& matcherCallAsString ) {
Phil Nashce612bf2012-11-01 08:27:09 +00002775 std::string matcherAsString = matcher.toString();
2776 if( matcherAsString == "{?}" )
2777 matcherAsString = matcherCallAsString;
2778 return ExpressionResultBuilder()
2779 .setRhs( matcherAsString )
2780 .setOp( "matches" );
2781 }
2782
2783 template<typename MatcherT, typename ArgT>
Phil Nash8defc712013-04-24 19:10:02 +01002784 ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher,
2785 ArgT const& arg,
2786 std::string const& matcherCallAsString ) {
Phil Nashce612bf2012-11-01 08:27:09 +00002787 return expressionResultBuilderFromMatcher( matcher, matcherCallAsString )
2788 .setLhs( Catch::toString( arg ) )
2789 .setResultType( matcher.match( arg ) );
2790 }
2791
2792 template<typename MatcherT, typename ArgT>
Phil Nash8defc712013-04-24 19:10:02 +01002793 ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher,
Phil Nashce612bf2012-11-01 08:27:09 +00002794 ArgT* arg,
Phil Nash8defc712013-04-24 19:10:02 +01002795 std::string const& matcherCallAsString ) {
Phil Nashce612bf2012-11-01 08:27:09 +00002796 return expressionResultBuilderFromMatcher( matcher, matcherCallAsString )
2797 .setLhs( Catch::toString( arg ) )
2798 .setResultType( matcher.match( arg ) );
2799 }
2800
2801struct TestFailureException{};
2802
Phil Nashce612bf2012-11-01 08:27:09 +00002803} // end namespace Catch
2804
2805///////////////////////////////////////////////////////////////////////////////
2806#define INTERNAL_CATCH_ASSERTIONINFO_NAME INTERNAL_CATCH_UNIQUE_NAME( __assertionInfo )
2807
2808///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002809#define INTERNAL_CATCH_ACCEPT_EXPR( evaluatedExpr, resultDisposition, originalExpr ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002810 if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, INTERNAL_CATCH_ASSERTIONINFO_NAME ) ) { \
2811 if( internal_catch_action & Catch::ResultAction::Debug ) BreakIntoDebugger(); \
2812 if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \
Phil Nash90a35942012-11-13 22:04:29 +00002813 if( !Catch::shouldContinueOnFailure( resultDisposition ) ) throw Catch::TestFailureException(); \
Phil Nash3df6c0d2013-03-11 18:38:29 +00002814 Catch::isTrue( false && originalExpr ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002815 }
2816
2817///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002818#define INTERNAL_CATCH_ACCEPT_INFO( expr, macroName, resultDisposition ) \
2819 Catch::AssertionInfo INTERNAL_CATCH_ASSERTIONINFO_NAME( macroName, CATCH_INTERNAL_LINEINFO, expr, resultDisposition );
Phil Nashce612bf2012-11-01 08:27:09 +00002820
2821///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002822#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002823 do { \
Phil Nash90a35942012-11-13 22:04:29 +00002824 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002825 try { \
Phil Nash90a35942012-11-13 22:04:29 +00002826 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002827 } catch( Catch::TestFailureException& ) { \
2828 throw; \
2829 } catch( ... ) { \
Phil Nash90a35942012-11-13 22:04:29 +00002830 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \
2831 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, expr ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002832 } \
2833 } while( Catch::isTrue( false ) )
2834
2835///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002836#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
2837 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2838 if( Catch::getResultCapture().getLastResult()->succeeded() )
Phil Nashce612bf2012-11-01 08:27:09 +00002839
2840///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002841#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
2842 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2843 if( !Catch::getResultCapture().getLastResult()->succeeded() )
Phil Nashce612bf2012-11-01 08:27:09 +00002844
2845///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002846#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002847 do { \
Phil Nash90a35942012-11-13 22:04:29 +00002848 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002849 try { \
2850 expr; \
Phil Nash90a35942012-11-13 22:04:29 +00002851 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002852 } \
2853 catch( ... ) { \
Phil Nash90a35942012-11-13 22:04:29 +00002854 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), resultDisposition, false ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002855 } \
2856} while( Catch::isTrue( false ) )
2857
2858///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002859#define INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002860 try { \
2861 if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \
2862 expr; \
Phil Nash90a35942012-11-13 22:04:29 +00002863 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::DidntThrowException ), resultDisposition, false ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002864 } \
2865 } \
2866 catch( Catch::TestFailureException& ) { \
2867 throw; \
2868 } \
2869 catch( exceptionType ) { \
Phil Nash90a35942012-11-13 22:04:29 +00002870 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002871 }
2872
2873///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002874#define INTERNAL_CATCH_THROWS( expr, exceptionType, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002875 do { \
Phil Nash90a35942012-11-13 22:04:29 +00002876 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
2877 INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002878 } while( Catch::isTrue( false ) )
2879
2880///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002881#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002882 do { \
Phil Nash90a35942012-11-13 22:04:29 +00002883 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
2884 INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002885 catch( ... ) { \
Phil Nash90a35942012-11-13 22:04:29 +00002886 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
2887 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002888 } \
2889 } while( Catch::isTrue( false ) )
2890
2891///////////////////////////////////////////////////////////////////////////////
Phil Nasha2773812013-02-02 20:37:58 +00002892#define INTERNAL_CATCH_MSG( log, messageType, resultDisposition, macroName ) \
Phil Nash90a35942012-11-13 22:04:29 +00002893 do { \
2894 INTERNAL_CATCH_ACCEPT_INFO( "", macroName, resultDisposition ); \
Phil Nasha2773812013-02-02 20:37:58 +00002895 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << log, resultDisposition, true ) \
Phil Nash90a35942012-11-13 22:04:29 +00002896 } while( Catch::isTrue( false ) )
Phil Nashce612bf2012-11-01 08:27:09 +00002897
2898///////////////////////////////////////////////////////////////////////////////
Phil Nashb5fd5a62013-06-28 17:09:57 +01002899#define INTERNAL_CATCH_INFO( log, macroName ) \
2900 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
Phil Nashce612bf2012-11-01 08:27:09 +00002901
2902///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002903#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002904 do { \
Phil Nash90a35942012-11-13 22:04:29 +00002905 INTERNAL_CATCH_ACCEPT_INFO( #arg " " #matcher, macroName, resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002906 try { \
Phil Nash90a35942012-11-13 22:04:29 +00002907 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002908 } catch( Catch::TestFailureException& ) { \
2909 throw; \
2910 } catch( ... ) { \
Phil Nash90a35942012-11-13 22:04:29 +00002911 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
2912 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002913 } \
2914 } while( Catch::isTrue( false ) )
2915
2916// #included from: internal/catch_section.hpp
2917#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
2918
Phil Nashaa7123b2013-08-15 19:01:00 +01002919// #included from: catch_timer.h
2920#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
2921
Phil Nash04a33642013-08-16 19:09:09 +01002922#ifdef CATCH_PLATFORM_WINDOWS
Phil Nashaa7123b2013-08-15 19:01:00 +01002923typedef unsigned long long uint64_t;
2924#else
2925#include <stdint.h>
2926#endif
2927
2928namespace Catch {
2929
2930 class Timer {
2931 public:
2932 Timer() : m_ticks( 0 ) {}
2933 void start();
2934 unsigned int getElapsedNanoseconds() const;
2935 unsigned int getElapsedMilliseconds() const;
2936 double getElapsedSeconds() const;
2937
2938 private:
2939 uint64_t m_ticks;
2940 };
2941
2942} // namespace Catch
2943
Phil Nashce612bf2012-11-01 08:27:09 +00002944#include <string>
2945
2946namespace Catch {
2947
2948 class Section {
2949 public:
Phil Nash8defc712013-04-24 19:10:02 +01002950 Section( SourceLineInfo const& lineInfo,
2951 std::string const& name,
2952 std::string const& description = "" )
Phil Nasha1fbfea2012-12-01 23:57:18 +00002953 : m_info( name, description, lineInfo ),
2954 m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( m_info, m_assertions ) )
Phil Nashaa7123b2013-08-15 19:01:00 +01002955 {
2956 m_timer.start();
2957 }
Phil Nashce612bf2012-11-01 08:27:09 +00002958
2959 ~Section() {
2960 if( m_sectionIncluded )
Phil Nashaa7123b2013-08-15 19:01:00 +01002961 getCurrentContext().getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() );
Phil Nashce612bf2012-11-01 08:27:09 +00002962 }
2963
2964 // This indicates whether the section should be executed or not
2965 operator bool() {
2966 return m_sectionIncluded;
2967 }
2968
2969 private:
Phil Nasha1fbfea2012-12-01 23:57:18 +00002970 SectionInfo m_info;
Phil Nashce612bf2012-11-01 08:27:09 +00002971
2972 std::string m_name;
2973 Counts m_assertions;
2974 bool m_sectionIncluded;
Phil Nashaa7123b2013-08-15 19:01:00 +01002975 Timer m_timer;
Phil Nashce612bf2012-11-01 08:27:09 +00002976 };
2977
2978} // end namespace Catch
2979
Phil Nash93906752013-03-16 20:21:51 +00002980#ifdef CATCH_CONFIG_VARIADIC_MACROS
2981 #define INTERNAL_CATCH_SECTION( ... ) \
2982 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
2983#else
2984 #define INTERNAL_CATCH_SECTION( name, desc ) \
2985 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, name, desc ) )
2986#endif
Phil Nashce612bf2012-11-01 08:27:09 +00002987
2988// #included from: internal/catch_generators.hpp
2989#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
2990
2991#include <iterator>
2992#include <vector>
2993#include <string>
2994#include <stdlib.h>
2995
2996namespace Catch {
2997
2998template<typename T>
2999struct IGenerator {
3000 virtual ~IGenerator() {}
3001 virtual T getValue( std::size_t index ) const = 0;
3002 virtual std::size_t size () const = 0;
3003};
3004
3005template<typename T>
3006class BetweenGenerator : public IGenerator<T> {
3007public:
3008 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
3009
3010 virtual T getValue( std::size_t index ) const {
Phil Nash2e7d9662013-01-16 09:44:43 +00003011 return m_from+static_cast<int>( index );
Phil Nashce612bf2012-11-01 08:27:09 +00003012 }
3013
3014 virtual std::size_t size() const {
3015 return static_cast<std::size_t>( 1+m_to-m_from );
3016 }
3017
3018private:
3019
3020 T m_from;
3021 T m_to;
3022};
3023
3024template<typename T>
3025class ValuesGenerator : public IGenerator<T> {
3026public:
3027 ValuesGenerator(){}
3028
3029 void add( T value ) {
3030 m_values.push_back( value );
3031 }
3032
3033 virtual T getValue( std::size_t index ) const {
3034 return m_values[index];
3035 }
3036
3037 virtual std::size_t size() const {
3038 return m_values.size();
3039 }
3040
3041private:
3042 std::vector<T> m_values;
3043};
3044
3045template<typename T>
3046class CompositeGenerator {
3047public:
3048 CompositeGenerator() : m_totalSize( 0 ) {}
3049
Phil Nasha04981b2013-03-08 09:30:25 +00003050 // *** Move semantics, similar to auto_ptr ***
Phil Nashce612bf2012-11-01 08:27:09 +00003051 CompositeGenerator( CompositeGenerator& other )
3052 : m_fileInfo( other.m_fileInfo ),
3053 m_totalSize( 0 )
3054 {
Phil Nasha04981b2013-03-08 09:30:25 +00003055 move( other );
Phil Nashce612bf2012-11-01 08:27:09 +00003056 }
3057
3058 CompositeGenerator& setFileInfo( const char* fileInfo ) {
3059 m_fileInfo = fileInfo;
3060 return *this;
3061 }
3062
3063 ~CompositeGenerator() {
3064 deleteAll( m_composed );
3065 }
3066
3067 operator T () const {
3068 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
3069
3070 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
3071 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
3072 for( size_t index = 0; it != itEnd; ++it )
3073 {
3074 const IGenerator<T>* generator = *it;
3075 if( overallIndex >= index && overallIndex < index + generator->size() )
3076 {
3077 return generator->getValue( overallIndex-index );
3078 }
3079 index += generator->size();
3080 }
3081 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
Phil Nasha04981b2013-03-08 09:30:25 +00003082 return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so
Phil Nashce612bf2012-11-01 08:27:09 +00003083 }
3084
3085 void add( const IGenerator<T>* generator ) {
3086 m_totalSize += generator->size();
3087 m_composed.push_back( generator );
3088 }
3089
3090 CompositeGenerator& then( CompositeGenerator& other ) {
3091 move( other );
3092 return *this;
3093 }
3094
3095 CompositeGenerator& then( T value ) {
3096 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
3097 valuesGen->add( value );
3098 add( valuesGen );
3099 return *this;
3100 }
3101
3102private:
3103
3104 void move( CompositeGenerator& other ) {
3105 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
3106 m_totalSize += other.m_totalSize;
3107 other.m_composed.clear();
3108 }
3109
3110 std::vector<const IGenerator<T>*> m_composed;
3111 std::string m_fileInfo;
3112 size_t m_totalSize;
3113};
3114
3115namespace Generators
3116{
3117 template<typename T>
3118 CompositeGenerator<T> between( T from, T to ) {
3119 CompositeGenerator<T> generators;
3120 generators.add( new BetweenGenerator<T>( from, to ) );
3121 return generators;
3122 }
3123
3124 template<typename T>
3125 CompositeGenerator<T> values( T val1, T val2 ) {
3126 CompositeGenerator<T> generators;
3127 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
3128 valuesGen->add( val1 );
3129 valuesGen->add( val2 );
3130 generators.add( valuesGen );
3131 return generators;
3132 }
3133
3134 template<typename T>
3135 CompositeGenerator<T> values( T val1, T val2, T val3 ){
3136 CompositeGenerator<T> generators;
3137 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
3138 valuesGen->add( val1 );
3139 valuesGen->add( val2 );
3140 valuesGen->add( val3 );
3141 generators.add( valuesGen );
3142 return generators;
3143 }
3144
3145 template<typename T>
3146 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
3147 CompositeGenerator<T> generators;
3148 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
3149 valuesGen->add( val1 );
3150 valuesGen->add( val2 );
3151 valuesGen->add( val3 );
3152 valuesGen->add( val4 );
3153 generators.add( valuesGen );
3154 return generators;
3155 }
3156
3157} // end namespace Generators
3158
3159using namespace Generators;
3160
3161} // end namespace Catch
3162
3163#define INTERNAL_CATCH_LINESTR2( line ) #line
3164#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
3165
3166#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
3167
3168// #included from: internal/catch_interfaces_exception.h
3169#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
3170
3171#include <string>
Phil Nash89d1e6c2011-05-24 08:23:02 +01003172
Phil Nash89d2a3f2012-05-16 15:09:17 +01003173namespace Catch {
3174
Phil Nash89d1e6c2011-05-24 08:23:02 +01003175 typedef std::string(*exceptionTranslateFunction)();
3176
Phil Nash89d2a3f2012-05-16 15:09:17 +01003177 struct IExceptionTranslator {
Phil Nasha695eb92012-08-13 07:46:10 +01003178 virtual ~IExceptionTranslator();
Phil Nash89d1e6c2011-05-24 08:23:02 +01003179 virtual std::string translate() const = 0;
3180 };
3181
Phil Nash89d2a3f2012-05-16 15:09:17 +01003182 struct IExceptionTranslatorRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +01003183 virtual ~IExceptionTranslatorRegistry();
Phil Nash89d1e6c2011-05-24 08:23:02 +01003184
Phil Nash89d2a3f2012-05-16 15:09:17 +01003185 virtual std::string translateActiveException() const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003186 };
3187
Phil Nash89d2a3f2012-05-16 15:09:17 +01003188 class ExceptionTranslatorRegistrar {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003189 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01003190 class ExceptionTranslator : public IExceptionTranslator {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003191 public:
3192
Phil Nash89d2a3f2012-05-16 15:09:17 +01003193 ExceptionTranslator( std::string(*translateFunction)( T& ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01003194 : m_translateFunction( translateFunction )
3195 {}
3196
Phil Nash89d2a3f2012-05-16 15:09:17 +01003197 virtual std::string translate() const {
3198 try {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003199 throw;
3200 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01003201 catch( T& ex ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003202 return m_translateFunction( ex );
3203 }
3204 }
3205
3206 protected:
3207 std::string(*m_translateFunction)( T& );
3208 };
3209
3210 public:
3211 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01003212 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
Phil Nash3b80af72012-08-09 07:47:30 +01003213 getMutableRegistryHub().registerTranslator
Phil Nash89d1e6c2011-05-24 08:23:02 +01003214 ( new ExceptionTranslator<T>( translateFunction ) );
3215 }
3216 };
3217}
3218
3219///////////////////////////////////////////////////////////////////////////////
3220#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
3221 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
3222 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
3223 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
3224
3225// #included from: internal/catch_approx.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01003226#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01003227
Phil Nash89d1e6c2011-05-24 08:23:02 +01003228#include <cmath>
3229#include <limits>
3230
Phil Nash89d2a3f2012-05-16 15:09:17 +01003231namespace Catch {
3232namespace Detail {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003233
Phil Nash89d2a3f2012-05-16 15:09:17 +01003234 class Approx {
3235 public:
3236 explicit Approx ( double value )
3237 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
3238 m_scale( 1.0 ),
3239 m_value( value )
3240 {}
Phil Nashf721a962011-06-07 14:13:57 +01003241
Phil Nash8defc712013-04-24 19:10:02 +01003242 Approx( Approx const& other )
Phil Nash89d2a3f2012-05-16 15:09:17 +01003243 : m_epsilon( other.m_epsilon ),
3244 m_scale( other.m_scale ),
3245 m_value( other.m_value )
3246 {}
Phil Nashf721a962011-06-07 14:13:57 +01003247
Phil Nash89d2a3f2012-05-16 15:09:17 +01003248 static Approx custom() {
3249 return Approx( 0 );
3250 }
Phil Nashf721a962011-06-07 14:13:57 +01003251
Phil Nash89d2a3f2012-05-16 15:09:17 +01003252 Approx operator()( double value ) {
3253 Approx approx( value );
3254 approx.epsilon( m_epsilon );
3255 approx.scale( m_scale );
3256 return approx;
3257 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003258
Phil Nash8defc712013-04-24 19:10:02 +01003259 friend bool operator == ( double lhs, Approx const& rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01003260 // Thanks to Richard Harris for his help refining this formula
3261 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
3262 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003263
Phil Nash8defc712013-04-24 19:10:02 +01003264 friend bool operator == ( Approx const& lhs, double rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01003265 return operator==( rhs, lhs );
3266 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003267
Phil Nash8defc712013-04-24 19:10:02 +01003268 friend bool operator != ( double lhs, Approx const& rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01003269 return !operator==( lhs, rhs );
3270 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003271
Phil Nash8defc712013-04-24 19:10:02 +01003272 friend bool operator != ( Approx const& lhs, double rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01003273 return !operator==( rhs, lhs );
3274 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003275
Phil Nash89d2a3f2012-05-16 15:09:17 +01003276 Approx& epsilon( double newEpsilon ) {
3277 m_epsilon = newEpsilon;
3278 return *this;
3279 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003280
Phil Nash89d2a3f2012-05-16 15:09:17 +01003281 Approx& scale( double newScale ) {
3282 m_scale = newScale;
3283 return *this;
3284 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003285
Phil Nash89d2a3f2012-05-16 15:09:17 +01003286 std::string toString() const {
3287 std::ostringstream oss;
Phil Nash67305122012-10-09 11:48:55 +01003288 oss << "Approx( " << m_value << " )";
Phil Nash89d2a3f2012-05-16 15:09:17 +01003289 return oss.str();
3290 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003291
Phil Nash89d2a3f2012-05-16 15:09:17 +01003292 private:
3293 double m_epsilon;
3294 double m_scale;
3295 double m_value;
3296 };
3297}
3298
3299template<>
Phil Nash8defc712013-04-24 19:10:02 +01003300inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01003301 return value.toString();
3302}
Phil Nash89d1e6c2011-05-24 08:23:02 +01003303
3304} // end namespace Catch
3305
Phil Nash371db8b2012-05-21 18:52:09 +01003306// #included from: internal/catch_matchers.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01003307#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01003308
3309namespace Catch {
3310namespace Matchers {
3311 namespace Impl {
Phil Nash9444bbc2012-10-12 07:58:17 +01003312
3313 template<typename ExpressionT>
3314 struct Matcher : SharedImpl<IShared>
3315 {
Phil Nasha8c65432013-02-19 08:46:09 +00003316 typedef ExpressionT ExpressionType;
3317
Phil Nash9444bbc2012-10-12 07:58:17 +01003318 virtual ~Matcher() {}
3319 virtual Ptr<Matcher> clone() const = 0;
Phil Nashff03cdf2012-12-06 08:44:51 +00003320 virtual bool match( ExpressionT const& expr ) const = 0;
Phil Nash9444bbc2012-10-12 07:58:17 +01003321 virtual std::string toString() const = 0;
3322 };
3323
3324 template<typename DerivedT, typename ExpressionT>
3325 struct MatcherImpl : Matcher<ExpressionT> {
3326
3327 virtual Ptr<Matcher<ExpressionT> > clone() const {
Phil Nash8defc712013-04-24 19:10:02 +01003328 return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) );
Phil Nash9444bbc2012-10-12 07:58:17 +01003329 }
3330 };
3331
3332 namespace Generic {
3333
3334 template<typename ExpressionT>
3335 class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
3336 public:
3337
3338 AllOf() {}
Phil Nash8defc712013-04-24 19:10:02 +01003339 AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {}
Phil Nash9444bbc2012-10-12 07:58:17 +01003340
Phil Nash8defc712013-04-24 19:10:02 +01003341 AllOf& add( Matcher<ExpressionT> const& matcher ) {
Phil Nash9444bbc2012-10-12 07:58:17 +01003342 m_matchers.push_back( matcher.clone() );
3343 return *this;
3344 }
Phil Nash8defc712013-04-24 19:10:02 +01003345 virtual bool match( ExpressionT const& expr ) const
Phil Nash9444bbc2012-10-12 07:58:17 +01003346 {
3347 for( std::size_t i = 0; i < m_matchers.size(); ++i )
3348 if( !m_matchers[i]->match( expr ) )
3349 return false;
3350 return true;
3351 }
3352 virtual std::string toString() const {
3353 std::ostringstream oss;
3354 oss << "( ";
3355 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
3356 if( i != 0 )
3357 oss << " and ";
3358 oss << m_matchers[i]->toString();
3359 }
3360 oss << " )";
3361 return oss.str();
3362 }
3363
3364 private:
3365 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
3366 };
3367
3368 template<typename ExpressionT>
3369 class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
3370 public:
3371
3372 AnyOf() {}
Phil Nash8defc712013-04-24 19:10:02 +01003373 AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {}
Phil Nash9444bbc2012-10-12 07:58:17 +01003374
Phil Nash8defc712013-04-24 19:10:02 +01003375 AnyOf& add( Matcher<ExpressionT> const& matcher ) {
Phil Nash9444bbc2012-10-12 07:58:17 +01003376 m_matchers.push_back( matcher.clone() );
3377 return *this;
3378 }
Phil Nash8defc712013-04-24 19:10:02 +01003379 virtual bool match( ExpressionT const& expr ) const
Phil Nash9444bbc2012-10-12 07:58:17 +01003380 {
3381 for( std::size_t i = 0; i < m_matchers.size(); ++i )
3382 if( m_matchers[i]->match( expr ) )
3383 return true;
3384 return false;
3385 }
3386 virtual std::string toString() const {
3387 std::ostringstream oss;
3388 oss << "( ";
3389 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
3390 if( i != 0 )
3391 oss << " or ";
3392 oss << m_matchers[i]->toString();
3393 }
3394 oss << " )";
3395 return oss.str();
3396 }
3397
3398 private:
3399 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
3400 };
3401
3402 }
3403
Phil Nash371db8b2012-05-21 18:52:09 +01003404 namespace StdString {
3405
Phil Nash8defc712013-04-24 19:10:02 +01003406 inline std::string makeString( std::string const& str ) { return str; }
Phil Nashd0d4d932013-04-23 08:02:48 +01003407 inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); }
3408
Phil Nash9444bbc2012-10-12 07:58:17 +01003409 struct Equals : MatcherImpl<Equals, std::string> {
Phil Nash8defc712013-04-24 19:10:02 +01003410 Equals( std::string const& str ) : m_str( str ){}
3411 Equals( Equals const& other ) : m_str( other.m_str ){}
Phil Nasha8570df2012-05-24 08:29:41 +01003412
Phil Nash9444bbc2012-10-12 07:58:17 +01003413 virtual ~Equals();
3414
Phil Nash8defc712013-04-24 19:10:02 +01003415 virtual bool match( std::string const& expr ) const {
Phil Nash9444bbc2012-10-12 07:58:17 +01003416 return m_str == expr;
3417 }
3418 virtual std::string toString() const {
3419 return "equals: \"" + m_str + "\"";
Phil Nasha8570df2012-05-24 08:29:41 +01003420 }
3421
Phil Nasha8570df2012-05-24 08:29:41 +01003422 std::string m_str;
3423 };
3424
Phil Nash9444bbc2012-10-12 07:58:17 +01003425 struct Contains : MatcherImpl<Contains, std::string> {
Phil Nash8defc712013-04-24 19:10:02 +01003426 Contains( std::string const& substr ) : m_substr( substr ){}
3427 Contains( Contains const& other ) : m_substr( other.m_substr ){}
Phil Nash371db8b2012-05-21 18:52:09 +01003428
Phil Nash9444bbc2012-10-12 07:58:17 +01003429 virtual ~Contains();
3430
Phil Nash8defc712013-04-24 19:10:02 +01003431 virtual bool match( std::string const& expr ) const {
Phil Nash9444bbc2012-10-12 07:58:17 +01003432 return expr.find( m_substr ) != std::string::npos;
3433 }
3434 virtual std::string toString() const {
3435 return "contains: \"" + m_substr + "\"";
Phil Nash371db8b2012-05-21 18:52:09 +01003436 }
3437
Phil Nash371db8b2012-05-21 18:52:09 +01003438 std::string m_substr;
3439 };
3440
Phil Nash9444bbc2012-10-12 07:58:17 +01003441 struct StartsWith : MatcherImpl<StartsWith, std::string> {
Phil Nash8defc712013-04-24 19:10:02 +01003442 StartsWith( std::string const& substr ) : m_substr( substr ){}
3443 StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){}
Phil Nash371db8b2012-05-21 18:52:09 +01003444
Phil Nash9444bbc2012-10-12 07:58:17 +01003445 virtual ~StartsWith();
3446
Phil Nash8defc712013-04-24 19:10:02 +01003447 virtual bool match( std::string const& expr ) const {
Phil Nash9444bbc2012-10-12 07:58:17 +01003448 return expr.find( m_substr ) == 0;
3449 }
3450 virtual std::string toString() const {
3451 return "starts with: \"" + m_substr + "\"";
Phil Nash371db8b2012-05-21 18:52:09 +01003452 }
3453
Phil Nash371db8b2012-05-21 18:52:09 +01003454 std::string m_substr;
3455 };
3456
Phil Nash9444bbc2012-10-12 07:58:17 +01003457 struct EndsWith : MatcherImpl<EndsWith, std::string> {
Phil Nash8defc712013-04-24 19:10:02 +01003458 EndsWith( std::string const& substr ) : m_substr( substr ){}
3459 EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){}
Phil Nash371db8b2012-05-21 18:52:09 +01003460
Phil Nash9444bbc2012-10-12 07:58:17 +01003461 virtual ~EndsWith();
3462
Phil Nash8defc712013-04-24 19:10:02 +01003463 virtual bool match( std::string const& expr ) const {
Phil Nash9444bbc2012-10-12 07:58:17 +01003464 return expr.find( m_substr ) == expr.size() - m_substr.size();
3465 }
3466 virtual std::string toString() const {
3467 return "ends with: \"" + m_substr + "\"";
Phil Nash371db8b2012-05-21 18:52:09 +01003468 }
3469
Phil Nash371db8b2012-05-21 18:52:09 +01003470 std::string m_substr;
3471 };
3472 } // namespace StdString
3473 } // namespace Impl
3474
Phil Nash9444bbc2012-10-12 07:58:17 +01003475 // The following functions create the actual matcher objects.
3476 // This allows the types to be inferred
3477 template<typename ExpressionT>
Phil Nash8defc712013-04-24 19:10:02 +01003478 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
3479 Impl::Matcher<ExpressionT> const& m2 ) {
Phil Nash9444bbc2012-10-12 07:58:17 +01003480 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
3481 }
3482 template<typename ExpressionT>
Phil Nash8defc712013-04-24 19:10:02 +01003483 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
3484 Impl::Matcher<ExpressionT> const& m2,
3485 Impl::Matcher<ExpressionT> const& m3 ) {
Phil Nash9444bbc2012-10-12 07:58:17 +01003486 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
3487 }
3488 template<typename ExpressionT>
Phil Nash8defc712013-04-24 19:10:02 +01003489 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
3490 Impl::Matcher<ExpressionT> const& m2 ) {
Phil Nash9444bbc2012-10-12 07:58:17 +01003491 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
3492 }
3493 template<typename ExpressionT>
Phil Nash8defc712013-04-24 19:10:02 +01003494 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
3495 Impl::Matcher<ExpressionT> const& m2,
3496 Impl::Matcher<ExpressionT> const& m3 ) {
Phil Nash9444bbc2012-10-12 07:58:17 +01003497 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
3498 }
3499
Phil Nash8defc712013-04-24 19:10:02 +01003500 inline Impl::StdString::Equals Equals( std::string const& str ) {
Phil Nashd0d4d932013-04-23 08:02:48 +01003501 return Impl::StdString::Equals( str );
3502 }
3503 inline Impl::StdString::Equals Equals( const char* str ) {
3504 return Impl::StdString::Equals( Impl::StdString::makeString( str ) );
3505 }
Phil Nash8defc712013-04-24 19:10:02 +01003506 inline Impl::StdString::Contains Contains( std::string const& substr ) {
Phil Nashd0d4d932013-04-23 08:02:48 +01003507 return Impl::StdString::Contains( substr );
3508 }
3509 inline Impl::StdString::Contains Contains( const char* substr ) {
3510 return Impl::StdString::Contains( Impl::StdString::makeString( substr ) );
3511 }
Phil Nash8defc712013-04-24 19:10:02 +01003512 inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) {
Phil Nashd0d4d932013-04-23 08:02:48 +01003513 return Impl::StdString::StartsWith( substr );
3514 }
3515 inline Impl::StdString::StartsWith StartsWith( const char* substr ) {
3516 return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) );
3517 }
Phil Nash8defc712013-04-24 19:10:02 +01003518 inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) {
Phil Nashd0d4d932013-04-23 08:02:48 +01003519 return Impl::StdString::EndsWith( substr );
3520 }
3521 inline Impl::StdString::EndsWith EndsWith( const char* substr ) {
3522 return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) );
3523 }
Phil Nash371db8b2012-05-21 18:52:09 +01003524
3525} // namespace Matchers
3526
3527using namespace Matchers;
3528
3529} // namespace Catch
3530
Phil Nash0f9c5512012-06-02 23:12:42 +01003531// These files are included here so the single_include script doesn't put them
3532// in the conditionally compiled sections
Phil Nash0f9c5512012-06-02 23:12:42 +01003533// #included from: internal/catch_interfaces_runner.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04003534#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
Phil Nash0f9c5512012-06-02 23:12:42 +01003535
3536#include <string>
3537
3538namespace Catch {
Phil Nasha1fbfea2012-12-01 23:57:18 +00003539 class TestCase;
Phil Nash0f9c5512012-06-02 23:12:42 +01003540
3541 struct IRunner {
Phil Nasha695eb92012-08-13 07:46:10 +01003542 virtual ~IRunner();
Phil Nash0f9c5512012-06-02 23:12:42 +01003543 };
3544}
3545
3546
Phil Nash371db8b2012-05-21 18:52:09 +01003547#ifdef __OBJC__
3548// #included from: internal/catch_objc.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01003549#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01003550
Phil Nash371db8b2012-05-21 18:52:09 +01003551#import <objc/runtime.h>
3552
3553#include <string>
3554
3555// NB. Any general catch headers included here must be included
3556// in catch.hpp first to make sure they are included by the single
3557// header for non obj-usage
Phil Nash81528252011-08-15 09:06:31 +01003558
Phil Nash83224e62011-08-12 18:53:28 +01003559///////////////////////////////////////////////////////////////////////////////
3560// This protocol is really only here for (self) documenting purposes, since
3561// all its methods are optional.
3562@protocol OcFixture
3563
3564@optional
3565
3566-(void) setUp;
3567-(void) tearDown;
3568
3569@end
3570
Phil Nash89d2a3f2012-05-16 15:09:17 +01003571namespace Catch {
Phil Nash83224e62011-08-12 18:53:28 +01003572
Phil Nash5bc030d2012-08-16 18:48:50 +01003573 class OcMethod : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +01003574
3575 public:
3576 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
3577
3578 virtual void invoke() const {
Phil Nash53c990a2012-03-17 18:20:06 +00003579 id obj = [[m_cls alloc] init];
Phil Nash83224e62011-08-12 18:53:28 +01003580
Phil Nash53c990a2012-03-17 18:20:06 +00003581 performOptionalSelector( obj, @selector(setUp) );
3582 performOptionalSelector( obj, m_sel );
3583 performOptionalSelector( obj, @selector(tearDown) );
Phil Nash83224e62011-08-12 18:53:28 +01003584
Phil Nash53c990a2012-03-17 18:20:06 +00003585 arcSafeRelease( obj );
Phil Nash83224e62011-08-12 18:53:28 +01003586 }
Phil Nash83224e62011-08-12 18:53:28 +01003587 private:
Phil Nash5bc030d2012-08-16 18:48:50 +01003588 virtual ~OcMethod() {}
3589
Phil Nash83224e62011-08-12 18:53:28 +01003590 Class m_cls;
3591 SEL m_sel;
3592 };
3593
Phil Nash89d2a3f2012-05-16 15:09:17 +01003594 namespace Detail{
Phil Nash83224e62011-08-12 18:53:28 +01003595
Phil Nash8defc712013-04-24 19:10:02 +01003596 inline bool startsWith( std::string const& str, std::string const& sub ) {
Phil Nash83224e62011-08-12 18:53:28 +01003597 return str.length() > sub.length() && str.substr( 0, sub.length() ) == sub;
3598 }
3599
Phil Nash89d2a3f2012-05-16 15:09:17 +01003600 inline std::string getAnnotation( Class cls,
Phil Nash8defc712013-04-24 19:10:02 +01003601 std::string const& annotationName,
3602 std::string const& testCaseName ) {
Phil Nash83224e62011-08-12 18:53:28 +01003603 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
3604 SEL sel = NSSelectorFromString( selStr );
Phil Nash53c990a2012-03-17 18:20:06 +00003605 arcSafeRelease( selStr );
3606 id value = performOptionalSelector( cls, sel );
3607 if( value )
3608 return [(NSString*)value UTF8String];
Phil Nash83224e62011-08-12 18:53:28 +01003609 return "";
3610 }
3611 }
3612
Phil Nash89d2a3f2012-05-16 15:09:17 +01003613 inline size_t registerTestMethods() {
Phil Nash83224e62011-08-12 18:53:28 +01003614 size_t noTestMethods = 0;
3615 int noClasses = objc_getClassList( NULL, 0 );
3616
Phil Nash861a1e72012-04-28 12:29:52 +01003617 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
Phil Nash53c990a2012-03-17 18:20:06 +00003618 objc_getClassList( classes, noClasses );
Phil Nash83224e62011-08-12 18:53:28 +01003619
Phil Nash89d2a3f2012-05-16 15:09:17 +01003620 for( int c = 0; c < noClasses; c++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01003621 Class cls = classes[c];
3622 {
3623 u_int count;
3624 Method* methods = class_copyMethodList( cls, &count );
Phil Nash7004f4a2012-05-22 08:56:59 +01003625 for( u_int m = 0; m < count ; m++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01003626 SEL selector = method_getName(methods[m]);
3627 std::string methodName = sel_getName(selector);
Phil Nash89d2a3f2012-05-16 15:09:17 +01003628 if( Detail::startsWith( methodName, "Catch_TestCase_" ) ) {
Phil Nash83224e62011-08-12 18:53:28 +01003629 std::string testCaseName = methodName.substr( 15 );
Phil Nash53c990a2012-03-17 18:20:06 +00003630 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
3631 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
Phil Nasha8c65432013-02-19 08:46:09 +00003632 const char* className = class_getName( cls );
Phil Nash83224e62011-08-12 18:53:28 +01003633
Phil Nash5bdae842013-02-19 19:47:18 +00003634 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
Phil Nash83224e62011-08-12 18:53:28 +01003635 noTestMethods++;
Phil Nash83224e62011-08-12 18:53:28 +01003636 }
3637 }
3638 free(methods);
3639 }
3640 }
3641 return noTestMethods;
3642 }
Phil Nash78d95a02012-03-04 21:22:36 +00003643
Phil Nash89d2a3f2012-05-16 15:09:17 +01003644 namespace Matchers {
3645 namespace Impl {
3646 namespace NSStringMatchers {
3647
Phil Nasha8c65432013-02-19 08:46:09 +00003648 template<typename MatcherT>
3649 struct StringHolder : MatcherImpl<MatcherT, NSString*>{
Phil Nash78d95a02012-03-04 21:22:36 +00003650 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
Phil Nasha8c65432013-02-19 08:46:09 +00003651 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
Phil Nash89d2a3f2012-05-16 15:09:17 +01003652 StringHolder() {
Phil Nash53c990a2012-03-17 18:20:06 +00003653 arcSafeRelease( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00003654 }
3655
3656 NSString* m_substr;
3657 };
3658
Phil Nasha8c65432013-02-19 08:46:09 +00003659 struct Equals : StringHolder<Equals> {
Phil Nash8d18d162012-03-14 20:06:14 +00003660 Equals( NSString* substr ) : StringHolder( substr ){}
3661
Phil Nasha8c65432013-02-19 08:46:09 +00003662 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01003663 return (str != nil || m_substr == nil ) &&
3664 [str isEqualToString:m_substr];
Phil Nash8d18d162012-03-14 20:06:14 +00003665 }
3666
Phil Nasha8c65432013-02-19 08:46:09 +00003667 virtual std::string toString() const {
3668 return "equals string: \"" + Catch::toString( m_substr ) + "\"";
Phil Nash8d18d162012-03-14 20:06:14 +00003669 }
3670 };
3671
Phil Nasha8c65432013-02-19 08:46:09 +00003672 struct Contains : StringHolder<Contains> {
Phil Nash78d95a02012-03-04 21:22:36 +00003673 Contains( NSString* substr ) : StringHolder( substr ){}
3674
Phil Nasha8c65432013-02-19 08:46:09 +00003675 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01003676 return (str != nil || m_substr == nil ) &&
3677 [str rangeOfString:m_substr].location != NSNotFound;
Phil Nash78d95a02012-03-04 21:22:36 +00003678 }
3679
Phil Nasha8c65432013-02-19 08:46:09 +00003680 virtual std::string toString() const {
3681 return "contains string: \"" + Catch::toString( m_substr ) + "\"";
Phil Nash78d95a02012-03-04 21:22:36 +00003682 }
3683 };
3684
Phil Nasha8c65432013-02-19 08:46:09 +00003685 struct StartsWith : StringHolder<StartsWith> {
Phil Nash78d95a02012-03-04 21:22:36 +00003686 StartsWith( NSString* substr ) : StringHolder( substr ){}
3687
Phil Nasha8c65432013-02-19 08:46:09 +00003688 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01003689 return (str != nil || m_substr == nil ) &&
3690 [str rangeOfString:m_substr].location == 0;
Phil Nash78d95a02012-03-04 21:22:36 +00003691 }
3692
Phil Nasha8c65432013-02-19 08:46:09 +00003693 virtual std::string toString() const {
3694 return "starts with: \"" + Catch::toString( m_substr ) + "\"";
Phil Nash78d95a02012-03-04 21:22:36 +00003695 }
3696 };
Phil Nasha8c65432013-02-19 08:46:09 +00003697 struct EndsWith : StringHolder<EndsWith> {
Phil Nash78d95a02012-03-04 21:22:36 +00003698 EndsWith( NSString* substr ) : StringHolder( substr ){}
3699
Phil Nasha8c65432013-02-19 08:46:09 +00003700 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01003701 return (str != nil || m_substr == nil ) &&
3702 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
Phil Nash78d95a02012-03-04 21:22:36 +00003703 }
3704
Phil Nasha8c65432013-02-19 08:46:09 +00003705 virtual std::string toString() const {
3706 return "ends with: \"" + Catch::toString( m_substr ) + "\"";
Phil Nash78d95a02012-03-04 21:22:36 +00003707 }
3708 };
3709
3710 } // namespace NSStringMatchers
3711 } // namespace Impl
3712
Phil Nash8d18d162012-03-14 20:06:14 +00003713 inline Impl::NSStringMatchers::Equals
3714 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
3715
Phil Nash78d95a02012-03-04 21:22:36 +00003716 inline Impl::NSStringMatchers::Contains
3717 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00003718
Phil Nash78d95a02012-03-04 21:22:36 +00003719 inline Impl::NSStringMatchers::StartsWith
3720 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00003721
Phil Nash78d95a02012-03-04 21:22:36 +00003722 inline Impl::NSStringMatchers::EndsWith
3723 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
3724
3725 } // namespace Matchers
3726
3727 using namespace Matchers;
3728
3729} // namespace Catch
Phil Nash83224e62011-08-12 18:53:28 +01003730
3731///////////////////////////////////////////////////////////////////////////////
3732#define OC_TEST_CASE( name, desc )\
Phil Nash53c990a2012-03-17 18:20:06 +00003733+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01003734{\
Phil Nash53c990a2012-03-17 18:20:06 +00003735return @ name; \
Phil Nash83224e62011-08-12 18:53:28 +01003736}\
Phil Nash53c990a2012-03-17 18:20:06 +00003737+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01003738{ \
Phil Nash53c990a2012-03-17 18:20:06 +00003739return @ desc; \
Phil Nash83224e62011-08-12 18:53:28 +01003740} \
3741-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
3742
3743#endif
3744
3745#if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER )
Phil Nasha695eb92012-08-13 07:46:10 +01003746// #included from: internal/catch_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04003747#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003748
3749// Collect all the implementation files together here
3750// These are the equivalent of what would usually be cpp files
3751
Phil Nash5bc030d2012-08-16 18:48:50 +01003752#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01003753#pragma clang diagnostic push
3754#pragma clang diagnostic ignored "-Wweak-vtables"
Phil Nash5bc030d2012-08-16 18:48:50 +01003755#endif
Phil Nasha695eb92012-08-13 07:46:10 +01003756
Phil Nash83224e62011-08-12 18:53:28 +01003757// #included from: catch_runner.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01003758#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
Phil Nash83224e62011-08-12 18:53:28 +01003759
Phil Nasha695eb92012-08-13 07:46:10 +01003760// #included from: internal/catch_commandline.hpp
3761#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
3762
Phil Nash786959d2013-06-07 19:07:50 +01003763// #included from: clara.h
3764#define TWOBLUECUBES_CLARA_H_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003765
Phil Nash19279252013-04-20 21:07:32 +01003766// #included from: catch_text.h
3767#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
Phil Nash38f7eef2013-03-29 13:44:33 +00003768
3769#include <string>
3770#include <vector>
3771
Phil Nash89d1e6c2011-05-24 08:23:02 +01003772namespace Catch {
3773
Phil Nash19279252013-04-20 21:07:32 +01003774 struct TextAttributes {
3775 TextAttributes()
3776 : initialIndent( std::string::npos ),
3777 indent( 0 ),
3778 width( CATCH_CONFIG_CONSOLE_WIDTH-1 ),
3779 tabChar( '\t' )
Phil Nash89d1e6c2011-05-24 08:23:02 +01003780 {}
Phil Nash3b80af72012-08-09 07:47:30 +01003781
Phil Nash19279252013-04-20 21:07:32 +01003782 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
3783 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
3784 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
3785 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
Phil Nash89d2a3f2012-05-16 15:09:17 +01003786
Phil Nash19279252013-04-20 21:07:32 +01003787 std::size_t initialIndent; // indent of first line, or npos
3788 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
3789 std::size_t width; // maximum width of text, including indent. Longer text will wrap
3790 char tabChar; // If this char is seen the indent is changed to current pos
Phil Nash89d1e6c2011-05-24 08:23:02 +01003791 };
3792
Phil Nash19279252013-04-20 21:07:32 +01003793 class Text {
Phil Nasha695eb92012-08-13 07:46:10 +01003794 public:
Phil Nash19279252013-04-20 21:07:32 +01003795 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() );
3796 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos );
Phil Nasha695eb92012-08-13 07:46:10 +01003797
Phil Nash38f7eef2013-03-29 13:44:33 +00003798 typedef std::vector<std::string>::const_iterator const_iterator;
Phil Nasha695eb92012-08-13 07:46:10 +01003799
Phil Nash38f7eef2013-03-29 13:44:33 +00003800 const_iterator begin() const { return lines.begin(); }
3801 const_iterator end() const { return lines.end(); }
3802 std::string const& last() const { return lines.back(); }
3803 std::size_t size() const { return lines.size(); }
3804 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
Phil Nash19279252013-04-20 21:07:32 +01003805 std::string toString() const;
Phil Nasha695eb92012-08-13 07:46:10 +01003806
Phil Nash19279252013-04-20 21:07:32 +01003807 friend std::ostream& operator << ( std::ostream& _stream, Text const& _text );
Phil Nasha695eb92012-08-13 07:46:10 +01003808
Phil Nasha695eb92012-08-13 07:46:10 +01003809 private:
Phil Nash19279252013-04-20 21:07:32 +01003810 std::string str;
3811 TextAttributes attr;
Phil Nash38f7eef2013-03-29 13:44:33 +00003812 std::vector<std::string> lines;
3813 };
3814
3815} // end namespace Catch
3816
Phil Nash786959d2013-06-07 19:07:50 +01003817namespace Clara {
3818 namespace Detail {
3819 template<typename T> struct RemoveConstRef{ typedef T type; };
3820 template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
3821 template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
3822 template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
3823
3824 template<typename T> struct IsBool { static const bool value = false; };
3825 template<> struct IsBool<bool> { static const bool value = true; };
Phil Nasha695eb92012-08-13 07:46:10 +01003826
3827 template<typename T>
Phil Nash786959d2013-06-07 19:07:50 +01003828 void convertInto( std::string const& _source, T& _dest ) {
3829 std::stringstream ss;
3830 ss << _source;
3831 ss >> _dest;
3832 if( ss.fail() )
3833 throw std::runtime_error( "Unable to convert " + _source + " to destination type" );
Phil Nasha695eb92012-08-13 07:46:10 +01003834 }
Phil Nash786959d2013-06-07 19:07:50 +01003835 inline void convertInto( std::string const& _source, std::string& _dest ) {
3836 _dest = _source;
3837 }
3838 inline void convertInto( std::string const& _source, bool& _dest ) {
3839 std::string sourceLC = _source;
3840 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower );
Phil Nash46118712013-08-16 19:01:32 +01003841 if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
Phil Nash786959d2013-06-07 19:07:50 +01003842 _dest = true;
Phil Nash46118712013-08-16 19:01:32 +01003843 else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
Phil Nash786959d2013-06-07 19:07:50 +01003844 _dest = false;
3845 else
Phil Nash46118712013-08-16 19:01:32 +01003846 throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
Phil Nash786959d2013-06-07 19:07:50 +01003847 }
3848 inline void convertInto( bool _source, bool& _dest ) {
3849 _dest = _source;
3850 }
3851 template<typename T>
3852 inline void convertInto( bool, T& ) {
3853 throw std::runtime_error( "Invalid conversion" );
3854 }
Phil Nasha695eb92012-08-13 07:46:10 +01003855
Phil Nash786959d2013-06-07 19:07:50 +01003856 template<typename ConfigT>
3857 struct IArgFunction {
3858 virtual ~IArgFunction() {}
3859 virtual void set( ConfigT& config, std::string const& value ) const = 0;
3860 virtual void setFlag( ConfigT& config ) const = 0;
3861 virtual bool takesArg() const = 0;
3862 virtual IArgFunction* clone() const = 0;
3863 };
3864
3865 template<typename ConfigT>
3866 class BoundArgFunction {
3867 public:
3868 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
3869 BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj->clone() ) {}
3870 BoundArgFunction& operator = ( BoundArgFunction const& other ) {
3871 IArgFunction<ConfigT>* newFunctionObj = other.functionObj->clone();
3872 delete functionObj;
3873 functionObj = newFunctionObj;
3874 return *this;
3875 }
3876 ~BoundArgFunction() { delete functionObj; }
3877
3878 void set( ConfigT& config, std::string const& value ) const {
3879 functionObj->set( config, value );
3880 }
3881 void setFlag( ConfigT& config ) const {
3882 functionObj->setFlag( config );
3883 }
3884 bool takesArg() const { return functionObj->takesArg(); }
3885 private:
3886 IArgFunction<ConfigT>* functionObj;
3887 };
3888
3889 template<typename C>
3890 struct NullBinder : IArgFunction<C>{
3891 virtual void set( C&, std::string const& ) const {}
3892 virtual void setFlag( C& ) const {}
3893 virtual bool takesArg() const { return true; }
3894 virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
3895 };
3896
3897 template<typename C, typename M>
3898 struct BoundDataMember : IArgFunction<C>{
3899 BoundDataMember( M C::* _member ) : member( _member ) {}
3900 virtual void set( C& p, std::string const& stringValue ) const {
3901 convertInto( stringValue, p.*member );
3902 }
3903 virtual void setFlag( C& p ) const {
3904 convertInto( true, p.*member );
3905 }
3906 virtual bool takesArg() const { return !IsBool<M>::value; }
3907 virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
3908 M C::* member;
3909 };
3910 template<typename C, typename M>
3911 struct BoundUnaryMethod : IArgFunction<C>{
3912 BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
3913 virtual void set( C& p, std::string const& stringValue ) const {
3914 typename RemoveConstRef<M>::type value;
3915 convertInto( stringValue, value );
3916 (p.*member)( value );
3917 }
3918 virtual void setFlag( C& p ) const {
3919 typename RemoveConstRef<M>::type value;
3920 convertInto( true, value );
3921 (p.*member)( value );
3922 }
3923 virtual bool takesArg() const { return !IsBool<M>::value; }
3924 virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
3925 void (C::*member)( M );
3926 };
3927 template<typename C>
3928 struct BoundNullaryMethod : IArgFunction<C>{
3929 BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {}
3930 virtual void set( C& p, std::string const& stringValue ) const {
3931 bool value;
3932 convertInto( stringValue, value );
3933 if( value )
3934 (p.*member)();
3935 }
3936 virtual void setFlag( C& p ) const {
3937 (p.*member)();
3938 }
3939 virtual bool takesArg() const { return false; }
3940 virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
3941 void (C::*member)();
3942 };
3943
3944 template<typename C>
3945 struct BoundUnaryFunction : IArgFunction<C>{
3946 BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {}
3947 virtual void set( C& obj, std::string const& stringValue ) const {
3948 bool value;
3949 convertInto( stringValue, value );
3950 if( value )
3951 function( obj );
3952 }
3953 virtual void setFlag( C& p ) const {
3954 function( p );
3955 }
3956 virtual bool takesArg() const { return false; }
3957 virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
3958 void (*function)( C& );
3959 };
3960
3961 template<typename C, typename T>
3962 struct BoundBinaryFunction : IArgFunction<C>{
3963 BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
3964 virtual void set( C& obj, std::string const& stringValue ) const {
3965 typename RemoveConstRef<T>::type value;
3966 convertInto( stringValue, value );
3967 function( obj, value );
3968 }
3969 virtual void setFlag( C& obj ) const {
3970 typename RemoveConstRef<T>::type value;
3971 convertInto( true, value );
3972 function( obj, value );
3973 }
3974 virtual bool takesArg() const { return !IsBool<T>::value; }
3975 virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
3976 void (*function)( C&, T );
3977 };
3978
3979 template<typename C, typename M>
3980 BoundArgFunction<C> makeBoundField( M C::* _member ) {
3981 return BoundArgFunction<C>( new BoundDataMember<C,M>( _member ) );
3982 }
3983 template<typename C, typename M>
3984 BoundArgFunction<C> makeBoundField( void (C::*_member)( M ) ) {
3985 return BoundArgFunction<C>( new BoundUnaryMethod<C,M>( _member ) );
3986 }
3987 template<typename C>
3988 BoundArgFunction<C> makeBoundField( void (C::*_member)() ) {
3989 return BoundArgFunction<C>( new BoundNullaryMethod<C>( _member ) );
3990 }
3991 template<typename C>
3992 BoundArgFunction<C> makeBoundField( void (*_function)( C& ) ) {
3993 return BoundArgFunction<C>( new BoundUnaryFunction<C>( _function ) );
3994 }
3995 template<typename C, typename T>
3996 BoundArgFunction<C> makeBoundField( void (*_function)( C&, T ) ) {
3997 return BoundArgFunction<C>( new BoundBinaryFunction<C, T>( _function ) );
3998 }
3999 } // namespace Detail
4000
4001 struct Parser {
4002 Parser() : separators( " \t=:" ) {}
4003
4004 struct Token {
4005 enum Type { Positional, ShortOpt, LongOpt };
4006 Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {}
4007 Type type;
4008 std::string data;
4009 };
4010
4011 void parseIntoTokens( int argc, char const * const * argv, std::vector<Parser::Token>& tokens ) const {
4012 for( int i = 1; i < argc; ++i )
4013 parseIntoTokens( argv[i] , tokens);
4014 }
4015 void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens ) const {
4016 while( !arg.empty() ) {
4017 Parser::Token token( Parser::Token::Positional, arg );
4018 arg = "";
4019 if( token.data[0] == '-' ) {
4020 if( token.data.size() > 1 && token.data[1] == '-' ) {
4021 token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) );
4022 }
4023 else {
4024 token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) );
4025 if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) {
4026 arg = "-" + token.data.substr( 1 );
4027 token.data = token.data.substr( 0, 1 );
4028 }
4029 }
4030 }
4031 if( token.type != Parser::Token::Positional ) {
4032 std::size_t pos = token.data.find_first_of( separators );
4033 if( pos != std::string::npos ) {
4034 arg = token.data.substr( pos+1 );
4035 token.data = token.data.substr( 0, pos );
4036 }
4037 }
4038 tokens.push_back( token );
4039 }
4040 }
4041 std::string separators;
Phil Nasha695eb92012-08-13 07:46:10 +01004042 };
4043
Phil Nash786959d2013-06-07 19:07:50 +01004044 template<typename ConfigT>
4045 class CommandLine {
4046
4047 struct Arg {
4048 Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ), position( -1 ) {}
4049
4050 bool hasShortName( std::string const& shortName ) const {
4051 for( std::vector<std::string>::const_iterator
4052 it = shortNames.begin(), itEnd = shortNames.end();
4053 it != itEnd;
4054 ++it )
4055 if( *it == shortName )
4056 return true;
4057 return false;
4058 }
4059 bool hasLongName( std::string const& _longName ) const {
4060 return _longName == longName;
4061 }
4062 bool takesArg() const {
Phil Nash46118712013-08-16 19:01:32 +01004063 return !hint.empty();
Phil Nash786959d2013-06-07 19:07:50 +01004064 }
4065 bool isFixedPositional() const {
4066 return position != -1;
4067 }
4068 bool isAnyPositional() const {
4069 return position == -1 && shortNames.empty() && longName.empty();
4070 }
4071 std::string dbgName() const {
4072 if( !longName.empty() )
4073 return "--" + longName;
4074 if( !shortNames.empty() )
4075 return "-" + shortNames[0];
4076 return "positional args";
4077 }
4078 void validate() const {
4079 if( boundField.takesArg() && !takesArg() )
4080 throw std::logic_error( dbgName() + " must specify an arg name" );
4081 }
4082 std::string commands() const {
4083 std::ostringstream oss;
4084 bool first = true;
4085 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
4086 for(; it != itEnd; ++it ) {
4087 if( first )
4088 first = false;
4089 else
4090 oss << ", ";
4091 oss << "-" << *it;
4092 }
4093 if( !longName.empty() ) {
4094 if( !first )
4095 oss << ", ";
4096 oss << "--" << longName;
4097 }
Phil Nash46118712013-08-16 19:01:32 +01004098 if( !hint.empty() )
4099 oss << " <" << hint << ">";
Phil Nash786959d2013-06-07 19:07:50 +01004100 return oss.str();
4101 }
4102
4103 Detail::BoundArgFunction<ConfigT> boundField;
4104 std::vector<std::string> shortNames;
4105 std::string longName;
4106 std::string description;
Phil Nash46118712013-08-16 19:01:32 +01004107 std::string hint;
Phil Nash786959d2013-06-07 19:07:50 +01004108 int position;
4109 };
4110
4111 class ArgBinder {
4112 public:
4113 template<typename F>
4114 ArgBinder( CommandLine* cl, F f )
4115 : m_cl( cl ),
4116 m_arg( Detail::makeBoundField( f ) )
4117 {}
4118 ArgBinder( ArgBinder& other )
4119 : m_cl( other.m_cl ),
4120 m_arg( other.m_arg )
4121 {
4122 other.m_cl = NULL;
4123 }
4124 ~ArgBinder() {
4125 if( m_cl ) {
4126 m_arg.validate();
4127 if( m_arg.isFixedPositional() ) {
4128 m_cl->m_positionalArgs.insert( std::make_pair( m_arg.position, m_arg ) );
4129 if( m_arg.position > m_cl->m_highestSpecifiedArgPosition )
4130 m_cl->m_highestSpecifiedArgPosition = m_arg.position;
4131 }
4132 else if( m_arg.isAnyPositional() ) {
4133 if( m_cl->m_arg.get() )
4134 throw std::logic_error( "Only one unpositional argument can be added" );
4135 m_cl->m_arg = std::auto_ptr<Arg>( new Arg( m_arg ) );
4136 }
4137 else
4138 m_cl->m_options.push_back( m_arg );
4139 }
4140 }
4141 ArgBinder& shortOpt( std::string const& name ) {
4142 m_arg.shortNames.push_back( name );
4143 return *this;
4144 }
4145 ArgBinder& longOpt( std::string const& name ) {
4146 m_arg.longName = name;
4147 return *this;
4148 }
4149 ArgBinder& describe( std::string const& description ) {
4150 m_arg.description = description;
4151 return *this;
4152 }
Phil Nash46118712013-08-16 19:01:32 +01004153 ArgBinder& hint( std::string const& hint ) {
4154 m_arg.hint = hint;
Phil Nash786959d2013-06-07 19:07:50 +01004155 return *this;
4156 }
4157 ArgBinder& position( int position ) {
4158 m_arg.position = position;
4159 return *this;
4160 }
4161 private:
4162 CommandLine* m_cl;
4163 Arg m_arg;
4164 };
4165
4166 public:
4167
4168 CommandLine()
4169 : m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
4170 m_highestSpecifiedArgPosition( 0 )
4171 {}
4172 CommandLine( CommandLine const& other )
4173 : m_boundProcessName( other.m_boundProcessName ),
4174 m_options ( other.m_options ),
4175 m_positionalArgs( other.m_positionalArgs ),
4176 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition )
4177 {
4178 if( other.m_arg.get() )
4179 m_arg = std::auto_ptr<Arg>( new Arg( *other.m_arg ) );
4180 }
4181
4182 template<typename F>
4183 ArgBinder bind( F f ) {
4184 ArgBinder binder( this, f );
4185 return binder;
4186 }
4187 template<typename F>
4188 void bindProcessName( F f ) {
4189 m_boundProcessName = Detail::makeBoundField( f );
4190 }
4191
4192 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = CATCH_CONFIG_CONSOLE_WIDTH ) const {
4193 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
4194 std::size_t maxWidth = 0;
4195 for( it = itBegin; it != itEnd; ++it )
4196 maxWidth = (std::max)( maxWidth, it->commands().size() );
4197
4198 for( it = itBegin; it != itEnd; ++it ) {
4199 Catch::Text usage( it->commands(), Catch::TextAttributes()
4200 .setWidth( maxWidth+indent )
4201 .setIndent( indent ) );
4202 // !TBD handle longer usage strings
4203 Catch::Text desc( it->description, Catch::TextAttributes()
4204 .setWidth( width - maxWidth -3 ) );
4205
Phil Nashcd688302013-06-29 12:11:32 +01004206 for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
Phil Nash786959d2013-06-07 19:07:50 +01004207 std::string usageCol = i < usage.size() ? usage[i] : "";
4208 os << usageCol;
4209
4210 if( i < desc.size() && !desc[i].empty() )
4211 os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' )
4212 << desc[i];
4213 os << "\n";
4214 }
4215 }
4216 }
4217 std::string optUsage() const {
4218 std::ostringstream oss;
4219 optUsage( oss );
4220 return oss.str();
4221 }
4222
4223 void argSynopsis( std::ostream& os ) const {
4224 for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
4225 if( i > 1 )
4226 os << " ";
4227 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
4228 if( it != m_positionalArgs.end() )
Phil Nash46118712013-08-16 19:01:32 +01004229 os << "<" << it->second.hint << ">";
Phil Nash786959d2013-06-07 19:07:50 +01004230 else if( m_arg.get() )
Phil Nash46118712013-08-16 19:01:32 +01004231 os << "<" << m_arg->hint << ">";
Phil Nash786959d2013-06-07 19:07:50 +01004232 else
4233 throw std::logic_error( "non consecutive positional arguments with no floating args" );
4234 }
4235 // !TBD No indication of mandatory args
4236 if( m_arg.get() ) {
4237 if( m_highestSpecifiedArgPosition > 1 )
4238 os << " ";
Phil Nash46118712013-08-16 19:01:32 +01004239 os << "[<" << m_arg->hint << "> ...]";
Phil Nash786959d2013-06-07 19:07:50 +01004240 }
4241 }
4242 std::string argSynopsis() const {
4243 std::ostringstream oss;
4244 argSynopsis( oss );
4245 return oss.str();
4246 }
4247
4248 void usage( std::ostream& os, std::string const& procName ) const {
4249 os << "usage:\n " << procName << " ";
4250 argSynopsis( os );
4251 if( !m_options.empty() ) {
4252 os << " [options]\n\nwhere options are: \n";
4253 optUsage( os, 2 );
4254 }
4255 os << "\n";
4256 }
4257 std::string usage( std::string const& procName ) const {
4258 std::ostringstream oss;
4259 usage( oss, procName );
4260 return oss.str();
4261 }
4262
4263 std::vector<Parser::Token> parseInto( int argc, char const * const * argv, ConfigT& config ) const {
4264 std::string processName = argv[0];
4265 std::size_t lastSlash = processName.find_last_of( "/\\" );
4266 if( lastSlash != std::string::npos )
4267 processName = processName.substr( lastSlash+1 );
4268 m_boundProcessName.set( config, processName );
4269 std::vector<Parser::Token> tokens;
4270 Parser parser;
4271 parser.parseIntoTokens( argc, argv, tokens );
4272 return populate( tokens, config );
4273 }
4274
4275 std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4276 if( m_options.empty() && m_positionalArgs.empty() )
4277 throw std::logic_error( "No options or arguments specified" );
4278
4279 std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
4280 unusedTokens = populateFixedArgs( unusedTokens, config );
4281 unusedTokens = populateFloatingArgs( unusedTokens, config );
4282 return unusedTokens;
4283 }
4284
4285 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4286 std::vector<Parser::Token> unusedTokens;
4287 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4288 Parser::Token const& token = tokens[i];
4289 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
4290 for(; it != itEnd; ++it ) {
4291 Arg const& arg = *it;
4292
4293 try {
4294 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
4295 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
4296 if( arg.takesArg() ) {
4297 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
4298 throw std::domain_error( "Expected argument to option " + token.data );
4299 arg.boundField.set( config, tokens[++i].data );
4300 }
4301 else {
4302 arg.boundField.setFlag( config );
4303 }
4304 break;
4305 }
4306 }
4307 catch( std::exception& ex ) {
Phil Nash46118712013-08-16 19:01:32 +01004308 throw std::runtime_error( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
Phil Nash786959d2013-06-07 19:07:50 +01004309 }
4310 }
4311 if( it == itEnd )
4312 unusedTokens.push_back( token );
4313 }
4314 return unusedTokens;
4315 }
4316 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4317 std::vector<Parser::Token> unusedTokens;
4318 int position = 1;
4319 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4320 Parser::Token const& token = tokens[i];
4321 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
4322 if( it != m_positionalArgs.end() )
4323 it->second.boundField.set( config, token.data );
4324 else
4325 unusedTokens.push_back( token );
4326 if( token.type == Parser::Token::Positional )
4327 position++;
4328 }
4329 return unusedTokens;
4330 }
4331 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4332 if( !m_arg.get() )
4333 return tokens;
4334 std::vector<Parser::Token> unusedTokens;
4335 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4336 Parser::Token const& token = tokens[i];
4337 if( token.type == Parser::Token::Positional )
4338 m_arg->boundField.set( config, token.data );
4339 else
4340 unusedTokens.push_back( token );
4341 }
4342 return unusedTokens;
4343 }
4344
4345 private:
4346 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
4347 std::vector<Arg> m_options;
4348 std::map<int, Arg> m_positionalArgs;
4349 std::auto_ptr<Arg> m_arg;
4350 int m_highestSpecifiedArgPosition;
4351 };
4352
4353} // end namespace Clara
4354
4355namespace Catch {
4356
4357 inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
4358 inline void abortAfterX( ConfigData& config, int x ) {
4359 if( x < 1 )
4360 throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" );
4361 config.abortAfter = x;
4362 }
4363 inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
4364
4365 inline void addWarning( ConfigData& config, std::string const& _warning ) {
4366 if( _warning == "NoAssertions" )
Phil Nashaa7123b2013-08-15 19:01:00 +01004367 config.warnings = (WarnAbout::What)( config.warnings | WarnAbout::NoAssertions );
Phil Nash786959d2013-06-07 19:07:50 +01004368 else
4369 throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" );
4370
4371 }
4372 inline void setVerbosity( ConfigData& config, int level ) {
4373 // !TBD: accept strings?
Phil Nashaa7123b2013-08-15 19:01:00 +01004374 config.verbosity = (Verbosity::Level)level;
4375 }
4376 inline void setShowDurations( ConfigData& config, bool _showDurations ) {
4377 config.showDurations = _showDurations
4378 ? ShowDurations::Always
4379 : ShowDurations::Never;
Phil Nash786959d2013-06-07 19:07:50 +01004380 }
4381
4382 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
4383
4384 Clara::CommandLine<ConfigData> cli;
4385
4386 cli.bindProcessName( &ConfigData::processName );
4387
4388 cli.bind( &ConfigData::showHelp )
4389 .describe( "display usage information" )
4390 .shortOpt( "?")
4391 .shortOpt( "h")
4392 .longOpt( "help" );
4393
4394 cli.bind( &ConfigData::listTests )
4395 .describe( "list all (or matching) test cases" )
4396 .shortOpt( "l")
4397 .longOpt( "list-tests" );
4398
4399 cli.bind( &ConfigData::listTags )
4400 .describe( "list all (or matching) tags" )
4401 .shortOpt( "t")
4402 .longOpt( "list-tags" );
4403
4404 cli.bind( &ConfigData::listReporters )
4405 .describe( "list all reporters" )
4406 .longOpt( "list-reporters" );
4407
4408 cli.bind( &ConfigData::showSuccessfulTests )
4409 .describe( "include successful tests in output" )
4410 .shortOpt( "s")
4411 .longOpt( "success" );
4412
4413 cli.bind( &ConfigData::shouldDebugBreak )
4414 .describe( "break into debugger on failure" )
4415 .shortOpt( "b")
4416 .longOpt( "break" );
4417
4418 cli.bind( &ConfigData::noThrow )
Phil Nash7d5f2712013-06-07 21:15:25 +01004419 .describe( "skip exception tests" )
Phil Nash786959d2013-06-07 19:07:50 +01004420 .shortOpt( "e")
4421 .longOpt( "nothrow" );
4422
4423 cli.bind( &ConfigData::outputFilename )
4424 .describe( "output filename" )
4425 .shortOpt( "o")
4426 .longOpt( "out" )
Phil Nash46118712013-08-16 19:01:32 +01004427 .hint( "filename" );
Phil Nash786959d2013-06-07 19:07:50 +01004428
4429 cli.bind( &ConfigData::reporterName )
4430 .describe( "reporter to use - defaults to console" )
4431 .shortOpt( "r")
4432 .longOpt( "reporter" )
Phil Nash46118712013-08-16 19:01:32 +01004433// .hint( "name[:filename]" );
4434 .hint( "name" );
Phil Nash786959d2013-06-07 19:07:50 +01004435
4436 cli.bind( &ConfigData::name )
4437 .describe( "suite name" )
4438 .shortOpt( "n")
4439 .longOpt( "name" )
Phil Nash46118712013-08-16 19:01:32 +01004440 .hint( "name" );
Phil Nash786959d2013-06-07 19:07:50 +01004441
4442 cli.bind( &abortAfterFirst )
4443 .describe( "abort at first failure" )
4444 .shortOpt( "a")
4445 .longOpt( "abort" );
4446
4447 cli.bind( &abortAfterX )
4448 .describe( "abort after x failures" )
4449 .shortOpt( "x")
4450 .longOpt( "abortx" )
Phil Nash46118712013-08-16 19:01:32 +01004451 .hint( "number of failures" );
Phil Nash786959d2013-06-07 19:07:50 +01004452
4453 cli.bind( &addWarning )
4454 .describe( "enable warnings" )
4455 .shortOpt( "w")
4456 .longOpt( "warn" )
Phil Nash46118712013-08-16 19:01:32 +01004457 .hint( "warning name" );
Phil Nash786959d2013-06-07 19:07:50 +01004458
4459// cli.bind( &setVerbosity )
4460// .describe( "level of verbosity (0=no output)" )
4461// .shortOpt( "v")
4462// .longOpt( "verbosity" )
Phil Nash46118712013-08-16 19:01:32 +01004463// .hint( "level" );
Phil Nash786959d2013-06-07 19:07:50 +01004464
4465 cli.bind( &addTestOrTags )
4466 .describe( "which test or tests to use" )
Phil Nash46118712013-08-16 19:01:32 +01004467 .hint( "test name, pattern or tags" );
Phil Nash786959d2013-06-07 19:07:50 +01004468
Phil Nashaa7123b2013-08-15 19:01:00 +01004469 cli.bind( &setShowDurations )
4470 .describe( "show test durations" )
4471 .shortOpt( "d")
4472 .longOpt( "durations" )
Phil Nash46118712013-08-16 19:01:32 +01004473 .hint( "yes/no" );
Phil Nashaa7123b2013-08-15 19:01:00 +01004474
Phil Nash786959d2013-06-07 19:07:50 +01004475 return cli;
4476 }
4477
Phil Nasha695eb92012-08-13 07:46:10 +01004478} // end namespace Catch
4479
4480// #included from: internal/catch_list.hpp
4481#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
4482
Phil Nash5c7d3d72013-04-01 11:27:10 +01004483// #included from: catch_console_colour.hpp
4484#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01004485
4486namespace Catch {
Phil Nash5c7d3d72013-04-01 11:27:10 +01004487
Phil Nash12c16ff2013-04-05 20:58:01 +01004488 namespace Detail {
4489 struct IColourImpl;
4490 }
Phil Nash5c7d3d72013-04-01 11:27:10 +01004491
Phil Nash12c16ff2013-04-05 20:58:01 +01004492 struct Colour {
4493 enum Code {
4494 None = 0,
Phil Nash5c7d3d72013-04-01 11:27:10 +01004495
Phil Nash12c16ff2013-04-05 20:58:01 +01004496 White,
4497 Red,
4498 Green,
4499 Blue,
4500 Cyan,
4501 Yellow,
4502 Grey,
Phil Nash5c7d3d72013-04-01 11:27:10 +01004503
Phil Nash12c16ff2013-04-05 20:58:01 +01004504 Bright = 0x10,
Phil Nash5c7d3d72013-04-01 11:27:10 +01004505
Phil Nash12c16ff2013-04-05 20:58:01 +01004506 BrightRed = Bright | Red,
4507 BrightGreen = Bright | Green,
4508 LightGrey = Bright | Grey,
4509 BrightWhite = Bright | White,
4510
4511 // By intention
4512 FileName = LightGrey,
4513 ResultError = BrightRed,
4514 ResultSuccess = BrightGreen,
4515
4516 Error = BrightRed,
4517 Success = Green,
4518
4519 OriginalExpression = Cyan,
4520 ReconstructedExpression = Yellow,
4521
4522 SecondaryText = LightGrey,
4523 Headers = White
Phil Nash5c7d3d72013-04-01 11:27:10 +01004524 };
4525
Phil Nash12c16ff2013-04-05 20:58:01 +01004526 // Use constructed object for RAII guard
4527 Colour( Code _colourCode );
4528 ~Colour();
Phil Nash5c7d3d72013-04-01 11:27:10 +01004529
Phil Nash12c16ff2013-04-05 20:58:01 +01004530 // Use static method for one-shot changes
4531 static void use( Code _colourCode );
Phil Nash5c7d3d72013-04-01 11:27:10 +01004532
4533 private:
Phil Nash12c16ff2013-04-05 20:58:01 +01004534 static Detail::IColourImpl* impl;
Phil Nash5c7d3d72013-04-01 11:27:10 +01004535 };
4536
4537} // end namespace Catch
4538
Phil Nasha695eb92012-08-13 07:46:10 +01004539#include <limits>
Phil Nash38f7eef2013-03-29 13:44:33 +00004540#include <algorithm>
Phil Nasha695eb92012-08-13 07:46:10 +01004541
4542namespace Catch {
Phil Nash8defc712013-04-24 19:10:02 +01004543 inline bool matchesFilters( std::vector<TestCaseFilters> const& filters, TestCase const& testCase ) {
Phil Nash56d5c422012-08-23 20:08:50 +01004544 std::vector<TestCaseFilters>::const_iterator it = filters.begin();
4545 std::vector<TestCaseFilters>::const_iterator itEnd = filters.end();
4546 for(; it != itEnd; ++it )
4547 if( !it->shouldInclude( testCase ) )
4548 return false;
4549 return true;
4550 }
Phil Nasha695eb92012-08-13 07:46:10 +01004551
Phil Nash786959d2013-06-07 19:07:50 +01004552 inline std::size_t listTests( Config const& config ) {
4553 if( config.filters().empty() )
Phil Nash38f7eef2013-03-29 13:44:33 +00004554 std::cout << "All available test cases:\n";
4555 else
4556 std::cout << "Matching test cases:\n";
4557 std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests();
4558 std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end();
4559
4560 // First pass - get max tags
4561 std::size_t maxTagLen = 0;
4562 std::size_t maxNameLen = 0;
4563 for(; it != itEnd; ++it ) {
Phil Nash786959d2013-06-07 19:07:50 +01004564 if( matchesFilters( config.filters(), *it ) ) {
Phil Nash38f7eef2013-03-29 13:44:33 +00004565 maxTagLen = (std::max)( it->getTestCaseInfo().tagsAsString.size(), maxTagLen );
4566 maxNameLen = (std::max)( it->getTestCaseInfo().name.size(), maxNameLen );
Phil Nasha695eb92012-08-13 07:46:10 +01004567 }
Phil Nasha695eb92012-08-13 07:46:10 +01004568 }
4569
Phil Nash38f7eef2013-03-29 13:44:33 +00004570 // Try to fit everything in. If not shrink tag column first, down to 30
4571 // then shrink name column until it all fits (strings will be wrapped within column)
4572 while( maxTagLen + maxNameLen > CATCH_CONFIG_CONSOLE_WIDTH-5 ) {
4573 if( maxTagLen > 30 )
4574 --maxTagLen;
Phil Nash56d5c422012-08-23 20:08:50 +01004575 else
Phil Nash38f7eef2013-03-29 13:44:33 +00004576 --maxNameLen;
4577 }
4578
4579 std::size_t matchedTests = 0;
4580 for( it = allTests.begin(); it != itEnd; ++it ) {
Phil Nash786959d2013-06-07 19:07:50 +01004581 if( matchesFilters( config.filters(), *it ) ) {
Phil Nash38f7eef2013-03-29 13:44:33 +00004582 matchedTests++;
Phil Nash19279252013-04-20 21:07:32 +01004583 Text nameWrapper( it->getTestCaseInfo().name,
Phil Nash786959d2013-06-07 19:07:50 +01004584 TextAttributes()
4585 .setWidth( maxNameLen )
4586 .setInitialIndent(2)
4587 .setIndent(4) );
Phil Nash38f7eef2013-03-29 13:44:33 +00004588
Phil Nash19279252013-04-20 21:07:32 +01004589 Text tagsWrapper( it->getTestCaseInfo().tagsAsString,
Phil Nash786959d2013-06-07 19:07:50 +01004590 TextAttributes()
4591 .setWidth( maxTagLen )
4592 .setInitialIndent(0)
4593 .setIndent( 2 ) );
Phil Nash38f7eef2013-03-29 13:44:33 +00004594
Phil Nashcd688302013-06-29 12:11:32 +01004595 for( std::size_t i = 0; i < (std::max)( nameWrapper.size(), tagsWrapper.size() ); ++i ) {
Phil Nash12c16ff2013-04-05 20:58:01 +01004596 Colour::Code colour = Colour::None;
Phil Nash5c7d3d72013-04-01 11:27:10 +01004597 if( it->getTestCaseInfo().isHidden )
Phil Nash12c16ff2013-04-05 20:58:01 +01004598 colour = Colour::SecondaryText;
Phil Nash38f7eef2013-03-29 13:44:33 +00004599 std::string nameCol;
Phil Nash5c7d3d72013-04-01 11:27:10 +01004600 if( i < nameWrapper.size() ) {
Phil Nash38f7eef2013-03-29 13:44:33 +00004601 nameCol = nameWrapper[i];
Phil Nash5c7d3d72013-04-01 11:27:10 +01004602 }
4603 else {
Phil Nash38f7eef2013-03-29 13:44:33 +00004604 nameCol = " ...";
Phil Nash12c16ff2013-04-05 20:58:01 +01004605 colour = Colour::SecondaryText;
Phil Nash5c7d3d72013-04-01 11:27:10 +01004606 }
4607
4608 {
Phil Nash12c16ff2013-04-05 20:58:01 +01004609 Colour colourGuard( colour );
Phil Nash5c7d3d72013-04-01 11:27:10 +01004610 std::cout << nameCol;
4611 }
Phil Nash38f7eef2013-03-29 13:44:33 +00004612 if( i < tagsWrapper.size() && !tagsWrapper[i].empty() ) {
Phil Nash5c7d3d72013-04-01 11:27:10 +01004613 if( i == 0 ) {
Phil Nash12c16ff2013-04-05 20:58:01 +01004614 Colour colourGuard( Colour::SecondaryText );
Phil Nash5c7d3d72013-04-01 11:27:10 +01004615 std::cout << " " << std::string( maxNameLen - nameCol.size(), '.' ) << " ";
4616 }
4617 else {
4618 std::cout << std::string( maxNameLen - nameCol.size(), ' ' ) << " ";
4619 }
4620 std::cout << tagsWrapper[i];
Phil Nash38f7eef2013-03-29 13:44:33 +00004621 }
4622 std::cout << "\n";
Phil Nash56d5c422012-08-23 20:08:50 +01004623 }
Phil Nasha695eb92012-08-13 07:46:10 +01004624 }
Phil Nasha695eb92012-08-13 07:46:10 +01004625 }
Phil Nash786959d2013-06-07 19:07:50 +01004626 if( config.filters().empty() )
4627 std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl;
Phil Nash38f7eef2013-03-29 13:44:33 +00004628 else
Phil Nash786959d2013-06-07 19:07:50 +01004629 std::cout << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl;
4630 return matchedTests;
Phil Nash38f7eef2013-03-29 13:44:33 +00004631 }
Phil Nasha695eb92012-08-13 07:46:10 +01004632
Phil Nash786959d2013-06-07 19:07:50 +01004633 inline std::size_t listTags( Config const& config ) {
4634 if( config.filters().empty() )
Phil Nash38f7eef2013-03-29 13:44:33 +00004635 std::cout << "All available tags:\n";
4636 else
4637 std::cout << "Matching tags:\n";
4638 std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests();
4639 std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end();
4640
4641 std::map<std::string, int> tagCounts;
4642
4643 std::size_t maxTagLen = 0;
4644
4645 for(; it != itEnd; ++it ) {
Phil Nash786959d2013-06-07 19:07:50 +01004646 if( matchesFilters( config.filters(), *it ) ) {
Phil Nash38f7eef2013-03-29 13:44:33 +00004647 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
4648 tagItEnd = it->getTestCaseInfo().tags.end();
4649 tagIt != tagItEnd;
4650 ++tagIt ) {
Phil Nash12c16ff2013-04-05 20:58:01 +01004651 std::string tagName = *tagIt;
Phil Nash38f7eef2013-03-29 13:44:33 +00004652 maxTagLen = (std::max)( maxTagLen, tagName.size() );
4653 std::map<std::string, int>::iterator countIt = tagCounts.find( tagName );
4654 if( countIt == tagCounts.end() )
4655 tagCounts.insert( std::make_pair( tagName, 1 ) );
4656 else
4657 countIt->second++;
4658 }
4659 }
Phil Nasha695eb92012-08-13 07:46:10 +01004660 }
Phil Nash12c16ff2013-04-05 20:58:01 +01004661 maxTagLen +=4;
Phil Nash38f7eef2013-03-29 13:44:33 +00004662 if( maxTagLen > CATCH_CONFIG_CONSOLE_WIDTH-10 )
4663 maxTagLen = CATCH_CONFIG_CONSOLE_WIDTH-10;
4664
4665 for( std::map<std::string, int>::const_iterator countIt = tagCounts.begin(), countItEnd = tagCounts.end();
4666 countIt != countItEnd;
4667 ++countIt ) {
Phil Nash19279252013-04-20 21:07:32 +01004668 Text wrapper( "[" + countIt->first + "]", TextAttributes()
4669 .setIndent(2)
4670 .setWidth( maxTagLen ) );
Phil Nash38f7eef2013-03-29 13:44:33 +00004671 std::cout << wrapper;
Phil Nash5c7d3d72013-04-01 11:27:10 +01004672 std::size_t dots = 2;
Phil Nash38f7eef2013-03-29 13:44:33 +00004673 if( maxTagLen > wrapper.last().size() )
Phil Nash5c7d3d72013-04-01 11:27:10 +01004674 dots += maxTagLen - wrapper.last().size();
4675 {
Phil Nash12c16ff2013-04-05 20:58:01 +01004676 Colour colourGuard( Colour::SecondaryText );
Phil Nash5c7d3d72013-04-01 11:27:10 +01004677 std::cout << std::string( dots, '.' );
4678 }
4679 std::cout << countIt->second
Phil Nash38f7eef2013-03-29 13:44:33 +00004680 << "\n";
4681 }
Phil Nash786959d2013-06-07 19:07:50 +01004682 std::cout << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl;
4683 return tagCounts.size();
Phil Nash38f7eef2013-03-29 13:44:33 +00004684 }
4685
Phil Nash786959d2013-06-07 19:07:50 +01004686 inline std::size_t listReporters( Config const& /*config*/ ) {
Phil Nash38f7eef2013-03-29 13:44:33 +00004687 std::cout << "Available reports:\n";
4688 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
Phil Nash786959d2013-06-07 19:07:50 +01004689 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
4690 std::size_t maxNameLen = 0;
4691 for(it = itBegin; it != itEnd; ++it )
4692 maxNameLen = (std::max)( maxNameLen, it->first.size() );
4693
4694 for(it = itBegin; it != itEnd; ++it ) {
4695 Text wrapper( it->second->getDescription(), TextAttributes()
4696 .setInitialIndent( 0 )
4697 .setIndent( 7+maxNameLen )
4698 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
4699 std::cout << " "
4700 << it->first
4701 << ":"
4702 << std::string( maxNameLen - it->first.size() + 2, ' ' )
4703 << wrapper << "\n";
Phil Nash38f7eef2013-03-29 13:44:33 +00004704 }
4705 std::cout << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01004706 return factories.size();
Phil Nash38f7eef2013-03-29 13:44:33 +00004707 }
4708
Phil Nash786959d2013-06-07 19:07:50 +01004709 inline Option<std::size_t> list( Config const& config ) {
4710 Option<std::size_t> listedCount;
4711 if( config.listTests() )
4712 listedCount = listedCount.valueOr(0) + listTests( config );
4713 if( config.listTags() )
4714 listedCount = listedCount.valueOr(0) + listTags( config );
4715 if( config.listReporters() )
4716 listedCount = listedCount.valueOr(0) + listReporters( config );
4717 return listedCount;
Phil Nasha695eb92012-08-13 07:46:10 +01004718 }
4719
4720} // end namespace Catch
4721
4722// #included from: internal/catch_runner_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004723#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01004724
Phil Nash8a52a392013-07-25 08:12:03 +01004725// #included from: catch_test_case_tracker.hpp
4726#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01004727
4728#include <map>
4729#include <string>
Phil Nash8a52a392013-07-25 08:12:03 +01004730#include <assert.h>
Phil Nasha695eb92012-08-13 07:46:10 +01004731
4732namespace Catch {
Phil Nash8a52a392013-07-25 08:12:03 +01004733namespace SectionTracking {
Phil Nasha695eb92012-08-13 07:46:10 +01004734
Phil Nash8a52a392013-07-25 08:12:03 +01004735 class TrackedSection {
4736
4737 typedef std::map<std::string, TrackedSection> TrackedSections;
4738
Phil Nasha695eb92012-08-13 07:46:10 +01004739 public:
Phil Nash8a52a392013-07-25 08:12:03 +01004740 enum RunState {
4741 NotStarted,
4742 Executing,
4743 ExecutingChildren,
4744 Completed
Phil Nasha695eb92012-08-13 07:46:10 +01004745 };
4746
Phil Nash8a52a392013-07-25 08:12:03 +01004747 TrackedSection( std::string const& name, TrackedSection* parent )
4748 : m_name( name ), m_runState( NotStarted ), m_parent( parent )
Phil Nasha695eb92012-08-13 07:46:10 +01004749 {}
4750
Phil Nash8a52a392013-07-25 08:12:03 +01004751 RunState runState() const { return m_runState; }
Phil Nasha695eb92012-08-13 07:46:10 +01004752
Phil Nash8a52a392013-07-25 08:12:03 +01004753 void addChild( std::string const& childName ) {
4754 m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) );
4755 }
4756 TrackedSection* getChild( std::string const& childName ) {
4757 return &m_children.find( childName )->second;
Phil Nasha1fbfea2012-12-01 23:57:18 +00004758 }
4759
Phil Nash8a52a392013-07-25 08:12:03 +01004760 void enter() {
4761 if( m_runState == NotStarted )
4762 m_runState = Executing;
Phil Nasha695eb92012-08-13 07:46:10 +01004763 }
Phil Nash8a52a392013-07-25 08:12:03 +01004764 void leave() {
4765 for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end();
4766 it != itEnd;
4767 ++it )
4768 if( it->second.runState() != Completed ) {
4769 m_runState = ExecutingChildren;
4770 return;
4771 }
4772 m_runState = Completed;
Phil Nasha695eb92012-08-13 07:46:10 +01004773 }
Phil Nash8a52a392013-07-25 08:12:03 +01004774 TrackedSection* getParent() {
Phil Nasha695eb92012-08-13 07:46:10 +01004775 return m_parent;
4776 }
Phil Nash8a52a392013-07-25 08:12:03 +01004777 bool hasChildren() const {
4778 return !m_children.empty();
Phil Nasha1fbfea2012-12-01 23:57:18 +00004779 }
4780
Phil Nasha695eb92012-08-13 07:46:10 +01004781 private:
Phil Nasha1fbfea2012-12-01 23:57:18 +00004782 std::string m_name;
Phil Nash8a52a392013-07-25 08:12:03 +01004783 RunState m_runState;
4784 TrackedSections m_children;
4785 TrackedSection* m_parent;
4786
Phil Nasha695eb92012-08-13 07:46:10 +01004787 };
Phil Nasha695eb92012-08-13 07:46:10 +01004788
Phil Nash8a52a392013-07-25 08:12:03 +01004789 class TestCaseTracker {
Phil Nasha695eb92012-08-13 07:46:10 +01004790 public:
Phil Nash8a52a392013-07-25 08:12:03 +01004791 TestCaseTracker( std::string const& testCaseName )
4792 : m_testCase( testCaseName, NULL ),
4793 m_currentSection( &m_testCase ),
4794 m_completedASectionThisRun( false )
Phil Nasha695eb92012-08-13 07:46:10 +01004795 {}
4796
Phil Nash8a52a392013-07-25 08:12:03 +01004797 bool enterSection( std::string const& name ) {
4798 if( m_completedASectionThisRun )
4799 return false;
4800 if( m_currentSection->runState() == TrackedSection::Executing ) {
4801 m_currentSection->addChild( name );
4802 return false;
4803 }
4804 else {
4805 TrackedSection* child = m_currentSection->getChild( name );
4806 if( child->runState() != TrackedSection::Completed ) {
4807 m_currentSection = child;
4808 m_currentSection->enter();
4809 return true;
4810 }
4811 return false;
Phil Nasha695eb92012-08-13 07:46:10 +01004812 }
4813 }
Phil Nash8a52a392013-07-25 08:12:03 +01004814 void leaveSection() {
4815 m_currentSection->leave();
Phil Nasha695eb92012-08-13 07:46:10 +01004816 m_currentSection = m_currentSection->getParent();
Phil Nash8a52a392013-07-25 08:12:03 +01004817 assert( m_currentSection != NULL );
4818 m_completedASectionThisRun = true;
Phil Nasha695eb92012-08-13 07:46:10 +01004819 }
4820
Phil Nash8a52a392013-07-25 08:12:03 +01004821 bool currentSectionHasChildren() const {
4822 return m_currentSection->hasChildren();
4823 }
4824 bool isCompleted() const {
4825 return m_testCase.runState() == TrackedSection::Completed;
Phil Nasha695eb92012-08-13 07:46:10 +01004826 }
4827
Phil Nash8a52a392013-07-25 08:12:03 +01004828 class Guard {
4829 public:
4830 Guard( TestCaseTracker& tracker )
4831 : m_tracker( tracker )
4832 {
4833 m_tracker.enterTestCase();
4834 }
4835 ~Guard() {
4836 m_tracker.leaveTestCase();
4837 }
4838 private:
Phil Nash801672b2013-07-25 08:18:09 +01004839 Guard( Guard const& );
4840 void operator = ( Guard const& );
Phil Nash8a52a392013-07-25 08:12:03 +01004841 TestCaseTracker& m_tracker;
4842 };
Phil Nasha695eb92012-08-13 07:46:10 +01004843
4844 private:
Phil Nash8a52a392013-07-25 08:12:03 +01004845 void enterTestCase() {
4846 m_currentSection = &m_testCase;
4847 m_completedASectionThisRun = false;
4848 m_testCase.enter();
4849 }
4850 void leaveTestCase() {
4851 m_testCase.leave();
4852 }
Phil Nashdd26e882013-03-25 09:25:31 +00004853
Phil Nash8a52a392013-07-25 08:12:03 +01004854 TrackedSection m_testCase;
4855 TrackedSection* m_currentSection;
4856 bool m_completedASectionThisRun;
Phil Nasha695eb92012-08-13 07:46:10 +01004857 };
Phil Nash8a52a392013-07-25 08:12:03 +01004858
4859} // namespace SectionTracking
4860
4861using SectionTracking::TestCaseTracker;
4862
4863} // namespace Catch
Phil Nasha695eb92012-08-13 07:46:10 +01004864
4865#include <set>
4866#include <string>
4867
4868namespace Catch {
4869
4870 class StreamRedirect {
4871
4872 public:
4873 StreamRedirect( std::ostream& stream, std::string& targetString )
4874 : m_stream( stream ),
4875 m_prevBuf( stream.rdbuf() ),
4876 m_targetString( targetString )
4877 {
4878 stream.rdbuf( m_oss.rdbuf() );
4879 }
4880
4881 ~StreamRedirect() {
4882 m_targetString += m_oss.str();
4883 m_stream.rdbuf( m_prevBuf );
4884 }
4885
4886 private:
4887 std::ostream& m_stream;
4888 std::streambuf* m_prevBuf;
4889 std::ostringstream m_oss;
4890 std::string& m_targetString;
4891 };
4892
4893 ///////////////////////////////////////////////////////////////////////////
4894
Phil Nash786959d2013-06-07 19:07:50 +01004895 class RunContext : public IResultCapture, public IRunner {
Phil Nasha695eb92012-08-13 07:46:10 +01004896
Phil Nash786959d2013-06-07 19:07:50 +01004897 RunContext( RunContext const& );
4898 void operator =( RunContext const& );
Phil Nasha695eb92012-08-13 07:46:10 +01004899
4900 public:
4901
Phil Nash786959d2013-06-07 19:07:50 +01004902 explicit RunContext( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> const& reporter )
4903 : m_runInfo( config->name() ),
Phil Nasha1fbfea2012-12-01 23:57:18 +00004904 m_context( getCurrentMutableContext() ),
Phil Nash8a52a392013-07-25 08:12:03 +01004905 m_activeTestCase( NULL ),
Phil Nasha695eb92012-08-13 07:46:10 +01004906 m_config( config ),
4907 m_reporter( reporter ),
4908 m_prevRunner( &m_context.getRunner() ),
4909 m_prevResultCapture( &m_context.getResultCapture() ),
4910 m_prevConfig( m_context.getConfig() )
4911 {
4912 m_context.setRunner( this );
Phil Nash786959d2013-06-07 19:07:50 +01004913 m_context.setConfig( m_config );
Phil Nasha695eb92012-08-13 07:46:10 +01004914 m_context.setResultCapture( this );
Phil Nasha1fbfea2012-12-01 23:57:18 +00004915 m_reporter->testRunStarting( m_runInfo );
Phil Nasha695eb92012-08-13 07:46:10 +01004916 }
4917
Phil Nash786959d2013-06-07 19:07:50 +01004918 virtual ~RunContext() {
Phil Nash2e7d9662013-01-16 09:44:43 +00004919 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
Phil Nasha695eb92012-08-13 07:46:10 +01004920 m_context.setRunner( m_prevRunner );
4921 m_context.setConfig( NULL );
4922 m_context.setResultCapture( m_prevResultCapture );
4923 m_context.setConfig( m_prevConfig );
4924 }
4925
Phil Nash2e7d9662013-01-16 09:44:43 +00004926 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
4927 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00004928 }
Phil Nash2e7d9662013-01-16 09:44:43 +00004929 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
4930 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00004931 }
Phil Nasha695eb92012-08-13 07:46:10 +01004932
Phil Nash8defc712013-04-24 19:10:02 +01004933 Totals runMatching( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004934
Phil Nasha1fbfea2012-12-01 23:57:18 +00004935 std::vector<TestCase> matchingTests = getRegistryHub().getTestCaseRegistry().getMatchingTestCases( testSpec );
Phil Nash5bc030d2012-08-16 18:48:50 +01004936
4937 Totals totals;
Phil Nash5bc030d2012-08-16 18:48:50 +01004938
Phil Nash2e7d9662013-01-16 09:44:43 +00004939 testGroupStarting( testSpec, groupIndex, groupsCount );
Phil Nash56d5c422012-08-23 20:08:50 +01004940
Phil Nasha1fbfea2012-12-01 23:57:18 +00004941 std::vector<TestCase>::const_iterator it = matchingTests.begin();
4942 std::vector<TestCase>::const_iterator itEnd = matchingTests.end();
Phil Nash56d5c422012-08-23 20:08:50 +01004943 for(; it != itEnd; ++it )
4944 totals += runTest( *it );
Phil Nash56d5c422012-08-23 20:08:50 +01004945
Phil Nash2e7d9662013-01-16 09:44:43 +00004946 testGroupEnded( testSpec, totals, groupIndex, groupsCount );
Phil Nash5bc030d2012-08-16 18:48:50 +01004947 return totals;
4948 }
4949
Phil Nash8defc712013-04-24 19:10:02 +01004950 Totals runTest( TestCase const& testCase ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004951 Totals prevTotals = m_totals;
4952
4953 std::string redirectedCout;
4954 std::string redirectedCerr;
4955
Phil Nasha1fbfea2012-12-01 23:57:18 +00004956 TestCaseInfo testInfo = testCase.getTestCaseInfo();
Phil Nasha695eb92012-08-13 07:46:10 +01004957
Phil Nasha1fbfea2012-12-01 23:57:18 +00004958 m_reporter->testCaseStarting( testInfo );
4959
Phil Nash8a52a392013-07-25 08:12:03 +01004960 m_activeTestCase = &testCase;
4961 m_testCaseTracker = TestCaseTracker( testInfo.name );
Phil Nasha695eb92012-08-13 07:46:10 +01004962
4963 do {
4964 do {
Phil Nasha695eb92012-08-13 07:46:10 +01004965 runCurrentTest( redirectedCout, redirectedCerr );
Phil Nasha695eb92012-08-13 07:46:10 +01004966 }
Phil Nash8a52a392013-07-25 08:12:03 +01004967 while( !m_testCaseTracker->isCompleted() && !aborting() );
Phil Nasha695eb92012-08-13 07:46:10 +01004968 }
4969 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
4970
Phil Nash28463672012-11-21 18:06:13 +00004971 Totals deltaTotals = m_totals.delta( prevTotals );
Phil Nash28463672012-11-21 18:06:13 +00004972 m_totals.testCases += deltaTotals.testCases;
Phil Nash2e7d9662013-01-16 09:44:43 +00004973 m_reporter->testCaseEnded( TestCaseStats( testInfo,
4974 deltaTotals,
4975 redirectedCout,
4976 redirectedCerr,
Phil Nash2e7d9662013-01-16 09:44:43 +00004977 aborting() ) );
Phil Nash28463672012-11-21 18:06:13 +00004978
Phil Nash8a52a392013-07-25 08:12:03 +01004979 m_activeTestCase = NULL;
4980 m_testCaseTracker.reset();
Phil Nasha695eb92012-08-13 07:46:10 +01004981
Phil Nash5bc030d2012-08-16 18:48:50 +01004982 return deltaTotals;
Phil Nasha695eb92012-08-13 07:46:10 +01004983 }
4984
Phil Nash786959d2013-06-07 19:07:50 +01004985 Ptr<IConfig const> config() const {
Phil Nasha695eb92012-08-13 07:46:10 +01004986 return m_config;
4987 }
4988
4989 private: // IResultCapture
4990
Phil Nash8defc712013-04-24 19:10:02 +01004991 virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) {
Phil Nash90a35942012-11-13 22:04:29 +00004992 m_lastAssertionInfo = assertionInfo;
4993 return actOnCurrentResult( assertionResult.buildResult( assertionInfo ) );
Phil Nasha695eb92012-08-13 07:46:10 +01004994 }
4995
Phil Nash8defc712013-04-24 19:10:02 +01004996 virtual void assertionEnded( AssertionResult const& result ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004997 if( result.getResultType() == ResultWas::Ok ) {
4998 m_totals.assertions.passed++;
4999 }
Phil Nash90a35942012-11-13 22:04:29 +00005000 else if( !result.isOk() ) {
Phil Nasha695eb92012-08-13 07:46:10 +01005001 m_totals.assertions.failed++;
Phil Nasha695eb92012-08-13 07:46:10 +01005002 }
5003
Phil Nashb5fd5a62013-06-28 17:09:57 +01005004 if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) )
5005 m_messages.clear();
Phil Nasha90a88a2012-11-19 19:59:10 +00005006
Phil Nasha2773812013-02-02 20:37:58 +00005007 // Reset working state
5008 m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
Phil Nasha695eb92012-08-13 07:46:10 +01005009 }
5010
5011 virtual bool sectionStarted (
Phil Nasha1fbfea2012-12-01 23:57:18 +00005012 SectionInfo const& sectionInfo,
Phil Nasha695eb92012-08-13 07:46:10 +01005013 Counts& assertions
5014 )
5015 {
5016 std::ostringstream oss;
Phil Nasha1fbfea2012-12-01 23:57:18 +00005017 oss << sectionInfo.name << "@" << sectionInfo.lineInfo;
Phil Nasha695eb92012-08-13 07:46:10 +01005018
Phil Nash8a52a392013-07-25 08:12:03 +01005019 if( !m_testCaseTracker->enterSection( oss.str() ) )
Phil Nasha695eb92012-08-13 07:46:10 +01005020 return false;
5021
Phil Nasha1fbfea2012-12-01 23:57:18 +00005022 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
Phil Nash90a35942012-11-13 22:04:29 +00005023
Phil Nasha1fbfea2012-12-01 23:57:18 +00005024 m_reporter->sectionStarting( sectionInfo );
5025
Phil Nasha695eb92012-08-13 07:46:10 +01005026 assertions = m_totals.assertions;
5027
5028 return true;
5029 }
Phil Nashaa7123b2013-08-15 19:01:00 +01005030 bool testForMissingAssertions( Counts& assertions ) {
5031 if( assertions.total() != 0 ||
5032 !m_config->warnAboutMissingAssertions() ||
5033 m_testCaseTracker->currentSectionHasChildren() )
5034 return false;
5035 m_totals.assertions.failed++;
5036 assertions.failed++;
5037 return true;
5038 }
Phil Nasha695eb92012-08-13 07:46:10 +01005039
Phil Nashaa7123b2013-08-15 19:01:00 +01005040 virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) {
Phil Nash5bdae842013-02-19 19:47:18 +00005041 if( std::uncaught_exception() ) {
Phil Nashaa7123b2013-08-15 19:01:00 +01005042 m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) );
Phil Nash5bdae842013-02-19 19:47:18 +00005043 return;
5044 }
5045
Phil Nasha70fbe32012-08-31 08:10:36 +01005046 Counts assertions = m_totals.assertions - prevAssertions;
Phil Nashaa7123b2013-08-15 19:01:00 +01005047 bool missingAssertions = testForMissingAssertions( assertions );
Phil Nasha1fbfea2012-12-01 23:57:18 +00005048
Phil Nash8a52a392013-07-25 08:12:03 +01005049 m_testCaseTracker->leaveSection();
Phil Nasha1fbfea2012-12-01 23:57:18 +00005050
Phil Nashaa7123b2013-08-15 19:01:00 +01005051 m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) );
Phil Nasha2773812013-02-02 20:37:58 +00005052 m_messages.clear();
Phil Nasha695eb92012-08-13 07:46:10 +01005053 }
5054
Phil Nashb5fd5a62013-06-28 17:09:57 +01005055 virtual void pushScopedMessage( MessageInfo const& message ) {
5056 m_messages.push_back( message );
Phil Nasha695eb92012-08-13 07:46:10 +01005057 }
5058
Phil Nashb5fd5a62013-06-28 17:09:57 +01005059 virtual void popScopedMessage( MessageInfo const& message ) {
5060 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
Phil Nasha695eb92012-08-13 07:46:10 +01005061 }
5062
5063 virtual bool shouldDebugBreak() const {
Phil Nash786959d2013-06-07 19:07:50 +01005064 return m_config->shouldDebugBreak();
Phil Nasha695eb92012-08-13 07:46:10 +01005065 }
5066
5067 virtual std::string getCurrentTestName() const {
Phil Nash8a52a392013-07-25 08:12:03 +01005068 return m_activeTestCase
5069 ? m_activeTestCase->getTestCaseInfo().name
Phil Nasha695eb92012-08-13 07:46:10 +01005070 : "";
5071 }
5072
Phil Nashce612bf2012-11-01 08:27:09 +00005073 virtual const AssertionResult* getLastResult() const {
Phil Nasha695eb92012-08-13 07:46:10 +01005074 return &m_lastResult;
5075 }
5076
Phil Nash56d5c422012-08-23 20:08:50 +01005077 public:
5078 // !TBD We need to do this another way!
Phil Nasha695eb92012-08-13 07:46:10 +01005079 bool aborting() const {
Phil Nash786959d2013-06-07 19:07:50 +01005080 return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() );
Phil Nasha695eb92012-08-13 07:46:10 +01005081 }
5082
Phil Nash56d5c422012-08-23 20:08:50 +01005083 private:
5084
Phil Nash8defc712013-04-24 19:10:02 +01005085 ResultAction::Value actOnCurrentResult( AssertionResult const& result ) {
Phil Nash90a35942012-11-13 22:04:29 +00005086 m_lastResult = result;
Phil Nasha2773812013-02-02 20:37:58 +00005087 assertionEnded( m_lastResult );
Phil Nasha695eb92012-08-13 07:46:10 +01005088
Phil Nasha695eb92012-08-13 07:46:10 +01005089 ResultAction::Value action = ResultAction::None;
5090
Phil Nash90a35942012-11-13 22:04:29 +00005091 if( !m_lastResult.isOk() ) {
Phil Nasha695eb92012-08-13 07:46:10 +01005092 action = ResultAction::Failed;
5093 if( shouldDebugBreak() )
5094 action = (ResultAction::Value)( action | ResultAction::Debug );
5095 if( aborting() )
5096 action = (ResultAction::Value)( action | ResultAction::Abort );
5097 }
5098 return action;
5099 }
5100
5101 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
Phil Nash8a52a392013-07-25 08:12:03 +01005102 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
5103 SectionInfo testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo );
5104 m_reporter->sectionStarting( testCaseSection );
Phil Nashaa7123b2013-08-15 19:01:00 +01005105 Counts prevAssertions = m_totals.assertions;
5106 double duration = 0;
Phil Nasha695eb92012-08-13 07:46:10 +01005107 try {
Phil Nash8a52a392013-07-25 08:12:03 +01005108 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
5109 TestCaseTracker::Guard guard( *m_testCaseTracker );
Phil Nashd768b1b2013-02-04 00:05:16 +00005110
Phil Nashaa7123b2013-08-15 19:01:00 +01005111 Timer timer;
5112 timer.start();
Phil Nasha1fbfea2012-12-01 23:57:18 +00005113 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
Phil Nasha695eb92012-08-13 07:46:10 +01005114 StreamRedirect coutRedir( std::cout, redirectedCout );
5115 StreamRedirect cerrRedir( std::cerr, redirectedCerr );
Phil Nash8a52a392013-07-25 08:12:03 +01005116 m_activeTestCase->invoke();
Phil Nasha695eb92012-08-13 07:46:10 +01005117 }
5118 else {
Phil Nash8a52a392013-07-25 08:12:03 +01005119 m_activeTestCase->invoke();
Phil Nasha70fbe32012-08-31 08:10:36 +01005120 }
Phil Nashaa7123b2013-08-15 19:01:00 +01005121 duration = timer.getElapsedSeconds();
Phil Nasha695eb92012-08-13 07:46:10 +01005122 }
5123 catch( TestFailureException& ) {
5124 // This just means the test was aborted due to failure
5125 }
5126 catch(...) {
Phil Nash90a35942012-11-13 22:04:29 +00005127 ExpressionResultBuilder exResult( ResultWas::ThrewException );
5128 exResult << translateActiveException();
5129 actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo ) );
Phil Nasha695eb92012-08-13 07:46:10 +01005130 }
Phil Nash8a52a392013-07-25 08:12:03 +01005131 // If sections ended prematurely due to an exception we stored their
5132 // infos here so we can tear them down outside the unwind process.
Phil Nash5bdae842013-02-19 19:47:18 +00005133 for( std::vector<UnfinishedSections>::const_iterator it = m_unfinishedSections.begin(),
5134 itEnd = m_unfinishedSections.end();
5135 it != itEnd;
5136 ++it )
Phil Nashaa7123b2013-08-15 19:01:00 +01005137 sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
Phil Nash5bdae842013-02-19 19:47:18 +00005138 m_unfinishedSections.clear();
Phil Nashd768b1b2013-02-04 00:05:16 +00005139 m_messages.clear();
Phil Nashaa7123b2013-08-15 19:01:00 +01005140
5141 Counts assertions = m_totals.assertions - prevAssertions;
5142 bool missingAssertions = testForMissingAssertions( assertions );
5143
5144 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
Phil Nash8a52a392013-07-25 08:12:03 +01005145 m_reporter->sectionEnded( testCaseSectionStats );
Phil Nasha695eb92012-08-13 07:46:10 +01005146 }
5147
5148 private:
Phil Nash5bdae842013-02-19 19:47:18 +00005149 struct UnfinishedSections {
Phil Nashaa7123b2013-08-15 19:01:00 +01005150 UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds )
5151 : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
Phil Nash5bdae842013-02-19 19:47:18 +00005152 {}
5153
5154 SectionInfo info;
5155 Counts prevAssertions;
Phil Nashaa7123b2013-08-15 19:01:00 +01005156 double durationInSeconds;
Phil Nash5bdae842013-02-19 19:47:18 +00005157 };
5158
Phil Nasha1fbfea2012-12-01 23:57:18 +00005159 TestRunInfo m_runInfo;
Phil Nasha695eb92012-08-13 07:46:10 +01005160 IMutableContext& m_context;
Phil Nash8a52a392013-07-25 08:12:03 +01005161 TestCase const* m_activeTestCase;
5162 Option<TestCaseTracker> m_testCaseTracker;
Phil Nashce612bf2012-11-01 08:27:09 +00005163 AssertionResult m_lastResult;
Phil Nasha695eb92012-08-13 07:46:10 +01005164
Phil Nash786959d2013-06-07 19:07:50 +01005165 Ptr<IConfig const> m_config;
Phil Nasha695eb92012-08-13 07:46:10 +01005166 Totals m_totals;
Phil Nasha1fbfea2012-12-01 23:57:18 +00005167 Ptr<IStreamingReporter> m_reporter;
Phil Nasha2773812013-02-02 20:37:58 +00005168 std::vector<MessageInfo> m_messages;
Phil Nasha695eb92012-08-13 07:46:10 +01005169 IRunner* m_prevRunner;
5170 IResultCapture* m_prevResultCapture;
Phil Nash786959d2013-06-07 19:07:50 +01005171 Ptr<IConfig const> m_prevConfig;
Phil Nash90a35942012-11-13 22:04:29 +00005172 AssertionInfo m_lastAssertionInfo;
Phil Nash5bdae842013-02-19 19:47:18 +00005173 std::vector<UnfinishedSections> m_unfinishedSections;
Phil Nasha695eb92012-08-13 07:46:10 +01005174 };
5175
5176} // end namespace Catch
5177
Phil Nash7673a302012-11-15 22:15:41 +00005178// #included from: internal/catch_version.h
5179#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
5180
5181namespace Catch {
5182
5183 // Versioning information
5184 struct Version {
Phil Nasha1fbfea2012-12-01 23:57:18 +00005185 Version( unsigned int _majorVersion,
5186 unsigned int _minorVersion,
5187 unsigned int _buildNumber,
5188 std::string const& _branchName )
5189 : majorVersion( _majorVersion ),
5190 minorVersion( _minorVersion ),
5191 buildNumber( _buildNumber ),
5192 branchName( _branchName )
5193 {}
5194
5195 const unsigned int majorVersion;
5196 const unsigned int minorVersion;
5197 const unsigned int buildNumber;
5198 const std::string branchName;
Phil Nashdd26e882013-03-25 09:25:31 +00005199
Phil Nash503d5d02013-07-03 08:25:11 +01005200 private:
5201 void operator=( Version const& );
Phil Nash7673a302012-11-15 22:15:41 +00005202 };
5203
5204 extern Version libraryVersion;
5205}
5206
Phil Nash89d1e6c2011-05-24 08:23:02 +01005207#include <fstream>
5208#include <stdlib.h>
5209#include <limits>
5210
Phil Nash89d2a3f2012-05-16 15:09:17 +01005211namespace Catch {
5212
Phil Nash786959d2013-06-07 19:07:50 +01005213 class Runner {
Phil Nash163088a2012-05-31 19:40:26 +01005214
Phil Nash56d5c422012-08-23 20:08:50 +01005215 public:
Phil Nash786959d2013-06-07 19:07:50 +01005216 Runner( Ptr<Config> const& config )
5217 : m_config( config )
Phil Nash06e959b2012-05-25 08:52:05 +01005218 {
Phil Nash67ec8702012-09-26 18:38:26 +01005219 openStream();
Phil Nash56d5c422012-08-23 20:08:50 +01005220 makeReporter();
5221 }
Phil Nash06e959b2012-05-25 08:52:05 +01005222
Phil Nash56d5c422012-08-23 20:08:50 +01005223 Totals runTests() {
5224
Phil Nash786959d2013-06-07 19:07:50 +01005225 std::vector<TestCaseFilters> filterGroups = m_config->filters();
Phil Nash56d5c422012-08-23 20:08:50 +01005226 if( filterGroups.empty() ) {
5227 TestCaseFilters filterGroup( "" );
Phil Nash56d5c422012-08-23 20:08:50 +01005228 filterGroups.push_back( filterGroup );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005229 }
Phil Nash56d5c422012-08-23 20:08:50 +01005230
Phil Nash786959d2013-06-07 19:07:50 +01005231 RunContext context( m_config.get(), m_reporter );
5232
Phil Nash56d5c422012-08-23 20:08:50 +01005233 Totals totals;
5234
Phil Nash2e7d9662013-01-16 09:44:43 +00005235 for( std::size_t i=0; i < filterGroups.size() && !context.aborting(); ++i ) {
5236 context.testGroupStarting( filterGroups[i].getName(), i, filterGroups.size() );
5237 totals += runTestsForGroup( context, filterGroups[i] );
5238 context.testGroupEnded( filterGroups[i].getName(), totals, i, filterGroups.size() );
Phil Nash56d5c422012-08-23 20:08:50 +01005239 }
5240 return totals;
5241 }
5242
Phil Nash786959d2013-06-07 19:07:50 +01005243 Totals runTestsForGroup( RunContext& context, const TestCaseFilters& filterGroup ) {
Phil Nash56d5c422012-08-23 20:08:50 +01005244 Totals totals;
Phil Nasha1fbfea2012-12-01 23:57:18 +00005245 std::vector<TestCase>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin();
5246 std::vector<TestCase>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end();
Phil Nash56d5c422012-08-23 20:08:50 +01005247 int testsRunForGroup = 0;
5248 for(; it != itEnd; ++it ) {
5249 if( filterGroup.shouldInclude( *it ) ) {
5250 testsRunForGroup++;
5251 if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
5252
5253 if( context.aborting() )
5254 break;
5255
5256 totals += context.runTest( *it );
5257 m_testsAlreadyRun.insert( *it );
5258 }
Phil Nash06e959b2012-05-25 08:52:05 +01005259 }
5260 }
Phil Nash5bdae842013-02-19 19:47:18 +00005261 if( testsRunForGroup == 0 && !filterGroup.getName().empty() )
Phil Nash37186a12013-03-13 12:19:30 +00005262 m_reporter->noMatchingTestCases( filterGroup.getName() );
Phil Nash56d5c422012-08-23 20:08:50 +01005263 return totals;
5264
Phil Nash89d1e6c2011-05-24 08:23:02 +01005265 }
Phil Nash56d5c422012-08-23 20:08:50 +01005266
5267 private:
Phil Nash67ec8702012-09-26 18:38:26 +01005268 void openStream() {
Phil Nash56d5c422012-08-23 20:08:50 +01005269 // Open output file, if specified
Phil Nash786959d2013-06-07 19:07:50 +01005270 if( !m_config->getFilename().empty() ) {
5271 m_ofs.open( m_config->getFilename().c_str() );
Phil Nash56d5c422012-08-23 20:08:50 +01005272 if( m_ofs.fail() ) {
5273 std::ostringstream oss;
Phil Nash786959d2013-06-07 19:07:50 +01005274 oss << "Unable to open file: '" << m_config->getFilename() << "'";
Phil Nash56d5c422012-08-23 20:08:50 +01005275 throw std::domain_error( oss.str() );
5276 }
Phil Nash786959d2013-06-07 19:07:50 +01005277 m_config->setStreamBuf( m_ofs.rdbuf() );
Phil Nash56d5c422012-08-23 20:08:50 +01005278 }
5279 }
5280 void makeReporter() {
Phil Nash786959d2013-06-07 19:07:50 +01005281 std::string reporterName = m_config->getReporterName().empty()
5282 ? "console"
5283 : m_config->getReporterName();
Phil Nash56d5c422012-08-23 20:08:50 +01005284
Phil Nash786959d2013-06-07 19:07:50 +01005285 m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() );
Phil Nash56d5c422012-08-23 20:08:50 +01005286 if( !m_reporter ) {
5287 std::ostringstream oss;
5288 oss << "No reporter registered with name: '" << reporterName << "'";
5289 throw std::domain_error( oss.str() );
5290 }
5291 }
5292
5293 private:
Phil Nash786959d2013-06-07 19:07:50 +01005294 Ptr<Config> m_config;
Phil Nash56d5c422012-08-23 20:08:50 +01005295 std::ofstream m_ofs;
Phil Nasha1fbfea2012-12-01 23:57:18 +00005296 Ptr<IStreamingReporter> m_reporter;
5297 std::set<TestCase> m_testsAlreadyRun;
Phil Nash56d5c422012-08-23 20:08:50 +01005298 };
5299
Phil Nash786959d2013-06-07 19:07:50 +01005300 class Session {
5301 static bool alreadyInstantiated;
Phil Nash56d5c422012-08-23 20:08:50 +01005302
Phil Nash786959d2013-06-07 19:07:50 +01005303 public:
Phil Nash56d5c422012-08-23 20:08:50 +01005304
Phil Nash786959d2013-06-07 19:07:50 +01005305 struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
5306
5307 Session()
5308 : m_cli( makeCommandLineParser() ) {
5309 if( alreadyInstantiated ) {
5310 std::string msg = "Only one instance of Catch::Session can ever be used";
5311 std::cerr << msg << std::endl;
5312 throw std::logic_error( msg );
Phil Nash56d5c422012-08-23 20:08:50 +01005313 }
Phil Nash786959d2013-06-07 19:07:50 +01005314 alreadyInstantiated = true;
Phil Nash56d5c422012-08-23 20:08:50 +01005315 }
Phil Nash786959d2013-06-07 19:07:50 +01005316 ~Session() {
Phil Nash3b80af72012-08-09 07:47:30 +01005317 Catch::cleanUp();
Phil Nash89d1e6c2011-05-24 08:23:02 +01005318 }
5319
Phil Nash786959d2013-06-07 19:07:50 +01005320 void showHelp( std::string const& processName ) {
5321 std::cout << "\nCatch v" << libraryVersion.majorVersion << "."
Phil Nasha1fbfea2012-12-01 23:57:18 +00005322 << libraryVersion.minorVersion << " build "
5323 << libraryVersion.buildNumber;
5324 if( libraryVersion.branchName != "master" )
5325 std::cout << " (" << libraryVersion.branchName << " branch)";
Phil Nash786959d2013-06-07 19:07:50 +01005326 std::cout << "\n";
Phil Nash89d1e6c2011-05-24 08:23:02 +01005327
Phil Nash786959d2013-06-07 19:07:50 +01005328 m_cli.usage( std::cout, processName );
5329 std::cout << "For more detail usage please see the project docs\n" << std::endl;
Phil Nash3b80af72012-08-09 07:47:30 +01005330 }
Phil Nash3b80af72012-08-09 07:47:30 +01005331
Phil Nash786959d2013-06-07 19:07:50 +01005332 int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
5333 try {
5334 m_unusedTokens = m_cli.parseInto( argc, argv, m_configData );
5335 if( unusedOptionBehaviour == OnUnusedOptions::Fail )
5336 enforceNoUsedTokens();
5337 if( m_configData.showHelp )
5338 showHelp( m_configData.processName );
5339 m_config.reset();
Phil Nash3b80af72012-08-09 07:47:30 +01005340 }
Phil Nash786959d2013-06-07 19:07:50 +01005341 catch( std::exception& ex ) {
Phil Nash46118712013-08-16 19:01:32 +01005342 {
5343 Colour colourGuard( Colour::Red );
5344 std::cerr << "\nError in input:\n"
5345 << Text( ex.what(), TextAttributes().setIndent(2) )
5346 << "\n\n";
5347 }
Phil Nash786959d2013-06-07 19:07:50 +01005348 m_cli.usage( std::cout, m_configData.processName );
5349 return (std::numeric_limits<int>::max)();
5350 }
5351 return 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01005352 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01005353
Phil Nash786959d2013-06-07 19:07:50 +01005354 void useConfigData( ConfigData const& _configData ) {
5355 m_configData = _configData;
5356 m_config.reset();
5357 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01005358
Phil Nash786959d2013-06-07 19:07:50 +01005359 void enforceNoUsedTokens() const {
5360 if( !m_unusedTokens.empty() ) {
5361 std::vector<Clara::Parser::Token>::const_iterator
5362 it = m_unusedTokens.begin(),
5363 itEnd = m_unusedTokens.end();
5364 std::string msg;
5365 for(; it != itEnd; ++it )
5366 msg += " unrecognised option: " + it->data + "\n";
5367 throw std::runtime_error( msg.substr( 0, msg.size()-1 ) );
5368 }
5369 }
5370
5371 int run( int argc, char* const argv[] ) {
5372
5373 int returnCode = applyCommandLine( argc, argv );
5374 if( returnCode == 0 )
5375 returnCode = run();
5376 return returnCode;
5377 }
5378
5379 int run() {
5380 if( m_configData.showHelp )
5381 return 0;
5382
5383 try
5384 {
5385 config(); // Force config to be constructed
5386 Runner runner( m_config );
5387
5388 // Handle list request
5389 if( Option<std::size_t> listed = list( config() ) )
5390 return static_cast<int>( *listed );
5391
5392 return static_cast<int>( runner.runTests().assertions.failed );
5393 }
5394 catch( std::exception& ex ) {
5395 std::cerr << ex.what() << std::endl;
5396 return (std::numeric_limits<int>::max)();
5397 }
5398 }
5399
5400 Clara::CommandLine<ConfigData> const& cli() const {
5401 return m_cli;
5402 }
5403 std::vector<Clara::Parser::Token> const& unusedTokens() const {
5404 return m_unusedTokens;
5405 }
5406 ConfigData& configData() {
5407 return m_configData;
5408 }
5409 Config& config() {
5410 if( !m_config )
5411 m_config = new Config( m_configData );
5412 return *m_config;
5413 }
5414
5415 private:
5416 Clara::CommandLine<ConfigData> m_cli;
5417 std::vector<Clara::Parser::Token> m_unusedTokens;
5418 ConfigData m_configData;
5419 Ptr<Config> m_config;
5420 };
5421
5422 bool Session::alreadyInstantiated = false;
Phil Nash89d1e6c2011-05-24 08:23:02 +01005423
5424} // end namespace Catch
5425
5426// #included from: catch_registry_hub.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005427#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01005428
Phil Nash89d1e6c2011-05-24 08:23:02 +01005429// #included from: catch_test_case_registry_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005430#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01005431
5432#include <vector>
5433#include <set>
Phil Nash3b80af72012-08-09 07:47:30 +01005434#include <sstream>
5435#include <iostream>
5436
5437namespace Catch {
5438
5439 class TestRegistry : public ITestCaseRegistry {
5440 public:
5441 TestRegistry() : m_unnamedCount( 0 ) {}
5442 virtual ~TestRegistry();
5443
Phil Nash8defc712013-04-24 19:10:02 +01005444 virtual void registerTest( TestCase const& testCase ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00005445 std::string name = testCase.getTestCaseInfo().name;
5446 if( name == "" ) {
Phil Nash3b80af72012-08-09 07:47:30 +01005447 std::ostringstream oss;
Phil Nash93906752013-03-16 20:21:51 +00005448 oss << "Anonymous test case " << ++m_unnamedCount;
Phil Nasha1fbfea2012-12-01 23:57:18 +00005449 return registerTest( testCase.withName( oss.str() ) );
Phil Nash3b80af72012-08-09 07:47:30 +01005450 }
5451
Phil Nasha1fbfea2012-12-01 23:57:18 +00005452 if( m_functions.find( testCase ) == m_functions.end() ) {
5453 m_functions.insert( testCase );
5454 m_functionsInOrder.push_back( testCase );
5455 if( !testCase.isHidden() )
5456 m_nonHiddenFunctions.push_back( testCase );
Phil Nash3b80af72012-08-09 07:47:30 +01005457 }
5458 else {
Phil Nash8defc712013-04-24 19:10:02 +01005459 TestCase const& prev = *m_functions.find( testCase );
Phil Nasha1fbfea2012-12-01 23:57:18 +00005460 std::cerr << "error: TEST_CASE( \"" << name << "\" ) already defined.\n"
5461 << "\tFirst seen at " << SourceLineInfo( prev.getTestCaseInfo().lineInfo ) << "\n"
5462 << "\tRedefined at " << SourceLineInfo( testCase.getTestCaseInfo().lineInfo ) << std::endl;
Phil Nash3b80af72012-08-09 07:47:30 +01005463 exit(1);
5464 }
5465 }
5466
Phil Nash8defc712013-04-24 19:10:02 +01005467 virtual std::vector<TestCase> const& getAllTests() const {
Phil Nash3b80af72012-08-09 07:47:30 +01005468 return m_functionsInOrder;
5469 }
5470
Phil Nash8defc712013-04-24 19:10:02 +01005471 virtual std::vector<TestCase> const& getAllNonHiddenTests() const {
Phil Nash3b80af72012-08-09 07:47:30 +01005472 return m_nonHiddenFunctions;
5473 }
5474
5475 // !TBD deprecated
Phil Nash8defc712013-04-24 19:10:02 +01005476 virtual std::vector<TestCase> getMatchingTestCases( std::string const& rawTestSpec ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00005477 std::vector<TestCase> matchingTests;
Phil Nash3b80af72012-08-09 07:47:30 +01005478 getMatchingTestCases( rawTestSpec, matchingTests );
5479 return matchingTests;
5480 }
5481
5482 // !TBD deprecated
Phil Nash8defc712013-04-24 19:10:02 +01005483 virtual void getMatchingTestCases( std::string const& rawTestSpec, std::vector<TestCase>& matchingTestsOut ) const {
Phil Nash3b80af72012-08-09 07:47:30 +01005484 TestCaseFilter filter( rawTestSpec );
5485
Phil Nasha1fbfea2012-12-01 23:57:18 +00005486 std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin();
5487 std::vector<TestCase>::const_iterator itEnd = m_functionsInOrder.end();
Phil Nash3b80af72012-08-09 07:47:30 +01005488 for(; it != itEnd; ++it ) {
5489 if( filter.shouldInclude( *it ) ) {
5490 matchingTestsOut.push_back( *it );
5491 }
5492 }
5493 }
Phil Nash8defc712013-04-24 19:10:02 +01005494 virtual void getMatchingTestCases( TestCaseFilters const& filters, std::vector<TestCase>& matchingTestsOut ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00005495 std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin();
5496 std::vector<TestCase>::const_iterator itEnd = m_functionsInOrder.end();
Phil Nash3b80af72012-08-09 07:47:30 +01005497 // !TBD: replace with algorithm
5498 for(; it != itEnd; ++it )
5499 if( filters.shouldInclude( *it ) )
5500 matchingTestsOut.push_back( *it );
5501 }
5502
5503 private:
5504
Phil Nasha1fbfea2012-12-01 23:57:18 +00005505 std::set<TestCase> m_functions;
5506 std::vector<TestCase> m_functionsInOrder;
5507 std::vector<TestCase> m_nonHiddenFunctions;
Phil Nash3b80af72012-08-09 07:47:30 +01005508 size_t m_unnamedCount;
5509 };
5510
5511 ///////////////////////////////////////////////////////////////////////////
5512
5513 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
5514 public:
5515
5516 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
5517
5518 virtual void invoke() const {
5519 m_fun();
5520 }
5521
5522 private:
5523 virtual ~FreeFunctionTestCase();
5524
5525 TestFunction m_fun;
5526 };
5527
Phil Nash8defc712013-04-24 19:10:02 +01005528 inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
Phil Nash90a35942012-11-13 22:04:29 +00005529 std::string className = classOrQualifiedMethodName;
Phil Nashf7378ee2013-09-07 12:07:38 +01005530 if( startsWith( className, "&" ) )
Phil Nash90a35942012-11-13 22:04:29 +00005531 {
5532 std::size_t lastColons = className.rfind( "::" );
5533 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
5534 if( penultimateColons == std::string::npos )
5535 penultimateColons = 1;
5536 className = className.substr( penultimateColons, lastColons-penultimateColons );
5537 }
5538 return className;
5539 }
5540
Phil Nash3b80af72012-08-09 07:47:30 +01005541 ///////////////////////////////////////////////////////////////////////////
5542
5543 AutoReg::AutoReg( TestFunction function,
Phil Nash93906752013-03-16 20:21:51 +00005544 SourceLineInfo const& lineInfo,
5545 NameAndDesc const& nameAndDesc ) {
Phil Nashaa7123b2013-08-15 19:01:00 +01005546 registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
Phil Nash3b80af72012-08-09 07:47:30 +01005547 }
5548
5549 AutoReg::~AutoReg() {}
5550
5551 void AutoReg::registerTestCase( ITestCase* testCase,
Phil Nash93906752013-03-16 20:21:51 +00005552 char const* classOrQualifiedMethodName,
5553 NameAndDesc const& nameAndDesc,
5554 SourceLineInfo const& lineInfo ) {
Phil Nash90a35942012-11-13 22:04:29 +00005555
Phil Nash93906752013-03-16 20:21:51 +00005556 getMutableRegistryHub().registerTest
5557 ( makeTestCase( testCase,
5558 extractClassName( classOrQualifiedMethodName ),
5559 nameAndDesc.name,
5560 nameAndDesc.description,
5561 lineInfo ) );
Phil Nash3b80af72012-08-09 07:47:30 +01005562 }
5563
5564} // end namespace Catch
5565
5566// #included from: catch_reporter_registry.hpp
5567#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
5568
5569#include <map>
5570
5571namespace Catch {
5572
5573 class ReporterRegistry : public IReporterRegistry {
5574
5575 public:
5576
5577 virtual ~ReporterRegistry() {
5578 deleteAllValues( m_factories );
5579 }
5580
Phil Nash786959d2013-06-07 19:07:50 +01005581 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const {
Phil Nash3b80af72012-08-09 07:47:30 +01005582 FactoryMap::const_iterator it = m_factories.find( name );
5583 if( it == m_factories.end() )
5584 return NULL;
Phil Nash786959d2013-06-07 19:07:50 +01005585 return it->second->create( ReporterConfig( config ) );
Phil Nash3b80af72012-08-09 07:47:30 +01005586 }
5587
Phil Nash8defc712013-04-24 19:10:02 +01005588 void registerReporter( std::string const& name, IReporterFactory* factory ) {
Phil Nash3b80af72012-08-09 07:47:30 +01005589 m_factories.insert( std::make_pair( name, factory ) );
5590 }
5591
Phil Nash8defc712013-04-24 19:10:02 +01005592 FactoryMap const& getFactories() const {
Phil Nash3b80af72012-08-09 07:47:30 +01005593 return m_factories;
5594 }
5595
5596 private:
5597 FactoryMap m_factories;
5598 };
5599}
5600
5601// #included from: catch_exception_translator_registry.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005602#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01005603
5604#ifdef __OBJC__
5605#import "Foundation/Foundation.h"
5606#endif
5607
5608namespace Catch {
5609
5610 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
5611 public:
5612 ~ExceptionTranslatorRegistry() {
5613 deleteAll( m_translators );
5614 }
5615
5616 virtual void registerTranslator( const IExceptionTranslator* translator ) {
5617 m_translators.push_back( translator );
5618 }
5619
5620 virtual std::string translateActiveException() const {
5621 try {
5622#ifdef __OBJC__
5623 // In Objective-C try objective-c exceptions first
5624 @try {
5625 throw;
5626 }
5627 @catch (NSException *exception) {
5628 return toString( [exception description] );
5629 }
5630#else
5631 throw;
5632#endif
5633 }
5634 catch( std::exception& ex ) {
5635 return ex.what();
5636 }
5637 catch( std::string& msg ) {
5638 return msg;
5639 }
5640 catch( const char* msg ) {
5641 return msg;
5642 }
5643 catch(...) {
5644 return tryTranslators( m_translators.begin() );
5645 }
5646 }
5647
5648 std::string tryTranslators( std::vector<const IExceptionTranslator*>::const_iterator it ) const {
5649 if( it == m_translators.end() )
5650 return "Unknown exception";
5651
5652 try {
5653 return (*it)->translate();
5654 }
5655 catch(...) {
5656 return tryTranslators( it+1 );
5657 }
5658 }
5659
5660 private:
5661 std::vector<const IExceptionTranslator*> m_translators;
5662 };
5663}
5664
5665namespace Catch {
5666
5667 namespace {
5668
5669 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
5670
Phil Nash8defc712013-04-24 19:10:02 +01005671 RegistryHub( RegistryHub const& );
5672 void operator=( RegistryHub const& );
Phil Nash3b80af72012-08-09 07:47:30 +01005673
5674 public: // IRegistryHub
5675 RegistryHub() {
5676 }
Phil Nash8defc712013-04-24 19:10:02 +01005677 virtual IReporterRegistry const& getReporterRegistry() const {
Phil Nash3b80af72012-08-09 07:47:30 +01005678 return m_reporterRegistry;
5679 }
Phil Nash8defc712013-04-24 19:10:02 +01005680 virtual ITestCaseRegistry const& getTestCaseRegistry() const {
Phil Nash3b80af72012-08-09 07:47:30 +01005681 return m_testCaseRegistry;
5682 }
5683 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
5684 return m_exceptionTranslatorRegistry;
5685 }
5686
5687 public: // IMutableRegistryHub
Phil Nash8defc712013-04-24 19:10:02 +01005688 virtual void registerReporter( std::string const& name, IReporterFactory* factory ) {
Phil Nash3b80af72012-08-09 07:47:30 +01005689 m_reporterRegistry.registerReporter( name, factory );
5690 }
Phil Nash8defc712013-04-24 19:10:02 +01005691 virtual void registerTest( TestCase const& testInfo ) {
Phil Nash3b80af72012-08-09 07:47:30 +01005692 m_testCaseRegistry.registerTest( testInfo );
5693 }
5694 virtual void registerTranslator( const IExceptionTranslator* translator ) {
5695 m_exceptionTranslatorRegistry.registerTranslator( translator );
5696 }
5697
5698 private:
5699 TestRegistry m_testCaseRegistry;
5700 ReporterRegistry m_reporterRegistry;
5701 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
5702 };
5703
5704 // Single, global, instance
5705 inline RegistryHub*& getTheRegistryHub() {
5706 static RegistryHub* theRegistryHub = NULL;
5707 if( !theRegistryHub )
5708 theRegistryHub = new RegistryHub();
5709 return theRegistryHub;
5710 }
5711 }
5712
5713 IRegistryHub& getRegistryHub() {
5714 return *getTheRegistryHub();
5715 }
5716 IMutableRegistryHub& getMutableRegistryHub() {
5717 return *getTheRegistryHub();
5718 }
5719 void cleanUp() {
5720 delete getTheRegistryHub();
5721 getTheRegistryHub() = NULL;
5722 cleanUpContext();
5723 }
Phil Nashce612bf2012-11-01 08:27:09 +00005724 std::string translateActiveException() {
5725 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
5726 }
Phil Nash3b80af72012-08-09 07:47:30 +01005727
5728} // end namespace Catch
Matt Wozniskif29c8982012-09-17 01:42:29 -04005729
Phil Nash3b80af72012-08-09 07:47:30 +01005730// #included from: catch_notimplemented_exception.hpp
5731#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
5732
5733#include <ostream>
5734
5735namespace Catch {
5736
Phil Nash8defc712013-04-24 19:10:02 +01005737 NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
Phil Nash3b80af72012-08-09 07:47:30 +01005738 : m_lineInfo( lineInfo ) {
5739 std::ostringstream oss;
Phil Nash2e7d9662013-01-16 09:44:43 +00005740 oss << lineInfo << ": function ";
Phil Nash3b80af72012-08-09 07:47:30 +01005741 oss << "not implemented";
5742 m_what = oss.str();
5743 }
5744
5745 const char* NotImplementedException::what() const throw() {
5746 return m_what.c_str();
5747 }
5748
5749} // end namespace Catch
5750
5751// #included from: catch_context_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005752#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01005753
Phil Nash3b80af72012-08-09 07:47:30 +01005754namespace Catch {
5755
5756 class Context : public IMutableContext {
5757
5758 Context() : m_config( NULL ) {}
Phil Nash8defc712013-04-24 19:10:02 +01005759 Context( Context const& );
5760 void operator=( Context const& );
Phil Nash3b80af72012-08-09 07:47:30 +01005761
5762 public: // IContext
5763 virtual IResultCapture& getResultCapture() {
5764 return *m_resultCapture;
5765 }
5766 virtual IRunner& getRunner() {
5767 return *m_runner;
5768 }
Phil Nash8defc712013-04-24 19:10:02 +01005769 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
Phil Nash3b80af72012-08-09 07:47:30 +01005770 return getGeneratorsForCurrentTest()
5771 .getGeneratorInfo( fileInfo, totalSize )
5772 .getCurrentIndex();
5773 }
5774 virtual bool advanceGeneratorsForCurrentTest() {
5775 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
5776 return generators && generators->moveNext();
5777 }
5778
Phil Nash786959d2013-06-07 19:07:50 +01005779 virtual Ptr<IConfig const> getConfig() const {
Phil Nash3b80af72012-08-09 07:47:30 +01005780 return m_config;
5781 }
5782
5783 public: // IMutableContext
5784 virtual void setResultCapture( IResultCapture* resultCapture ) {
5785 m_resultCapture = resultCapture;
5786 }
5787 virtual void setRunner( IRunner* runner ) {
5788 m_runner = runner;
5789 }
Phil Nash786959d2013-06-07 19:07:50 +01005790 virtual void setConfig( Ptr<IConfig const> const& config ) {
Phil Nash3b80af72012-08-09 07:47:30 +01005791 m_config = config;
5792 }
5793
5794 friend IMutableContext& getCurrentMutableContext();
5795
5796 private:
5797 IGeneratorsForTest* findGeneratorsForCurrentTest() {
5798 std::string testName = getResultCapture().getCurrentTestName();
5799
5800 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
5801 m_generatorsByTestName.find( testName );
5802 return it != m_generatorsByTestName.end()
Phil Nash8a52a392013-07-25 08:12:03 +01005803 ? it->second
5804 : NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01005805 }
5806
5807 IGeneratorsForTest& getGeneratorsForCurrentTest() {
5808 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
5809 if( !generators ) {
5810 std::string testName = getResultCapture().getCurrentTestName();
5811 generators = createGeneratorsForTest();
5812 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
5813 }
5814 return *generators;
5815 }
5816
5817 private:
5818 IRunner* m_runner;
5819 IResultCapture* m_resultCapture;
Phil Nash786959d2013-06-07 19:07:50 +01005820 Ptr<IConfig const> m_config;
Phil Nash3b80af72012-08-09 07:47:30 +01005821 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
5822 };
5823
5824 namespace {
5825 Context* currentContext = NULL;
5826 }
5827 IMutableContext& getCurrentMutableContext() {
5828 if( !currentContext )
5829 currentContext = new Context();
5830 return *currentContext;
5831 }
5832 IContext& getCurrentContext() {
5833 return getCurrentMutableContext();
5834 }
5835
Phil Nash8defc712013-04-24 19:10:02 +01005836 Stream createStream( std::string const& streamName ) {
Phil Nash67ec8702012-09-26 18:38:26 +01005837 if( streamName == "stdout" ) return Stream( std::cout.rdbuf(), false );
5838 if( streamName == "stderr" ) return Stream( std::cerr.rdbuf(), false );
5839 if( streamName == "debug" ) return Stream( new StreamBufImpl<OutputDebugWriter>, true );
Phil Nash3b80af72012-08-09 07:47:30 +01005840
5841 throw std::domain_error( "Unknown stream: " + streamName );
5842 }
5843
5844 void cleanUpContext() {
5845 delete currentContext;
5846 currentContext = NULL;
5847 }
5848}
Matt Wozniskif29c8982012-09-17 01:42:29 -04005849
Phil Nash3b80af72012-08-09 07:47:30 +01005850// #included from: catch_console_colour_impl.hpp
5851#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
5852
Phil Nash12c16ff2013-04-05 20:58:01 +01005853namespace Catch { namespace Detail {
5854 struct IColourImpl {
5855 virtual ~IColourImpl() {}
5856 virtual void use( Colour::Code _colourCode ) = 0;
5857 };
5858}}
5859
Phil Nash3df6c0d2013-03-11 18:38:29 +00005860#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
Phil Nash3b80af72012-08-09 07:47:30 +01005861
Phil Nash4b5e0082013-06-29 20:31:17 +01005862#ifndef NOMINMAX
Phil Nash23520432013-06-28 14:11:28 +01005863#define NOMINMAX
Phil Nash4b5e0082013-06-29 20:31:17 +01005864#endif
Phil Nash39075592013-07-01 19:02:29 +01005865
5866#ifdef __AFXDLL
5867#include <AfxWin.h>
5868#else
Phil Nash3b80af72012-08-09 07:47:30 +01005869#include <windows.h>
Phil Nash39075592013-07-01 19:02:29 +01005870#endif
Phil Nash3b80af72012-08-09 07:47:30 +01005871
5872namespace Catch {
Phil Nash3df6c0d2013-03-11 18:38:29 +00005873namespace {
Phil Nash3b80af72012-08-09 07:47:30 +01005874
Phil Nash12c16ff2013-04-05 20:58:01 +01005875 class Win32ColourImpl : public Detail::IColourImpl {
Phil Nash3b80af72012-08-09 07:47:30 +01005876 public:
Phil Nash12c16ff2013-04-05 20:58:01 +01005877 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
Phil Nash3b80af72012-08-09 07:47:30 +01005878 {
Phil Nash12c16ff2013-04-05 20:58:01 +01005879 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
5880 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
5881 originalAttributes = csbiInfo.wAttributes;
Phil Nash3b80af72012-08-09 07:47:30 +01005882 }
Phil Nash3b80af72012-08-09 07:47:30 +01005883
Phil Nash12c16ff2013-04-05 20:58:01 +01005884 virtual void use( Colour::Code _colourCode ) {
5885 switch( _colourCode ) {
5886 case Colour::None: return setTextAttribute( originalAttributes );
5887 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
5888 case Colour::Red: return setTextAttribute( FOREGROUND_RED );
5889 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
5890 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
5891 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
5892 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
5893 case Colour::Grey: return setTextAttribute( 0 );
Phil Nash3b80af72012-08-09 07:47:30 +01005894
Phil Nash12c16ff2013-04-05 20:58:01 +01005895 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
5896 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
5897 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
Phil Nash23520432013-06-28 14:11:28 +01005898 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
Phil Nash3b80af72012-08-09 07:47:30 +01005899
Phil Nash12c16ff2013-04-05 20:58:01 +01005900 case Colour::Bright: throw std::logic_error( "not a colour" );
5901 }
Phil Nash3b80af72012-08-09 07:47:30 +01005902 }
Phil Nash3b80af72012-08-09 07:47:30 +01005903
5904 private:
Phil Nash12c16ff2013-04-05 20:58:01 +01005905 void setTextAttribute( WORD _textAttribute ) {
5906 SetConsoleTextAttribute( stdoutHandle, _textAttribute );
Phil Nash3b80af72012-08-09 07:47:30 +01005907 }
Phil Nash12c16ff2013-04-05 20:58:01 +01005908 HANDLE stdoutHandle;
5909 WORD originalAttributes;
Phil Nash3b80af72012-08-09 07:47:30 +01005910 };
5911
Phil Nash3df6c0d2013-03-11 18:38:29 +00005912 inline bool shouldUseColourForPlatform() {
5913 return true;
5914 }
5915
Phil Nash12c16ff2013-04-05 20:58:01 +01005916 Win32ColourImpl platformColourImpl;
Phil Nash3df6c0d2013-03-11 18:38:29 +00005917
5918} // end anon namespace
Phil Nash3b80af72012-08-09 07:47:30 +01005919} // end namespace Catch
5920
Phil Nash3df6c0d2013-03-11 18:38:29 +00005921#else // Not Windows - assumed to be POSIX compatible //////////////////////////
Phil Nashce612bf2012-11-01 08:27:09 +00005922
5923#include <unistd.h>
5924
5925namespace Catch {
Phil Nash3df6c0d2013-03-11 18:38:29 +00005926namespace {
Phil Nashce612bf2012-11-01 08:27:09 +00005927
5928 // use POSIX/ ANSI console terminal codes
Phil Nash12c16ff2013-04-05 20:58:01 +01005929 // Thanks to Adam Strzelecki for original contribution
5930 // (http://github.com/nanoant)
Phil Nashce612bf2012-11-01 08:27:09 +00005931 // https://github.com/philsquared/Catch/pull/131
Phil Nash12c16ff2013-04-05 20:58:01 +01005932 class PosixColourImpl : public Detail::IColourImpl {
5933 public:
5934 virtual void use( Colour::Code _colourCode ) {
5935 switch( _colourCode ) {
5936 case Colour::None:
5937 case Colour::White: return setColour( "[0m" );
5938 case Colour::Red: return setColour( "[0;31m" );
5939 case Colour::Green: return setColour( "[0;32m" );
5940 case Colour::Blue: return setColour( "[0:34m" );
5941 case Colour::Cyan: return setColour( "[0;36m" );
5942 case Colour::Yellow: return setColour( "[0;33m" );
5943 case Colour::Grey: return setColour( "[1;30m" );
Phil Nashce612bf2012-11-01 08:27:09 +00005944
Phil Nash12c16ff2013-04-05 20:58:01 +01005945 case Colour::LightGrey: return setColour( "[0;37m" );
5946 case Colour::BrightRed: return setColour( "[1;31m" );
Phil Nash243f2d22013-04-12 10:43:06 +01005947 case Colour::BrightGreen: return setColour( "[1;32m" );
Phil Nash12c16ff2013-04-05 20:58:01 +01005948 case Colour::BrightWhite: return setColour( "[1;37m" );
Phil Nashce612bf2012-11-01 08:27:09 +00005949
Phil Nash12c16ff2013-04-05 20:58:01 +01005950 case Colour::Bright: throw std::logic_error( "not a colour" );
Phil Nashce612bf2012-11-01 08:27:09 +00005951 }
5952 }
Phil Nash12c16ff2013-04-05 20:58:01 +01005953 private:
5954 void setColour( const char* _escapeCode ) {
5955 std::cout << '\033' << _escapeCode;
Phil Nash3df6c0d2013-03-11 18:38:29 +00005956 }
5957 };
5958
5959 inline bool shouldUseColourForPlatform() {
5960 return isatty( fileno(stdout) );
Phil Nashce612bf2012-11-01 08:27:09 +00005961 }
5962
Phil Nash12c16ff2013-04-05 20:58:01 +01005963 PosixColourImpl platformColourImpl;
Phil Nashce612bf2012-11-01 08:27:09 +00005964
Phil Nash12c16ff2013-04-05 20:58:01 +01005965} // end anon namespace
5966} // end namespace Catch
Phil Nash3b80af72012-08-09 07:47:30 +01005967
Phil Nash3df6c0d2013-03-11 18:38:29 +00005968#endif // not Windows
Phil Nash3b80af72012-08-09 07:47:30 +01005969
5970namespace Catch {
5971
5972 namespace {
Phil Nash12c16ff2013-04-05 20:58:01 +01005973 struct NoColourImpl : Detail::IColourImpl {
5974 void use( Colour::Code ) {}
5975 };
5976 NoColourImpl noColourImpl;
5977 static const bool shouldUseColour = shouldUseColourForPlatform() &&
5978 !isDebuggerActive();
Phil Nash3b80af72012-08-09 07:47:30 +01005979 }
5980
Phil Nash12c16ff2013-04-05 20:58:01 +01005981 Colour::Colour( Code _colourCode ){ use( _colourCode ); }
5982 Colour::~Colour(){ use( None ); }
5983 void Colour::use( Code _colourCode ) {
5984 impl->use( _colourCode );
Phil Nash3b80af72012-08-09 07:47:30 +01005985 }
5986
Phil Nash12c16ff2013-04-05 20:58:01 +01005987 Detail::IColourImpl* Colour::impl = shouldUseColour
5988 ? static_cast<Detail::IColourImpl*>( &platformColourImpl )
5989 : static_cast<Detail::IColourImpl*>( &noColourImpl );
Phil Nash3b80af72012-08-09 07:47:30 +01005990
5991} // end namespace Catch
5992
Phil Nash3b80af72012-08-09 07:47:30 +01005993// #included from: catch_generators_impl.hpp
5994#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
5995
5996#include <vector>
5997#include <string>
5998#include <map>
5999
6000namespace Catch {
6001
6002 struct GeneratorInfo : IGeneratorInfo {
6003
6004 GeneratorInfo( std::size_t size )
6005 : m_size( size ),
6006 m_currentIndex( 0 )
6007 {}
6008
6009 bool moveNext() {
6010 if( ++m_currentIndex == m_size ) {
6011 m_currentIndex = 0;
6012 return false;
6013 }
6014 return true;
6015 }
6016
6017 std::size_t getCurrentIndex() const {
6018 return m_currentIndex;
6019 }
6020
6021 std::size_t m_size;
6022 std::size_t m_currentIndex;
6023 };
6024
6025 ///////////////////////////////////////////////////////////////////////////
6026
6027 class GeneratorsForTest : public IGeneratorsForTest {
6028
6029 public:
6030 ~GeneratorsForTest() {
6031 deleteAll( m_generatorsInOrder );
6032 }
6033
Phil Nash8defc712013-04-24 19:10:02 +01006034 IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
Phil Nash3b80af72012-08-09 07:47:30 +01006035 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
6036 if( it == m_generatorsByName.end() ) {
6037 IGeneratorInfo* info = new GeneratorInfo( size );
6038 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
6039 m_generatorsInOrder.push_back( info );
6040 return *info;
6041 }
6042 return *it->second;
6043 }
6044
6045 bool moveNext() {
6046 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
6047 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
6048 for(; it != itEnd; ++it ) {
6049 if( (*it)->moveNext() )
6050 return true;
6051 }
6052 return false;
6053 }
6054
6055 private:
6056 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
6057 std::vector<IGeneratorInfo*> m_generatorsInOrder;
6058 };
6059
6060 IGeneratorsForTest* createGeneratorsForTest()
6061 {
6062 return new GeneratorsForTest();
6063 }
6064
6065} // end namespace Catch
6066
Phil Nashce612bf2012-11-01 08:27:09 +00006067// #included from: catch_assertionresult.hpp
6068#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01006069
6070namespace Catch {
6071
Phil Nash8defc712013-04-24 19:10:02 +01006072 AssertionInfo::AssertionInfo( std::string const& _macroName,
6073 SourceLineInfo const& _lineInfo,
6074 std::string const& _capturedExpression,
Phil Nash90a35942012-11-13 22:04:29 +00006075 ResultDisposition::Flags _resultDisposition )
6076 : macroName( _macroName ),
6077 lineInfo( _lineInfo ),
6078 capturedExpression( _capturedExpression ),
6079 resultDisposition( _resultDisposition )
Phil Nash786959d2013-06-07 19:07:50 +01006080 {}
Phil Nash90a35942012-11-13 22:04:29 +00006081
Phil Nashce612bf2012-11-01 08:27:09 +00006082 AssertionResult::AssertionResult() {}
Phil Nash3b80af72012-08-09 07:47:30 +01006083
Phil Nash8defc712013-04-24 19:10:02 +01006084 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
Phil Nashce612bf2012-11-01 08:27:09 +00006085 : m_info( info ),
6086 m_resultData( data )
6087 {}
Phil Nash3b80af72012-08-09 07:47:30 +01006088
Phil Nashce612bf2012-11-01 08:27:09 +00006089 AssertionResult::~AssertionResult() {}
Phil Nash3b80af72012-08-09 07:47:30 +01006090
Phil Nash90a35942012-11-13 22:04:29 +00006091 // Result was a success
6092 bool AssertionResult::succeeded() const {
6093 return Catch::isOk( m_resultData.resultType );
6094 }
6095
6096 // Result was a success, or failure is suppressed
6097 bool AssertionResult::isOk() const {
6098 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
Phil Nash3b80af72012-08-09 07:47:30 +01006099 }
6100
Phil Nashce612bf2012-11-01 08:27:09 +00006101 ResultWas::OfType AssertionResult::getResultType() const {
6102 return m_resultData.resultType;
Phil Nash3b80af72012-08-09 07:47:30 +01006103 }
6104
Phil Nashce612bf2012-11-01 08:27:09 +00006105 bool AssertionResult::hasExpression() const {
6106 return !m_info.capturedExpression.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01006107 }
6108
Phil Nashce612bf2012-11-01 08:27:09 +00006109 bool AssertionResult::hasMessage() const {
6110 return !m_resultData.message.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01006111 }
6112
Phil Nashce612bf2012-11-01 08:27:09 +00006113 std::string AssertionResult::getExpression() const {
Phil Nash786959d2013-06-07 19:07:50 +01006114 if( shouldNegate( m_info.resultDisposition ) )
6115 return "!" + m_info.capturedExpression;
6116 else
6117 return m_info.capturedExpression;
6118 }
6119 std::string AssertionResult::getExpressionInMacro() const {
6120 if( m_info.macroName.empty() )
6121 return m_info.capturedExpression;
6122 else
6123 return m_info.macroName + "( " + m_info.capturedExpression + " )";
Phil Nash3b80af72012-08-09 07:47:30 +01006124 }
6125
Phil Nashce612bf2012-11-01 08:27:09 +00006126 bool AssertionResult::hasExpandedExpression() const {
Phil Nash67305122012-10-09 11:48:55 +01006127 return hasExpression() && getExpandedExpression() != getExpression();
Phil Nash3b80af72012-08-09 07:47:30 +01006128 }
6129
Phil Nashce612bf2012-11-01 08:27:09 +00006130 std::string AssertionResult::getExpandedExpression() const {
6131 return m_resultData.reconstructedExpression;
Phil Nash3b80af72012-08-09 07:47:30 +01006132 }
6133
Phil Nashce612bf2012-11-01 08:27:09 +00006134 std::string AssertionResult::getMessage() const {
6135 return m_resultData.message;
6136 }
6137 SourceLineInfo AssertionResult::getSourceInfo() const {
6138 return m_info.lineInfo;
Phil Nash3b80af72012-08-09 07:47:30 +01006139 }
6140
Phil Nashce612bf2012-11-01 08:27:09 +00006141 std::string AssertionResult::getTestMacroName() const {
6142 return m_info.macroName;
Phil Nash3b80af72012-08-09 07:47:30 +01006143 }
6144
6145} // end namespace Catch
6146
Phil Nashce612bf2012-11-01 08:27:09 +00006147// #included from: catch_expressionresult_builder.hpp
6148#define TWOBLUECUBES_CATCH_EXPRESSIONRESULT_BUILDER_HPP_INCLUDED
6149
6150#include <assert.h>
Phil Nash3b80af72012-08-09 07:47:30 +01006151
6152namespace Catch {
6153
Phil Nashce612bf2012-11-01 08:27:09 +00006154 ExpressionResultBuilder::ExpressionResultBuilder( ResultWas::OfType resultType ) {
6155 m_data.resultType = resultType;
Phil Nash67305122012-10-09 11:48:55 +01006156 }
Phil Nash8defc712013-04-24 19:10:02 +01006157 ExpressionResultBuilder::ExpressionResultBuilder( ExpressionResultBuilder const& other )
Phil Nashce612bf2012-11-01 08:27:09 +00006158 : m_data( other.m_data ),
6159 m_exprComponents( other.m_exprComponents )
Phil Nash67305122012-10-09 11:48:55 +01006160 {
Phil Nashce612bf2012-11-01 08:27:09 +00006161 m_stream << other.m_stream.str();
Phil Nash3b80af72012-08-09 07:47:30 +01006162 }
Phil Nash8defc712013-04-24 19:10:02 +01006163 ExpressionResultBuilder& ExpressionResultBuilder::operator=(ExpressionResultBuilder const& other ) {
Phil Nashce612bf2012-11-01 08:27:09 +00006164 m_data = other.m_data;
6165 m_exprComponents = other.m_exprComponents;
6166 m_stream.str("");
6167 m_stream << other.m_stream.str();
6168 return *this;
6169 }
6170 ExpressionResultBuilder& ExpressionResultBuilder::setResultType( ResultWas::OfType result ) {
6171 m_data.resultType = result;
6172 return *this;
6173 }
6174 ExpressionResultBuilder& ExpressionResultBuilder::setResultType( bool result ) {
6175 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
6176 return *this;
6177 }
Phil Nash90a35942012-11-13 22:04:29 +00006178 ExpressionResultBuilder& ExpressionResultBuilder::endExpression( ResultDisposition::Flags resultDisposition ) {
6179 m_exprComponents.shouldNegate = shouldNegate( resultDisposition );
Phil Nashce612bf2012-11-01 08:27:09 +00006180 return *this;
6181 }
Phil Nash8defc712013-04-24 19:10:02 +01006182 ExpressionResultBuilder& ExpressionResultBuilder::setLhs( std::string const& lhs ) {
Phil Nashce612bf2012-11-01 08:27:09 +00006183 m_exprComponents.lhs = lhs;
6184 return *this;
6185 }
Phil Nash8defc712013-04-24 19:10:02 +01006186 ExpressionResultBuilder& ExpressionResultBuilder::setRhs( std::string const& rhs ) {
Phil Nashce612bf2012-11-01 08:27:09 +00006187 m_exprComponents.rhs = rhs;
6188 return *this;
6189 }
Phil Nash8defc712013-04-24 19:10:02 +01006190 ExpressionResultBuilder& ExpressionResultBuilder::setOp( std::string const& op ) {
Phil Nashce612bf2012-11-01 08:27:09 +00006191 m_exprComponents.op = op;
6192 return *this;
6193 }
Phil Nash8defc712013-04-24 19:10:02 +01006194 AssertionResult ExpressionResultBuilder::buildResult( AssertionInfo const& info ) const
Phil Nashce612bf2012-11-01 08:27:09 +00006195 {
6196 assert( m_data.resultType != ResultWas::Unknown );
Phil Nash3b80af72012-08-09 07:47:30 +01006197
Phil Nashce612bf2012-11-01 08:27:09 +00006198 AssertionResultData data = m_data;
6199
6200 // Flip bool results if shouldNegate is set
6201 if( m_exprComponents.shouldNegate && data.resultType == ResultWas::Ok )
6202 data.resultType = ResultWas::ExpressionFailed;
6203 else if( m_exprComponents.shouldNegate && data.resultType == ResultWas::ExpressionFailed )
6204 data.resultType = ResultWas::Ok;
6205
6206 data.message = m_stream.str();
6207 data.reconstructedExpression = reconstructExpression( info );
6208 if( m_exprComponents.shouldNegate ) {
6209 if( m_exprComponents.op == "" )
6210 data.reconstructedExpression = "!" + data.reconstructedExpression;
Phil Nash67305122012-10-09 11:48:55 +01006211 else
Phil Nashce612bf2012-11-01 08:27:09 +00006212 data.reconstructedExpression = "!(" + data.reconstructedExpression + ")";
6213 }
6214 return AssertionResult( info, data );
6215 }
Phil Nash8defc712013-04-24 19:10:02 +01006216 std::string ExpressionResultBuilder::reconstructExpression( AssertionInfo const& info ) const {
Phil Nashce612bf2012-11-01 08:27:09 +00006217 if( m_exprComponents.op == "" )
6218 return m_exprComponents.lhs.empty() ? info.capturedExpression : m_exprComponents.op + m_exprComponents.lhs;
6219 else if( m_exprComponents.op == "matches" )
6220 return m_exprComponents.lhs + " " + m_exprComponents.rhs;
6221 else if( m_exprComponents.op != "!" ) {
Phil Nashdd26e882013-03-25 09:25:31 +00006222 if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 &&
6223 m_exprComponents.lhs.find("\n") == std::string::npos &&
6224 m_exprComponents.rhs.find("\n") == std::string::npos )
Phil Nashce612bf2012-11-01 08:27:09 +00006225 return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs;
Phil Nashce612bf2012-11-01 08:27:09 +00006226 else
Phil Nash767f1582013-03-04 12:19:15 +01006227 return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs;
Phil Nash67305122012-10-09 11:48:55 +01006228 }
6229 else
Phil Nashce612bf2012-11-01 08:27:09 +00006230 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 +01006231 }
6232
6233} // end namespace Catch
6234
Phil Nash5bc030d2012-08-16 18:48:50 +01006235// #included from: catch_test_case_info.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04006236#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
Phil Nash5bc030d2012-08-16 18:48:50 +01006237
6238namespace Catch {
6239
Phil Nasha1fbfea2012-12-01 23:57:18 +00006240 TestCase makeTestCase( ITestCase* _testCase,
Phil Nash8defc712013-04-24 19:10:02 +01006241 std::string const& _className,
6242 std::string const& _name,
6243 std::string const& _descOrTags,
6244 SourceLineInfo const& _lineInfo )
Phil Nashfc1baac2012-09-15 17:53:27 +01006245 {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006246 std::string desc = _descOrTags;
6247 bool isHidden( startsWith( _name, "./" ) );
6248 std::set<std::string> tags;
6249 TagExtracter( tags ).parse( desc );
Phil Nashb5fd5a62013-06-28 17:09:57 +01006250 if( tags.find( "hide" ) != tags.end() || tags.find( "." ) != tags.end() )
Phil Nasha1fbfea2012-12-01 23:57:18 +00006251 isHidden = true;
6252
6253 TestCaseInfo info( _name, _className, desc, tags, isHidden, _lineInfo );
6254 return TestCase( _testCase, info );
Phil Nashfc1baac2012-09-15 17:53:27 +01006255 }
Phil Nash5bc030d2012-08-16 18:48:50 +01006256
Phil Nash8defc712013-04-24 19:10:02 +01006257 TestCaseInfo::TestCaseInfo( std::string const& _name,
6258 std::string const& _className,
6259 std::string const& _description,
6260 std::set<std::string> const& _tags,
Phil Nasha1fbfea2012-12-01 23:57:18 +00006261 bool _isHidden,
Phil Nash8defc712013-04-24 19:10:02 +01006262 SourceLineInfo const& _lineInfo )
Phil Nasha1fbfea2012-12-01 23:57:18 +00006263 : name( _name ),
6264 className( _className ),
6265 description( _description ),
6266 tags( _tags ),
Phil Nashff03cdf2012-12-06 08:44:51 +00006267 lineInfo( _lineInfo ),
6268 isHidden( _isHidden )
Phil Nash38f7eef2013-03-29 13:44:33 +00006269 {
6270 std::ostringstream oss;
6271 for( std::set<std::string>::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it )
6272 oss << "[" << *it << "]";
6273 tagsAsString = oss.str();
6274 }
Phil Nash5bc030d2012-08-16 18:48:50 +01006275
Phil Nash8defc712013-04-24 19:10:02 +01006276 TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
Phil Nasha1fbfea2012-12-01 23:57:18 +00006277 : name( other.name ),
6278 className( other.className ),
6279 description( other.description ),
6280 tags( other.tags ),
Phil Nash38f7eef2013-03-29 13:44:33 +00006281 tagsAsString( other.tagsAsString ),
Phil Nashff03cdf2012-12-06 08:44:51 +00006282 lineInfo( other.lineInfo ),
6283 isHidden( other.isHidden )
Phil Nash5bc030d2012-08-16 18:48:50 +01006284 {}
6285
Phil Nash8defc712013-04-24 19:10:02 +01006286 TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
Phil Nasha1fbfea2012-12-01 23:57:18 +00006287
Phil Nash8defc712013-04-24 19:10:02 +01006288 TestCase::TestCase( TestCase const& other )
Phil Nasha1fbfea2012-12-01 23:57:18 +00006289 : TestCaseInfo( other ),
6290 test( other.test )
Phil Nash5bc030d2012-08-16 18:48:50 +01006291 {}
6292
Phil Nash8defc712013-04-24 19:10:02 +01006293 TestCase TestCase::withName( std::string const& _newName ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006294 TestCase other( *this );
6295 other.name = _newName;
6296 return other;
Phil Nash5bc030d2012-08-16 18:48:50 +01006297 }
6298
Phil Nasha1fbfea2012-12-01 23:57:18 +00006299 void TestCase::invoke() const {
6300 test->invoke();
Phil Nash5bc030d2012-08-16 18:48:50 +01006301 }
6302
Phil Nasha1fbfea2012-12-01 23:57:18 +00006303 bool TestCase::isHidden() const {
6304 return TestCaseInfo::isHidden;
Phil Nashfc1baac2012-09-15 17:53:27 +01006305 }
6306
Phil Nash8defc712013-04-24 19:10:02 +01006307 bool TestCase::hasTag( std::string const& tag ) const {
Phil Nashdd26e882013-03-25 09:25:31 +00006308 return tags.find( toLower( tag ) ) != tags.end();
Phil Nashfc1baac2012-09-15 17:53:27 +01006309 }
Phil Nash8defc712013-04-24 19:10:02 +01006310 bool TestCase::matchesTags( std::string const& tagPattern ) const {
Phil Nash799ecf92012-09-24 08:30:13 +01006311 TagExpression exp;
6312 TagExpressionParser( exp ).parse( tagPattern );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006313 return exp.matches( tags );
Phil Nash799ecf92012-09-24 08:30:13 +01006314 }
Phil Nash8defc712013-04-24 19:10:02 +01006315 std::set<std::string> const& TestCase::getTags() const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006316 return tags;
Phil Nash5bc030d2012-08-16 18:48:50 +01006317 }
6318
Phil Nasha1fbfea2012-12-01 23:57:18 +00006319 void TestCase::swap( TestCase& other ) {
6320 test.swap( other.test );
6321 className.swap( other.className );
6322 name.swap( other.name );
6323 description.swap( other.description );
6324 std::swap( lineInfo, other.lineInfo );
Phil Nash5bc030d2012-08-16 18:48:50 +01006325 }
6326
Phil Nash8defc712013-04-24 19:10:02 +01006327 bool TestCase::operator == ( TestCase const& other ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006328 return test.get() == other.test.get() &&
6329 name == other.name &&
6330 className == other.className;
Phil Nash5bc030d2012-08-16 18:48:50 +01006331 }
6332
Phil Nash8defc712013-04-24 19:10:02 +01006333 bool TestCase::operator < ( TestCase const& other ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006334 return name < other.name;
Phil Nash5bc030d2012-08-16 18:48:50 +01006335 }
Phil Nash8defc712013-04-24 19:10:02 +01006336 TestCase& TestCase::operator = ( TestCase const& other ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006337 TestCase temp( other );
Phil Nashd2ec8492012-08-23 19:48:57 +01006338 swap( temp );
6339 return *this;
6340 }
Phil Nash799ecf92012-09-24 08:30:13 +01006341
Phil Nash8defc712013-04-24 19:10:02 +01006342 TestCaseInfo const& TestCase::getTestCaseInfo() const
Phil Nasha1fbfea2012-12-01 23:57:18 +00006343 {
6344 return *this;
6345 }
6346
Phil Nash799ecf92012-09-24 08:30:13 +01006347} // end namespace Catch
Phil Nash5bc030d2012-08-16 18:48:50 +01006348
Phil Nash7673a302012-11-15 22:15:41 +00006349// #included from: catch_version.hpp
6350#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
6351
6352namespace Catch {
6353
6354 // These numbers are maintained by a script
Phil Nashf7378ee2013-09-07 12:07:38 +01006355 Version libraryVersion( 1, 0, 9, "master" );
Phil Nash7673a302012-11-15 22:15:41 +00006356}
6357
Phil Nash19279252013-04-20 21:07:32 +01006358// #included from: catch_text.hpp
6359#define TWOBLUECUBES_CATCH_TEXT_HPP_INCLUDED
6360
6361#include <string>
6362#include <vector>
Phil Nash2e7d9662013-01-16 09:44:43 +00006363
6364namespace Catch {
6365
Phil Nash19279252013-04-20 21:07:32 +01006366 Text::Text( std::string const& _str, TextAttributes const& _attr )
6367 : attr( _attr )
6368 {
6369 std::string wrappableChars = " [({.,/|\\-";
6370 std::size_t indent = _attr.initialIndent != std::string::npos
6371 ? _attr.initialIndent
6372 : _attr.indent;
6373 std::string remainder = _str;
Phil Nash2e7d9662013-01-16 09:44:43 +00006374
Phil Nash19279252013-04-20 21:07:32 +01006375 while( !remainder.empty() ) {
6376 assert( lines.size() < 1000 );
6377 std::size_t tabPos = std::string::npos;
6378 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
6379 std::size_t pos = remainder.find_first_of( '\n' );
6380 if( pos <= width ) {
6381 width = pos;
Phil Nash2e7d9662013-01-16 09:44:43 +00006382 }
Phil Nash19279252013-04-20 21:07:32 +01006383 pos = remainder.find_last_of( _attr.tabChar, width );
6384 if( pos != std::string::npos ) {
6385 tabPos = pos;
6386 if( remainder[width] == '\n' )
6387 width--;
6388 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
6389 }
6390
6391 if( width == remainder.size() ) {
6392 spliceLine( indent, remainder, width );
6393 }
6394 else if( remainder[width] == '\n' ) {
6395 spliceLine( indent, remainder, width );
6396 if( width <= 1 || remainder.size() != 1 )
6397 remainder = remainder.substr( 1 );
6398 indent = _attr.indent;
6399 }
6400 else {
6401 pos = remainder.find_last_of( wrappableChars, width );
6402 if( pos != std::string::npos && pos > 0 ) {
6403 spliceLine( indent, remainder, pos );
6404 if( remainder[0] == ' ' )
6405 remainder = remainder.substr( 1 );
Phil Nash38f7eef2013-03-29 13:44:33 +00006406 }
6407 else {
Phil Nash19279252013-04-20 21:07:32 +01006408 spliceLine( indent, remainder, width-1 );
6409 lines.back() += "-";
Phil Nash38f7eef2013-03-29 13:44:33 +00006410 }
Phil Nash19279252013-04-20 21:07:32 +01006411 if( lines.size() == 1 )
6412 indent = _attr.indent;
6413 if( tabPos != std::string::npos )
6414 indent += tabPos;
Phil Nash38f7eef2013-03-29 13:44:33 +00006415 }
Phil Nash2e7d9662013-01-16 09:44:43 +00006416 }
6417 }
6418
Phil Nash19279252013-04-20 21:07:32 +01006419 void Text::spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
6420 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
6421 _remainder = _remainder.substr( _pos );
Phil Nash2e7d9662013-01-16 09:44:43 +00006422 }
Phil Nash19279252013-04-20 21:07:32 +01006423
6424 std::string Text::toString() const {
Phil Nash2e7d9662013-01-16 09:44:43 +00006425 std::ostringstream oss;
Phil Nash38f7eef2013-03-29 13:44:33 +00006426 oss << *this;
Phil Nash2e7d9662013-01-16 09:44:43 +00006427 return oss.str();
6428 }
6429
Phil Nash19279252013-04-20 21:07:32 +01006430 std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
6431 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
6432 it != itEnd; ++it ) {
6433 if( it != _text.begin() )
6434 _stream << "\n";
6435 _stream << *it;
6436 }
6437 return _stream;
Phil Nash12c16ff2013-04-05 20:58:01 +01006438 }
6439
Phil Nash2e7d9662013-01-16 09:44:43 +00006440} // end namespace Catch
6441
Phil Nasha2773812013-02-02 20:37:58 +00006442// #included from: catch_message.hpp
6443#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
6444
6445namespace Catch {
6446
6447 MessageInfo::MessageInfo( std::string const& _macroName,
6448 SourceLineInfo const& _lineInfo,
6449 ResultWas::OfType _type )
6450 : macroName( _macroName ),
6451 lineInfo( _lineInfo ),
6452 type( _type ),
6453 sequence( ++globalCount )
6454 {}
6455
6456 // This may need protecting if threading support is added
6457 unsigned int MessageInfo::globalCount = 0;
6458
6459 ////////////////////////////////////////////////////////////////////////////
6460
Phil Nashb5fd5a62013-06-28 17:09:57 +01006461 ScopedMessage::ScopedMessage( MessageBuilder const& builder )
6462 : m_info( builder.m_info )
6463 {
6464 m_info.message = builder.m_stream.str();
6465 getResultCapture().pushScopedMessage( m_info );
Phil Nasha2773812013-02-02 20:37:58 +00006466 }
Phil Nashb5fd5a62013-06-28 17:09:57 +01006467 ScopedMessage::~ScopedMessage() {
6468 getResultCapture().popScopedMessage( m_info );
Phil Nasha2773812013-02-02 20:37:58 +00006469 }
6470
6471} // end namespace Catch
6472
Phil Nash243f2d22013-04-12 10:43:06 +01006473// #included from: catch_legacy_reporter_adapter.hpp
Phil Nash87641772013-04-08 11:50:41 +01006474#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
6475
6476// #included from: catch_legacy_reporter_adapter.h
6477#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
6478
6479namespace Catch
6480{
6481 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
6482 {
6483 public:
Phil Nash786959d2013-06-07 19:07:50 +01006484 LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
Phil Nash87641772013-04-08 11:50:41 +01006485 virtual ~LegacyReporterAdapter();
6486
6487 virtual ReporterPreferences getPreferences() const;
6488 virtual void noMatchingTestCases( std::string const& );
6489 virtual void testRunStarting( TestRunInfo const& );
6490 virtual void testGroupStarting( GroupInfo const& groupInfo );
6491 virtual void testCaseStarting( TestCaseInfo const& testInfo );
6492 virtual void sectionStarting( SectionInfo const& sectionInfo );
6493 virtual void assertionStarting( AssertionInfo const& );
Phil Nashb5fd5a62013-06-28 17:09:57 +01006494 virtual bool assertionEnded( AssertionStats const& assertionStats );
Phil Nash87641772013-04-08 11:50:41 +01006495 virtual void sectionEnded( SectionStats const& sectionStats );
6496 virtual void testCaseEnded( TestCaseStats const& testCaseStats );
6497 virtual void testGroupEnded( TestGroupStats const& testGroupStats );
6498 virtual void testRunEnded( TestRunStats const& testRunStats );
6499
6500 private:
6501 Ptr<IReporter> m_legacyReporter;
Phil Nash87641772013-04-08 11:50:41 +01006502 };
6503}
6504
6505namespace Catch
6506{
Phil Nash786959d2013-06-07 19:07:50 +01006507 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
6508 : m_legacyReporter( legacyReporter )
Phil Nash87641772013-04-08 11:50:41 +01006509 {}
6510 LegacyReporterAdapter::~LegacyReporterAdapter() {}
6511
6512 ReporterPreferences LegacyReporterAdapter::getPreferences() const {
6513 ReporterPreferences prefs;
6514 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
6515 return prefs;
6516 }
6517
6518 void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
6519 void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
6520 m_legacyReporter->StartTesting();
6521 }
6522 void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
6523 m_legacyReporter->StartGroup( groupInfo.name );
6524 }
6525 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
6526 m_legacyReporter->StartTestCase( testInfo );
6527 }
6528 void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
6529 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
6530 }
6531 void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
6532 // Not on legacy interface
6533 }
6534
Phil Nashb5fd5a62013-06-28 17:09:57 +01006535 bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
Phil Nash87641772013-04-08 11:50:41 +01006536 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
6537 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
6538 it != itEnd;
6539 ++it ) {
6540 if( it->type == ResultWas::Info ) {
6541 ExpressionResultBuilder expressionBuilder( it->type );
6542 expressionBuilder << it->message;
6543 AssertionInfo info( it->macroName, it->lineInfo, "", ResultDisposition::Normal );
6544 AssertionResult result = expressionBuilder.buildResult( info );
6545 m_legacyReporter->Result( result );
6546 }
6547 }
6548 }
6549 m_legacyReporter->Result( assertionStats.assertionResult );
Phil Nashb5fd5a62013-06-28 17:09:57 +01006550 return true;
Phil Nash87641772013-04-08 11:50:41 +01006551 }
6552 void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
6553 if( sectionStats.missingAssertions )
6554 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
6555 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
6556 }
6557 void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
Phil Nash87641772013-04-08 11:50:41 +01006558 m_legacyReporter->EndTestCase
6559 ( testCaseStats.testInfo,
6560 testCaseStats.totals,
6561 testCaseStats.stdOut,
6562 testCaseStats.stdErr );
6563 }
6564 void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
6565 if( testGroupStats.aborting )
6566 m_legacyReporter->Aborted();
6567 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
6568 }
6569 void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
6570 m_legacyReporter->EndTesting( testRunStats.totals );
6571 }
6572}
6573
Phil Nashaa7123b2013-08-15 19:01:00 +01006574// #included from: catch_timer.hpp
6575
6576#ifdef __clang__
6577#pragma clang diagnostic push
6578#pragma clang diagnostic ignored "-Wc++11-long-long"
6579#endif
6580
Phil Nash04a33642013-08-16 19:09:09 +01006581#ifdef CATCH_PLATFORM_WINDOWS
Phil Nashaa7123b2013-08-15 19:01:00 +01006582#include <windows.h>
6583#else
6584#include <sys/time.h>
6585#endif
6586
6587namespace Catch {
6588
6589 namespace {
Phil Nash04a33642013-08-16 19:09:09 +01006590#ifdef CATCH_PLATFORM_WINDOWS
Phil Nashaa7123b2013-08-15 19:01:00 +01006591 uint64_t getCurrentTicks() {
6592 static uint64_t hz=0, hzo=0;
6593 if (!hz) {
6594 QueryPerformanceFrequency((LARGE_INTEGER*)&hz);
6595 QueryPerformanceCounter((LARGE_INTEGER*)&hzo);
6596 }
6597 uint64_t t;
6598 QueryPerformanceCounter((LARGE_INTEGER*)&t);
6599 return ((t-hzo)*1000000)/hz;
6600 }
6601#else
6602 uint64_t getCurrentTicks() {
6603 timeval t;
6604 gettimeofday(&t,NULL);
6605 return (uint64_t)t.tv_sec * 1000000ull + (uint64_t)t.tv_usec;
6606 }
6607#endif
6608 }
6609
6610 void Timer::start() {
6611 m_ticks = getCurrentTicks();
6612 }
6613 unsigned int Timer::getElapsedNanoseconds() const {
6614 return (unsigned int)(getCurrentTicks() - m_ticks);
6615 }
6616 unsigned int Timer::getElapsedMilliseconds() const {
6617 return (unsigned int)((getCurrentTicks() - m_ticks)/1000);
6618 }
6619 double Timer::getElapsedSeconds() const {
6620 return (getCurrentTicks() - m_ticks)/1000000.0;
6621 }
6622
6623} // namespace Catch
6624
6625#ifdef __clang__
6626#pragma clang diagnostic pop
6627#endif
Phil Nash3faa4122013-08-15 19:09:07 +01006628// #included from: ../reporters/catch_reporter_xml.hpp
6629#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
Phil Nash56d5c422012-08-23 20:08:50 +01006630
6631// #included from: ../internal/catch_reporter_registrars.hpp
6632#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
6633
6634namespace Catch {
6635
6636 template<typename T>
Phil Nasha1fbfea2012-12-01 23:57:18 +00006637 class LegacyReporterRegistrar {
6638
6639 class ReporterFactory : public IReporterFactory {
Phil Nash8defc712013-04-24 19:10:02 +01006640 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
Phil Nash786959d2013-06-07 19:07:50 +01006641 return new LegacyReporterAdapter( new T( config ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006642 }
6643
6644 virtual std::string getDescription() const {
6645 return T::getDescription();
6646 }
6647 };
6648
6649 public:
6650
Phil Nash8defc712013-04-24 19:10:02 +01006651 LegacyReporterRegistrar( std::string const& name ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006652 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
6653 }
6654 };
6655
6656 template<typename T>
Phil Nash56d5c422012-08-23 20:08:50 +01006657 class ReporterRegistrar {
6658
6659 class ReporterFactory : public IReporterFactory {
6660
Phil Nasha1fbfea2012-12-01 23:57:18 +00006661 // *** Please Note ***:
6662 // - If you end up here looking at a compiler error because it's trying to register
6663 // your custom reporter class be aware that the native reporter interface has changed
6664 // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via
6665 // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter.
6666 // However please consider updating to the new interface as the old one is now
6667 // deprecated and will probably be removed quite soon!
6668 // Please contact me via github if you have any questions at all about this.
6669 // In fact, ideally, please contact me anyway to let me know you've hit this - as I have
6670 // no idea who is actually using custom reporters at all (possibly no-one!).
6671 // The new interface is designed to minimise exposure to interface changes in the future.
Phil Nash8defc712013-04-24 19:10:02 +01006672 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
Phil Nash56d5c422012-08-23 20:08:50 +01006673 return new T( config );
6674 }
6675
6676 virtual std::string getDescription() const {
6677 return T::getDescription();
6678 }
6679 };
6680
6681 public:
6682
Phil Nash8defc712013-04-24 19:10:02 +01006683 ReporterRegistrar( std::string const& name ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006684 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
6685 }
6686 };
6687}
6688
Phil Nasha1fbfea2012-12-01 23:57:18 +00006689#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
6690 Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name );
Phil Nash56d5c422012-08-23 20:08:50 +01006691#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
6692 Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name );
6693
Phil Nash56d5c422012-08-23 20:08:50 +01006694// #included from: ../internal/catch_xmlwriter.hpp
6695#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
6696
6697#include <sstream>
Phil Nash9e7e63c2012-09-29 20:54:03 +01006698#include <iostream>
Phil Nash56d5c422012-08-23 20:08:50 +01006699#include <string>
6700#include <vector>
6701
6702namespace Catch {
6703
6704 class XmlWriter {
6705 public:
6706
6707 class ScopedElement {
6708 public:
6709 ScopedElement( XmlWriter* writer )
6710 : m_writer( writer )
6711 {}
6712
Phil Nash8defc712013-04-24 19:10:02 +01006713 ScopedElement( ScopedElement const& other )
Phil Nash56d5c422012-08-23 20:08:50 +01006714 : m_writer( other.m_writer ){
6715 other.m_writer = NULL;
6716 }
6717
6718 ~ScopedElement() {
6719 if( m_writer )
6720 m_writer->endElement();
6721 }
6722
Phil Nash8defc712013-04-24 19:10:02 +01006723 ScopedElement& writeText( std::string const& text, bool indent = true ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006724 m_writer->writeText( text, indent );
Phil Nash56d5c422012-08-23 20:08:50 +01006725 return *this;
6726 }
6727
6728 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01006729 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006730 m_writer->writeAttribute( name, attribute );
6731 return *this;
6732 }
6733
6734 private:
6735 mutable XmlWriter* m_writer;
6736 };
6737
6738 XmlWriter()
6739 : m_tagIsOpen( false ),
6740 m_needsNewline( false ),
6741 m_os( &std::cout )
6742 {}
6743
6744 XmlWriter( std::ostream& os )
6745 : m_tagIsOpen( false ),
6746 m_needsNewline( false ),
6747 m_os( &os )
6748 {}
6749
6750 ~XmlWriter() {
6751 while( !m_tags.empty() )
6752 endElement();
6753 }
6754
Phil Nash8defc712013-04-24 19:10:02 +01006755 XmlWriter& operator = ( XmlWriter const& other ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006756 XmlWriter temp( other );
6757 swap( temp );
6758 return *this;
6759 }
6760
6761 void swap( XmlWriter& other ) {
6762 std::swap( m_tagIsOpen, other.m_tagIsOpen );
6763 std::swap( m_needsNewline, other.m_needsNewline );
6764 std::swap( m_tags, other.m_tags );
6765 std::swap( m_indent, other.m_indent );
6766 std::swap( m_os, other.m_os );
6767 }
6768
Phil Nash8defc712013-04-24 19:10:02 +01006769 XmlWriter& startElement( std::string const& name ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006770 ensureTagClosed();
6771 newlineIfNecessary();
6772 stream() << m_indent << "<" << name;
6773 m_tags.push_back( name );
6774 m_indent += " ";
6775 m_tagIsOpen = true;
6776 return *this;
6777 }
6778
Phil Nash8defc712013-04-24 19:10:02 +01006779 ScopedElement scopedElement( std::string const& name ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006780 ScopedElement scoped( this );
6781 startElement( name );
6782 return scoped;
6783 }
6784
6785 XmlWriter& endElement() {
6786 newlineIfNecessary();
6787 m_indent = m_indent.substr( 0, m_indent.size()-2 );
6788 if( m_tagIsOpen ) {
6789 stream() << "/>\n";
6790 m_tagIsOpen = false;
6791 }
6792 else {
6793 stream() << m_indent << "</" << m_tags.back() << ">\n";
6794 }
6795 m_tags.pop_back();
6796 return *this;
6797 }
6798
Phil Nash8defc712013-04-24 19:10:02 +01006799 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006800 if( !name.empty() && !attribute.empty() ) {
6801 stream() << " " << name << "=\"";
6802 writeEncodedText( attribute );
6803 stream() << "\"";
6804 }
6805 return *this;
6806 }
6807
Phil Nash8defc712013-04-24 19:10:02 +01006808 XmlWriter& writeAttribute( std::string const& name, bool attribute ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006809 stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
6810 return *this;
6811 }
6812
6813 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01006814 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006815 if( !name.empty() )
6816 stream() << " " << name << "=\"" << attribute << "\"";
6817 return *this;
6818 }
6819
Phil Nash8defc712013-04-24 19:10:02 +01006820 XmlWriter& writeText( std::string const& text, bool indent = true ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006821 if( !text.empty() ){
6822 bool tagWasOpen = m_tagIsOpen;
6823 ensureTagClosed();
Phil Nasha1fbfea2012-12-01 23:57:18 +00006824 if( tagWasOpen && indent )
Phil Nash56d5c422012-08-23 20:08:50 +01006825 stream() << m_indent;
6826 writeEncodedText( text );
6827 m_needsNewline = true;
6828 }
6829 return *this;
6830 }
6831
Phil Nash8defc712013-04-24 19:10:02 +01006832 XmlWriter& writeComment( std::string const& text ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006833 ensureTagClosed();
6834 stream() << m_indent << "<!--" << text << "-->";
6835 m_needsNewline = true;
6836 return *this;
6837 }
6838
6839 XmlWriter& writeBlankLine() {
6840 ensureTagClosed();
6841 stream() << "\n";
6842 return *this;
6843 }
6844
6845 private:
6846
6847 std::ostream& stream() {
6848 return *m_os;
6849 }
6850
6851 void ensureTagClosed() {
6852 if( m_tagIsOpen ) {
6853 stream() << ">\n";
6854 m_tagIsOpen = false;
6855 }
6856 }
6857
6858 void newlineIfNecessary() {
6859 if( m_needsNewline ) {
6860 stream() << "\n";
6861 m_needsNewline = false;
6862 }
6863 }
6864
Phil Nash8defc712013-04-24 19:10:02 +01006865 void writeEncodedText( std::string const& text ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006866 static const char* charsToEncode = "<&\"";
6867 std::string mtext = text;
6868 std::string::size_type pos = mtext.find_first_of( charsToEncode );
6869 while( pos != std::string::npos ) {
6870 stream() << mtext.substr( 0, pos );
6871
6872 switch( mtext[pos] ) {
6873 case '<':
6874 stream() << "&lt;";
6875 break;
6876 case '&':
6877 stream() << "&amp;";
6878 break;
6879 case '\"':
6880 stream() << "&quot;";
6881 break;
6882 }
6883 mtext = mtext.substr( pos+1 );
6884 pos = mtext.find_first_of( charsToEncode );
6885 }
6886 stream() << mtext;
6887 }
6888
6889 bool m_tagIsOpen;
6890 bool m_needsNewline;
6891 std::vector<std::string> m_tags;
6892 std::string m_indent;
6893 std::ostream* m_os;
6894 };
6895
6896}
6897namespace Catch {
6898 class XmlReporter : public SharedImpl<IReporter> {
6899 public:
Phil Nash8a52a392013-07-25 08:12:03 +01006900 XmlReporter( ReporterConfig const& config ) : m_config( config ), m_sectionDepth( 0 ) {}
Phil Nash56d5c422012-08-23 20:08:50 +01006901
6902 static std::string getDescription() {
6903 return "Reports test results as an XML document";
6904 }
6905 virtual ~XmlReporter();
6906
6907 private: // IReporter
6908
6909 virtual bool shouldRedirectStdout() const {
6910 return true;
6911 }
6912
6913 virtual void StartTesting() {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006914 m_xml = XmlWriter( m_config.stream() );
Phil Nash56d5c422012-08-23 20:08:50 +01006915 m_xml.startElement( "Catch" );
Phil Nash786959d2013-06-07 19:07:50 +01006916 if( !m_config.fullConfig()->name().empty() )
6917 m_xml.writeAttribute( "name", m_config.fullConfig()->name() );
Phil Nash56d5c422012-08-23 20:08:50 +01006918 }
6919
6920 virtual void EndTesting( const Totals& totals ) {
6921 m_xml.scopedElement( "OverallResults" )
6922 .writeAttribute( "successes", totals.assertions.passed )
6923 .writeAttribute( "failures", totals.assertions.failed );
6924 m_xml.endElement();
6925 }
6926
6927 virtual void StartGroup( const std::string& groupName ) {
6928 m_xml.startElement( "Group" )
6929 .writeAttribute( "name", groupName );
6930 }
6931
6932 virtual void EndGroup( const std::string&, const Totals& totals ) {
6933 m_xml.scopedElement( "OverallResults" )
6934 .writeAttribute( "successes", totals.assertions.passed )
6935 .writeAttribute( "failures", totals.assertions.failed );
6936 m_xml.endElement();
6937 }
6938
6939 virtual void StartSection( const std::string& sectionName, const std::string& description ) {
Phil Nash8a52a392013-07-25 08:12:03 +01006940 if( m_sectionDepth++ > 0 ) {
6941 m_xml.startElement( "Section" )
6942 .writeAttribute( "name", sectionName )
6943 .writeAttribute( "description", description );
6944 }
Phil Nash56d5c422012-08-23 20:08:50 +01006945 }
Phil Nasha70fbe32012-08-31 08:10:36 +01006946 virtual void NoAssertionsInSection( const std::string& ) {}
6947 virtual void NoAssertionsInTestCase( const std::string& ) {}
Phil Nash56d5c422012-08-23 20:08:50 +01006948
6949 virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) {
Phil Nash8a52a392013-07-25 08:12:03 +01006950 if( --m_sectionDepth > 0 ) {
6951 m_xml.scopedElement( "OverallResults" )
6952 .writeAttribute( "successes", assertions.passed )
6953 .writeAttribute( "failures", assertions.failed );
6954 m_xml.endElement();
6955 }
Phil Nash56d5c422012-08-23 20:08:50 +01006956 }
6957
6958 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006959 m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.name );
Phil Nash56d5c422012-08-23 20:08:50 +01006960 m_currentTestSuccess = true;
6961 }
6962
Phil Nashce612bf2012-11-01 08:27:09 +00006963 virtual void Result( const Catch::AssertionResult& assertionResult ) {
Phil Nash786959d2013-06-07 19:07:50 +01006964 if( !m_config.fullConfig()->includeSuccessfulResults() && assertionResult.getResultType() == ResultWas::Ok )
Phil Nash56d5c422012-08-23 20:08:50 +01006965 return;
6966
Phil Nashce612bf2012-11-01 08:27:09 +00006967 if( assertionResult.hasExpression() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006968 m_xml.startElement( "Expression" )
Phil Nash90a35942012-11-13 22:04:29 +00006969 .writeAttribute( "success", assertionResult.succeeded() )
Phil Nashce612bf2012-11-01 08:27:09 +00006970 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
6971 .writeAttribute( "line", assertionResult.getSourceInfo().line );
Phil Nash56d5c422012-08-23 20:08:50 +01006972
6973 m_xml.scopedElement( "Original" )
Phil Nashce612bf2012-11-01 08:27:09 +00006974 .writeText( assertionResult.getExpression() );
Phil Nash56d5c422012-08-23 20:08:50 +01006975 m_xml.scopedElement( "Expanded" )
Phil Nashce612bf2012-11-01 08:27:09 +00006976 .writeText( assertionResult.getExpandedExpression() );
Phil Nash90a35942012-11-13 22:04:29 +00006977 m_currentTestSuccess &= assertionResult.succeeded();
Phil Nash56d5c422012-08-23 20:08:50 +01006978 }
6979
Phil Nashce612bf2012-11-01 08:27:09 +00006980 switch( assertionResult.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006981 case ResultWas::ThrewException:
6982 m_xml.scopedElement( "Exception" )
Phil Nashce612bf2012-11-01 08:27:09 +00006983 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
6984 .writeAttribute( "line", assertionResult.getSourceInfo().line )
6985 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01006986 m_currentTestSuccess = false;
6987 break;
6988 case ResultWas::Info:
6989 m_xml.scopedElement( "Info" )
Phil Nashce612bf2012-11-01 08:27:09 +00006990 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01006991 break;
6992 case ResultWas::Warning:
6993 m_xml.scopedElement( "Warning" )
Phil Nashce612bf2012-11-01 08:27:09 +00006994 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01006995 break;
6996 case ResultWas::ExplicitFailure:
6997 m_xml.scopedElement( "Failure" )
Phil Nashce612bf2012-11-01 08:27:09 +00006998 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01006999 m_currentTestSuccess = false;
7000 break;
7001 case ResultWas::Unknown:
7002 case ResultWas::Ok:
7003 case ResultWas::FailureBit:
7004 case ResultWas::ExpressionFailed:
7005 case ResultWas::Exception:
7006 case ResultWas::DidntThrowException:
7007 break;
7008 }
Phil Nashce612bf2012-11-01 08:27:09 +00007009 if( assertionResult.hasExpression() )
Phil Nash56d5c422012-08-23 20:08:50 +01007010 m_xml.endElement();
7011 }
7012
7013 virtual void Aborted() {
7014 // !TBD
7015 }
7016
7017 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) {
7018 m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess );
7019 m_xml.endElement();
7020 }
7021
7022 private:
7023 ReporterConfig m_config;
7024 bool m_currentTestSuccess;
7025 XmlWriter m_xml;
Phil Nash8a52a392013-07-25 08:12:03 +01007026 int m_sectionDepth;
Phil Nash56d5c422012-08-23 20:08:50 +01007027 };
7028
7029} // end namespace Catch
7030
7031// #included from: ../reporters/catch_reporter_junit.hpp
7032#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
7033
Phil Nashf276a052012-12-02 00:05:51 +00007034#include <assert.h>
7035
Phil Nash56d5c422012-08-23 20:08:50 +01007036namespace Catch {
7037
Phil Nashaa7123b2013-08-15 19:01:00 +01007038 class JunitReporter : public CumulativeReporterBase {
Phil Nash56d5c422012-08-23 20:08:50 +01007039 public:
Phil Nashaa7123b2013-08-15 19:01:00 +01007040 JunitReporter( ReporterConfig const& _config )
7041 : CumulativeReporterBase( _config ),
7042 xml( _config.stream() )
Phil Nash56d5c422012-08-23 20:08:50 +01007043 {}
Phil Nashaa7123b2013-08-15 19:01:00 +01007044
7045 ~JunitReporter();
Phil Nash56d5c422012-08-23 20:08:50 +01007046
7047 static std::string getDescription() {
7048 return "Reports test results in an XML format that looks like Ant's junitreport target";
7049 }
7050
Phil Nashaa7123b2013-08-15 19:01:00 +01007051 virtual void noMatchingTestCases( std::string const& /*spec*/ ) {}
Phil Nash56d5c422012-08-23 20:08:50 +01007052
Phil Nashaa7123b2013-08-15 19:01:00 +01007053 virtual ReporterPreferences getPreferences() const {
7054 ReporterPreferences prefs;
7055 prefs.shouldRedirectStdOut = true;
7056 return prefs;
Phil Nash56d5c422012-08-23 20:08:50 +01007057 }
7058
Phil Nashaa7123b2013-08-15 19:01:00 +01007059 virtual void testRunStarting( TestRunInfo const& runInfo ) {
7060 CumulativeReporterBase::testRunStarting( runInfo );
7061 xml.startElement( "testsuites" );
7062 }
Phil Nash56d5c422012-08-23 20:08:50 +01007063
Phil Nashaa7123b2013-08-15 19:01:00 +01007064 virtual void testGroupStarting( GroupInfo const& groupInfo ) {
7065 suiteTimer.start();
7066 stdOutForSuite.str("");
7067 stdErrForSuite.str("");
7068 unexpectedExceptions = 0;
7069 CumulativeReporterBase::testGroupStarting( groupInfo );
7070 }
7071
7072 virtual bool assertionEnded( AssertionStats const& assertionStats ) {
7073 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException )
7074 unexpectedExceptions++;
7075 return CumulativeReporterBase::assertionEnded( assertionStats );
7076 }
7077
7078 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
7079 stdOutForSuite << testCaseStats.stdOut;
7080 stdErrForSuite << testCaseStats.stdErr;
7081 CumulativeReporterBase::testCaseEnded( testCaseStats );
7082 }
7083
7084 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
7085 double suiteTime = suiteTimer.getElapsedSeconds();
7086 CumulativeReporterBase::testGroupEnded( testGroupStats );
7087 writeGroup( *m_testGroups.back(), suiteTime );
7088 }
7089
7090 virtual void testRunEnded() {
7091 xml.endElement();
7092 }
7093
7094 void writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
7095 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
7096 TestGroupStats const& stats = groupNode.value;
7097 xml.writeAttribute( "name", stats.groupInfo.name );
7098 xml.writeAttribute( "errors", unexpectedExceptions );
7099 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
7100 xml.writeAttribute( "tests", stats.totals.assertions.total() );
7101 xml.writeAttribute( "hostname", "tbd" ); // !TBD
7102 if( m_config->showDurations() == ShowDurations::Never )
7103 xml.writeAttribute( "time", "" );
Phil Nashef60d542012-11-16 08:47:03 +00007104 else
Phil Nashaa7123b2013-08-15 19:01:00 +01007105 xml.writeAttribute( "time", suiteTime );
7106 xml.writeAttribute( "timestamp", "tbd" ); // !TBD
7107
7108 // Write test cases
7109 for( TestGroupNode::ChildNodes::const_iterator
7110 it = groupNode.children.begin(), itEnd = groupNode.children.end();
7111 it != itEnd;
7112 ++it )
7113 writeTestCase( **it );
7114
7115 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false );
7116 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false );
Phil Nash56d5c422012-08-23 20:08:50 +01007117 }
7118
Phil Nashaa7123b2013-08-15 19:01:00 +01007119 void writeTestCase( TestCaseNode const& testCaseNode ) {
7120 TestCaseStats const& stats = testCaseNode.value;
7121
7122 // All test cases have exactly one section - which represents the
7123 // test case itself. That section may have 0-n nested sections
7124 assert( testCaseNode.children.size() == 1 );
7125 SectionNode const& rootSection = *testCaseNode.children.front();
7126
7127 std::string className = stats.testInfo.className;
7128
7129 if( className.empty() ) {
7130 if( rootSection.childSections.empty() )
7131 className = "global";
7132 }
7133 writeSection( className, "", rootSection );
Phil Nash56d5c422012-08-23 20:08:50 +01007134 }
7135
Phil Nashaa7123b2013-08-15 19:01:00 +01007136 void writeSection( std::string const& className,
7137 std::string const& rootName,
7138 SectionNode const& sectionNode ) {
7139 std::string name = trim( sectionNode.stats.sectionInfo.name );
7140 if( !rootName.empty() )
7141 name = rootName + "/" + name;
Phil Nash56d5c422012-08-23 20:08:50 +01007142
Phil Nashaa7123b2013-08-15 19:01:00 +01007143 if( !sectionNode.assertions.empty() ||
7144 !sectionNode.stdOut.empty() ||
7145 !sectionNode.stdErr.empty() ) {
7146 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
7147 if( className.empty() ) {
7148 xml.writeAttribute( "classname", name );
7149 xml.writeAttribute( "name", "root" );
7150 }
7151 else {
7152 xml.writeAttribute( "classname", className );
7153 xml.writeAttribute( "name", name );
7154 }
7155 xml.writeAttribute( "time", toString( sectionNode.stats.durationInSeconds ) );
Phil Nasha70fbe32012-08-31 08:10:36 +01007156
Phil Nashaa7123b2013-08-15 19:01:00 +01007157 writeAssertions( sectionNode );
Phil Nash56d5c422012-08-23 20:08:50 +01007158
Phil Nashaa7123b2013-08-15 19:01:00 +01007159 if( !sectionNode.stdOut.empty() )
7160 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
7161 if( !sectionNode.stdErr.empty() )
7162 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
7163 }
7164 for( SectionNode::ChildSections::const_iterator
7165 it = sectionNode.childSections.begin(),
7166 itEnd = sectionNode.childSections.end();
7167 it != itEnd;
7168 ++it )
7169 if( className.empty() )
7170 writeSection( name, "", **it );
7171 else
7172 writeSection( className, name, **it );
Phil Nash56d5c422012-08-23 20:08:50 +01007173 }
7174
Phil Nashaa7123b2013-08-15 19:01:00 +01007175 void writeAssertions( SectionNode const& sectionNode ) {
7176 for( SectionNode::Assertions::const_iterator
7177 it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
7178 it != itEnd;
7179 ++it )
7180 writeAssertion( *it );
7181 }
7182 void writeAssertion( AssertionStats const& stats ) {
7183 AssertionResult const& result = stats.assertionResult;
7184 if( !result.isOk() ) {
7185 std::string elementName;
7186 switch( result.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01007187 case ResultWas::ThrewException:
Phil Nashaa7123b2013-08-15 19:01:00 +01007188 elementName = "error";
Phil Nash56d5c422012-08-23 20:08:50 +01007189 break;
7190 case ResultWas::ExplicitFailure:
Phil Nashaa7123b2013-08-15 19:01:00 +01007191 elementName = "failure";
Phil Nash56d5c422012-08-23 20:08:50 +01007192 break;
7193 case ResultWas::ExpressionFailed:
Phil Nashaa7123b2013-08-15 19:01:00 +01007194 elementName = "failure";
Phil Nash56d5c422012-08-23 20:08:50 +01007195 break;
Phil Nash243f2d22013-04-12 10:43:06 +01007196 case ResultWas::DidntThrowException:
Phil Nashaa7123b2013-08-15 19:01:00 +01007197 elementName = "failure";
Phil Nash243f2d22013-04-12 10:43:06 +01007198 break;
Phil Nashaa7123b2013-08-15 19:01:00 +01007199
7200 // We should never see these here:
7201 case ResultWas::Info:
7202 case ResultWas::Warning:
7203 case ResultWas::Ok:
Phil Nash56d5c422012-08-23 20:08:50 +01007204 case ResultWas::Unknown:
7205 case ResultWas::FailureBit:
7206 case ResultWas::Exception:
Phil Nashaa7123b2013-08-15 19:01:00 +01007207 elementName = "internalError";
Phil Nash56d5c422012-08-23 20:08:50 +01007208 break;
7209 }
Phil Nashaa7123b2013-08-15 19:01:00 +01007210
7211 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
7212
7213 xml.writeAttribute( "message", result.getExpandedExpression() );
7214 xml.writeAttribute( "type", result.getTestMacroName() );
7215
7216 std::ostringstream oss;
7217 if( !result.getMessage().empty() )
7218 oss << result.getMessage() << "\n";
7219 for( std::vector<MessageInfo>::const_iterator
7220 it = stats.infoMessages.begin(),
7221 itEnd = stats.infoMessages.end();
7222 it != itEnd;
7223 ++it )
7224 if( it->type == ResultWas::Info )
7225 oss << it->message << "\n";
7226
7227 oss << "at " << result.getSourceInfo();
7228 xml.writeText( oss.str(), false );
Phil Nash56d5c422012-08-23 20:08:50 +01007229 }
7230 }
7231
Phil Nashaa7123b2013-08-15 19:01:00 +01007232 XmlWriter xml;
7233 Timer suiteTimer;
7234 std::ostringstream stdOutForSuite;
7235 std::ostringstream stdErrForSuite;
7236 unsigned int unexpectedExceptions;
Phil Nash56d5c422012-08-23 20:08:50 +01007237 };
7238
Phil Nashaa7123b2013-08-15 19:01:00 +01007239 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
7240
Phil Nash56d5c422012-08-23 20:08:50 +01007241} // end namespace Catch
7242
Phil Nashff03cdf2012-12-06 08:44:51 +00007243// #included from: ../reporters/catch_reporter_console.hpp
7244#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
7245
7246namespace Catch {
7247
Phil Nash2e7d9662013-01-16 09:44:43 +00007248 struct ConsoleReporter : StreamingReporterBase {
Phil Nashff03cdf2012-12-06 08:44:51 +00007249 ConsoleReporter( ReporterConfig const& _config )
Phil Nash2e7d9662013-01-16 09:44:43 +00007250 : StreamingReporterBase( _config ),
Phil Nasha04981b2013-03-08 09:30:25 +00007251 m_headerPrinted( false ),
Phil Nashcf5ced52012-12-14 07:50:08 +00007252 m_atLeastOneTestCasePrinted( false )
Phil Nashff03cdf2012-12-06 08:44:51 +00007253 {}
7254
7255 virtual ~ConsoleReporter();
7256 static std::string getDescription() {
7257 return "Reports test results as plain lines of text";
7258 }
7259 virtual ReporterPreferences getPreferences() const {
7260 ReporterPreferences prefs;
7261 prefs.shouldRedirectStdOut = false;
7262 return prefs;
Phil Nashff03cdf2012-12-06 08:44:51 +00007263 }
Phil Nashff03cdf2012-12-06 08:44:51 +00007264
Phil Nash37186a12013-03-13 12:19:30 +00007265 virtual void noMatchingTestCases( std::string const& spec ) {
7266 stream << "No test cases matched '" << spec << "'" << std::endl;
7267 }
7268
Phil Nashbcad0932012-12-10 08:54:57 +00007269 virtual void assertionStarting( AssertionInfo const& ) {
Phil Nashff03cdf2012-12-06 08:44:51 +00007270 }
Phil Nashbcad0932012-12-10 08:54:57 +00007271
Phil Nashb5fd5a62013-06-28 17:09:57 +01007272 virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
Phil Nash2e7d9662013-01-16 09:44:43 +00007273 AssertionResult const& result = _assertionStats.assertionResult;
Phil Nashbcad0932012-12-10 08:54:57 +00007274
7275 // Drop out if result was successful and we're not printing those
Phil Nash786959d2013-06-07 19:07:50 +01007276 if( !m_config->includeSuccessfulResults() && result.isOk() )
Phil Nashb5fd5a62013-06-28 17:09:57 +01007277 return false;
Phil Nashbcad0932012-12-10 08:54:57 +00007278
7279 lazyPrint();
7280
Phil Nashe4756452013-01-26 20:18:30 +00007281 AssertionPrinter printer( stream, _assertionStats );
7282 printer.print();
Phil Nash2e7d9662013-01-16 09:44:43 +00007283 stream << std::endl;
Phil Nashb5fd5a62013-06-28 17:09:57 +01007284 return true;
Phil Nash2e7d9662013-01-16 09:44:43 +00007285 }
7286
Phil Nashe4756452013-01-26 20:18:30 +00007287 virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
Phil Nasha04981b2013-03-08 09:30:25 +00007288 m_headerPrinted = false;
Phil Nashe4756452013-01-26 20:18:30 +00007289 StreamingReporterBase::sectionStarting( _sectionInfo );
Phil Nash2e7d9662013-01-16 09:44:43 +00007290 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007291 virtual void sectionEnded( SectionStats const& _sectionStats ) {
7292 if( _sectionStats.missingAssertions ) {
7293 lazyPrint();
Phil Nash12c16ff2013-04-05 20:58:01 +01007294 Colour colour( Colour::ResultError );
Phil Nashaa7123b2013-08-15 19:01:00 +01007295 if( m_sectionStack.size() > 1 )
7296 stream << "\nNo assertions in section";
7297 else
7298 stream << "\nNo assertions in test case";
7299 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +00007300 }
Phil Nash46118712013-08-16 19:01:32 +01007301 if( m_headerPrinted ) {
7302 if( m_config->showDurations() == ShowDurations::Always )
7303 stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl;
7304 m_headerPrinted = false;
7305 }
Phil Nashf7378ee2013-09-07 12:07:38 +01007306 else {
7307 if( m_config->showDurations() == ShowDurations::Always )
7308 stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl;
7309 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007310 StreamingReporterBase::sectionEnded( _sectionStats );
7311 }
7312
7313 virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) {
Phil Nash2e7d9662013-01-16 09:44:43 +00007314 StreamingReporterBase::testCaseEnded( _testCaseStats );
Phil Nasha04981b2013-03-08 09:30:25 +00007315 m_headerPrinted = false;
Phil Nash2e7d9662013-01-16 09:44:43 +00007316 }
7317 virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) {
Phil Nashaa7123b2013-08-15 19:01:00 +01007318 if( currentGroupInfo.used ) {
Phil Nash2e7d9662013-01-16 09:44:43 +00007319 printSummaryDivider();
7320 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
7321 printTotals( _testGroupStats.totals );
7322 stream << "\n" << std::endl;
7323 }
7324 StreamingReporterBase::testGroupEnded( _testGroupStats );
7325 }
7326 virtual void testRunEnded( TestRunStats const& _testRunStats ) {
7327 if( m_atLeastOneTestCasePrinted )
7328 printTotalsDivider();
7329 printTotals( _testRunStats.totals );
7330 stream << "\n" << std::endl;
7331 StreamingReporterBase::testRunEnded( _testRunStats );
7332 }
7333
7334 private:
Phil Nashe4756452013-01-26 20:18:30 +00007335
7336 class AssertionPrinter {
Phil Nash503d5d02013-07-03 08:25:11 +01007337 void operator= ( AssertionPrinter const& );
Phil Nashe4756452013-01-26 20:18:30 +00007338 public:
7339 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats )
7340 : stream( _stream ),
7341 stats( _stats ),
7342 result( _stats.assertionResult ),
Phil Nash12c16ff2013-04-05 20:58:01 +01007343 colour( Colour::None ),
Phil Nasha2773812013-02-02 20:37:58 +00007344 message( result.getMessage() ),
7345 messages( _stats.infoMessages )
Phil Nashe4756452013-01-26 20:18:30 +00007346 {
7347 switch( result.getResultType() ) {
7348 case ResultWas::Ok:
Phil Nash12c16ff2013-04-05 20:58:01 +01007349 colour = Colour::Success;
Phil Nashe4756452013-01-26 20:18:30 +00007350 passOrFail = "PASSED";
Phil Nasha2773812013-02-02 20:37:58 +00007351 //if( result.hasMessage() )
7352 if( _stats.infoMessages.size() == 1 )
Phil Nashe4756452013-01-26 20:18:30 +00007353 messageLabel = "with message";
Phil Nasha2773812013-02-02 20:37:58 +00007354 if( _stats.infoMessages.size() > 1 )
7355 messageLabel = "with messages";
Phil Nashe4756452013-01-26 20:18:30 +00007356 break;
7357 case ResultWas::ExpressionFailed:
7358 if( result.isOk() ) {
Phil Nash12c16ff2013-04-05 20:58:01 +01007359 colour = Colour::Success;
Phil Nashe4756452013-01-26 20:18:30 +00007360 passOrFail = "FAILED - but was ok";
7361 }
7362 else {
Phil Nash12c16ff2013-04-05 20:58:01 +01007363 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +00007364 passOrFail = "FAILED";
7365 }
Phil Nasha2773812013-02-02 20:37:58 +00007366 if( _stats.infoMessages.size() == 1 )
Phil Nashe4756452013-01-26 20:18:30 +00007367 messageLabel = "with message";
Phil Nasha2773812013-02-02 20:37:58 +00007368 if( _stats.infoMessages.size() > 1 )
7369 messageLabel = "with messages";
Phil Nashe4756452013-01-26 20:18:30 +00007370 break;
7371 case ResultWas::ThrewException:
Phil Nash12c16ff2013-04-05 20:58:01 +01007372 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +00007373 passOrFail = "FAILED";
7374 messageLabel = "due to unexpected exception with message";
7375 break;
7376 case ResultWas::DidntThrowException:
Phil Nash12c16ff2013-04-05 20:58:01 +01007377 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +00007378 passOrFail = "FAILED";
7379 messageLabel = "because no exception was thrown where one was expected";
7380 break;
7381 case ResultWas::Info:
7382 messageLabel = "info";
7383 break;
7384 case ResultWas::Warning:
7385 messageLabel = "warning";
7386 break;
7387 case ResultWas::ExplicitFailure:
7388 passOrFail = "FAILED";
Phil Nash12c16ff2013-04-05 20:58:01 +01007389 colour = Colour::Error;
Phil Nasha2773812013-02-02 20:37:58 +00007390 if( _stats.infoMessages.size() == 1 )
7391 messageLabel = "explicitly with message";
7392 if( _stats.infoMessages.size() > 1 )
7393 messageLabel = "explicitly with messages";
Phil Nashe4756452013-01-26 20:18:30 +00007394 break;
Phil Nashe4756452013-01-26 20:18:30 +00007395 // These cases are here to prevent compiler warnings
7396 case ResultWas::Unknown:
7397 case ResultWas::FailureBit:
Phil Nash243f2d22013-04-12 10:43:06 +01007398 case ResultWas::Exception:
Phil Nashe4756452013-01-26 20:18:30 +00007399 passOrFail = "** internal error **";
Phil Nash12c16ff2013-04-05 20:58:01 +01007400 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +00007401 break;
7402 }
7403 }
7404
7405 void print() const {
Phil Nash767f1582013-03-04 12:19:15 +01007406 printSourceInfo();
Phil Nashe4756452013-01-26 20:18:30 +00007407 if( stats.totals.assertions.total() > 0 ) {
Phil Nash767f1582013-03-04 12:19:15 +01007408 if( result.isOk() )
7409 stream << "\n";
Phil Nashe4756452013-01-26 20:18:30 +00007410 printResultType();
7411 printOriginalExpression();
7412 printReconstructedExpression();
7413 }
Phil Nash767f1582013-03-04 12:19:15 +01007414 else {
7415 stream << "\n";
7416 }
Phil Nashe4756452013-01-26 20:18:30 +00007417 printMessage();
Phil Nashe4756452013-01-26 20:18:30 +00007418 }
7419
7420 private:
7421 void printResultType() const {
7422 if( !passOrFail.empty() ) {
Phil Nash12c16ff2013-04-05 20:58:01 +01007423 Colour colourGuard( colour );
Phil Nashe4756452013-01-26 20:18:30 +00007424 stream << passOrFail << ":\n";
7425 }
7426 }
7427 void printOriginalExpression() const {
7428 if( result.hasExpression() ) {
Phil Nash12c16ff2013-04-05 20:58:01 +01007429 Colour colourGuard( Colour::OriginalExpression );
Phil Nashe4756452013-01-26 20:18:30 +00007430 stream << " ";
Phil Nash786959d2013-06-07 19:07:50 +01007431 stream << result.getExpressionInMacro();
Phil Nashe4756452013-01-26 20:18:30 +00007432 stream << "\n";
7433 }
7434 }
7435 void printReconstructedExpression() const {
7436 if( result.hasExpandedExpression() ) {
7437 stream << "with expansion:\n";
Phil Nash12c16ff2013-04-05 20:58:01 +01007438 Colour colourGuard( Colour::ReconstructedExpression );
Phil Nash19279252013-04-20 21:07:32 +01007439 stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n";
Phil Nashe4756452013-01-26 20:18:30 +00007440 }
7441 }
7442 void printMessage() const {
7443 if( !messageLabel.empty() )
7444 stream << messageLabel << ":" << "\n";
Phil Nasha2773812013-02-02 20:37:58 +00007445 for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
7446 it != itEnd;
7447 ++it ) {
Phil Nash19279252013-04-20 21:07:32 +01007448 stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n";
Phil Nasha2773812013-02-02 20:37:58 +00007449 }
Phil Nashe4756452013-01-26 20:18:30 +00007450 }
7451 void printSourceInfo() const {
Phil Nash12c16ff2013-04-05 20:58:01 +01007452 Colour colourGuard( Colour::FileName );
Phil Nash767f1582013-03-04 12:19:15 +01007453 stream << result.getSourceInfo() << ": ";
Phil Nashe4756452013-01-26 20:18:30 +00007454 }
7455
Phil Nashe4756452013-01-26 20:18:30 +00007456 std::ostream& stream;
7457 AssertionStats const& stats;
7458 AssertionResult const& result;
Phil Nash12c16ff2013-04-05 20:58:01 +01007459 Colour::Code colour;
Phil Nashe4756452013-01-26 20:18:30 +00007460 std::string passOrFail;
7461 std::string messageLabel;
7462 std::string message;
Phil Nasha2773812013-02-02 20:37:58 +00007463 std::vector<MessageInfo> messages;
Phil Nashe4756452013-01-26 20:18:30 +00007464 };
Phil Nash2e7d9662013-01-16 09:44:43 +00007465
7466 void lazyPrint() {
7467
Phil Nashaa7123b2013-08-15 19:01:00 +01007468 if( !currentTestRunInfo.used )
Phil Nash2e7d9662013-01-16 09:44:43 +00007469 lazyPrintRunInfo();
Phil Nashaa7123b2013-08-15 19:01:00 +01007470 if( !currentGroupInfo.used )
Phil Nash2e7d9662013-01-16 09:44:43 +00007471 lazyPrintGroupInfo();
Phil Nash2e7d9662013-01-16 09:44:43 +00007472
Phil Nasha04981b2013-03-08 09:30:25 +00007473 if( !m_headerPrinted ) {
7474 printTestCaseAndSectionHeader();
7475 m_headerPrinted = true;
7476 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007477 m_atLeastOneTestCasePrinted = true;
7478 }
7479 void lazyPrintRunInfo() {
Phil Nash93906752013-03-16 20:21:51 +00007480 stream << "\n" << getTildes() << "\n";
Phil Nash12c16ff2013-04-05 20:58:01 +01007481 Colour colour( Colour::SecondaryText );
Phil Nashaa7123b2013-08-15 19:01:00 +01007482 stream << currentTestRunInfo->name
Phil Nash786959d2013-06-07 19:07:50 +01007483 << " is a Catch v" << libraryVersion.majorVersion << "."
Phil Nash2e7d9662013-01-16 09:44:43 +00007484 << libraryVersion.minorVersion << " b"
7485 << libraryVersion.buildNumber;
7486 if( libraryVersion.branchName != "master" )
7487 stream << " (" << libraryVersion.branchName << ")";
7488 stream << " host application.\n"
7489 << "Run with -? for options\n\n";
7490
Phil Nashaa7123b2013-08-15 19:01:00 +01007491 currentTestRunInfo.used = true;
Phil Nash2e7d9662013-01-16 09:44:43 +00007492 }
7493 void lazyPrintGroupInfo() {
Phil Nashaa7123b2013-08-15 19:01:00 +01007494 if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) {
7495 printClosedHeader( "Group: " + currentGroupInfo->name );
7496 currentGroupInfo.used = true;
Phil Nash2e7d9662013-01-16 09:44:43 +00007497 }
7498 }
Phil Nasha04981b2013-03-08 09:30:25 +00007499 void printTestCaseAndSectionHeader() {
Phil Nashaa7123b2013-08-15 19:01:00 +01007500 assert( !m_sectionStack.empty() );
7501 printOpenHeader( currentTestCaseInfo->name );
Phil Nash2e7d9662013-01-16 09:44:43 +00007502
Phil Nashaa7123b2013-08-15 19:01:00 +01007503 if( m_sectionStack.size() > 1 ) {
7504 Colour colourGuard( Colour::Headers );
7505
7506 std::vector<SectionInfo>::const_iterator
7507 it = m_sectionStack.begin()+1, // Skip first section (test case)
7508 itEnd = m_sectionStack.end();
7509 for( ; it != itEnd; ++it )
7510 printHeaderString( it->name, 2 );
Phil Nash2e7d9662013-01-16 09:44:43 +00007511 }
Phil Nashaa7123b2013-08-15 19:01:00 +01007512
7513 SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
Phil Nash19279252013-04-20 21:07:32 +01007514
7515 if( !lineInfo.empty() ){
7516 stream << getDashes() << "\n";
7517 Colour colourGuard( Colour::FileName );
7518 stream << lineInfo << "\n";
7519 }
Phil Nasha04981b2013-03-08 09:30:25 +00007520 stream << getDots() << "\n" << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +00007521 }
7522
Phil Nasha04981b2013-03-08 09:30:25 +00007523 void printClosedHeader( std::string const& _name ) {
7524 printOpenHeader( _name );
7525 stream << getDots() << "\n";
7526 }
Phil Nash19279252013-04-20 21:07:32 +01007527 void printOpenHeader( std::string const& _name ) {
Phil Nash5c7d3d72013-04-01 11:27:10 +01007528 stream << getDashes() << "\n";
Phil Nash5c7d3d72013-04-01 11:27:10 +01007529 {
Phil Nash12c16ff2013-04-05 20:58:01 +01007530 Colour colourGuard( Colour::Headers );
Phil Nash19279252013-04-20 21:07:32 +01007531 printHeaderString( _name );
Phil Nash5c7d3d72013-04-01 11:27:10 +01007532 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007533 }
7534
Phil Nash12c16ff2013-04-05 20:58:01 +01007535 // if string has a : in first line will set indent to follow it on
7536 // subsequent lines
Phil Nash19279252013-04-20 21:07:32 +01007537 void printHeaderString( std::string const& _string, std::size_t indent = 0 ) {
Phil Nash12c16ff2013-04-05 20:58:01 +01007538 std::size_t i = _string.find( ": " );
7539 if( i != std::string::npos )
7540 i+=2;
7541 else
7542 i = 0;
Phil Nash19279252013-04-20 21:07:32 +01007543 stream << Text( _string, TextAttributes()
7544 .setIndent( indent+i)
7545 .setInitialIndent( indent ) ) << "\n";
Phil Nash12c16ff2013-04-05 20:58:01 +01007546 }
7547
Phil Nash2e7d9662013-01-16 09:44:43 +00007548 void printTotals( const Totals& totals ) {
7549 if( totals.assertions.total() == 0 ) {
7550 stream << "No tests ran";
7551 }
7552 else if( totals.assertions.failed ) {
Phil Nash12c16ff2013-04-05 20:58:01 +01007553 Colour colour( Colour::ResultError );
Phil Nash2e7d9662013-01-16 09:44:43 +00007554 printCounts( "test case", totals.testCases );
7555 if( totals.testCases.failed > 0 ) {
7556 stream << " (";
7557 printCounts( "assertion", totals.assertions );
7558 stream << ")";
7559 }
Phil Nashbcad0932012-12-10 08:54:57 +00007560 }
7561 else {
Phil Nash12c16ff2013-04-05 20:58:01 +01007562 Colour colour( Colour::ResultSuccess );
Phil Nash2e7d9662013-01-16 09:44:43 +00007563 stream << "All tests passed ("
7564 << pluralise( totals.assertions.passed, "assertion" ) << " in "
7565 << pluralise( totals.testCases.passed, "test case" ) << ")";
Phil Nashbcad0932012-12-10 08:54:57 +00007566 }
Phil Nashff03cdf2012-12-06 08:44:51 +00007567 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007568 void printCounts( std::string const& label, Counts const& counts ) {
Phil Nashf1178122012-12-11 09:03:14 +00007569 if( counts.total() == 1 ) {
7570 stream << "1 " << label << " - ";
7571 if( counts.failed )
7572 stream << "failed";
7573 else
7574 stream << "passed";
7575 }
7576 else {
7577 stream << counts.total() << " " << label << "s ";
7578 if( counts.passed ) {
7579 if( counts.failed )
7580 stream << "- " << counts.failed << " failed";
7581 else if( counts.passed == 2 )
7582 stream << "- both passed";
7583 else
7584 stream << "- all passed";
7585 }
7586 else {
7587 if( counts.failed == 2 )
7588 stream << "- both failed";
7589 else
7590 stream << "- all failed";
7591 }
7592 }
Phil Nashff03cdf2012-12-06 08:44:51 +00007593 }
7594
Phil Nash2e7d9662013-01-16 09:44:43 +00007595 void printTotalsDivider() {
7596 stream << getDoubleDashes() << "\n";
Phil Nashff03cdf2012-12-06 08:44:51 +00007597 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007598 void printSummaryDivider() {
7599 stream << getDashes() << "\n";
Phil Nashff03cdf2012-12-06 08:44:51 +00007600 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007601 static std::string const& getDashes() {
Phil Nashe4756452013-01-26 20:18:30 +00007602 static const std::string dashes( CATCH_CONFIG_CONSOLE_WIDTH-1, '-' );
Phil Nash2e7d9662013-01-16 09:44:43 +00007603 return dashes;
Phil Nashff03cdf2012-12-06 08:44:51 +00007604 }
Phil Nash3ce320d2013-01-18 08:09:28 +00007605 static std::string const& getDots() {
Phil Nashe4756452013-01-26 20:18:30 +00007606 static const std::string dots( CATCH_CONFIG_CONSOLE_WIDTH-1, '.' );
Phil Nash3ce320d2013-01-18 08:09:28 +00007607 return dots;
7608 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007609 static std::string const& getDoubleDashes() {
Phil Nashe4756452013-01-26 20:18:30 +00007610 static const std::string doubleDashes( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' );
Phil Nash2e7d9662013-01-16 09:44:43 +00007611 return doubleDashes;
Phil Nashff03cdf2012-12-06 08:44:51 +00007612 }
Phil Nash93906752013-03-16 20:21:51 +00007613 static std::string const& getTildes() {
7614 static const std::string dots( CATCH_CONFIG_CONSOLE_WIDTH-1, '~' );
7615 return dots;
7616 }
Phil Nashff03cdf2012-12-06 08:44:51 +00007617
Phil Nashcf5ced52012-12-14 07:50:08 +00007618 private:
Phil Nasha04981b2013-03-08 09:30:25 +00007619 bool m_headerPrinted;
Phil Nashcf5ced52012-12-14 07:50:08 +00007620 bool m_atLeastOneTestCasePrinted;
Phil Nashff03cdf2012-12-06 08:44:51 +00007621 };
7622
7623 INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter )
7624
7625} // end namespace Catch
7626
Phil Nasha695eb92012-08-13 07:46:10 +01007627namespace Catch {
7628 NonCopyable::~NonCopyable() {}
7629 IShared::~IShared() {}
Phil Nashad7445d2013-07-02 08:49:29 +01007630 StreamBufBase::~StreamBufBase() throw() {}
Phil Nasha695eb92012-08-13 07:46:10 +01007631 IContext::~IContext() {}
7632 IResultCapture::~IResultCapture() {}
7633 ITestCase::~ITestCase() {}
7634 ITestCaseRegistry::~ITestCaseRegistry() {}
7635 IRegistryHub::~IRegistryHub() {}
7636 IMutableRegistryHub::~IMutableRegistryHub() {}
7637 IExceptionTranslator::~IExceptionTranslator() {}
7638 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
7639 IReporter::~IReporter() {}
7640 IReporterFactory::~IReporterFactory() {}
7641 IReporterRegistry::~IReporterRegistry() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +00007642 IStreamingReporter::~IStreamingReporter() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +00007643 AssertionStats::~AssertionStats() {}
7644 SectionStats::~SectionStats() {}
7645 TestCaseStats::~TestCaseStats() {}
7646 TestGroupStats::~TestGroupStats() {}
7647 TestRunStats::~TestRunStats() {}
Phil Nashaa7123b2013-08-15 19:01:00 +01007648 CumulativeReporterBase::SectionNode::~SectionNode() {}
7649 CumulativeReporterBase::~CumulativeReporterBase() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +00007650
Phil Nash2e7d9662013-01-16 09:44:43 +00007651 StreamingReporterBase::~StreamingReporterBase() {}
Phil Nashff03cdf2012-12-06 08:44:51 +00007652 ConsoleReporter::~ConsoleReporter() {}
Phil Nasha695eb92012-08-13 07:46:10 +01007653 IRunner::~IRunner() {}
7654 IMutableContext::~IMutableContext() {}
7655 IConfig::~IConfig() {}
7656 XmlReporter::~XmlReporter() {}
7657 JunitReporter::~JunitReporter() {}
7658 TestRegistry::~TestRegistry() {}
7659 FreeFunctionTestCase::~FreeFunctionTestCase() {}
7660 IGeneratorInfo::~IGeneratorInfo() {}
7661 IGeneratorsForTest::~IGeneratorsForTest() {}
Phil Nash799ecf92012-09-24 08:30:13 +01007662 TagParser::~TagParser() {}
7663 TagExtracter::~TagExtracter() {}
7664 TagExpressionParser::~TagExpressionParser() {}
Phil Nasha695eb92012-08-13 07:46:10 +01007665
Phil Nash9444bbc2012-10-12 07:58:17 +01007666 Matchers::Impl::StdString::Equals::~Equals() {}
7667 Matchers::Impl::StdString::Contains::~Contains() {}
7668 Matchers::Impl::StdString::StartsWith::~StartsWith() {}
7669 Matchers::Impl::StdString::EndsWith::~EndsWith() {}
7670
Phil Nasha695eb92012-08-13 07:46:10 +01007671 void Config::dummy() {}
7672
Phil Nasha1fbfea2012-12-01 23:57:18 +00007673 INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter )
Phil Nasha695eb92012-08-13 07:46:10 +01007674}
7675
Phil Nash5bc030d2012-08-16 18:48:50 +01007676#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01007677#pragma clang diagnostic pop
Phil Nash89d1e6c2011-05-24 08:23:02 +01007678#endif
Matt Wozniskif29c8982012-09-17 01:42:29 -04007679
Phil Nash5bc030d2012-08-16 18:48:50 +01007680#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01007681
7682#ifdef CATCH_CONFIG_MAIN
7683// #included from: internal/catch_default_main.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01007684#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01007685
Phil Nash176eb812012-05-11 08:17:16 +01007686#ifndef __OBJC__
Phil Nash89d1e6c2011-05-24 08:23:02 +01007687
Phil Nash176eb812012-05-11 08:17:16 +01007688// Standard C/C++ main entry point
7689int main (int argc, char * const argv[]) {
Phil Nash786959d2013-06-07 19:07:50 +01007690 return Catch::Session().run( argc, argv );
Phil Nash176eb812012-05-11 08:17:16 +01007691}
7692
7693#else // __OBJC__
7694
7695// Objective-C entry point
7696int main (int argc, char * const argv[]) {
Phil Nash53c990a2012-03-17 18:20:06 +00007697#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +01007698 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Phil Nash53c990a2012-03-17 18:20:06 +00007699#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01007700
7701 Catch::registerTestMethods();
Phil Nash786959d2013-06-07 19:07:50 +01007702 int result = Catch::Session().run( argc, (char* const*)argv );
Phil Nash89d1e6c2011-05-24 08:23:02 +01007703
Phil Nash53c990a2012-03-17 18:20:06 +00007704#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +01007705 [pool drain];
Phil Nash53c990a2012-03-17 18:20:06 +00007706#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01007707
Phil Nashdd5b9c22012-02-18 09:58:30 +00007708 return result;
Phil Nash89d1e6c2011-05-24 08:23:02 +01007709}
7710
Phil Nash176eb812012-05-11 08:17:16 +01007711#endif // __OBJC__
7712
Phil Nash89d1e6c2011-05-24 08:23:02 +01007713#endif
7714
Phil Nash89d1e6c2011-05-24 08:23:02 +01007715//////
7716
Phil Nash46bcd4b2012-07-20 18:43:48 +01007717// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
7718#ifdef CATCH_CONFIG_PREFIX_ALL
7719
Phil Nash90a35942012-11-13 22:04:29 +00007720#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
7721#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 +01007722
Phil Nash90a35942012-11-13 22:04:29 +00007723#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" )
7724#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
7725#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007726
Phil Nash90a35942012-11-13 22:04:29 +00007727#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
7728#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CATCH_CHECK_FALSE" )
7729#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" )
7730#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
7731#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 +01007732
Phil Nash90a35942012-11-13 22:04:29 +00007733#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
7734#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
7735#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007736
Phil Nash90a35942012-11-13 22:04:29 +00007737#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
7738#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007739
Phil Nasha2773812013-02-02 20:37:58 +00007740#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
Phil Nash90a35942012-11-13 22:04:29 +00007741#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN" )
7742#define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL" )
7743#define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED" )
Phil Nashb5fd5a62013-06-28 17:09:57 +01007744#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
Phil Nasha2773812013-02-02 20:37:58 +00007745#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
Phil Nashb5fd5a62013-06-28 17:09:57 +01007746#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007747
Phil Nash93906752013-03-16 20:21:51 +00007748#ifdef CATCH_CONFIG_VARIADIC_MACROS
7749 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
Phil Nash786959d2013-06-07 19:07:50 +01007750 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +00007751 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
7752 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
7753#else
7754 #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
Phil Nash786959d2013-06-07 19:07:50 +01007755 #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
Phil Nash93906752013-03-16 20:21:51 +00007756 #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
7757 #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
7758#endif
7759#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007760
7761#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
Phil Nasha1fbfea2012-12-01 23:57:18 +00007762#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007763
7764#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
7765
Phil Nash37186a12013-03-13 12:19:30 +00007766// "BDD-style" convenience wrappers
Phil Nashbd7f7972013-03-21 09:00:24 +00007767#ifdef CATCH_CONFIG_VARIADIC_MACROS
7768#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
7769#else
Phil Nash37186a12013-03-13 12:19:30 +00007770#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
Phil Nashbd7f7972013-03-21 09:00:24 +00007771#endif
Phil Nash37186a12013-03-13 12:19:30 +00007772#define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" )
7773#define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" )
7774#define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" )
7775#define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" )
7776#define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" )
7777
Phil Nash46bcd4b2012-07-20 18:43:48 +01007778// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
7779#else
7780
Phil Nash90a35942012-11-13 22:04:29 +00007781#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
7782#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "REQUIRE_FALSE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01007783
Phil Nash90a35942012-11-13 22:04:29 +00007784#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "REQUIRE_THROWS" )
7785#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
7786#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01007787
Phil Nash90a35942012-11-13 22:04:29 +00007788#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
7789#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CHECK_FALSE" )
7790#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" )
7791#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
7792#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01007793
Phil Nash90a35942012-11-13 22:04:29 +00007794#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" )
7795#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
7796#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01007797
Phil Nash90a35942012-11-13 22:04:29 +00007798#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
7799#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
Phil Nash78d95a02012-03-04 21:22:36 +00007800
Phil Nasha2773812013-02-02 20:37:58 +00007801#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
Phil Nash90a35942012-11-13 22:04:29 +00007802#define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN" )
7803#define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL" )
7804#define SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED" )
Phil Nashb5fd5a62013-06-28 17:09:57 +01007805#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
Phil Nasha2773812013-02-02 20:37:58 +00007806#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
Phil Nashb5fd5a62013-06-28 17:09:57 +01007807#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01007808
Phil Nash93906752013-03-16 20:21:51 +00007809#ifdef CATCH_CONFIG_VARIADIC_MACROS
7810 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
Phil Nash786959d2013-06-07 19:07:50 +01007811 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +00007812 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
7813 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
7814#else
7815 #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
Phil Nash786959d2013-06-07 19:07:50 +01007816 #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
Phil Nash93906752013-03-16 20:21:51 +00007817 #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
7818 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
7819#endif
7820#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01007821
7822#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
Phil Nasha1fbfea2012-12-01 23:57:18 +00007823#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
Phil Nash89d1e6c2011-05-24 08:23:02 +01007824
7825#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
7826
Phil Nash46bcd4b2012-07-20 18:43:48 +01007827#endif
7828
7829#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
Phil Nash89d1e6c2011-05-24 08:23:02 +01007830
Phil Nash37186a12013-03-13 12:19:30 +00007831// "BDD-style" convenience wrappers
Phil Nashbd7f7972013-03-21 09:00:24 +00007832#ifdef CATCH_CONFIG_VARIADIC_MACROS
7833#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
7834#else
Phil Nash37186a12013-03-13 12:19:30 +00007835#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
Phil Nashbd7f7972013-03-21 09:00:24 +00007836#endif
Phil Nash38f7eef2013-03-29 13:44:33 +00007837#define GIVEN( desc ) SECTION( " Given: " desc, "" )
7838#define WHEN( desc ) SECTION( " When: " desc, "" )
7839#define AND_WHEN( desc ) SECTION( "And when: " desc, "" )
7840#define THEN( desc ) SECTION( " Then: " desc, "" )
7841#define AND_THEN( desc ) SECTION( " And: " desc, "" )
Phil Nash37186a12013-03-13 12:19:30 +00007842
Phil Nash89d1e6c2011-05-24 08:23:02 +01007843using Catch::Detail::Approx;
7844
Phil Nash5bc030d2012-08-16 18:48:50 +01007845#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01007846#pragma clang diagnostic pop
Phil Nash5bc030d2012-08-16 18:48:50 +01007847#endif
Phil Nasha695eb92012-08-13 07:46:10 +01007848
Phil Nashaec1e5e2012-05-09 19:37:51 +01007849#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01007850