blob: 07d2af592f9008dba17dc63acbf2f49e0c2a4d41 [file] [log] [blame]
Phil Nash89d1e6c2011-05-24 08:23:02 +01001/*
Phil Nashe571e6f2012-08-24 18:54:56 +01002 * Generated: 2012-08-24 18:54:08.754777
Phil Nash4df051b2012-05-22 22:22:22 +01003 * ----------------------------------------------------------
Phil Nashaec1e5e2012-05-09 19:37:51 +01004 * This file has been merged from multiple headers. Please don't edit it directly
5 * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
Phil Nash89d1e6c2011-05-24 08:23:02 +01006 *
7 * Distributed under the Boost Software License, Version 1.0. (See accompanying
8 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Phil Nash89d1e6c2011-05-24 08:23:02 +01009 */
Phil Nashaec1e5e2012-05-09 19:37:51 +010010#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
11#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010012
Phil Nash3b80af72012-08-09 07:47:30 +010013#define TWOBLUECUBES_CATCH_HPP_INCLUDED
Phil Nash0f9c5512012-06-02 23:12:42 +010014
Phil Nash5bc030d2012-08-16 18:48:50 +010015#ifdef __clang__
16#pragma clang diagnostic ignored "-Wno-global-constructors"
17
Phil Nasha695eb92012-08-13 07:46:10 +010018#pragma clang diagnostic push
19#pragma clang diagnostic ignored "-Wpadded"
Phil Nash5bc030d2012-08-16 18:48:50 +010020#endif
Phil Nasha695eb92012-08-13 07:46:10 +010021
Phil Nash3b80af72012-08-09 07:47:30 +010022// #included from: internal/catch_notimplemented_exception.h
23#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010024
Phil Nash89d1e6c2011-05-24 08:23:02 +010025// #included from: catch_common.h
Phil Nash3b80af72012-08-09 07:47:30 +010026#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010027
Phil Nash89d1e6c2011-05-24 08:23:02 +010028#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
29#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
30#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
31
32#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
33#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
34
35#ifdef __GNUC__
Phil Nasha695eb92012-08-13 07:46:10 +010036#define CATCH_ATTRIBUTE_NORETURN __attribute__ ((noreturn))
Phil Nash89d1e6c2011-05-24 08:23:02 +010037#else
Phil Nasha695eb92012-08-13 07:46:10 +010038#define CATCH_ATTRIBUTE_NORETURN
Phil Nash89d1e6c2011-05-24 08:23:02 +010039#endif
40
41#include <sstream>
42#include <stdexcept>
43#include <algorithm>
44
Phil Nash89d2a3f2012-05-16 15:09:17 +010045namespace Catch {
46
Phil Nashd31737f2012-05-09 19:04:00 +010047 class NonCopyable {
Phil Nash89d1e6c2011-05-24 08:23:02 +010048 NonCopyable( const NonCopyable& );
49 void operator = ( const NonCopyable& );
50 protected:
Phil Nashd31737f2012-05-09 19:04:00 +010051 NonCopyable() {}
Phil Nasha695eb92012-08-13 07:46:10 +010052 virtual ~NonCopyable();
Phil Nash89d1e6c2011-05-24 08:23:02 +010053 };
54
Phil Nash163088a2012-05-31 19:40:26 +010055 class SafeBool {
56 public:
57 typedef void (SafeBool::*type)() const;
58
59 static type makeSafe( bool value ) {
60 return value ? &SafeBool::trueValue : 0;
61 }
62 private:
63 void trueValue() const {}
64 };
65
Phil Nash89d1e6c2011-05-24 08:23:02 +010066 template<typename ContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +010067 inline void deleteAll( ContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010068 typename ContainerT::const_iterator it = container.begin();
69 typename ContainerT::const_iterator itEnd = container.end();
70 for(; it != itEnd; ++it )
71 {
72 delete *it;
73 }
74 }
75 template<typename AssociativeContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +010076 inline void deleteAllValues( AssociativeContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010077 typename AssociativeContainerT::const_iterator it = container.begin();
78 typename AssociativeContainerT::const_iterator itEnd = container.end();
79 for(; it != itEnd; ++it )
80 {
81 delete it->second;
82 }
83 }
84
85 template<typename ContainerT, typename Function>
Phil Nashd31737f2012-05-09 19:04:00 +010086 inline void forEach( ContainerT& container, Function function ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010087 std::for_each( container.begin(), container.end(), function );
88 }
89
90 template<typename ContainerT, typename Function>
Phil Nashd31737f2012-05-09 19:04:00 +010091 inline void forEach( const ContainerT& container, Function function ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010092 std::for_each( container.begin(), container.end(), function );
93 }
94
Phil Nash56d5c422012-08-23 20:08:50 +010095 inline bool startsWith( const std::string& s, const std::string& prefix ) {
96 return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
97 }
Phil Nash4c97fc52012-08-24 08:23:50 +010098 inline bool endsWith( const std::string& s, const std::string& suffix ) {
99 return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
100 }
101 inline bool contains( const std::string& s, const std::string& infix ) {
102 return s.find( infix ) != std::string::npos;
103 }
104
105 struct pluralise {
106 pluralise( std::size_t count, const std::string& label )
107 : m_count( count ),
108 m_label( label )
109 {}
110
111 friend std::ostream& operator << ( std::ostream& os, const pluralise& pluraliser ) {
112 os << pluraliser.m_count << " " << pluraliser.m_label;
113 if( pluraliser.m_count != 1 )
114 os << "s";
115 return os;
116 }
117
118 std::size_t m_count;
119 std::string m_label;
120 };
Phil Nash56d5c422012-08-23 20:08:50 +0100121
Phil Nash89d2a3f2012-05-16 15:09:17 +0100122 struct SourceLineInfo {
123
Phil Nashd31737f2012-05-09 19:04:00 +0100124 SourceLineInfo() : line( 0 ){}
Phil Nash62179662012-05-11 19:06:43 +0100125 SourceLineInfo( const std::string& _file, std::size_t _line )
126 : file( _file ),
127 line( _line )
Phil Nash6e0f58d2012-02-15 18:37:21 +0000128 {}
Phil Nashabf27162012-07-05 18:37:58 +0100129 SourceLineInfo( const std::string& _function, const std::string& _file, std::size_t _line )
130 : function( _function ),
131 file( _file ),
132 line( _line )
133 {}
Phil Nashd31737f2012-05-09 19:04:00 +0100134 SourceLineInfo( const SourceLineInfo& other )
135 : file( other.file ),
136 line( other.line )
137 {}
138 void swap( SourceLineInfo& other ){
139 file.swap( other.file );
140 std::swap( line, other.line );
141 }
Phil Nash6e0f58d2012-02-15 18:37:21 +0000142
Phil Nashabf27162012-07-05 18:37:58 +0100143 std::string function;
Phil Nash6e0f58d2012-02-15 18:37:21 +0000144 std::string file;
145 std::size_t line;
146 };
147
Phil Nashd31737f2012-05-09 19:04:00 +0100148 inline std::ostream& operator << ( std::ostream& os, const SourceLineInfo& info ) {
Phil Nash6e0f58d2012-02-15 18:37:21 +0000149#ifndef __GNUG__
150 os << info.file << "(" << info.line << "): ";
151#else
152 os << info.file << ":" << info.line << ": ";
153#endif
154 return os;
155 }
156
Phil Nasha695eb92012-08-13 07:46:10 +0100157 CATCH_ATTRIBUTE_NORETURN
158 inline void throwLogicError( const std::string& message, const SourceLineInfo& locationInfo ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100159 std::ostringstream oss;
Phil Nasha695eb92012-08-13 07:46:10 +0100160 oss << "Internal Catch error: '" << message << "' at: " << locationInfo;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100161 throw std::logic_error( oss.str() );
162 }
163}
164
Phil Nasha695eb92012-08-13 07:46:10 +0100165#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
166#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100167
Phil Nash3b80af72012-08-09 07:47:30 +0100168#include <ostream>
169
170namespace Catch {
171
172 class NotImplementedException : public std::exception
173 {
174 public:
175 NotImplementedException( const SourceLineInfo& lineInfo );
176
177 virtual ~NotImplementedException() throw() {}
178
179 virtual const char* what() const throw();
180
181 private:
182 std::string m_what;
183 SourceLineInfo m_lineInfo;
184 };
185
186} // end namespace Catch
187
188///////////////////////////////////////////////////////////////////////////////
189#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
190
191// #included from: internal/catch_context.h
192#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
193
194// #included from: catch_interfaces_reporter.h
195#define TWOBLUECUBES_CATCH_IREPORTERREGISTRY_INCLUDED
196
Phil Nashf7299fc2012-02-25 09:39:45 +0000197// #included from: catch_totals.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100198#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
Phil Nashf7299fc2012-02-25 09:39:45 +0000199
Phil Nash89d2a3f2012-05-16 15:09:17 +0100200namespace Catch {
201
202 struct Counts {
Phil Nash176eb812012-05-11 08:17:16 +0100203 Counts() : passed( 0 ), failed( 0 ) {}
Phil Nashf7299fc2012-02-25 09:39:45 +0000204
Phil Nash176eb812012-05-11 08:17:16 +0100205 Counts operator - ( const Counts& other ) const {
Phil Nashf7299fc2012-02-25 09:39:45 +0000206 Counts diff;
207 diff.passed = passed - other.passed;
208 diff.failed = failed - other.failed;
209 return diff;
210 }
Phil Nash7004f4a2012-05-22 08:56:59 +0100211 Counts& operator += ( const Counts& other ) {
212 passed += other.passed;
213 failed += other.failed;
214 return *this;
215 }
Phil Nashf7299fc2012-02-25 09:39:45 +0000216
Phil Nash176eb812012-05-11 08:17:16 +0100217 std::size_t total() const {
Phil Nashf7299fc2012-02-25 09:39:45 +0000218 return passed + failed;
219 }
Phil Nash176eb812012-05-11 08:17:16 +0100220
Phil Nashf7299fc2012-02-25 09:39:45 +0000221 std::size_t passed;
222 std::size_t failed;
223 };
224
Phil Nash89d2a3f2012-05-16 15:09:17 +0100225 struct Totals {
226
Phil Nash176eb812012-05-11 08:17:16 +0100227 Totals operator - ( const Totals& other ) const {
Phil Nashf7299fc2012-02-25 09:39:45 +0000228 Totals diff;
229 diff.assertions = assertions - other.assertions;
230 diff.testCases = testCases - other.testCases;
231 return diff;
232 }
233
Phil Nash7004f4a2012-05-22 08:56:59 +0100234 Totals delta( const Totals& prevTotals ) const {
235 Totals diff = *this - prevTotals;
236 if( diff.assertions.failed > 0 )
237 ++diff.testCases.failed;
238 else
239 ++diff.testCases.passed;
240 return diff;
241 }
242
Phil Nash5bc030d2012-08-16 18:48:50 +0100243 Totals& operator += ( const Totals& other ) {
244 assertions += other.assertions;
245 testCases += other.testCases;
246 return *this;
247 }
248
Phil Nashf7299fc2012-02-25 09:39:45 +0000249 Counts assertions;
250 Counts testCases;
251 };
252}
253
Phil Nash49e6d532012-05-05 19:35:35 +0100254// #included from: catch_ptr.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100255#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
Phil Nash49e6d532012-05-05 19:35:35 +0100256
Phil Nash89d2a3f2012-05-16 15:09:17 +0100257namespace Catch {
258
Phil Nash49e6d532012-05-05 19:35:35 +0100259 // An intrusive reference counting smart pointer.
260 // T must implement addRef() and release() methods
261 // typically implementing the IShared interface
262 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100263 class Ptr {
Phil Nash49e6d532012-05-05 19:35:35 +0100264 public:
265 Ptr() : m_p( NULL ){}
266 Ptr( T* p ) : m_p( p ){
Phil Nash61756972012-07-28 20:37:07 +0100267 if( m_p )
268 m_p->addRef();
Phil Nash49e6d532012-05-05 19:35:35 +0100269 }
270 Ptr( const Ptr& other ) : m_p( other.m_p ){
Phil Nash61756972012-07-28 20:37:07 +0100271 if( m_p )
272 m_p->addRef();
Phil Nash49e6d532012-05-05 19:35:35 +0100273 }
274 ~Ptr(){
275 if( m_p )
276 m_p->release();
277 }
278 Ptr& operator = ( T* p ){
279 Ptr temp( p );
280 swap( temp );
281 return *this;
282 }
283 Ptr& operator = ( Ptr& other ){
284 Ptr temp( other );
285 swap( temp );
286 return *this;
287 }
288 void swap( Ptr& other ){
289 std::swap( m_p, other.m_p );
290 }
291
292 T* get(){
293 return m_p;
294 }
295 const T* get() const{
296 return m_p;
297 }
298
Phil Nash56d5c422012-08-23 20:08:50 +0100299 T& operator*() const {
Phil Nash49e6d532012-05-05 19:35:35 +0100300 return *m_p;
301 }
302
Phil Nash56d5c422012-08-23 20:08:50 +0100303 T* operator->() const {
Phil Nash49e6d532012-05-05 19:35:35 +0100304 return m_p;
305 }
Phil Nash56d5c422012-08-23 20:08:50 +0100306
Phil Nash61756972012-07-28 20:37:07 +0100307 bool operator !() const {
308 return m_p == NULL;
309 }
Phil Nash49e6d532012-05-05 19:35:35 +0100310
311 private:
312 T* m_p;
313 };
314
315 struct IShared : NonCopyable {
Phil Nasha695eb92012-08-13 07:46:10 +0100316 virtual ~IShared();
Phil Nash49e6d532012-05-05 19:35:35 +0100317 virtual void addRef() = 0;
318 virtual void release() = 0;
319 };
320
321 template<typename T>
322 struct SharedImpl : T {
323
324 SharedImpl() : m_rc( 0 ){}
325
326 virtual void addRef(){
327 ++m_rc;
328 }
329 virtual void release(){
330 if( --m_rc == 0 )
331 delete this;
332 }
333
334 int m_rc;
335 };
336
337} // end namespace Catch
338
Phil Nash89d1e6c2011-05-24 08:23:02 +0100339#include <string>
340#include <ostream>
341#include <map>
342
343namespace Catch
344{
Phil Nashd2553cd2012-07-20 19:07:42 +0100345 struct ReporterConfig
346 {
347 ReporterConfig( const std::string& _name,
348 std::ostream& _stream,
349 bool _includeSuccessfulResults = false )
350 : name( _name ),
351 stream( _stream ),
352 includeSuccessfulResults( _includeSuccessfulResults )
353 {}
354
355 std::string name;
356 std::ostream& stream;
357 bool includeSuccessfulResults;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100358 };
359
360 class TestCaseInfo;
361 class ResultInfo;
362
Phil Nashd31737f2012-05-09 19:04:00 +0100363 struct IReporter : IShared {
Phil Nasha695eb92012-08-13 07:46:10 +0100364 virtual ~IReporter();
Phil Nashd31737f2012-05-09 19:04:00 +0100365 virtual bool shouldRedirectStdout() const = 0;
366 virtual void StartTesting() = 0;
367 virtual void EndTesting( const Totals& totals ) = 0;
368 virtual void StartGroup( const std::string& groupName ) = 0;
369 virtual void EndGroup( const std::string& groupName, const Totals& totals ) = 0;
Phil Nash89d2a3f2012-05-16 15:09:17 +0100370 virtual void StartSection( const std::string& sectionName, const std::string& description ) = 0;
Phil Nashd31737f2012-05-09 19:04:00 +0100371 virtual void EndSection( const std::string& sectionName, const Counts& assertions ) = 0;
372 virtual void StartTestCase( const TestCaseInfo& testInfo ) = 0;
Phil Nash19b2aa62012-06-01 19:40:27 +0100373 virtual void Aborted() = 0;
Phil Nashd31737f2012-05-09 19:04:00 +0100374 virtual void EndTestCase( const TestCaseInfo& testInfo, const Totals& totals, const std::string& stdOut, const std::string& stdErr ) = 0;
375 virtual void Result( const ResultInfo& result ) = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100376 };
377
Phil Nashd31737f2012-05-09 19:04:00 +0100378 struct IReporterFactory {
Phil Nasha695eb92012-08-13 07:46:10 +0100379 virtual ~IReporterFactory();
Phil Nashd2553cd2012-07-20 19:07:42 +0100380 virtual IReporter* create( const ReporterConfig& config ) const = 0;
Phil Nashd31737f2012-05-09 19:04:00 +0100381 virtual std::string getDescription() const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100382 };
383
Phil Nashd31737f2012-05-09 19:04:00 +0100384 struct IReporterRegistry {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100385 typedef std::map<std::string, IReporterFactory*> FactoryMap;
386
Phil Nasha695eb92012-08-13 07:46:10 +0100387 virtual ~IReporterRegistry();
Phil Nashd2553cd2012-07-20 19:07:42 +0100388 virtual IReporter* create( const std::string& name, const ReporterConfig& config ) const = 0;
Phil Nashd31737f2012-05-09 19:04:00 +0100389 virtual const FactoryMap& getFactories() const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100390 };
391
Phil Nash89d2a3f2012-05-16 15:09:17 +0100392 inline std::string trim( const std::string& str ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100393 std::string::size_type start = str.find_first_not_of( "\n\r\t " );
394 std::string::size_type end = str.find_last_not_of( "\n\r\t " );
395
Phil Nash918046a2012-02-28 20:04:42 +0000396 return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
Phil Nash89d1e6c2011-05-24 08:23:02 +0100397 }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100398}
399
Phil Nashe4636872012-06-05 20:51:05 +0100400// #included from: catch_interfaces_config.h
Phil Nash3b80af72012-08-09 07:47:30 +0100401#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
Phil Nashe4636872012-06-05 20:51:05 +0100402
403namespace Catch {
404
405 struct IConfig {
406
Phil Nasha695eb92012-08-13 07:46:10 +0100407 virtual ~IConfig();
Phil Nashe4636872012-06-05 20:51:05 +0100408
409 virtual bool allowThrows() const = 0;
410 };
411}
412
Phil Nash3b80af72012-08-09 07:47:30 +0100413// #included from: catch_interfaces_generators.h
414#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
415
416#include <string>
417
418namespace Catch {
419
420 struct IGeneratorInfo {
Phil Nasha695eb92012-08-13 07:46:10 +0100421 virtual ~IGeneratorInfo();
Phil Nash3b80af72012-08-09 07:47:30 +0100422 virtual bool moveNext() = 0;
423 virtual std::size_t getCurrentIndex() const = 0;
424 };
425
426 struct IGeneratorsForTest {
Phil Nasha695eb92012-08-13 07:46:10 +0100427 virtual ~IGeneratorsForTest();
Phil Nash3b80af72012-08-09 07:47:30 +0100428
429 virtual IGeneratorInfo& getGeneratorInfo( const std::string& fileInfo, std::size_t size ) = 0;
430 virtual bool moveNext() = 0;
431 };
432
433 IGeneratorsForTest* createGeneratorsForTest();
434
435} // end namespace Catch
436
Phil Nash89d1e6c2011-05-24 08:23:02 +0100437#include <memory>
438#include <vector>
439#include <stdlib.h>
440
Phil Nash89d2a3f2012-05-16 15:09:17 +0100441namespace Catch {
442
Phil Nash89d1e6c2011-05-24 08:23:02 +0100443 class TestCaseInfo;
444 struct IResultCapture;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100445 struct IRunner;
Phil Nash3b80af72012-08-09 07:47:30 +0100446 struct IGeneratorsForTest;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100447
Phil Nasha695eb92012-08-13 07:46:10 +0100448 class StreamBufBase : public std::streambuf {
449 public:
450 virtual ~StreamBufBase();
451 };
Phil Nash176eb812012-05-11 08:17:16 +0100452
Phil Nash371db8b2012-05-21 18:52:09 +0100453 struct IContext
454 {
Phil Nasha695eb92012-08-13 07:46:10 +0100455 virtual ~IContext();
Phil Nash06e959b2012-05-25 08:52:05 +0100456
Phil Nash371db8b2012-05-21 18:52:09 +0100457 virtual IResultCapture& getResultCapture() = 0;
458 virtual IRunner& getRunner() = 0;
Phil Nash371db8b2012-05-21 18:52:09 +0100459 virtual size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ) = 0;
460 virtual bool advanceGeneratorsForCurrentTest() = 0;
Phil Nashe4636872012-06-05 20:51:05 +0100461 virtual const IConfig* getConfig() const = 0;
Phil Nash371db8b2012-05-21 18:52:09 +0100462 };
463
464 struct IMutableContext : IContext
465 {
Phil Nasha695eb92012-08-13 07:46:10 +0100466 virtual ~IMutableContext();
Phil Nash371db8b2012-05-21 18:52:09 +0100467 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
468 virtual void setRunner( IRunner* runner ) = 0;
Phil Nashe4636872012-06-05 20:51:05 +0100469 virtual void setConfig( const IConfig* config ) = 0;
Phil Nash371db8b2012-05-21 18:52:09 +0100470 };
471
472 IContext& getCurrentContext();
473 IMutableContext& getCurrentMutableContext();
Phil Nash3b80af72012-08-09 07:47:30 +0100474 void cleanUpContext();
475 std::streambuf* createStreamBuf( const std::string& streamName );
Phil Nash371db8b2012-05-21 18:52:09 +0100476
Phil Nash89d1e6c2011-05-24 08:23:02 +0100477}
478
479// #included from: internal/catch_test_registry.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100480#define TWOBLUECUBES_CATCH_REGISTRY_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100481
Phil Nash0f9c5512012-06-02 23:12:42 +0100482// #included from: catch_interfaces_testcase.h
Phil Nash3b80af72012-08-09 07:47:30 +0100483#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
Phil Nash0f9c5512012-06-02 23:12:42 +0100484
485#include <vector>
486
487namespace Catch {
Phil Nash56d5c422012-08-23 20:08:50 +0100488
489 class TestCaseFilters;
490
Phil Nash5bc030d2012-08-16 18:48:50 +0100491 struct ITestCase : IShared {
Phil Nash0f9c5512012-06-02 23:12:42 +0100492 virtual void invoke () const = 0;
Phil Nash5bc030d2012-08-16 18:48:50 +0100493 protected:
494 virtual ~ITestCase();
Phil Nash0f9c5512012-06-02 23:12:42 +0100495 };
496
497 class TestCaseInfo;
498
499 struct ITestCaseRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +0100500 virtual ~ITestCaseRegistry();
Phil Nash0f9c5512012-06-02 23:12:42 +0100501 virtual const std::vector<TestCaseInfo>& getAllTests() const = 0;
Phil Nash3b80af72012-08-09 07:47:30 +0100502 virtual std::vector<TestCaseInfo> getMatchingTestCases( const std::string& rawTestSpec ) const = 0;
Phil Nash0f9c5512012-06-02 23:12:42 +0100503 };
504}
505
Phil Nash89d2a3f2012-05-16 15:09:17 +0100506namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100507
508template<typename C>
Phil Nash5bc030d2012-08-16 18:48:50 +0100509class MethodTestCase : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +0100510
Phil Nash176eb812012-05-11 08:17:16 +0100511public:
512 MethodTestCase( void (C::*method)() ) : m_method( method ) {}
Phil Nash89d1e6c2011-05-24 08:23:02 +0100513
Phil Nash176eb812012-05-11 08:17:16 +0100514 virtual void invoke() const {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100515 C obj;
516 (obj.*m_method)();
517 }
518
Phil Nash89d1e6c2011-05-24 08:23:02 +0100519private:
Phil Nash5bc030d2012-08-16 18:48:50 +0100520 virtual ~MethodTestCase() {}
521
Phil Nash89d1e6c2011-05-24 08:23:02 +0100522 void (C::*m_method)();
523};
524
525typedef void(*TestFunction)();
526
Phil Nash89d2a3f2012-05-16 15:09:17 +0100527struct AutoReg {
528
Phil Nash176eb812012-05-11 08:17:16 +0100529 AutoReg( TestFunction function,
530 const char* name,
531 const char* description,
532 const SourceLineInfo& lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100533
Phil Nash89d1e6c2011-05-24 08:23:02 +0100534 template<typename C>
Phil Nash176eb812012-05-11 08:17:16 +0100535 AutoReg( void (C::*method)(),
536 const char* name,
537 const char* description,
538 const SourceLineInfo& lineInfo ) {
Phil Nashd31737f2012-05-09 19:04:00 +0100539 registerTestCase( new MethodTestCase<C>( method ), name, description, lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100540 }
541
Phil Nash176eb812012-05-11 08:17:16 +0100542 void registerTestCase( ITestCase* testCase,
543 const char* name,
544 const char* description,
545 const SourceLineInfo& lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100546
Phil Nash176eb812012-05-11 08:17:16 +0100547 ~AutoReg();
Phil Nash89d1e6c2011-05-24 08:23:02 +0100548
549private:
Phil Nash176eb812012-05-11 08:17:16 +0100550 AutoReg( const AutoReg& );
551 void operator= ( const AutoReg& );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100552};
553
554} // end namespace Catch
555
556///////////////////////////////////////////////////////////////////////////////
557#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
Phil Nashd31737f2012-05-09 19:04:00 +0100558 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )(); \
559 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ ), Name, Desc, CATCH_INTERNAL_LINEINFO ); }\
560 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100561
562///////////////////////////////////////////////////////////////////////////////
563#define INTERNAL_CATCH_TESTCASE_NORETURN( Name, Desc ) \
Phil Nasha695eb92012-08-13 07:46:10 +0100564 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )() CATCH_ATTRIBUTE_NORETURN; \
Phil Nashd31737f2012-05-09 19:04:00 +0100565 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ ), Name, Desc, CATCH_INTERNAL_LINEINFO ); }\
566 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100567
568///////////////////////////////////////////////////////////////////////////////
Phil Nash46bcd4b2012-07-20 18:43:48 +0100569#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
Phil Nashd31737f2012-05-09 19:04:00 +0100570 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, Name, Desc, CATCH_INTERNAL_LINEINFO ); }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100571
572///////////////////////////////////////////////////////////////////////////////
573#define TEST_CASE_METHOD( ClassName, TestName, Desc )\
Phil Nashfd78e0f2011-12-28 19:56:39 +0000574 namespace{ \
Phil Nashd31737f2012-05-09 19:04:00 +0100575 struct INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ ) : ClassName{ \
Phil Nashfd78e0f2011-12-28 19:56:39 +0000576 void test(); \
577 }; \
Phil Nashd31737f2012-05-09 19:04:00 +0100578 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ )::test, TestName, Desc, CATCH_INTERNAL_LINEINFO ); \
Phil Nashfd78e0f2011-12-28 19:56:39 +0000579 } \
Phil Nashd31737f2012-05-09 19:04:00 +0100580 void INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ )::test()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100581
582// #included from: internal/catch_capture.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100583#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100584
Phil Nash89d2a3f2012-05-16 15:09:17 +0100585// #included from: catch_expression_builder.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100586#define TWOBLUECUBES_CATCH_EXPRESSION_BUILDER_HPP_INCLUDED
Phil Nash89d2a3f2012-05-16 15:09:17 +0100587
Phil Nash176eb812012-05-11 08:17:16 +0100588// #included from: catch_expression.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100589#define TWOBLUECUBES_CATCH_EXPRESSION_HPP_INCLUDED
Phil Nash176eb812012-05-11 08:17:16 +0100590
Phil Nash3b80af72012-08-09 07:47:30 +0100591// #included from: catch_resultinfo_builder.h
592#define TWOBLUECUBES_CATCH_RESULTINFO_BUILDER_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +0100593
Phil Nashd31737f2012-05-09 19:04:00 +0100594// #included from: catch_tostring.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100595#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +0100596
Phil Nashd31737f2012-05-09 19:04:00 +0100597#include <sstream>
598
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 Nashd31737f2012-05-09 19:04:00 +0100648 struct NonStreamable {
649 template<typename T> NonStreamable( const T& ){}
650 };
651
652 // If the type does not have its own << overload for ostream then
653 // this one will be used instead
654 inline std::ostream& operator << ( std::ostream& ss, NonStreamable ){
655 return ss << "{?}";
656 }
657
658 template<typename T>
659 inline std::string makeString( const T& value ) {
660 std::ostringstream oss;
661 oss << value;
662 return oss.str();
663 }
664
665 template<typename T>
666 inline std::string makeString( T* p ) {
667 if( !p )
668 return INTERNAL_CATCH_STRINGIFY( NULL );
669 std::ostringstream oss;
670 oss << p;
671 return oss.str();
672 }
673
674 template<typename T>
675 inline std::string makeString( const T* p ) {
676 if( !p )
677 return INTERNAL_CATCH_STRINGIFY( NULL );
678 std::ostringstream oss;
679 oss << p;
680 return oss.str();
681 }
682
683} // end namespace Detail
684
685/// \brief converts any type to a string
686///
687/// The default template forwards on to ostringstream - except when an
688/// ostringstream overload does not exist - in which case it attempts to detect
689/// that and writes {?}.
690/// Overload (not specialise) this template for custom typs that you don't want
691/// to provide an ostream overload for.
692template<typename T>
693std::string toString( const T& value ) {
694 return Detail::makeString( value );
695}
696
697// Built in overloads
698
699inline std::string toString( const std::string& value ) {
700 return "\"" + value + "\"";
701}
702
703inline std::string toString( const std::wstring& value ) {
704 std::ostringstream oss;
705 oss << "\"";
706 for(size_t i = 0; i < value.size(); ++i )
707 oss << static_cast<char>( value[i] <= 0xff ? value[i] : '?');
708 oss << "\"";
709 return oss.str();
710}
711
712inline std::string toString( const char* const value ) {
713 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
714}
715
716inline std::string toString( char* const value ) {
717 return Catch::toString( static_cast<const char*>( value ) );
718}
719
720inline std::string toString( int value ) {
721 std::ostringstream oss;
722 oss << value;
723 return oss.str();
724}
725
726inline std::string toString( unsigned long value ) {
727 std::ostringstream oss;
728 if( value > 8192 )
729 oss << "0x" << std::hex << value;
730 else
731 oss << value;
732 return oss.str();
733}
734
735inline std::string toString( unsigned int value ) {
Phil Nash62179662012-05-11 19:06:43 +0100736 return toString( static_cast<unsigned long>( value ) );
Phil Nashd31737f2012-05-09 19:04:00 +0100737}
738
739inline std::string toString( const double value ) {
740 std::ostringstream oss;
741 oss << value;
742 return oss.str();
743}
744
745inline std::string toString( bool value ) {
746 return value ? "true" : "false";
747}
748
Phil Nash78372d02012-06-06 08:06:40 +0100749inline std::string toString( char value ) {
750 return value < ' '
751 ? toString( (unsigned int)value )
752 : Detail::makeString( value );
753}
754
755inline std::string toString( signed char value ) {
756 return toString( static_cast<char>( value ) );
757}
758
Phil Nash176eb812012-05-11 08:17:16 +0100759#ifdef CATCH_CONFIG_CPP11_NULLPTR
Phil Nash06e959b2012-05-25 08:52:05 +0100760inline std::string toString( std::nullptr_t ) {
Phil Nash176eb812012-05-11 08:17:16 +0100761 return "nullptr";
762}
763#endif
764
Phil Nash0dc9e432012-08-01 08:17:07 +0100765#ifdef __OBJC__
Phil Nash0dc9e432012-08-01 08:17:07 +0100766 inline std::string toString( NSString const * const& nsstring ) {
767 return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
768 }
769 inline std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
770 return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
771 }
772 inline std::string toString( NSObject* const& nsObject ) {
773 return toString( [nsObject description] );
774 }
775#endif
776
Phil Nashd31737f2012-05-09 19:04:00 +0100777} // end namespace Catch
778
Phil Nash3b80af72012-08-09 07:47:30 +0100779// #included from: catch_resultinfo.h
780#define TWOBLUECUBES_CATCH_RESULT_INFO_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100781
Phil Nash89d1e6c2011-05-24 08:23:02 +0100782#include <string>
783// #included from: catch_result_type.h
Phil Nash3b80af72012-08-09 07:47:30 +0100784#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100785
Phil Nash89d2a3f2012-05-16 15:09:17 +0100786namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100787
Phil Nash89d2a3f2012-05-16 15:09:17 +0100788struct ResultWas { enum OfType {
789 Unknown = -1,
790 Ok = 0,
791 Info = 1,
792 Warning = 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100793
Phil Nash89d2a3f2012-05-16 15:09:17 +0100794 FailureBit = 0x10,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100795
Phil Nash89d2a3f2012-05-16 15:09:17 +0100796 ExpressionFailed = FailureBit | 1,
797 ExplicitFailure = FailureBit | 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100798
Phil Nash89d2a3f2012-05-16 15:09:17 +0100799 Exception = 0x100 | FailureBit,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100800
Phil Nash89d2a3f2012-05-16 15:09:17 +0100801 ThrewException = Exception | 1,
802 DidntThrowException = Exception | 2
Phil Nash89d1e6c2011-05-24 08:23:02 +0100803
Phil Nash89d2a3f2012-05-16 15:09:17 +0100804}; };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100805
Phil Nash89d2a3f2012-05-16 15:09:17 +0100806struct ResultAction { enum Value {
807 None,
Phil Nash19b2aa62012-06-01 19:40:27 +0100808 Failed = 1, // Failure - but no debug break if Debug bit not set
809 Debug = 2, // If this bit is set, invoke the debugger
810 Abort = 4 // Test run should abort
Phil Nash89d2a3f2012-05-16 15:09:17 +0100811}; };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100812
813}
814
815
Phil Nash89d2a3f2012-05-16 15:09:17 +0100816namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100817
Phil Nash89d2a3f2012-05-16 15:09:17 +0100818 class ResultInfo {
819 public:
Phil Nash3b80af72012-08-09 07:47:30 +0100820 ResultInfo();
Phil Nash89d2a3f2012-05-16 15:09:17 +0100821 ResultInfo( const char* expr,
822 ResultWas::OfType result,
823 bool isNot,
824 const SourceLineInfo& lineInfo,
825 const char* macroName,
Phil Nash3b80af72012-08-09 07:47:30 +0100826 const char* message );
Phil Nasha695eb92012-08-13 07:46:10 +0100827 ~ResultInfo();
Phil Nash89d1e6c2011-05-24 08:23:02 +0100828
Phil Nash3b80af72012-08-09 07:47:30 +0100829 bool ok() const;
830 ResultWas::OfType getResultType() const;
831 bool hasExpression() const;
832 bool hasMessage() const;
833 std::string getExpression() const;
834 bool hasExpandedExpression() const;
835 std::string getExpandedExpression() const;
836 std::string getMessage() const;
837 std::string getFilename() const;
838 std::size_t getLine() const;
839 std::string getTestMacroName() const;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100840
841 protected:
842
Phil Nash3b80af72012-08-09 07:47:30 +0100843 std::string getExpandedExpressionInternal() const;
844 bool isNotExpression( const char* expr );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100845
846 protected:
847 std::string m_macroName;
Phil Nashd31737f2012-05-09 19:04:00 +0100848 SourceLineInfo m_lineInfo;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100849 std::string m_expr, m_lhs, m_rhs, m_op;
850 std::string m_message;
851 ResultWas::OfType m_result;
852 bool m_isNot;
853 };
854
855} // end namespace Catch
856
Phil Nash89d1e6c2011-05-24 08:23:02 +0100857// #included from: catch_evaluate.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100858#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100859
Phil Nash89d2a3f2012-05-16 15:09:17 +0100860namespace Catch {
861namespace Internal {
862
863 enum Operator {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100864 IsEqualTo,
865 IsNotEqualTo,
866 IsLessThan,
867 IsGreaterThan,
868 IsLessThanOrEqualTo,
869 IsGreaterThanOrEqualTo
870 };
871
Phil Nash371db8b2012-05-21 18:52:09 +0100872 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
873 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
874 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
875 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
876 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
877 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
878 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100879
880 // So the compare overloads can be operator agnostic we convey the operator as a template
881 // enum, which is used to specialise an Evaluator for doing the comparison.
882 template<typename T1, typename T2, Operator Op>
883 class Evaluator{};
884
885 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100886 struct Evaluator<T1, T2, IsEqualTo> {
887 static bool evaluate( const T1& lhs, const T2& rhs) {
Phil Nashd31737f2012-05-09 19:04:00 +0100888 return const_cast<T1&>( lhs ) == const_cast<T2&>( rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100889 }
890 };
891 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100892 struct Evaluator<T1, T2, IsNotEqualTo> {
893 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100894 return const_cast<T1&>( lhs ) != const_cast<T2&>( rhs );
895 }
896 };
897 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100898 struct Evaluator<T1, T2, IsLessThan> {
899 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100900 return const_cast<T1&>( lhs ) < const_cast<T2&>( rhs );
901 }
902 };
903 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100904 struct Evaluator<T1, T2, IsGreaterThan> {
905 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100906 return const_cast<T1&>( lhs ) > const_cast<T2&>( rhs );
907 }
908 };
909 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100910 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
911 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100912 return const_cast<T1&>( lhs ) >= const_cast<T2&>( rhs );
913 }
914 };
915 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100916 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
917 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100918 return const_cast<T1&>( lhs ) <= const_cast<T2&>( rhs );
919 }
920 };
921
922 template<Operator Op, typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100923 bool applyEvaluator( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100924 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
925 }
926
927 // "base" overload
928 template<Operator Op, typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100929 bool compare( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100930 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
931 }
932
933 // unsigned X to int
Phil Nash89d2a3f2012-05-16 15:09:17 +0100934 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100935 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
936 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100937 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100938 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
939 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100940 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100941 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
942 }
943
944 // unsigned X to long
Phil Nash89d2a3f2012-05-16 15:09:17 +0100945 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100946 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
947 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100948 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100949 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
950 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100951 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100952 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
953 }
954
955 // int to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +0100956 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100957 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
958 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100959 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100960 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
961 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100962 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100963 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
964 }
965
966 // long to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +0100967 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -0300968 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100969 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100970 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -0300971 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100972 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100973 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -0300974 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100975 }
976
Phil Nash06e959b2012-05-25 08:52:05 +0100977 // pointer to long (when comparing against NULL)
Phil Nash89d1e6c2011-05-24 08:23:02 +0100978 template<Operator Op, typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100979 bool compare( long lhs, const T* rhs ) {
Phil Nash6f1543b2012-05-07 19:46:19 +0100980 return Evaluator<const T*, const T*, Op>::evaluate( reinterpret_cast<const T*>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100981 }
982
983 template<Operator Op, typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100984 bool compare( long lhs, T* rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100985 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
Phil Nash6f1543b2012-05-07 19:46:19 +0100986 }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100987
Phil Nash6f1543b2012-05-07 19:46:19 +0100988 template<Operator Op, typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100989 bool compare( const T* lhs, long rhs ) {
Phil Nash6f1543b2012-05-07 19:46:19 +0100990 return Evaluator<const T*, const T*, Op>::evaluate( lhs, reinterpret_cast<const T*>( rhs ) );
991 }
992
993 template<Operator Op, typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100994 bool compare( T* lhs, long rhs ) {
Phil Nash6f1543b2012-05-07 19:46:19 +0100995 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100996 }
997
Phil Nash06e959b2012-05-25 08:52:05 +0100998 // pointer to int (when comparing against NULL)
999 template<Operator Op, typename T>
1000 bool compare( int lhs, const T* rhs ) {
1001 return Evaluator<const T*, const T*, Op>::evaluate( reinterpret_cast<const T*>( lhs ), rhs );
1002 }
1003
1004 template<Operator Op, typename T>
1005 bool compare( int lhs, T* rhs ) {
1006 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1007 }
1008
1009 template<Operator Op, typename T>
1010 bool compare( const T* lhs, int rhs ) {
1011 return Evaluator<const T*, const T*, Op>::evaluate( lhs, reinterpret_cast<const T*>( rhs ) );
1012 }
1013
1014 template<Operator Op, typename T>
1015 bool compare( T* lhs, int rhs ) {
1016 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1017 }
1018
Phil Nash89d1e6c2011-05-24 08:23:02 +01001019} // end of namespace Internal
1020} // end of namespace Catch
1021
Phil Nash89d2a3f2012-05-16 15:09:17 +01001022namespace Catch {
Phil Nashf51d3162011-12-28 10:37:31 +00001023
Phil Nash89d1e6c2011-05-24 08:23:02 +01001024struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
1025
Phil Nash89d2a3f2012-05-16 15:09:17 +01001026class ResultInfoBuilder : public ResultInfo {
1027
Phil Nash89d1e6c2011-05-24 08:23:02 +01001028public:
1029
Phil Nash3b80af72012-08-09 07:47:30 +01001030 ResultInfoBuilder();
Phil Nashd31737f2012-05-09 19:04:00 +01001031
1032 ResultInfoBuilder( const char* expr,
1033 bool isNot,
1034 const SourceLineInfo& lineInfo,
1035 const char* macroName,
Phil Nash3b80af72012-08-09 07:47:30 +01001036 const char* message = "" );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001037
Phil Nash3b80af72012-08-09 07:47:30 +01001038 void setResultType( ResultWas::OfType result );
1039 void setMessage( const std::string& message );
1040 void setLineInfo( const SourceLineInfo& lineInfo );
1041 void setLhs( const std::string& lhs );
1042 void setRhs( const std::string& rhs );
1043 void setOp( const std::string& op );
Phil Nash78d95a02012-03-04 21:22:36 +00001044
Phil Nash89d1e6c2011-05-24 08:23:02 +01001045 template<typename RhsT>
1046 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator ||
1047 (
1048 const RhsT&
1049 );
1050
Phil Nash89d1e6c2011-05-24 08:23:02 +01001051 template<typename RhsT>
1052 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator &&
1053 (
1054 const RhsT&
1055 );
1056
1057private:
Phil Nash89d2a3f2012-05-16 15:09:17 +01001058 friend class ExpressionBuilder;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001059 template<typename T> friend class Expression;
1060
1061 template<typename T> friend class PtrExpression;
1062
Phil Nash3b80af72012-08-09 07:47:30 +01001063 ResultInfoBuilder& captureBoolExpression( bool result );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001064
Phil Nash89d1e6c2011-05-24 08:23:02 +01001065 template<Internal::Operator Op, typename T1, typename T2>
Phil Nashd31737f2012-05-09 19:04:00 +01001066 ResultInfoBuilder& captureExpression( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001067 setResultType( Internal::compare<Op>( lhs, rhs ) ? ResultWas::Ok : ResultWas::ExpressionFailed );
1068 m_lhs = Catch::toString( lhs );
1069 m_rhs = Catch::toString( rhs );
1070 m_op = Internal::OperatorTraits<Op>::getName();
1071 return *this;
1072 }
1073
Phil Nash4021d652011-07-15 08:12:10 +01001074 template<Internal::Operator Op, typename T>
Phil Nashd31737f2012-05-09 19:04:00 +01001075 ResultInfoBuilder& captureExpression( const T* lhs, int rhs ) {
Phil Nash4021d652011-07-15 08:12:10 +01001076 return captureExpression<Op>( lhs, reinterpret_cast<const T*>( rhs ) );
1077 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001078};
1079
Phil Nashd31737f2012-05-09 19:04:00 +01001080} // end namespace Catch
1081
Phil Nash89d2a3f2012-05-16 15:09:17 +01001082namespace Catch {
Phil Nash176eb812012-05-11 08:17:16 +01001083
1084template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001085class Expression {
Phil Nash176eb812012-05-11 08:17:16 +01001086 void operator = ( const Expression& );
1087
1088public:
1089 Expression( ResultInfoBuilder& result, T lhs )
1090 : m_result( result ),
1091 m_lhs( lhs )
1092 {}
1093
1094 template<typename RhsT>
1095 ResultInfoBuilder& operator == ( const RhsT& rhs ) {
1096 return m_result.captureExpression<Internal::IsEqualTo>( m_lhs, rhs );
1097 }
1098
1099 template<typename RhsT>
1100 ResultInfoBuilder& operator != ( const RhsT& rhs ) {
1101 return m_result.captureExpression<Internal::IsNotEqualTo>( m_lhs, rhs );
1102 }
1103
1104 template<typename RhsT>
1105 ResultInfoBuilder& operator < ( const RhsT& rhs ) {
1106 return m_result.captureExpression<Internal::IsLessThan>( m_lhs, rhs );
1107 }
1108
1109 template<typename RhsT>
1110 ResultInfoBuilder& operator > ( const RhsT& rhs ) {
1111 return m_result.captureExpression<Internal::IsGreaterThan>( m_lhs, rhs );
1112 }
1113
1114 template<typename RhsT>
1115 ResultInfoBuilder& operator <= ( const RhsT& rhs ) {
1116 return m_result.captureExpression<Internal::IsLessThanOrEqualTo>( m_lhs, rhs );
1117 }
1118
1119 template<typename RhsT>
1120 ResultInfoBuilder& operator >= ( const RhsT& rhs ) {
1121 return m_result.captureExpression<Internal::IsGreaterThanOrEqualTo>( m_lhs, rhs );
1122 }
1123
1124 ResultInfoBuilder& operator == ( bool rhs ) {
1125 return m_result.captureExpression<Internal::IsEqualTo>( m_lhs, rhs );
1126 }
1127
1128 ResultInfoBuilder& operator != ( bool rhs ) {
1129 return m_result.captureExpression<Internal::IsNotEqualTo>( m_lhs, rhs );
1130 }
1131
1132 operator ResultInfoBuilder& () {
1133 return m_result.captureBoolExpression( m_lhs );
1134 }
1135
1136 template<typename RhsT>
1137 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( const RhsT& );
1138
1139 template<typename RhsT>
1140 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( const RhsT& );
1141
1142private:
1143 ResultInfoBuilder& m_result;
1144 T m_lhs;
1145};
1146
Phil Nash176eb812012-05-11 08:17:16 +01001147} // end namespace Catch
1148
Phil Nash89d2a3f2012-05-16 15:09:17 +01001149#include <sstream>
1150
1151namespace Catch {
1152
1153class ExpressionBuilder {
1154public:
1155
1156 ExpressionBuilder( const SourceLineInfo& lineInfo,
1157 const char* macroName,
1158 const char* expr = "",
1159 bool isNot = false )
1160 : m_result( expr, isNot, lineInfo, macroName ),
1161 m_messageStream()
1162 {}
1163
1164 template<typename T>
1165 Expression<const T&> operator->* ( const T & operand ) {
1166 Expression<const T&> expr( m_result, operand );
1167 return expr;
1168 }
1169
Phil Nash89d2a3f2012-05-16 15:09:17 +01001170 Expression<bool> operator->* ( bool value ) {
1171 Expression<bool> expr( m_result, value );
1172 return expr;
1173 }
1174
1175 template<typename T>
1176 ExpressionBuilder& operator << ( const T & value ) {
1177 m_messageStream << Catch::toString( value );
1178 return *this;
1179 }
1180
1181 template<typename MatcherT, typename ArgT>
1182 ExpressionBuilder& acceptMatcher( const MatcherT& matcher,
1183 const ArgT& arg,
1184 const std::string& matcherCallAsString ) {
1185 std::string matcherAsString = Catch::toString( matcher );
1186 if( matcherAsString == "{?}" )
1187 matcherAsString = matcherCallAsString;
1188 m_result.setLhs( Catch::toString( arg ) );
1189 m_result.setRhs( matcherAsString );
1190 m_result.setOp( "matches" );
1191 m_result.setResultType( matcher( arg ) ? ResultWas::Ok : ResultWas::ExpressionFailed );
1192 return *this;
1193 }
1194
1195 template<typename MatcherT, typename ArgT>
1196 ExpressionBuilder& acceptMatcher( const MatcherT& matcher,
1197 ArgT* arg,
1198 const std::string& matcherCallAsString ) {
1199 std::string matcherAsString = Catch::toString( matcher );
1200 if( matcherAsString == "{?}" )
1201 matcherAsString = matcherCallAsString;
1202 m_result.setLhs( Catch::toString( arg ) );
1203 m_result.setRhs( matcherAsString );
1204 m_result.setOp( "matches" );
1205 m_result.setResultType( matcher( arg ) ? ResultWas::Ok : ResultWas::ExpressionFailed );
1206 return *this;
1207 }
1208
1209 ExpressionBuilder& setResultType( ResultWas::OfType resultType ) {
1210 m_result.setResultType( resultType );
1211 return *this;
1212 }
1213
1214 operator ResultInfoBuilder&() {
1215 m_result.setMessage( m_messageStream.str() );
1216 return m_result;
1217 }
1218
1219private:
1220 ResultInfoBuilder m_result;
1221 std::ostringstream m_messageStream;
1222};
1223
1224} // end namespace Catch
1225
Phil Nashd31737f2012-05-09 19:04:00 +01001226// #included from: catch_interfaces_capture.h
Phil Nash3b80af72012-08-09 07:47:30 +01001227#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01001228
Phil Nashd31737f2012-05-09 19:04:00 +01001229#include <string>
1230
Phil Nash89d2a3f2012-05-16 15:09:17 +01001231namespace Catch {
1232
Phil Nashd31737f2012-05-09 19:04:00 +01001233 class TestCaseInfo;
1234 class ScopedInfo;
1235 class ResultInfoBuilder;
1236 class ResultInfo;
1237
Phil Nash89d2a3f2012-05-16 15:09:17 +01001238 struct IResultCapture {
Phil Nashd31737f2012-05-09 19:04:00 +01001239
Phil Nasha695eb92012-08-13 07:46:10 +01001240 virtual ~IResultCapture();
Phil Nashd31737f2012-05-09 19:04:00 +01001241
Phil Nash89d2a3f2012-05-16 15:09:17 +01001242 virtual void testEnded( const ResultInfo& result ) = 0;
1243 virtual bool sectionStarted( const std::string& name,
1244 const std::string& description,
1245 const SourceLineInfo& lineInfo,
1246 Counts& assertions ) = 0;
1247 virtual void sectionEnded( const std::string& name, const Counts& assertions ) = 0;
1248 virtual void pushScopedInfo( ScopedInfo* scopedInfo ) = 0;
1249 virtual void popScopedInfo( ScopedInfo* scopedInfo ) = 0;
1250 virtual bool shouldDebugBreak() const = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001251
Phil Nash89d2a3f2012-05-16 15:09:17 +01001252 virtual ResultAction::Value acceptResult( bool result ) = 0;
1253 virtual ResultAction::Value acceptResult( ResultWas::OfType result ) = 0;
1254 virtual ResultAction::Value acceptExpression( const ResultInfoBuilder& resultInfo ) = 0;
1255 virtual void acceptMessage( const std::string& msg ) = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001256
Phil Nash89d2a3f2012-05-16 15:09:17 +01001257 virtual std::string getCurrentTestName() const = 0;
1258 virtual const ResultInfo* getLastResult() const = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001259 };
1260}
1261
1262// #included from: catch_debugger.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01001263#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01001264
Phil Nashd31737f2012-05-09 19:04:00 +01001265#include <iostream>
1266
1267#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
1268#define CATCH_PLATFORM_MAC
1269#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
1270#define CATCH_PLATFORM_IPHONE
1271#elif defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
1272#define CATCH_PLATFORM_WINDOWS
1273#endif
1274
1275#ifdef CATCH_PLATFORM_MAC
1276
1277 #include <assert.h>
1278 #include <stdbool.h>
1279 #include <sys/types.h>
1280 #include <unistd.h>
1281 #include <sys/sysctl.h>
1282
Phil Nash89d2a3f2012-05-16 15:09:17 +01001283 namespace Catch{
1284
Phil Nashd31737f2012-05-09 19:04:00 +01001285 // The following function is taken directly from the following technical note:
1286 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
1287
Phil Nashd31737f2012-05-09 19:04:00 +01001288 // Returns true if the current process is being debugged (either
1289 // running under the debugger or has a debugger attached post facto).
Phil Nash89d2a3f2012-05-16 15:09:17 +01001290 inline bool isDebuggerActive(){
1291
Phil Nashd31737f2012-05-09 19:04:00 +01001292 int junk;
1293 int mib[4];
1294 struct kinfo_proc info;
1295 size_t size;
1296
1297 // Initialize the flags so that, if sysctl fails for some bizarre
1298 // reason, we get a predictable result.
1299
1300 info.kp_proc.p_flag = 0;
1301
1302 // Initialize mib, which tells sysctl the info we want, in this case
1303 // we're looking for information about a specific process ID.
1304
1305 mib[0] = CTL_KERN;
1306 mib[1] = KERN_PROC;
1307 mib[2] = KERN_PROC_PID;
1308 mib[3] = getpid();
1309
1310 // Call sysctl.
1311
1312 size = sizeof(info);
1313 junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
1314 assert(junk == 0);
1315
1316 // We're being debugged if the P_TRACED flag is set.
1317
1318 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
1319 }
1320 }
1321
1322 // The following code snippet taken from:
1323 // http://cocoawithlove.com/2008/03/break-into-debugger.html
1324 #ifdef DEBUG
1325 #if defined(__ppc64__) || defined(__ppc__)
1326 #define BreakIntoDebugger() \
Phil Nash89d2a3f2012-05-16 15:09:17 +01001327 if( Catch::isDebuggerActive() ) { \
Phil Nashd31737f2012-05-09 19:04:00 +01001328 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
1329 : : : "memory","r0","r3","r4" ); \
1330 }
1331 #else
1332 #define BreakIntoDebugger() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
1333 #endif
1334 #else
1335 inline void BreakIntoDebugger(){}
1336 #endif
1337
1338#elif defined(_MSC_VER)
1339 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
1340 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { __debugbreak(); }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001341 inline bool isDebuggerActive() {
Phil Nashd31737f2012-05-09 19:04:00 +01001342 return IsDebuggerPresent() != 0;
1343 }
Phil Nash176eb812012-05-11 08:17:16 +01001344#elif defined(__MINGW32__)
1345 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
1346 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
1347 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { DebugBreak(); }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001348 inline bool isDebuggerActive() {
Phil Nash176eb812012-05-11 08:17:16 +01001349 return IsDebuggerPresent() != 0;
1350 }
Phil Nashd31737f2012-05-09 19:04:00 +01001351#else
1352 inline void BreakIntoDebugger(){}
1353 inline bool isDebuggerActive() { return false; }
1354#endif
1355
1356#ifdef CATCH_PLATFORM_WINDOWS
1357extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001358inline void writeToDebugConsole( const std::string& text ) {
Phil Nashd31737f2012-05-09 19:04:00 +01001359 ::OutputDebugStringA( text.c_str() );
1360}
1361#else
Phil Nash89d2a3f2012-05-16 15:09:17 +01001362inline void writeToDebugConsole( const std::string& text ) {
Phil Nashd31737f2012-05-09 19:04:00 +01001363 // !TBD: Need a version for Mac/ XCode and other IDEs
1364 std::cout << text;
1365}
1366#endif // CATCH_PLATFORM_WINDOWS
1367
Phil Nash89d2a3f2012-05-16 15:09:17 +01001368#include <ostream>
Phil Nashd31737f2012-05-09 19:04:00 +01001369
Phil Nash89d2a3f2012-05-16 15:09:17 +01001370namespace Catch {
Phil Nashd31737f2012-05-09 19:04:00 +01001371
1372struct TestFailureException{};
Phil Nashd31737f2012-05-09 19:04:00 +01001373
Phil Nash89d2a3f2012-05-16 15:09:17 +01001374class ScopedInfo {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001375public:
Phil Nashd31737f2012-05-09 19:04:00 +01001376 ScopedInfo() : m_oss() {
Phil Nash371db8b2012-05-21 18:52:09 +01001377 getCurrentContext().getResultCapture().pushScopedInfo( this );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001378 }
1379
Phil Nashd31737f2012-05-09 19:04:00 +01001380 ~ScopedInfo() {
Phil Nash371db8b2012-05-21 18:52:09 +01001381 getCurrentContext().getResultCapture().popScopedInfo( this );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001382 }
1383
Phil Nashd31737f2012-05-09 19:04:00 +01001384 template<typename T>
1385 ScopedInfo& operator << ( const T& value ) {
1386 m_oss << value;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001387 return *this;
1388 }
1389
Phil Nashd31737f2012-05-09 19:04:00 +01001390 std::string getInfo () const {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001391 return m_oss.str();
1392 }
1393
1394private:
1395 std::ostringstream m_oss;
1396};
1397
Phil Nash89d1e6c2011-05-24 08:23:02 +01001398// This is just here to avoid compiler warnings with macro constants
Phil Nashd31737f2012-05-09 19:04:00 +01001399inline bool isTrue( bool value ){ return value; }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001400
1401} // end namespace Catch
1402
1403///////////////////////////////////////////////////////////////////////////////
Phil Nashd31737f2012-05-09 19:04:00 +01001404#define INTERNAL_CATCH_ACCEPT_EXPR( expr, stopOnFailure, originalExpr ) \
Phil Nashe4636872012-06-05 20:51:05 +01001405 if( Catch::ResultAction::Value internal_catch_action = Catch::getCurrentContext().getResultCapture().acceptExpression( expr ) ) { \
Phil Nash19b2aa62012-06-01 19:40:27 +01001406 if( internal_catch_action & Catch::ResultAction::Debug ) BreakIntoDebugger(); \
1407 if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001408 if( Catch::isTrue( stopOnFailure ) ) throw Catch::TestFailureException(); \
Phil Nashd31737f2012-05-09 19:04:00 +01001409 if( Catch::isTrue( false ) ){ bool this_is_here_to_invoke_warnings = ( originalExpr ); Catch::isTrue( this_is_here_to_invoke_warnings ); } \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001410 }
1411
1412///////////////////////////////////////////////////////////////////////////////
1413#define INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ) \
Phil Nashe4636872012-06-05 20:51:05 +01001414 do { try { \
Phil Nash89d2a3f2012-05-16 15:09:17 +01001415 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr, isNot )->*expr ), stopOnFailure, expr ); \
Phil Nashe4636872012-06-05 20:51:05 +01001416 } catch( Catch::TestFailureException& ) { \
Phil Nash333e6e62012-02-17 19:50:59 +00001417 throw; \
Phil Nashe4636872012-06-05 20:51:05 +01001418 } catch( ... ) { \
Phil Nash3b80af72012-08-09 07:47:30 +01001419 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getRegistryHub().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, expr ); \
Phil Nash333e6e62012-02-17 19:50:59 +00001420 throw; \
Phil Nashe4636872012-06-05 20:51:05 +01001421 } } while( Catch::isTrue( false ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01001422
1423///////////////////////////////////////////////////////////////////////////////
Phil Nasha162e222012-02-10 08:30:13 +00001424#define INTERNAL_CATCH_IF( expr, isNot, stopOnFailure, macroName ) \
1425 INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \
Phil Nash371db8b2012-05-21 18:52:09 +01001426 if( Catch::getCurrentContext().getResultCapture().getLastResult()->ok() )
Phil Nasha162e222012-02-10 08:30:13 +00001427
1428///////////////////////////////////////////////////////////////////////////////
1429#define INTERNAL_CATCH_ELSE( expr, isNot, stopOnFailure, macroName ) \
1430 INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \
Phil Nash371db8b2012-05-21 18:52:09 +01001431 if( !Catch::getCurrentContext().getResultCapture().getLastResult()->ok() )
Phil Nasha162e222012-02-10 08:30:13 +00001432
1433///////////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01001434#define INTERNAL_CATCH_NO_THROW( expr, stopOnFailure, macroName ) \
Phil Nashe4636872012-06-05 20:51:05 +01001435 try { \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001436 expr; \
Phil Nash89d2a3f2012-05-16 15:09:17 +01001437 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure, false ); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001438 } \
Phil Nashe4636872012-06-05 20:51:05 +01001439 catch( ... ) { \
Phil Nash3b80af72012-08-09 07:47:30 +01001440 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getRegistryHub().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001441 }
1442
1443///////////////////////////////////////////////////////////////////////////////
1444#define INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \
Phil Nashe4636872012-06-05 20:51:05 +01001445 try { \
1446 if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \
1447 expr; \
1448 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::DidntThrowException ), stopOnFailure, false ); \
1449 } \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001450 } \
Phil Nashe4636872012-06-05 20:51:05 +01001451 catch( Catch::TestFailureException& ) { \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001452 throw; \
1453 } \
Phil Nashe4636872012-06-05 20:51:05 +01001454 catch( exceptionType ) { \
Phil Nash89d2a3f2012-05-16 15:09:17 +01001455 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure, false ); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001456 }
1457
1458///////////////////////////////////////////////////////////////////////////////
1459#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, stopOnFailure, macroName ) \
1460 INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \
Phil Nashe4636872012-06-05 20:51:05 +01001461 catch( ... ) { \
Phil Nash3b80af72012-08-09 07:47:30 +01001462 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getRegistryHub().getExceptionTranslatorRegistry() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001463 }
1464
1465///////////////////////////////////////////////////////////////////////////////
1466#define INTERNAL_CATCH_MSG( reason, resultType, stopOnFailure, macroName ) \
Phil Nash371db8b2012-05-21 18:52:09 +01001467 Catch::getCurrentContext().getResultCapture().acceptExpression( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName ) << reason ).setResultType( resultType ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001468
1469///////////////////////////////////////////////////////////////////////////////
1470#define INTERNAL_CATCH_SCOPED_INFO( log ) \
1471 Catch::ScopedInfo INTERNAL_CATCH_UNIQUE_NAME( info ); \
1472 INTERNAL_CATCH_UNIQUE_NAME( info ) << log
1473
Phil Nash78d95a02012-03-04 21:22:36 +00001474///////////////////////////////////////////////////////////////////////////////
1475#define INTERNAL_CHECK_THAT( arg, matcher, stopOnFailure, macroName ) \
Phil Nashe4636872012-06-05 20:51:05 +01001476 do { try { \
Phil Nasha8570df2012-05-24 08:29:41 +01001477 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #arg " " #matcher, false ).acceptMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), stopOnFailure, false ); \
Phil Nashe4636872012-06-05 20:51:05 +01001478 } catch( Catch::TestFailureException& ) { \
Phil Nash78d95a02012-03-04 21:22:36 +00001479 throw; \
Phil Nashe4636872012-06-05 20:51:05 +01001480 } catch( ... ) { \
Phil Nash3b80af72012-08-09 07:47:30 +01001481 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #arg " " #matcher ) << Catch::getRegistryHub().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, false ); \
Phil Nash78d95a02012-03-04 21:22:36 +00001482 throw; \
1483 }}while( Catch::isTrue( false ) )
1484
Phil Nash89d1e6c2011-05-24 08:23:02 +01001485// #included from: internal/catch_section.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01001486#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01001487
Phil Nash89d1e6c2011-05-24 08:23:02 +01001488#include <string>
1489
Phil Nash89d2a3f2012-05-16 15:09:17 +01001490namespace Catch {
1491
1492 class Section {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001493 public:
Phil Nash89d2a3f2012-05-16 15:09:17 +01001494 Section( const std::string& name,
1495 const std::string& description,
1496 const SourceLineInfo& lineInfo )
Phil Nash89d1e6c2011-05-24 08:23:02 +01001497 : m_name( name ),
Phil Nash371db8b2012-05-21 18:52:09 +01001498 m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( name, description, lineInfo, m_assertions ) )
Phil Nash89d2a3f2012-05-16 15:09:17 +01001499 {}
Phil Nash89d1e6c2011-05-24 08:23:02 +01001500
Phil Nash89d2a3f2012-05-16 15:09:17 +01001501 ~Section() {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001502 if( m_sectionIncluded )
Phil Nash371db8b2012-05-21 18:52:09 +01001503 getCurrentContext().getResultCapture().sectionEnded( m_name, m_assertions );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001504 }
1505
Phil Nash89d1e6c2011-05-24 08:23:02 +01001506 // This indicates whether the section should be executed or not
Phil Nash89d2a3f2012-05-16 15:09:17 +01001507 operator bool() {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001508 return m_sectionIncluded;
1509 }
1510
1511 private:
1512
1513 std::string m_name;
Phil Nashf7299fc2012-02-25 09:39:45 +00001514 Counts m_assertions;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001515 bool m_sectionIncluded;
1516 };
1517
1518} // end namespace Catch
1519
1520#define INTERNAL_CATCH_SECTION( name, desc ) \
Phil Nashd31737f2012-05-09 19:04:00 +01001521 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( name, desc, CATCH_INTERNAL_LINEINFO ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01001522
1523// #included from: internal/catch_generators.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01001524#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01001525
Phil Nash89d1e6c2011-05-24 08:23:02 +01001526#include <iterator>
1527#include <vector>
1528#include <string>
1529#include <stdlib.h>
1530
Phil Nash89d2a3f2012-05-16 15:09:17 +01001531namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001532
1533template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001534struct IGenerator {
1535 virtual ~IGenerator() {}
1536 virtual T getValue( std::size_t index ) const = 0;
1537 virtual std::size_t size () const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001538};
1539
1540template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001541class BetweenGenerator : public IGenerator<T> {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001542public:
Phil Nash89d2a3f2012-05-16 15:09:17 +01001543 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
Phil Nash89d1e6c2011-05-24 08:23:02 +01001544
Phil Nash89d2a3f2012-05-16 15:09:17 +01001545 virtual T getValue( std::size_t index ) const {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001546 return m_from+static_cast<T>( index );
1547 }
1548
Phil Nash89d2a3f2012-05-16 15:09:17 +01001549 virtual std::size_t size() const {
Phil Nashd31737f2012-05-09 19:04:00 +01001550 return static_cast<std::size_t>( 1+m_to-m_from );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001551 }
1552
1553private:
1554
1555 T m_from;
1556 T m_to;
1557};
1558
1559template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001560class ValuesGenerator : public IGenerator<T> {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001561public:
Phil Nash89d2a3f2012-05-16 15:09:17 +01001562 ValuesGenerator(){}
Phil Nash89d1e6c2011-05-24 08:23:02 +01001563
Phil Nash89d2a3f2012-05-16 15:09:17 +01001564 void add( T value ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001565 m_values.push_back( value );
1566 }
1567
Phil Nash89d2a3f2012-05-16 15:09:17 +01001568 virtual T getValue( std::size_t index ) const {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001569 return m_values[index];
1570 }
1571
Phil Nash89d2a3f2012-05-16 15:09:17 +01001572 virtual std::size_t size() const {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001573 return m_values.size();
1574 }
1575
1576private:
Phil Nash89d1e6c2011-05-24 08:23:02 +01001577 std::vector<T> m_values;
1578};
1579
1580template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001581class CompositeGenerator {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001582public:
Phil Nash89d2a3f2012-05-16 15:09:17 +01001583 CompositeGenerator() : m_totalSize( 0 ) {}
Phil Nash89d1e6c2011-05-24 08:23:02 +01001584
Phil Nash89d1e6c2011-05-24 08:23:02 +01001585 // *** Move semantics, similar to auto_ptr ***
1586 CompositeGenerator( CompositeGenerator& other )
Phil Nash89d2a3f2012-05-16 15:09:17 +01001587 : m_fileInfo( other.m_fileInfo ),
1588 m_totalSize( 0 )
Phil Nash89d1e6c2011-05-24 08:23:02 +01001589 {
1590 move( other );
1591 }
1592
Phil Nash89d2a3f2012-05-16 15:09:17 +01001593 CompositeGenerator& setFileInfo( const char* fileInfo ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001594 m_fileInfo = fileInfo;
1595 return *this;
1596 }
1597
Phil Nash89d2a3f2012-05-16 15:09:17 +01001598 ~CompositeGenerator() {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001599 deleteAll( m_composed );
1600 }
1601
Phil Nash89d2a3f2012-05-16 15:09:17 +01001602 operator T () const {
Phil Nash371db8b2012-05-21 18:52:09 +01001603 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001604
1605 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
1606 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
1607 for( size_t index = 0; it != itEnd; ++it )
1608 {
1609 const IGenerator<T>* generator = *it;
1610 if( overallIndex >= index && overallIndex < index + generator->size() )
1611 {
1612 return generator->getValue( overallIndex-index );
1613 }
1614 index += generator->size();
1615 }
1616 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
1617 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
1618 }
1619
Phil Nash89d2a3f2012-05-16 15:09:17 +01001620 void add( const IGenerator<T>* generator ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001621 m_totalSize += generator->size();
1622 m_composed.push_back( generator );
1623 }
1624
Phil Nash89d2a3f2012-05-16 15:09:17 +01001625 CompositeGenerator& then( CompositeGenerator& other ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001626 move( other );
1627 return *this;
1628 }
1629
Phil Nash89d2a3f2012-05-16 15:09:17 +01001630 CompositeGenerator& then( T value ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001631 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1632 valuesGen->add( value );
1633 add( valuesGen );
1634 return *this;
1635 }
1636
1637private:
1638
Phil Nash89d2a3f2012-05-16 15:09:17 +01001639 void move( CompositeGenerator& other ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001640 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
1641 m_totalSize += other.m_totalSize;
1642 other.m_composed.clear();
1643 }
1644
1645 std::vector<const IGenerator<T>*> m_composed;
1646 std::string m_fileInfo;
1647 size_t m_totalSize;
1648};
1649
1650namespace Generators
1651{
Phil Nash89d1e6c2011-05-24 08:23:02 +01001652 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001653 CompositeGenerator<T> between( T from, T to ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001654 CompositeGenerator<T> generators;
1655 generators.add( new BetweenGenerator<T>( from, to ) );
1656 return generators;
1657 }
1658
Phil Nash89d1e6c2011-05-24 08:23:02 +01001659 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001660 CompositeGenerator<T> values( T val1, T val2 ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001661 CompositeGenerator<T> generators;
1662 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1663 valuesGen->add( val1 );
1664 valuesGen->add( val2 );
1665 generators.add( valuesGen );
1666 return generators;
1667 }
1668
Phil Nash89d1e6c2011-05-24 08:23:02 +01001669 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001670 CompositeGenerator<T> values( T val1, T val2, T val3 ){
Phil Nash89d1e6c2011-05-24 08:23:02 +01001671 CompositeGenerator<T> generators;
1672 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1673 valuesGen->add( val1 );
1674 valuesGen->add( val2 );
1675 valuesGen->add( val3 );
1676 generators.add( valuesGen );
1677 return generators;
1678 }
1679
Phil Nash89d1e6c2011-05-24 08:23:02 +01001680 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001681 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001682 CompositeGenerator<T> generators;
1683 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1684 valuesGen->add( val1 );
1685 valuesGen->add( val2 );
1686 valuesGen->add( val3 );
1687 valuesGen->add( val4 );
1688 generators.add( valuesGen );
1689 return generators;
1690 }
1691
1692} // end namespace Generators
1693
1694using namespace Generators;
1695
1696} // end namespace Catch
1697
1698#define INTERNAL_CATCH_LINESTR2( line ) #line
1699#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
1700
1701#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
1702
1703// #included from: internal/catch_interfaces_exception.h
Phil Nash3b80af72012-08-09 07:47:30 +01001704#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTIONS_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01001705
Phil Nash89d1e6c2011-05-24 08:23:02 +01001706#include <string>
Phil Nash3b80af72012-08-09 07:47:30 +01001707// #included from: catch_interfaces_registry_hub.h
1708#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
1709
Phil Nash3b80af72012-08-09 07:47:30 +01001710#include <vector>
Phil Nash3b80af72012-08-09 07:47:30 +01001711
1712namespace Catch {
1713
1714 class TestCaseInfo;
Phil Nash3b80af72012-08-09 07:47:30 +01001715 struct ITestCaseRegistry;
1716 struct IExceptionTranslatorRegistry;
1717 struct IExceptionTranslator;
1718
1719 struct IRegistryHub {
Phil Nasha695eb92012-08-13 07:46:10 +01001720 virtual ~IRegistryHub();
Phil Nash3b80af72012-08-09 07:47:30 +01001721
1722 virtual const IReporterRegistry& getReporterRegistry() const = 0;
1723 virtual const ITestCaseRegistry& getTestCaseRegistry() const = 0;
1724 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
1725 };
1726
1727 struct IMutableRegistryHub {
Phil Nasha695eb92012-08-13 07:46:10 +01001728 virtual ~IMutableRegistryHub();
Phil Nash3b80af72012-08-09 07:47:30 +01001729 virtual void registerReporter( const std::string& name, IReporterFactory* factory ) = 0;
1730 virtual void registerTest( const TestCaseInfo& testInfo ) = 0;
1731 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
1732 };
1733
1734 IRegistryHub& getRegistryHub();
1735 IMutableRegistryHub& getMutableRegistryHub();
1736 void cleanUp();
1737}
1738
Phil Nash89d1e6c2011-05-24 08:23:02 +01001739
Phil Nash89d2a3f2012-05-16 15:09:17 +01001740namespace Catch {
1741
Phil Nash89d1e6c2011-05-24 08:23:02 +01001742 typedef std::string(*exceptionTranslateFunction)();
1743
Phil Nash89d2a3f2012-05-16 15:09:17 +01001744 struct IExceptionTranslator {
Phil Nasha695eb92012-08-13 07:46:10 +01001745 virtual ~IExceptionTranslator();
Phil Nash89d1e6c2011-05-24 08:23:02 +01001746 virtual std::string translate() const = 0;
1747 };
1748
Phil Nash89d2a3f2012-05-16 15:09:17 +01001749 struct IExceptionTranslatorRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +01001750 virtual ~IExceptionTranslatorRegistry();
Phil Nash89d1e6c2011-05-24 08:23:02 +01001751
Phil Nash89d2a3f2012-05-16 15:09:17 +01001752 virtual std::string translateActiveException() const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001753 };
1754
Phil Nash89d2a3f2012-05-16 15:09:17 +01001755 class ExceptionTranslatorRegistrar {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001756 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001757 class ExceptionTranslator : public IExceptionTranslator {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001758 public:
1759
Phil Nash89d2a3f2012-05-16 15:09:17 +01001760 ExceptionTranslator( std::string(*translateFunction)( T& ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01001761 : m_translateFunction( translateFunction )
1762 {}
1763
Phil Nash89d2a3f2012-05-16 15:09:17 +01001764 virtual std::string translate() const {
1765 try {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001766 throw;
1767 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001768 catch( T& ex ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001769 return m_translateFunction( ex );
1770 }
1771 }
1772
1773 protected:
1774 std::string(*m_translateFunction)( T& );
1775 };
1776
1777 public:
1778 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001779 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
Phil Nash3b80af72012-08-09 07:47:30 +01001780 getMutableRegistryHub().registerTranslator
Phil Nash89d1e6c2011-05-24 08:23:02 +01001781 ( new ExceptionTranslator<T>( translateFunction ) );
1782 }
1783 };
1784}
1785
1786///////////////////////////////////////////////////////////////////////////////
1787#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
1788 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
1789 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
1790 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
1791
1792// #included from: internal/catch_approx.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01001793#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01001794
Phil Nash89d1e6c2011-05-24 08:23:02 +01001795#include <cmath>
1796#include <limits>
1797
Phil Nash89d2a3f2012-05-16 15:09:17 +01001798namespace Catch {
1799namespace Detail {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001800
Phil Nash89d2a3f2012-05-16 15:09:17 +01001801 class Approx {
1802 public:
1803 explicit Approx ( double value )
1804 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
1805 m_scale( 1.0 ),
1806 m_value( value )
1807 {}
Phil Nashf721a962011-06-07 14:13:57 +01001808
Phil Nash89d2a3f2012-05-16 15:09:17 +01001809 Approx( const Approx& other )
1810 : m_epsilon( other.m_epsilon ),
1811 m_scale( other.m_scale ),
1812 m_value( other.m_value )
1813 {}
Phil Nashf721a962011-06-07 14:13:57 +01001814
Phil Nash89d2a3f2012-05-16 15:09:17 +01001815 static Approx custom() {
1816 return Approx( 0 );
1817 }
Phil Nashf721a962011-06-07 14:13:57 +01001818
Phil Nash89d2a3f2012-05-16 15:09:17 +01001819 Approx operator()( double value ) {
1820 Approx approx( value );
1821 approx.epsilon( m_epsilon );
1822 approx.scale( m_scale );
1823 return approx;
1824 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001825
Phil Nash89d2a3f2012-05-16 15:09:17 +01001826 friend bool operator == ( double lhs, const Approx& rhs ) {
1827 // Thanks to Richard Harris for his help refining this formula
1828 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
1829 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001830
Phil Nash89d2a3f2012-05-16 15:09:17 +01001831 friend bool operator == ( const Approx& lhs, double rhs ) {
1832 return operator==( rhs, lhs );
1833 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001834
Phil Nash89d2a3f2012-05-16 15:09:17 +01001835 friend bool operator != ( double lhs, const Approx& rhs ) {
1836 return !operator==( lhs, rhs );
1837 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001838
Phil Nash89d2a3f2012-05-16 15:09:17 +01001839 friend bool operator != ( const Approx& lhs, double rhs ) {
1840 return !operator==( rhs, lhs );
1841 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001842
Phil Nash89d2a3f2012-05-16 15:09:17 +01001843 Approx& epsilon( double newEpsilon ) {
1844 m_epsilon = newEpsilon;
1845 return *this;
1846 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001847
Phil Nash89d2a3f2012-05-16 15:09:17 +01001848 Approx& scale( double newScale ) {
1849 m_scale = newScale;
1850 return *this;
1851 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001852
Phil Nash89d2a3f2012-05-16 15:09:17 +01001853 std::string toString() const {
1854 std::ostringstream oss;
1855 oss << "Approx( " << m_value << ")";
1856 return oss.str();
1857 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001858
Phil Nash89d2a3f2012-05-16 15:09:17 +01001859 private:
1860 double m_epsilon;
1861 double m_scale;
1862 double m_value;
1863 };
1864}
1865
1866template<>
1867inline std::string toString<Detail::Approx>( const Detail::Approx& value ) {
1868 return value.toString();
1869}
Phil Nash89d1e6c2011-05-24 08:23:02 +01001870
1871} // end namespace Catch
1872
Phil Nash371db8b2012-05-21 18:52:09 +01001873// #included from: internal/catch_matchers.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01001874#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01001875
1876namespace Catch {
1877namespace Matchers {
1878 namespace Impl {
1879 namespace StdString {
1880
Phil Nasha8570df2012-05-24 08:29:41 +01001881 struct Equals {
1882 Equals( const std::string& str ) : m_str( str ){}
1883
1884 bool operator()( const std::string& str ) const
1885 {
1886 return str == m_str;
1887 }
1888
1889 friend std::ostream& operator<<( std::ostream& os, const Equals& matcher )
1890 {
1891 os << "equals: \"" << matcher.m_str << "\"";
1892 return os;
1893 }
1894 std::string m_str;
1895 };
1896
Phil Nash371db8b2012-05-21 18:52:09 +01001897 struct Contains {
1898 Contains( const std::string& substr ) : m_substr( substr ){}
1899
1900 bool operator()( const std::string& str ) const
1901 {
1902 return str.find( m_substr ) != std::string::npos;
1903 }
1904
1905 friend std::ostream& operator<<( std::ostream& os, const Contains& matcher )
1906 {
1907 os << "contains: \"" << matcher.m_substr << "\"";
1908 return os;
1909 }
1910 std::string m_substr;
1911 };
1912
1913 struct StartsWith {
1914 StartsWith( const std::string& substr ) : m_substr( substr ){}
1915
1916 bool operator()( const std::string& str ) const
1917 {
1918 return str.find( m_substr ) == 0;
1919 }
1920
1921 friend std::ostream& operator<<( std::ostream& os, const StartsWith& matcher )
1922 {
1923 os << "starts with: \"" << matcher.m_substr << "\"";
1924 return os;
1925 }
1926 std::string m_substr;
1927 };
1928
1929 struct EndsWith {
1930 EndsWith( const std::string& substr ) : m_substr( substr ){}
1931
1932 bool operator()( const std::string& str ) const
1933 {
1934 return str.find( m_substr ) == str.size() - m_substr.size();
1935 }
1936
1937 friend std::ostream& operator<<( std::ostream& os, const EndsWith& matcher )
1938 {
1939 os << "ends with: \"" << matcher.m_substr << "\"";
1940 return os;
1941 }
1942 std::string m_substr;
1943 };
1944 } // namespace StdString
1945 } // namespace Impl
1946
Phil Nasha8570df2012-05-24 08:29:41 +01001947 inline Impl::StdString::Equals Equals( const std::string& str ){ return Impl::StdString::Equals( str ); }
Phil Nash371db8b2012-05-21 18:52:09 +01001948 inline Impl::StdString::Contains Contains( const std::string& substr ){ return Impl::StdString::Contains( substr ); }
1949 inline Impl::StdString::StartsWith StartsWith( const std::string& substr ){ return Impl::StdString::StartsWith( substr ); }
1950 inline Impl::StdString::EndsWith EndsWith( const std::string& substr ){ return Impl::StdString::EndsWith( substr ); }
1951
1952} // namespace Matchers
1953
1954using namespace Matchers;
1955
1956} // namespace Catch
1957
Phil Nash0f9c5512012-06-02 23:12:42 +01001958// These files are included here so the single_include script doesn't put them
1959// in the conditionally compiled sections
Phil Nash5bc030d2012-08-16 18:48:50 +01001960// #included from: internal/catch_test_case_info.h
1961#define TWOBLUECUBES_CATCH_TESTCASEINFO_H_INCLUDED
Phil Nash0f9c5512012-06-02 23:12:42 +01001962
Phil Nash0f9c5512012-06-02 23:12:42 +01001963#include <string>
1964
1965namespace Catch {
1966
Phil Nash5bc030d2012-08-16 18:48:50 +01001967 struct ITestCase;
1968
Phil Nash0f9c5512012-06-02 23:12:42 +01001969 class TestCaseInfo {
1970 public:
Phil Nash5bc030d2012-08-16 18:48:50 +01001971 TestCaseInfo();
1972
Phil Nash0f9c5512012-06-02 23:12:42 +01001973 TestCaseInfo( ITestCase* testCase,
1974 const char* name,
1975 const char* description,
Phil Nash5bc030d2012-08-16 18:48:50 +01001976 const SourceLineInfo& lineInfo );
Phil Nash0f9c5512012-06-02 23:12:42 +01001977
Phil Nash5bc030d2012-08-16 18:48:50 +01001978 TestCaseInfo( const TestCaseInfo& other, const std::string& name );
Phil Nashd2ec8492012-08-23 19:48:57 +01001979 TestCaseInfo( const TestCaseInfo& other );
Phil Nash0f9c5512012-06-02 23:12:42 +01001980
Phil Nash5bc030d2012-08-16 18:48:50 +01001981 void invoke() const;
1982 const std::string& getName() const;
1983 const std::string& getDescription() const;
1984 const SourceLineInfo& getLineInfo() const;
1985 bool isHidden() const;
Phil Nash0f9c5512012-06-02 23:12:42 +01001986
Phil Nash5bc030d2012-08-16 18:48:50 +01001987 void swap( TestCaseInfo& other );
1988 bool operator == ( const TestCaseInfo& other ) const;
1989 bool operator < ( const TestCaseInfo& other ) const;
Phil Nashd2ec8492012-08-23 19:48:57 +01001990 TestCaseInfo& operator = ( const TestCaseInfo& other );
Phil Nash0f9c5512012-06-02 23:12:42 +01001991
1992 private:
Phil Nash5bc030d2012-08-16 18:48:50 +01001993 Ptr<ITestCase> m_test;
Phil Nash0f9c5512012-06-02 23:12:42 +01001994 std::string m_name;
1995 std::string m_description;
1996 SourceLineInfo m_lineInfo;
1997 };
Phil Nash0f9c5512012-06-02 23:12:42 +01001998}
1999
2000// #included from: internal/catch_interfaces_runner.h
Phil Nash3b80af72012-08-09 07:47:30 +01002001#define TWOBLUECUBES_INTERNAL_CATCH_INTERFACES_RUNNER_H_INCLUDED
Phil Nash0f9c5512012-06-02 23:12:42 +01002002
2003#include <string>
2004
2005namespace Catch {
2006 class TestCaseInfo;
2007
2008 struct IRunner {
Phil Nasha695eb92012-08-13 07:46:10 +01002009 virtual ~IRunner();
Phil Nash0f9c5512012-06-02 23:12:42 +01002010 };
2011}
2012
2013
Phil Nash371db8b2012-05-21 18:52:09 +01002014#ifdef __OBJC__
2015// #included from: internal/catch_objc.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002016#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01002017
Phil Nash371db8b2012-05-21 18:52:09 +01002018#import <objc/runtime.h>
2019
2020#include <string>
2021
2022// NB. Any general catch headers included here must be included
2023// in catch.hpp first to make sure they are included by the single
2024// header for non obj-usage
Phil Nash81528252011-08-15 09:06:31 +01002025
Phil Nash83224e62011-08-12 18:53:28 +01002026///////////////////////////////////////////////////////////////////////////////
2027// This protocol is really only here for (self) documenting purposes, since
2028// all its methods are optional.
2029@protocol OcFixture
2030
2031@optional
2032
2033-(void) setUp;
2034-(void) tearDown;
2035
2036@end
2037
Phil Nash89d2a3f2012-05-16 15:09:17 +01002038namespace Catch {
Phil Nash83224e62011-08-12 18:53:28 +01002039
Phil Nash5bc030d2012-08-16 18:48:50 +01002040 class OcMethod : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002041
2042 public:
2043 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
2044
2045 virtual void invoke() const {
Phil Nash53c990a2012-03-17 18:20:06 +00002046 id obj = [[m_cls alloc] init];
Phil Nash83224e62011-08-12 18:53:28 +01002047
Phil Nash53c990a2012-03-17 18:20:06 +00002048 performOptionalSelector( obj, @selector(setUp) );
2049 performOptionalSelector( obj, m_sel );
2050 performOptionalSelector( obj, @selector(tearDown) );
Phil Nash83224e62011-08-12 18:53:28 +01002051
Phil Nash53c990a2012-03-17 18:20:06 +00002052 arcSafeRelease( obj );
Phil Nash83224e62011-08-12 18:53:28 +01002053 }
Phil Nash83224e62011-08-12 18:53:28 +01002054 private:
Phil Nash5bc030d2012-08-16 18:48:50 +01002055 virtual ~OcMethod() {}
2056
Phil Nash83224e62011-08-12 18:53:28 +01002057 Class m_cls;
2058 SEL m_sel;
2059 };
2060
Phil Nash89d2a3f2012-05-16 15:09:17 +01002061 namespace Detail{
Phil Nash83224e62011-08-12 18:53:28 +01002062
Phil Nash89d2a3f2012-05-16 15:09:17 +01002063 inline bool startsWith( const std::string& str, const std::string& sub ) {
Phil Nash83224e62011-08-12 18:53:28 +01002064 return str.length() > sub.length() && str.substr( 0, sub.length() ) == sub;
2065 }
2066
Phil Nash89d2a3f2012-05-16 15:09:17 +01002067 inline std::string getAnnotation( Class cls,
2068 const std::string& annotationName,
2069 const std::string& testCaseName ) {
Phil Nash83224e62011-08-12 18:53:28 +01002070 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2071 SEL sel = NSSelectorFromString( selStr );
Phil Nash53c990a2012-03-17 18:20:06 +00002072 arcSafeRelease( selStr );
2073 id value = performOptionalSelector( cls, sel );
2074 if( value )
2075 return [(NSString*)value UTF8String];
Phil Nash83224e62011-08-12 18:53:28 +01002076 return "";
2077 }
2078 }
2079
Phil Nash89d2a3f2012-05-16 15:09:17 +01002080 inline size_t registerTestMethods() {
Phil Nash83224e62011-08-12 18:53:28 +01002081 size_t noTestMethods = 0;
2082 int noClasses = objc_getClassList( NULL, 0 );
2083
Phil Nash861a1e72012-04-28 12:29:52 +01002084 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
Phil Nash53c990a2012-03-17 18:20:06 +00002085 objc_getClassList( classes, noClasses );
Phil Nash83224e62011-08-12 18:53:28 +01002086
Phil Nash89d2a3f2012-05-16 15:09:17 +01002087 for( int c = 0; c < noClasses; c++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01002088 Class cls = classes[c];
2089 {
2090 u_int count;
2091 Method* methods = class_copyMethodList( cls, &count );
Phil Nash7004f4a2012-05-22 08:56:59 +01002092 for( u_int m = 0; m < count ; m++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01002093 SEL selector = method_getName(methods[m]);
2094 std::string methodName = sel_getName(selector);
Phil Nash89d2a3f2012-05-16 15:09:17 +01002095 if( Detail::startsWith( methodName, "Catch_TestCase_" ) ) {
Phil Nash83224e62011-08-12 18:53:28 +01002096 std::string testCaseName = methodName.substr( 15 );
Phil Nash53c990a2012-03-17 18:20:06 +00002097 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
2098 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
Phil Nash83224e62011-08-12 18:53:28 +01002099
Phil Nash3b80af72012-08-09 07:47:30 +01002100 getMutableRegistryHub().registerTest( TestCaseInfo( new OcMethod( cls, selector ), name.c_str(), desc.c_str(), SourceLineInfo() ) );
Phil Nash83224e62011-08-12 18:53:28 +01002101 noTestMethods++;
Phil Nash83224e62011-08-12 18:53:28 +01002102 }
2103 }
2104 free(methods);
2105 }
2106 }
2107 return noTestMethods;
2108 }
Phil Nash78d95a02012-03-04 21:22:36 +00002109
Phil Nash89d2a3f2012-05-16 15:09:17 +01002110 namespace Matchers {
2111 namespace Impl {
2112 namespace NSStringMatchers {
2113
2114 struct StringHolder {
Phil Nash78d95a02012-03-04 21:22:36 +00002115 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
Phil Nash89d2a3f2012-05-16 15:09:17 +01002116 StringHolder() {
Phil Nash53c990a2012-03-17 18:20:06 +00002117 arcSafeRelease( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00002118 }
2119
2120 NSString* m_substr;
2121 };
2122
Phil Nash89d2a3f2012-05-16 15:09:17 +01002123 struct Equals : StringHolder {
Phil Nash8d18d162012-03-14 20:06:14 +00002124 Equals( NSString* substr ) : StringHolder( substr ){}
2125
Phil Nash89d2a3f2012-05-16 15:09:17 +01002126 bool operator()( NSString* str ) const {
Phil Nash8d18d162012-03-14 20:06:14 +00002127 return [str isEqualToString:m_substr];
2128 }
2129
Phil Nash89d2a3f2012-05-16 15:09:17 +01002130 friend std::ostream& operator<<( std::ostream& os, const Equals& matcher ) {
Phil Nash8d18d162012-03-14 20:06:14 +00002131 os << "equals string: " << Catch::toString( matcher.m_substr );
2132 return os;
2133 }
2134 };
2135
Phil Nash89d2a3f2012-05-16 15:09:17 +01002136 struct Contains : StringHolder {
Phil Nash78d95a02012-03-04 21:22:36 +00002137 Contains( NSString* substr ) : StringHolder( substr ){}
2138
Phil Nash89d2a3f2012-05-16 15:09:17 +01002139 bool operator()( NSString* str ) const {
Phil Nash78d95a02012-03-04 21:22:36 +00002140 return [str rangeOfString:m_substr].location != NSNotFound;
2141 }
2142
Phil Nash89d2a3f2012-05-16 15:09:17 +01002143 friend std::ostream& operator<<( std::ostream& os, const Contains& matcher ) {
Phil Nash78d95a02012-03-04 21:22:36 +00002144 os << "contains: " << Catch::toString( matcher.m_substr );
2145 return os;
2146 }
2147 };
2148
Phil Nash89d2a3f2012-05-16 15:09:17 +01002149 struct StartsWith : StringHolder {
Phil Nash78d95a02012-03-04 21:22:36 +00002150 StartsWith( NSString* substr ) : StringHolder( substr ){}
2151
Phil Nash89d2a3f2012-05-16 15:09:17 +01002152 bool operator()( NSString* str ) const {
Phil Nash78d95a02012-03-04 21:22:36 +00002153 return [str rangeOfString:m_substr].location == 0;
2154 }
2155
Phil Nash89d2a3f2012-05-16 15:09:17 +01002156 friend std::ostream& operator<<( std::ostream& os, const StartsWith& matcher ) {
Phil Nash78d95a02012-03-04 21:22:36 +00002157 os << "starts with: " << Catch::toString( matcher.m_substr );
2158 return os;
2159 }
2160 };
Phil Nash89d2a3f2012-05-16 15:09:17 +01002161 struct EndsWith : StringHolder {
Phil Nash78d95a02012-03-04 21:22:36 +00002162 EndsWith( NSString* substr ) : StringHolder( substr ){}
2163
Phil Nash89d2a3f2012-05-16 15:09:17 +01002164 bool operator()( NSString* str ) const {
Phil Nash78d95a02012-03-04 21:22:36 +00002165 return [str rangeOfString:m_substr].location == [str length] - [m_substr length];
2166 }
2167
Phil Nash89d2a3f2012-05-16 15:09:17 +01002168 friend std::ostream& operator<<( std::ostream& os, const EndsWith& matcher ) {
Phil Nash78d95a02012-03-04 21:22:36 +00002169 os << "ends with: " << Catch::toString( matcher.m_substr );
2170 return os;
2171 }
2172 };
2173
2174 } // namespace NSStringMatchers
2175 } // namespace Impl
2176
Phil Nash8d18d162012-03-14 20:06:14 +00002177 inline Impl::NSStringMatchers::Equals
2178 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
2179
Phil Nash78d95a02012-03-04 21:22:36 +00002180 inline Impl::NSStringMatchers::Contains
2181 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00002182
Phil Nash78d95a02012-03-04 21:22:36 +00002183 inline Impl::NSStringMatchers::StartsWith
2184 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00002185
Phil Nash78d95a02012-03-04 21:22:36 +00002186 inline Impl::NSStringMatchers::EndsWith
2187 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
2188
2189 } // namespace Matchers
2190
2191 using namespace Matchers;
2192
2193} // namespace Catch
Phil Nash83224e62011-08-12 18:53:28 +01002194
2195///////////////////////////////////////////////////////////////////////////////
2196#define OC_TEST_CASE( name, desc )\
Phil Nash53c990a2012-03-17 18:20:06 +00002197+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01002198{\
Phil Nash53c990a2012-03-17 18:20:06 +00002199return @ name; \
Phil Nash83224e62011-08-12 18:53:28 +01002200}\
Phil Nash53c990a2012-03-17 18:20:06 +00002201+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01002202{ \
Phil Nash53c990a2012-03-17 18:20:06 +00002203return @ desc; \
Phil Nash83224e62011-08-12 18:53:28 +01002204} \
2205-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
2206
2207#endif
2208
2209#if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER )
Phil Nasha695eb92012-08-13 07:46:10 +01002210// #included from: internal/catch_impl.hpp
2211
2212// Collect all the implementation files together here
2213// These are the equivalent of what would usually be cpp files
2214
Phil Nash5bc030d2012-08-16 18:48:50 +01002215#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01002216#pragma clang diagnostic push
2217#pragma clang diagnostic ignored "-Wweak-vtables"
Phil Nash5bc030d2012-08-16 18:48:50 +01002218#endif
Phil Nasha695eb92012-08-13 07:46:10 +01002219
Phil Nash83224e62011-08-12 18:53:28 +01002220// #included from: catch_runner.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002221#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
Phil Nash83224e62011-08-12 18:53:28 +01002222
Phil Nasha695eb92012-08-13 07:46:10 +01002223// #included from: internal/catch_commandline.hpp
2224#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
2225
2226// #included from: catch_config.hpp
2227#define TWOBLUECUBES_CATCH_RUNNERCONFIG_HPP_INCLUDED
2228
Phil Nash56d5c422012-08-23 20:08:50 +01002229// #included from: catch_test_spec.h
2230#define TWOBLUECUBES_CATCH_TESTSPEC_H_INCLUDED
2231
2232#include <string>
2233
2234namespace Catch {
2235
2236 struct IfFilterMatches{ enum DoWhat {
2237 IncludeTests,
2238 ExcludeTests
2239 }; };
2240
2241 class TestCaseFilter {
Phil Nash4c97fc52012-08-24 08:23:50 +01002242 enum WildcardPosition {
2243 NoWildcard = 0,
2244 WildcardAtStart = 1,
2245 WildcardAtEnd = 2,
2246 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
2247 };
2248
Phil Nash56d5c422012-08-23 20:08:50 +01002249 public:
2250 TestCaseFilter( const std::string& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::IncludeTests )
Phil Nash4c97fc52012-08-24 08:23:50 +01002251 : m_stringToMatch( testSpec ),
Phil Nash56d5c422012-08-23 20:08:50 +01002252 m_filterType( matchBehaviour ),
Phil Nash4c97fc52012-08-24 08:23:50 +01002253 m_wildcardPosition( NoWildcard )
Phil Nash56d5c422012-08-23 20:08:50 +01002254 {
Phil Nash4c97fc52012-08-24 08:23:50 +01002255 if( m_stringToMatch[0] == '*' ) {
2256 m_stringToMatch = m_stringToMatch.substr( 1 );
2257 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtStart );
2258 }
2259 if( m_stringToMatch[m_stringToMatch.size()-1] == '*' ) {
2260 m_stringToMatch = m_stringToMatch.substr( 0, m_stringToMatch.size()-1 );
2261 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtEnd );
Phil Nash56d5c422012-08-23 20:08:50 +01002262 }
2263 }
2264
2265 IfFilterMatches::DoWhat getFilterType() const {
2266 return m_filterType;
2267 }
2268
2269 bool shouldInclude( const TestCaseInfo& testCase ) const {
2270 return isMatch( testCase ) == (m_filterType == IfFilterMatches::IncludeTests);
2271 }
2272 private:
2273
2274 bool isMatch( const TestCaseInfo& testCase ) const {
2275 const std::string& name = testCase.getName();
Phil Nash4c97fc52012-08-24 08:23:50 +01002276
2277 switch( m_wildcardPosition ) {
2278 case NoWildcard:
2279 return m_stringToMatch == name;
2280 case WildcardAtStart:
2281 return endsWith( name, m_stringToMatch );
2282 case WildcardAtEnd:
2283 return startsWith( name, m_stringToMatch );
2284 case WildcardAtBothEnds:
2285 return contains( name, m_stringToMatch );
2286 }
2287
Phil Nash56d5c422012-08-23 20:08:50 +01002288 }
2289
Phil Nash4c97fc52012-08-24 08:23:50 +01002290 std::string m_stringToMatch;
Phil Nash56d5c422012-08-23 20:08:50 +01002291 IfFilterMatches::DoWhat m_filterType;
Phil Nash4c97fc52012-08-24 08:23:50 +01002292 WildcardPosition m_wildcardPosition;
Phil Nash56d5c422012-08-23 20:08:50 +01002293 };
2294
2295 class TestCaseFilters {
2296 public:
2297 TestCaseFilters( const std::string& name ) : m_name( name ) {}
2298
2299 std::string getName() const {
2300 return m_name;
2301 }
2302
2303 void addFilter( const TestCaseFilter& filter ) {
2304 if( filter.getFilterType() == IfFilterMatches::ExcludeTests )
2305 m_exclusionFilters.push_back( filter );
2306 else
2307 m_inclusionFilters.push_back( filter );
2308 }
2309
2310 bool shouldInclude( const TestCaseInfo& testCase ) const {
2311 if( !m_inclusionFilters.empty() ) {
2312 std::vector<TestCaseFilter>::const_iterator it = m_inclusionFilters.begin();
2313 std::vector<TestCaseFilter>::const_iterator itEnd = m_inclusionFilters.end();
2314 for(; it != itEnd; ++it )
2315 if( it->shouldInclude( testCase ) )
2316 break;
2317 if( it == itEnd )
2318 return false;
2319 }
2320 std::vector<TestCaseFilter>::const_iterator it = m_exclusionFilters.begin();
2321 std::vector<TestCaseFilter>::const_iterator itEnd = m_exclusionFilters.end();
2322 for(; it != itEnd; ++it )
2323 if( !it->shouldInclude( testCase ) )
2324 return false;
2325 return true;
2326 }
2327 private:
2328 std::vector<TestCaseFilter> m_inclusionFilters;
2329 std::vector<TestCaseFilter> m_exclusionFilters;
2330 std::string m_name;
2331 };
2332
2333}
2334
Phil Nasha695eb92012-08-13 07:46:10 +01002335#include <memory>
2336#include <vector>
2337#include <string>
2338#include <iostream>
2339
2340namespace Catch {
2341
2342 struct Include { enum WhichResults {
2343 FailedOnly,
2344 SuccessfulResults
2345 }; };
2346
2347 struct List{ enum What {
2348 None = 0,
2349
2350 Reports = 1,
2351 Tests = 2,
2352 All = 3,
2353
Phil Nash56d5c422012-08-23 20:08:50 +01002354 TestNames = 6,
2355
Phil Nasha695eb92012-08-13 07:46:10 +01002356 WhatMask = 0xf,
2357
2358 AsText = 0x10,
2359 AsXml = 0x11,
2360
2361 AsMask = 0xf0
2362 }; };
2363
2364 struct ConfigData {
2365 ConfigData()
2366 : listSpec( List::None ),
2367 shouldDebugBreak( false ),
2368 includeWhichResults( Include::FailedOnly ),
2369 cutoff( -1 ),
2370 allowThrows( true )
2371 {}
2372
2373 std::string reporter;
2374 std::string outputFilename;
2375 List::What listSpec;
Phil Nash56d5c422012-08-23 20:08:50 +01002376 std::vector<TestCaseFilters> filters;
Phil Nasha695eb92012-08-13 07:46:10 +01002377 bool shouldDebugBreak;
2378 std::string stream;
2379 Include::WhichResults includeWhichResults;
2380 std::string name;
2381 int cutoff;
2382 bool allowThrows;
2383 };
2384
2385 class Config : public IConfig {
2386 private:
2387 Config( const Config& other );
2388 Config& operator = ( const Config& other );
2389 virtual void dummy();
2390 public:
2391
2392 Config()
2393 : m_streambuf( NULL ),
2394 m_os( std::cout.rdbuf() )
2395 {}
2396
2397 Config( const ConfigData& data )
2398 : m_data( data ),
2399 m_streambuf( NULL ),
2400 m_os( std::cout.rdbuf() )
2401 {}
2402
2403 virtual ~Config() {
2404 m_os.rdbuf( std::cout.rdbuf() );
2405 delete m_streambuf;
2406 }
2407
2408 void setFilename( const std::string& filename ) {
2409 m_data.outputFilename = filename;
2410 }
2411
Phil Nasha695eb92012-08-13 07:46:10 +01002412 List::What getListSpec( void ) const {
2413 return m_data.listSpec;
2414 }
2415
2416 const std::string& getFilename() const {
2417 return m_data.outputFilename ;
2418 }
2419
2420 List::What listWhat() const {
2421 return static_cast<List::What>( m_data.listSpec & List::WhatMask );
2422 }
2423
2424 List::What listAs() const {
2425 return static_cast<List::What>( m_data.listSpec & List::AsMask );
2426 }
2427
2428 std::string getName() const {
2429 return m_data.name;
2430 }
2431
2432 bool shouldDebugBreak() const {
2433 return m_data.shouldDebugBreak;
2434 }
2435
2436 virtual std::ostream& stream() const {
2437 return m_os;
2438 }
2439
2440 void setStreamBuf( std::streambuf* buf ) {
2441 m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
2442 }
2443
2444 void useStream( const std::string& streamName ) {
2445 std::streambuf* newBuf = createStreamBuf( streamName );
2446 setStreamBuf( newBuf );
2447 delete m_streambuf;
2448 m_streambuf = newBuf;
2449 }
2450
2451 virtual bool includeSuccessfulResults() const {
2452 return m_data.includeWhichResults == Include::SuccessfulResults;
2453 }
2454
2455 int getCutoff() const {
2456 return m_data.cutoff;
2457 }
2458
2459 virtual bool allowThrows() const {
2460 return m_data.allowThrows;
2461 }
2462
2463 ConfigData& data() {
2464 return m_data;
2465 }
2466
2467 private:
2468 ConfigData m_data;
2469
2470 // !TBD Move these out of here
2471 std::streambuf* m_streambuf;
2472 mutable std::ostream m_os;
2473 };
2474
2475} // end namespace Catch
2476
2477namespace Catch {
2478
2479 class Command {
2480 public:
2481 Command(){}
2482
2483 explicit Command( const std::string& name ) : m_name( name ) {}
2484
2485 Command& operator += ( const std::string& arg ) {
2486 m_args.push_back( arg );
2487 return *this;
2488 }
2489 Command& operator += ( const Command& other ) {
2490 std::copy( other.m_args.begin(), other.m_args.end(), std::back_inserter( m_args ) );
2491 if( m_name.empty() )
2492 m_name = other.m_name;
2493 return *this;
2494 }
2495 Command operator + ( const Command& other ) {
2496 Command newCommand( *this );
2497 newCommand += other;
2498 return newCommand;
2499 }
2500
2501 operator SafeBool::type() const {
Phil Nashe571e6f2012-08-24 18:54:56 +01002502 return SafeBool::makeSafe( !m_name.empty() || !m_args.empty() );
Phil Nasha695eb92012-08-13 07:46:10 +01002503 }
2504
2505 std::string name() const { return m_name; }
2506 std::string operator[]( std::size_t i ) const { return m_args[i]; }
2507 std::size_t argsCount() const { return m_args.size(); }
2508
2509 CATCH_ATTRIBUTE_NORETURN
2510 void raiseError( const std::string& message ) const {
2511 std::ostringstream oss;
2512 oss << "Error while parsing " << m_name << ". " << message << ".";
2513 if( m_args.size() > 0 )
2514 oss << " Arguments where:";
2515 for( std::size_t i = 0; i < m_args.size(); ++i )
2516 oss << " " << m_args[i];
2517 throw std::domain_error( oss.str() );
2518 }
2519
2520 private:
2521
2522 std::string m_name;
2523 std::vector<std::string> m_args;
2524 };
2525
2526 class CommandParser {
2527 public:
2528 CommandParser( int argc, char const * const * argv ) : m_argc( static_cast<std::size_t>( argc ) ), m_argv( argv ) {}
2529
2530 Command find( const std::string& arg1, const std::string& arg2, const std::string& arg3 ) const {
2531 return find( arg1 ) + find( arg2 ) + find( arg3 );
2532 }
2533
2534 Command find( const std::string& shortArg, const std::string& longArg ) const {
2535 return find( shortArg ) + find( longArg );
2536 }
2537 Command find( const std::string& arg ) const {
Phil Nashe571e6f2012-08-24 18:54:56 +01002538 for( std::size_t i = 1; i < m_argc; ++i )
Phil Nasha695eb92012-08-13 07:46:10 +01002539 if( m_argv[i] == arg )
Phil Nashe571e6f2012-08-24 18:54:56 +01002540 return getArgs( m_argv[i], i+1 );
Phil Nasha695eb92012-08-13 07:46:10 +01002541 return Command();
2542 }
Phil Nashe571e6f2012-08-24 18:54:56 +01002543 Command getDefaultArgs() const {
2544 return getArgs( "", 1 );
2545 }
Phil Nasha695eb92012-08-13 07:46:10 +01002546
2547 private:
Phil Nashe571e6f2012-08-24 18:54:56 +01002548 Command getArgs( const std::string& cmdName, std::size_t from ) const {
2549 Command command( cmdName );
2550 for( std::size_t i = from; i < m_argc && m_argv[i][0] != '-'; ++i )
Phil Nasha695eb92012-08-13 07:46:10 +01002551 command += m_argv[i];
2552 return command;
2553 }
2554
2555 std::size_t m_argc;
2556 char const * const * m_argv;
2557 };
2558
2559 inline void parseIntoConfig( const CommandParser& parser, ConfigData& config ) {
2560
2561 if( Command cmd = parser.find( "-l", "--list" ) ) {
2562 if( cmd.argsCount() > 2 )
2563 cmd.raiseError( "Expected upto 2 arguments" );
2564
Phil Nash56d5c422012-08-23 20:08:50 +01002565 config.listSpec = List::TestNames;
Phil Nasha695eb92012-08-13 07:46:10 +01002566 if( cmd.argsCount() >= 1 ) {
Phil Nash56d5c422012-08-23 20:08:50 +01002567 if( cmd[0] == "all" )
2568 config.listSpec = List::All;
2569 else if( cmd[0] == "tests" )
Phil Nasha695eb92012-08-13 07:46:10 +01002570 config.listSpec = List::Tests;
2571 else if( cmd[0] == "reporters" )
2572 config.listSpec = List::Reports;
2573 else
2574 cmd.raiseError( "Expected [tests] or [reporters]" );
2575 }
2576 if( cmd.argsCount() >= 2 ) {
2577 if( cmd[1] == "xml" )
Phil Nash56d5c422012-08-23 20:08:50 +01002578 config.listSpec = static_cast<List::What>( config.listSpec | List::AsXml );
Phil Nasha695eb92012-08-13 07:46:10 +01002579 else if( cmd[1] == "text" )
Phil Nash56d5c422012-08-23 20:08:50 +01002580 config.listSpec = static_cast<List::What>( config.listSpec | List::AsText );
Phil Nasha695eb92012-08-13 07:46:10 +01002581 else
2582 cmd.raiseError( "Expected [xml] or [text]" );
2583 }
2584 }
2585
Phil Nashe571e6f2012-08-24 18:54:56 +01002586 if( Command cmd = parser.find( "-t", "--test" ) + parser.getDefaultArgs() ) {
Phil Nasha695eb92012-08-13 07:46:10 +01002587 if( cmd.argsCount() == 0 )
2588 cmd.raiseError( "Expected at least one argument" );
Phil Nash56d5c422012-08-23 20:08:50 +01002589 std::string groupName;
2590 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
2591 if( i != 0 )
2592 groupName += " ";
2593 groupName += cmd[i];
2594 }
2595 TestCaseFilters filters( groupName );
2596 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
Phil Nashe571e6f2012-08-24 18:54:56 +01002597 std::cout << "[" << cmd[i] << "]" << std::endl;
Phil Nash56d5c422012-08-23 20:08:50 +01002598 if( startsWith( cmd[i], "exclude:" ) )
2599 filters.addFilter( TestCaseFilter( cmd[i].substr( 8 ), IfFilterMatches::ExcludeTests ) );
Phil Nashe571e6f2012-08-24 18:54:56 +01002600 else if( startsWith( cmd[i], "ex:" ) )
2601 filters.addFilter( TestCaseFilter( cmd[i].substr( 3 ), IfFilterMatches::ExcludeTests ) );
Phil Nash56d5c422012-08-23 20:08:50 +01002602 else
2603 filters.addFilter( TestCaseFilter( cmd[i] ) );
2604 }
2605 config.filters.push_back( filters );
Phil Nasha695eb92012-08-13 07:46:10 +01002606 }
2607
2608 if( Command cmd = parser.find( "-r", "--reporter" ) ) {
2609 if( cmd.argsCount() != 1 )
2610 cmd.raiseError( "Expected one argument" );
2611 config.reporter = cmd[0];
2612 }
2613
2614 if( Command cmd = parser.find( "-o", "--out" ) ) {
2615 if( cmd.argsCount() == 0 )
2616 cmd.raiseError( "Expected filename" );
2617 if( cmd[0][0] == '%' )
2618 config.stream = cmd[0].substr( 1 );
2619 else
2620 config.outputFilename = cmd[0];
2621 }
2622
2623 if( Command cmd = parser.find( "-s", "--success" ) ) {
2624 if( cmd.argsCount() != 0 )
2625 cmd.raiseError( "Does not accept arguments" );
2626 config.includeWhichResults = Include::SuccessfulResults;
2627 }
2628
2629 if( Command cmd = parser.find( "-b", "--break" ) ) {
2630 if( cmd.argsCount() != 0 )
2631 cmd.raiseError( "Does not accept arguments" );
2632 config.shouldDebugBreak = true;
2633 }
2634
2635 if( Command cmd = parser.find( "-n", "--name" ) ) {
2636 if( cmd.argsCount() != 1 )
2637 cmd.raiseError( "Expected a name" );
2638 config.name = cmd[0];
2639 }
2640
2641 if( Command cmd = parser.find( "-a", "--abort" ) ) {
2642 if( cmd.argsCount() > 1 )
2643 cmd.raiseError( "Only accepts 0-1 arguments" );
2644 int threshold = 1;
2645 if( cmd.argsCount() == 1 ) {
2646 std::stringstream ss;
2647 ss << cmd[0];
2648 ss >> threshold;
2649 if( ss.fail() || threshold <= 0 )
2650 cmd.raiseError( "threshold must be a number greater than zero" );
2651 }
2652 config.cutoff = threshold;
2653 }
2654
2655 if( Command cmd = parser.find( "-nt", "--nothrow" ) ) {
2656 if( cmd.argsCount() != 0 )
2657 cmd.raiseError( "Does not accept arguments" );
2658 config.allowThrows = false;
2659 }
2660
2661 }
2662
2663} // end namespace Catch
2664
2665// #included from: internal/catch_list.hpp
2666#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
2667
2668#include <limits>
2669
2670namespace Catch {
Phil Nash56d5c422012-08-23 20:08:50 +01002671 inline bool matchesFilters( const std::vector<TestCaseFilters>& filters, const TestCaseInfo& testCase ) {
2672 std::vector<TestCaseFilters>::const_iterator it = filters.begin();
2673 std::vector<TestCaseFilters>::const_iterator itEnd = filters.end();
2674 for(; it != itEnd; ++it )
2675 if( !it->shouldInclude( testCase ) )
2676 return false;
2677 return true;
2678 }
2679 inline void List( const ConfigData& config ) {
Phil Nasha695eb92012-08-13 07:46:10 +01002680
Phil Nash5bc030d2012-08-16 18:48:50 +01002681 if( config.listSpec & List::Reports ) {
Phil Nasha695eb92012-08-13 07:46:10 +01002682 std::cout << "Available reports:\n";
2683 IReporterRegistry::FactoryMap::const_iterator it = getRegistryHub().getReporterRegistry().getFactories().begin();
2684 IReporterRegistry::FactoryMap::const_iterator itEnd = getRegistryHub().getReporterRegistry().getFactories().end();
2685 for(; it != itEnd; ++it ) {
2686 // !TBD: consider listAs()
2687 std::cout << "\t" << it->first << "\n\t\t'" << it->second->getDescription() << "'\n";
2688 }
2689 std::cout << std::endl;
2690 }
2691
Phil Nash5bc030d2012-08-16 18:48:50 +01002692 if( config.listSpec & List::Tests ) {
Phil Nash56d5c422012-08-23 20:08:50 +01002693 if( config.filters.empty() )
Phil Nash4c97fc52012-08-24 08:23:50 +01002694 std::cout << "All available test cases:\n";
Phil Nash56d5c422012-08-23 20:08:50 +01002695 else
Phil Nash4c97fc52012-08-24 08:23:50 +01002696 std::cout << "Matching test cases:\n";
Phil Nasha695eb92012-08-13 07:46:10 +01002697 std::vector<TestCaseInfo>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin();
2698 std::vector<TestCaseInfo>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end();
Phil Nash4c97fc52012-08-24 08:23:50 +01002699 std::size_t matchedTests = 0;
Phil Nasha695eb92012-08-13 07:46:10 +01002700 for(; it != itEnd; ++it ) {
Phil Nash56d5c422012-08-23 20:08:50 +01002701 if( matchesFilters( config.filters, *it ) ) {
Phil Nash4c97fc52012-08-24 08:23:50 +01002702 matchedTests++;
Phil Nash56d5c422012-08-23 20:08:50 +01002703 // !TBD: consider listAs()
2704 std::cout << "\t" << it->getName() << "\n";
2705 if( ( config.listSpec & List::TestNames ) != List::TestNames )
2706 std::cout << "\t\t '" << it->getDescription() << "'\n";
2707 }
Phil Nasha695eb92012-08-13 07:46:10 +01002708 }
Phil Nash4c97fc52012-08-24 08:23:50 +01002709 if( config.filters.empty() )
2710 std::cout << pluralise( matchedTests, "test case" ) << std::endl;
2711 else
2712 std::cout << pluralise( matchedTests, "matching test case" ) << std::endl;
Phil Nasha695eb92012-08-13 07:46:10 +01002713 }
2714
Phil Nash5bc030d2012-08-16 18:48:50 +01002715 if( ( config.listSpec & List::All ) == 0 ) {
Phil Nash56d5c422012-08-23 20:08:50 +01002716 std::ostringstream oss;
2717 oss << "Unknown list type";
2718 throw std::domain_error( oss.str() );
Phil Nasha695eb92012-08-13 07:46:10 +01002719 }
Phil Nasha695eb92012-08-13 07:46:10 +01002720 }
2721
2722} // end namespace Catch
2723
2724// #included from: internal/catch_runner_impl.hpp
2725#define TWOBLUECUBES_INTERNAL_CATCH_RUNNER_HPP_INCLUDED
2726
2727// #included from: catch_running_test.hpp
2728#define TWOBLUECUBES_INTERNAL_CATCH_RUNNING_TEST_HPP_INCLUDED
2729
2730// #included from: catch_section_info.hpp
2731#define TWOBLUECUBES_INTERNAL_CATCH_SECTION_INFO_HPP_INCLUDED
2732
2733#include <map>
2734#include <string>
2735
2736namespace Catch {
2737
2738 class SectionInfo {
2739 public:
2740
2741 enum Status {
2742 Root,
2743 Unknown,
2744 Branch,
2745 TestedBranch,
2746 TestedLeaf
2747 };
2748
2749 SectionInfo( SectionInfo* parent )
2750 : m_status( Unknown ),
2751 m_parent( parent )
2752 {}
2753
2754 SectionInfo()
2755 : m_status( Root ),
2756 m_parent( NULL )
2757 {}
2758
2759 ~SectionInfo() {
2760 deleteAllValues( m_subSections );
2761 }
2762
2763 bool shouldRun() const {
2764 return m_status < TestedBranch;
2765 }
2766
2767 bool ran() {
2768 if( m_status < Branch ) {
2769 m_status = TestedLeaf;
2770 return true;
2771 }
2772 return false;
2773 }
2774
2775 void ranToCompletion() {
2776 if( m_status == Branch && !hasUntestedSections() )
2777 m_status = TestedBranch;
2778 }
2779
2780 SectionInfo* findSubSection( const std::string& name ) {
2781 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.find( name );
2782 return it != m_subSections.end()
2783 ? it->second
2784 : NULL;
2785 }
2786
2787 SectionInfo* addSubSection( const std::string& name ) {
2788 SectionInfo* subSection = new SectionInfo( this );
2789 m_subSections.insert( std::make_pair( name, subSection ) );
2790 m_status = Branch;
2791 return subSection;
2792 }
2793
2794 SectionInfo* getParent() {
2795 return m_parent;
2796 }
2797
2798 bool hasUntestedSections() const {
2799 if( m_status == Unknown )
2800 return true;
2801
2802 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.begin();
2803 std::map<std::string, SectionInfo*>::const_iterator itEnd = m_subSections.end();
2804 for(; it != itEnd; ++it ) {
2805 if( it->second->hasUntestedSections() )
2806 return true;
2807 }
2808 return false;
2809 }
2810
2811 private:
2812 Status m_status;
2813 std::map<std::string, SectionInfo*> m_subSections;
2814 SectionInfo* m_parent;
2815 };
2816}
2817
2818namespace Catch {
2819
2820 class RunningTest {
2821
2822 enum RunStatus {
2823 NothingRun,
2824 EncounteredASection,
2825 RanAtLeastOneSection,
2826 RanToCompletionWithSections,
2827 RanToCompletionWithNoSections
2828 };
2829
2830 public:
2831 explicit RunningTest( const TestCaseInfo* info = NULL )
2832 : m_info( info ),
2833 m_runStatus( RanAtLeastOneSection ),
2834 m_currentSection( &m_rootSection ),
2835 m_changed( false )
2836 {}
2837
2838 bool wasSectionSeen() const {
2839 return m_runStatus == RanAtLeastOneSection ||
2840 m_runStatus == RanToCompletionWithSections;
2841 }
2842
2843 void reset() {
2844 m_runStatus = NothingRun;
2845 m_changed = false;
2846 m_lastSectionToRun = NULL;
2847 }
2848
2849 void ranToCompletion() {
2850 if( m_runStatus == RanAtLeastOneSection ||
2851 m_runStatus == EncounteredASection ) {
2852 m_runStatus = RanToCompletionWithSections;
2853 if( m_lastSectionToRun ) {
2854 m_lastSectionToRun->ranToCompletion();
2855 m_changed = true;
2856 }
2857 }
2858 else {
2859 m_runStatus = RanToCompletionWithNoSections;
2860 }
2861 }
2862
2863 bool addSection( const std::string& name ) {
2864 if( m_runStatus == NothingRun )
2865 m_runStatus = EncounteredASection;
2866
2867 SectionInfo* thisSection = m_currentSection->findSubSection( name );
2868 if( !thisSection ) {
2869 thisSection = m_currentSection->addSubSection( name );
2870 m_changed = true;
2871 }
2872
2873 if( !wasSectionSeen() && thisSection->shouldRun() ) {
2874 m_currentSection = thisSection;
2875 m_lastSectionToRun = NULL;
2876 return true;
2877 }
2878 return false;
2879 }
2880
2881 void endSection( const std::string& ) {
2882 if( m_currentSection->ran() ) {
2883 m_runStatus = RanAtLeastOneSection;
2884 m_changed = true;
2885 }
2886 else if( m_runStatus == EncounteredASection ) {
2887 m_runStatus = RanAtLeastOneSection;
2888 m_lastSectionToRun = m_currentSection;
2889 }
2890 m_currentSection = m_currentSection->getParent();
2891 }
2892
2893 const TestCaseInfo& getTestCaseInfo() const {
2894 return *m_info;
2895 }
2896
2897 bool hasUntestedSections() const {
2898 return m_runStatus == RanAtLeastOneSection ||
2899 ( m_rootSection.hasUntestedSections() && m_changed );
2900 }
2901
2902 private:
2903 const TestCaseInfo* m_info;
2904 RunStatus m_runStatus;
2905 SectionInfo m_rootSection;
2906 SectionInfo* m_currentSection;
2907 SectionInfo* m_lastSectionToRun;
2908 bool m_changed;
2909 };
2910}
2911
2912#include <set>
2913#include <string>
2914
2915namespace Catch {
2916
2917 class StreamRedirect {
2918
2919 public:
2920 StreamRedirect( std::ostream& stream, std::string& targetString )
2921 : m_stream( stream ),
2922 m_prevBuf( stream.rdbuf() ),
2923 m_targetString( targetString )
2924 {
2925 stream.rdbuf( m_oss.rdbuf() );
2926 }
2927
2928 ~StreamRedirect() {
2929 m_targetString += m_oss.str();
2930 m_stream.rdbuf( m_prevBuf );
2931 }
2932
2933 private:
2934 std::ostream& m_stream;
2935 std::streambuf* m_prevBuf;
2936 std::ostringstream m_oss;
2937 std::string& m_targetString;
2938 };
2939
2940 ///////////////////////////////////////////////////////////////////////////
2941
2942 class Runner : public IResultCapture, public IRunner {
2943
2944 Runner( const Runner& );
2945 void operator =( const Runner& );
2946
2947 public:
2948
Phil Nash56d5c422012-08-23 20:08:50 +01002949 explicit Runner( const Config& config, const Ptr<IReporter>& reporter )
Phil Nasha695eb92012-08-13 07:46:10 +01002950 : m_context( getCurrentMutableContext() ),
2951 m_runningTest( NULL ),
2952 m_config( config ),
2953 m_reporter( reporter ),
2954 m_prevRunner( &m_context.getRunner() ),
2955 m_prevResultCapture( &m_context.getResultCapture() ),
2956 m_prevConfig( m_context.getConfig() )
2957 {
2958 m_context.setRunner( this );
2959 m_context.setConfig( &m_config );
2960 m_context.setResultCapture( this );
2961 m_reporter->StartTesting();
2962 }
2963
2964 virtual ~Runner() {
2965 m_reporter->EndTesting( m_totals );
2966 m_context.setRunner( m_prevRunner );
2967 m_context.setConfig( NULL );
2968 m_context.setResultCapture( m_prevResultCapture );
2969 m_context.setConfig( m_prevConfig );
2970 }
2971
Phil Nash56d5c422012-08-23 20:08:50 +01002972 Totals runMatching( const std::string& testSpec ) {
Phil Nasha695eb92012-08-13 07:46:10 +01002973
Phil Nash56d5c422012-08-23 20:08:50 +01002974 std::vector<TestCaseInfo> matchingTests = getRegistryHub().getTestCaseRegistry().getMatchingTestCases( testSpec );
Phil Nash5bc030d2012-08-16 18:48:50 +01002975
2976 Totals totals;
Phil Nash5bc030d2012-08-16 18:48:50 +01002977
Phil Nash56d5c422012-08-23 20:08:50 +01002978 m_reporter->StartGroup( testSpec );
2979
2980 std::vector<TestCaseInfo>::const_iterator it = matchingTests.begin();
2981 std::vector<TestCaseInfo>::const_iterator itEnd = matchingTests.end();
2982 for(; it != itEnd; ++it )
2983 totals += runTest( *it );
2984 // !TBD use std::accumulate?
2985
2986 m_reporter->EndGroup( testSpec, totals );
Phil Nash5bc030d2012-08-16 18:48:50 +01002987 return totals;
2988 }
2989
2990 Totals runTest( const TestCaseInfo& testInfo ) {
Phil Nasha695eb92012-08-13 07:46:10 +01002991 Totals prevTotals = m_totals;
2992
2993 std::string redirectedCout;
2994 std::string redirectedCerr;
2995
2996 m_reporter->StartTestCase( testInfo );
2997
2998 m_runningTest = new RunningTest( &testInfo );
2999
3000 do {
3001 do {
Phil Nasha695eb92012-08-13 07:46:10 +01003002 m_currentResult.setLineInfo( m_runningTest->getTestCaseInfo().getLineInfo() );
3003 runCurrentTest( redirectedCout, redirectedCerr );
Phil Nasha695eb92012-08-13 07:46:10 +01003004 }
3005 while( m_runningTest->hasUntestedSections() && !aborting() );
3006 }
3007 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
3008
3009 delete m_runningTest;
3010 m_runningTest = NULL;
3011
3012 Totals deltaTotals = m_totals.delta( prevTotals );
3013 m_totals.testCases += deltaTotals.testCases;
3014 m_reporter->EndTestCase( testInfo, deltaTotals, redirectedCout, redirectedCerr );
Phil Nash5bc030d2012-08-16 18:48:50 +01003015 return deltaTotals;
Phil Nasha695eb92012-08-13 07:46:10 +01003016 }
3017
3018 const Config& config() const {
3019 return m_config;
3020 }
3021
3022 private: // IResultCapture
3023
3024 virtual ResultAction::Value acceptResult( bool result ) {
3025 return acceptResult( result ? ResultWas::Ok : ResultWas::ExpressionFailed );
3026 }
3027
3028 virtual ResultAction::Value acceptResult( ResultWas::OfType result ) {
3029 m_currentResult.setResultType( result );
3030 return actOnCurrentResult();
3031 }
3032
3033 virtual ResultAction::Value acceptExpression( const ResultInfoBuilder& resultInfo ) {
3034 m_currentResult = resultInfo;
3035 return actOnCurrentResult();
3036 }
3037
3038 virtual void acceptMessage( const std::string& msg ) {
3039 m_currentResult.setMessage( msg );
3040 }
3041
3042 virtual void testEnded( const ResultInfo& result ) {
3043 if( result.getResultType() == ResultWas::Ok ) {
3044 m_totals.assertions.passed++;
3045 }
3046 else if( !result.ok() ) {
3047 m_totals.assertions.failed++;
3048
3049 std::vector<ResultInfo>::const_iterator it = m_info.begin();
3050 std::vector<ResultInfo>::const_iterator itEnd = m_info.end();
3051 for(; it != itEnd; ++it )
3052 m_reporter->Result( *it );
3053 m_info.clear();
3054 }
3055
3056 if( result.getResultType() == ResultWas::Info )
3057 m_info.push_back( result );
3058 else
3059 m_reporter->Result( result );
3060 }
3061
3062 virtual bool sectionStarted (
3063 const std::string& name,
3064 const std::string& description,
3065 const SourceLineInfo& lineInfo,
3066 Counts& assertions
3067 )
3068 {
3069 std::ostringstream oss;
3070 oss << name << "@" << lineInfo;
3071
3072 if( !m_runningTest->addSection( oss.str() ) )
3073 return false;
3074
3075 m_currentResult.setLineInfo( lineInfo );
3076 m_reporter->StartSection( name, description );
3077 assertions = m_totals.assertions;
3078
3079 return true;
3080 }
3081
3082 virtual void sectionEnded( const std::string& name, const Counts& prevAssertions ) {
3083 m_runningTest->endSection( name );
3084 m_reporter->EndSection( name, m_totals.assertions - prevAssertions );
3085 }
3086
3087 virtual void pushScopedInfo( ScopedInfo* scopedInfo ) {
3088 m_scopedInfos.push_back( scopedInfo );
3089 }
3090
3091 virtual void popScopedInfo( ScopedInfo* scopedInfo ) {
3092 if( m_scopedInfos.back() == scopedInfo )
3093 m_scopedInfos.pop_back();
3094 }
3095
3096 virtual bool shouldDebugBreak() const {
3097 return m_config.shouldDebugBreak();
3098 }
3099
3100 virtual std::string getCurrentTestName() const {
3101 return m_runningTest
3102 ? m_runningTest->getTestCaseInfo().getName()
3103 : "";
3104 }
3105
3106 virtual const ResultInfo* getLastResult() const {
3107 return &m_lastResult;
3108 }
3109
Phil Nash56d5c422012-08-23 20:08:50 +01003110 public:
3111 // !TBD We need to do this another way!
Phil Nasha695eb92012-08-13 07:46:10 +01003112 bool aborting() const {
3113 return m_totals.assertions.failed == static_cast<std::size_t>( m_config.getCutoff() );
3114 }
3115
Phil Nash56d5c422012-08-23 20:08:50 +01003116 private:
3117
Phil Nasha695eb92012-08-13 07:46:10 +01003118 ResultAction::Value actOnCurrentResult() {
3119 testEnded( m_currentResult );
3120 m_lastResult = m_currentResult;
3121
3122 m_currentResult = ResultInfoBuilder();
3123
3124 ResultAction::Value action = ResultAction::None;
3125
3126 if( !m_lastResult.ok() ) {
3127 action = ResultAction::Failed;
3128 if( shouldDebugBreak() )
3129 action = (ResultAction::Value)( action | ResultAction::Debug );
3130 if( aborting() )
3131 action = (ResultAction::Value)( action | ResultAction::Abort );
3132 }
3133 return action;
3134 }
3135
3136 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
3137 try {
3138 m_runningTest->reset();
3139 if( m_reporter->shouldRedirectStdout() ) {
3140 StreamRedirect coutRedir( std::cout, redirectedCout );
3141 StreamRedirect cerrRedir( std::cerr, redirectedCerr );
3142 m_runningTest->getTestCaseInfo().invoke();
3143 }
3144 else {
3145 m_runningTest->getTestCaseInfo().invoke();
3146 }
3147 m_runningTest->ranToCompletion();
3148 }
3149 catch( TestFailureException& ) {
3150 // This just means the test was aborted due to failure
3151 }
3152 catch(...) {
3153 acceptMessage( getRegistryHub().getExceptionTranslatorRegistry().translateActiveException() );
3154 acceptResult( ResultWas::ThrewException );
3155 }
3156 m_info.clear();
3157 }
3158
3159 private:
3160 IMutableContext& m_context;
3161 RunningTest* m_runningTest;
3162 ResultInfoBuilder m_currentResult;
3163 ResultInfo m_lastResult;
3164
3165 const Config& m_config;
3166 Totals m_totals;
3167 Ptr<IReporter> m_reporter;
3168 std::vector<ScopedInfo*> m_scopedInfos;
3169 std::vector<ResultInfo> m_info;
3170 IRunner* m_prevRunner;
3171 IResultCapture* m_prevResultCapture;
3172 const IConfig* m_prevConfig;
3173 };
3174
3175} // end namespace Catch
3176
Phil Nash89d1e6c2011-05-24 08:23:02 +01003177#include <fstream>
3178#include <stdlib.h>
3179#include <limits>
3180
Phil Nash89d2a3f2012-05-16 15:09:17 +01003181namespace Catch {
3182
Phil Nash56d5c422012-08-23 20:08:50 +01003183 class Runner2 { // This will become Runner when Runner becomes Context
Phil Nash163088a2012-05-31 19:40:26 +01003184
Phil Nash56d5c422012-08-23 20:08:50 +01003185 public:
3186 Runner2( Config& configWrapper )
3187 : m_configWrapper( configWrapper ),
3188 m_config( configWrapper.data() )
Phil Nash06e959b2012-05-25 08:52:05 +01003189 {
Phil Nash56d5c422012-08-23 20:08:50 +01003190 resolveStream();
3191 makeReporter();
3192 }
Phil Nash06e959b2012-05-25 08:52:05 +01003193
Phil Nash56d5c422012-08-23 20:08:50 +01003194 Totals runTests() {
3195
3196 std::vector<TestCaseFilters> filterGroups = m_config.filters;
3197 if( filterGroups.empty() ) {
3198 TestCaseFilters filterGroup( "" );
3199 filterGroup.addFilter( TestCaseFilter( "./*", IfFilterMatches::ExcludeTests ) );
3200 filterGroups.push_back( filterGroup );
Phil Nash89d1e6c2011-05-24 08:23:02 +01003201 }
Phil Nash56d5c422012-08-23 20:08:50 +01003202
3203 Runner context( m_configWrapper, m_reporter ); // This Runner will be renamed Context
3204 Totals totals;
3205
3206 std::vector<TestCaseFilters>::const_iterator it = filterGroups.begin();
3207 std::vector<TestCaseFilters>::const_iterator itEnd = filterGroups.end();
3208 for(; it != itEnd; ++it ) {
3209 m_reporter->StartGroup( it->getName() );
3210 runTestsForGroup( context, *it );
3211 if( context.aborting() )
3212 m_reporter->Aborted();
3213 m_reporter->EndGroup( it->getName(), totals );
3214 }
3215 return totals;
3216 }
3217
3218 Totals runTestsForGroup( Runner& context, const TestCaseFilters& filterGroup ) {
3219 Totals totals;
3220 std::vector<TestCaseInfo>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin();
3221 std::vector<TestCaseInfo>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end();
3222 int testsRunForGroup = 0;
3223 for(; it != itEnd; ++it ) {
3224 if( filterGroup.shouldInclude( *it ) ) {
3225 testsRunForGroup++;
3226 if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
3227
3228 if( context.aborting() )
3229 break;
3230
3231 totals += context.runTest( *it );
3232 m_testsAlreadyRun.insert( *it );
3233 }
Phil Nash06e959b2012-05-25 08:52:05 +01003234 }
3235 }
Phil Nash56d5c422012-08-23 20:08:50 +01003236 if( testsRunForGroup == 0 )
3237 std::cerr << "\n[No test cases matched with: " << filterGroup.getName() << "]" << std::endl;
3238 return totals;
3239
Phil Nash89d1e6c2011-05-24 08:23:02 +01003240 }
Phil Nash56d5c422012-08-23 20:08:50 +01003241
3242 private:
3243 void resolveStream() {
3244 if( !m_config.stream.empty() ) {
3245 if( m_config.stream[0] == '%' )
3246 m_configWrapper.useStream( m_config.stream.substr( 1 ) );
3247 else
3248 m_configWrapper.setFilename( m_config.stream );
3249 }
3250 // Open output file, if specified
3251 if( !m_config.outputFilename.empty() ) {
3252 m_ofs.open( m_config.outputFilename.c_str() );
3253 if( m_ofs.fail() ) {
3254 std::ostringstream oss;
3255 oss << "Unable to open file: '" << m_config.outputFilename << "'";
3256 throw std::domain_error( oss.str() );
3257 }
3258 m_configWrapper.setStreamBuf( m_ofs.rdbuf() );
3259 }
3260 }
3261 void makeReporter() {
3262 std::string reporterName = m_config.reporter.empty()
3263 ? "basic"
3264 : m_config.reporter;
3265
3266 ReporterConfig reporterConfig( m_config.name, m_configWrapper.stream(), m_config.includeWhichResults == Include::SuccessfulResults );
3267
3268 m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, reporterConfig );
3269 if( !m_reporter ) {
3270 std::ostringstream oss;
3271 oss << "No reporter registered with name: '" << reporterName << "'";
3272 throw std::domain_error( oss.str() );
3273 }
3274 }
3275
3276 private:
3277 Config& m_configWrapper;
3278 const ConfigData& m_config;
3279 std::ofstream m_ofs;
3280 Ptr<IReporter> m_reporter;
3281 std::set<TestCaseInfo> m_testsAlreadyRun;
3282 };
3283
3284 inline int Main( Config& configWrapper ) {
3285 int result = 0;
3286 try
3287 {
3288 Runner2 runner( configWrapper );
3289
3290 const ConfigData& config = configWrapper.data();
3291
3292 // Handle list request
3293 if( config.listSpec != List::None ) {
3294 List( config );
3295 return 0;
3296 }
3297
3298 result = static_cast<int>( runner.runTests().assertions.failed );
3299
3300 }
3301 catch( std::exception& ex ) {
3302 std::cerr << ex.what() << std::endl;
3303 result = (std::numeric_limits<int>::max)();
3304 }
3305
Phil Nash3b80af72012-08-09 07:47:30 +01003306 Catch::cleanUp();
Phil Nash371db8b2012-05-21 18:52:09 +01003307 return result;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003308 }
3309
Phil Nash163088a2012-05-31 19:40:26 +01003310 inline void showUsage( std::ostream& os ) {
Phil Nashabf27162012-07-05 18:37:58 +01003311 os << "\t-?, -h, --help\n"
Phil Nash56d5c422012-08-23 20:08:50 +01003312 << "\t-l, --list [all | tests | reporters [xml]]\n"
Phil Nash163088a2012-05-31 19:40:26 +01003313 << "\t-t, --test <testspec> [<testspec>...]\n"
3314 << "\t-r, --reporter <reporter name>\n"
3315 << "\t-o, --out <file name>|<%stream name>\n"
3316 << "\t-s, --success\n"
3317 << "\t-b, --break\n"
Phil Nash0f9c5512012-06-02 23:12:42 +01003318 << "\t-n, --name <name>\n"
Phil Nash5d73c5a2012-07-17 08:04:19 +01003319 << "\t-a, --abort [#]\n"
Phil Nashabf27162012-07-05 18:37:58 +01003320 << "\t-nt, --nothrow\n\n"
Phil Nash163088a2012-05-31 19:40:26 +01003321 << "For more detail usage please see: https://github.com/philsquared/Catch/wiki/Command-line" << std::endl;
3322 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01003323 inline void showHelp( std::string exeName ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003324 std::string::size_type pos = exeName.find_last_of( "/\\" );
Phil Nash89d2a3f2012-05-16 15:09:17 +01003325 if( pos != std::string::npos ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003326 exeName = exeName.substr( pos+1 );
3327 }
3328
Phil Nash163088a2012-05-31 19:40:26 +01003329 std::cout << exeName << " is a CATCH host application. Options are as follows:\n\n";
3330 showUsage( std::cout );
Phil Nash89d1e6c2011-05-24 08:23:02 +01003331 }
3332
Phil Nash89d2a3f2012-05-16 15:09:17 +01003333 inline int Main( int argc, char* const argv[], Config& config ) {
Phil Nash163088a2012-05-31 19:40:26 +01003334
Phil Nashabf27162012-07-05 18:37:58 +01003335 try {
3336 CommandParser parser( argc, argv );
Phil Nash89d1e6c2011-05-24 08:23:02 +01003337
Phil Nashabf27162012-07-05 18:37:58 +01003338 if( Command cmd = parser.find( "-h", "-?", "--help" ) ) {
3339 if( cmd.argsCount() != 0 )
3340 cmd.raiseError( "Does not accept arguments" );
3341
3342 showHelp( argv[0] );
Phil Nash3b80af72012-08-09 07:47:30 +01003343 Catch::cleanUp();
Phil Nashabf27162012-07-05 18:37:58 +01003344 return 0;
3345 }
3346
3347 parseIntoConfig( parser, config.data() );
Phil Nashabf27162012-07-05 18:37:58 +01003348 }
3349 catch( std::exception& ex ) {
Phil Nash6f220862012-07-23 08:24:52 +01003350 std::cerr << ex.what() << "\n\nUsage: ...\n\n";
Phil Nash163088a2012-05-31 19:40:26 +01003351 showUsage( std::cerr );
Phil Nash3b80af72012-08-09 07:47:30 +01003352 Catch::cleanUp();
Phil Nash89d1e6c2011-05-24 08:23:02 +01003353 return (std::numeric_limits<int>::max)();
3354 }
3355
Phil Nash89d1e6c2011-05-24 08:23:02 +01003356 return Main( config );
3357 }
3358
Phil Nash89d2a3f2012-05-16 15:09:17 +01003359 inline int Main( int argc, char* const argv[] ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003360 Config config;
Phil Nash371db8b2012-05-21 18:52:09 +01003361// !TBD: This doesn't always work, for some reason
Phil Nash89d1e6c2011-05-24 08:23:02 +01003362// if( isDebuggerActive() )
3363// config.useStream( "debug" );
Phil Nash371db8b2012-05-21 18:52:09 +01003364 return Main( argc, argv, config );
Phil Nash89d1e6c2011-05-24 08:23:02 +01003365 }
3366
3367} // end namespace Catch
3368
Phil Nash3b80af72012-08-09 07:47:30 +01003369// #included from: catch_registry_hub.hpp
3370
3371// #included from: catch_test_case_registry_impl.hpp
3372
3373#include <vector>
3374#include <set>
3375#include <sstream>
3376#include <iostream>
3377
3378namespace Catch {
3379
3380 class TestRegistry : public ITestCaseRegistry {
3381 public:
3382 TestRegistry() : m_unnamedCount( 0 ) {}
Phil Nasha695eb92012-08-13 07:46:10 +01003383 virtual ~TestRegistry();
Phil Nash3b80af72012-08-09 07:47:30 +01003384
3385 virtual void registerTest( const TestCaseInfo& testInfo ) {
3386 if( testInfo.getName() == "" ) {
3387 std::ostringstream oss;
3388 oss << testInfo.getName() << "unnamed/" << ++m_unnamedCount;
3389 return registerTest( TestCaseInfo( testInfo, oss.str() ) );
3390 }
3391
3392 if( m_functions.find( testInfo ) == m_functions.end() ) {
3393 m_functions.insert( testInfo );
3394 m_functionsInOrder.push_back( testInfo );
Phil Nash5bc030d2012-08-16 18:48:50 +01003395 if( !testInfo.isHidden() )
3396 m_nonHiddenFunctions.push_back( testInfo );
Phil Nash3b80af72012-08-09 07:47:30 +01003397 }
3398 else {
3399 const TestCaseInfo& prev = *m_functions.find( testInfo );
3400 std::cerr << "error: TEST_CASE( \"" << testInfo.getName() << "\" ) already defined.\n"
3401 << "\tFirst seen at " << SourceLineInfo( prev.getLineInfo() ) << "\n"
3402 << "\tRedefined at " << SourceLineInfo( testInfo.getLineInfo() ) << std::endl;
3403 exit(1);
3404 }
3405 }
3406
3407 virtual const std::vector<TestCaseInfo>& getAllTests() const {
3408 return m_functionsInOrder;
3409 }
3410
Phil Nash5bc030d2012-08-16 18:48:50 +01003411 virtual const std::vector<TestCaseInfo>& getAllNonHiddenTests() const {
3412 return m_nonHiddenFunctions;
3413 }
3414
Phil Nash56d5c422012-08-23 20:08:50 +01003415 // !TBD deprecated
Phil Nash3b80af72012-08-09 07:47:30 +01003416 virtual std::vector<TestCaseInfo> getMatchingTestCases( const std::string& rawTestSpec ) const {
Phil Nash5bc030d2012-08-16 18:48:50 +01003417 std::vector<TestCaseInfo> matchingTests;
3418 getMatchingTestCases( rawTestSpec, matchingTests );
3419 return matchingTests;
3420 }
3421
Phil Nash56d5c422012-08-23 20:08:50 +01003422 // !TBD deprecated
Phil Nash5bc030d2012-08-16 18:48:50 +01003423 virtual void getMatchingTestCases( const std::string& rawTestSpec, std::vector<TestCaseInfo>& matchingTestsOut ) const {
Phil Nash56d5c422012-08-23 20:08:50 +01003424 TestCaseFilter filter( rawTestSpec );
Phil Nash5bc030d2012-08-16 18:48:50 +01003425
Phil Nash3b80af72012-08-09 07:47:30 +01003426 std::vector<TestCaseInfo>::const_iterator it = m_functionsInOrder.begin();
3427 std::vector<TestCaseInfo>::const_iterator itEnd = m_functionsInOrder.end();
3428 for(; it != itEnd; ++it ) {
Phil Nash56d5c422012-08-23 20:08:50 +01003429 if( filter.shouldInclude( *it ) ) {
Phil Nash5bc030d2012-08-16 18:48:50 +01003430 matchingTestsOut.push_back( *it );
Phil Nash3b80af72012-08-09 07:47:30 +01003431 }
3432 }
Phil Nash3b80af72012-08-09 07:47:30 +01003433 }
Phil Nash56d5c422012-08-23 20:08:50 +01003434 virtual void getMatchingTestCases( const TestCaseFilters& filters, std::vector<TestCaseInfo>& matchingTestsOut ) const {
3435 std::vector<TestCaseInfo>::const_iterator it = m_functionsInOrder.begin();
3436 std::vector<TestCaseInfo>::const_iterator itEnd = m_functionsInOrder.end();
3437 // !TBD: replace with algorithm
3438 for(; it != itEnd; ++it )
3439 if( filters.shouldInclude( *it ) )
3440 matchingTestsOut.push_back( *it );
3441 }
Phil Nash3b80af72012-08-09 07:47:30 +01003442
3443 private:
3444
3445 std::set<TestCaseInfo> m_functions;
3446 std::vector<TestCaseInfo> m_functionsInOrder;
Phil Nash5bc030d2012-08-16 18:48:50 +01003447 std::vector<TestCaseInfo> m_nonHiddenFunctions;
Phil Nash3b80af72012-08-09 07:47:30 +01003448 size_t m_unnamedCount;
3449 };
3450
3451 ///////////////////////////////////////////////////////////////////////////
3452
Phil Nash5bc030d2012-08-16 18:48:50 +01003453 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
Phil Nash3b80af72012-08-09 07:47:30 +01003454 public:
3455
3456 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
3457
3458 virtual void invoke() const {
3459 m_fun();
3460 }
3461
Phil Nash3b80af72012-08-09 07:47:30 +01003462 private:
Phil Nash5bc030d2012-08-16 18:48:50 +01003463 virtual ~FreeFunctionTestCase();
3464
Phil Nash3b80af72012-08-09 07:47:30 +01003465 TestFunction m_fun;
3466 };
3467
3468 ///////////////////////////////////////////////////////////////////////////
3469
3470 AutoReg::AutoReg( TestFunction function,
3471 const char* name,
3472 const char* description,
3473 const SourceLineInfo& lineInfo ) {
3474 registerTestCase( new FreeFunctionTestCase( function ), name, description, lineInfo );
3475 }
3476
3477 AutoReg::~AutoReg() {}
3478
3479 void AutoReg::registerTestCase( ITestCase* testCase,
3480 const char* name,
3481 const char* description,
3482 const SourceLineInfo& lineInfo ) {
3483 getMutableRegistryHub().registerTest( TestCaseInfo( testCase, name, description, lineInfo ) );
3484 }
3485
3486} // end namespace Catch
3487
3488// #included from: catch_reporter_registry.hpp
3489#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
3490
3491#include <map>
3492
3493namespace Catch {
3494
3495 class ReporterRegistry : public IReporterRegistry {
3496
3497 public:
3498
Phil Nasha695eb92012-08-13 07:46:10 +01003499 virtual ~ReporterRegistry() {
Phil Nash3b80af72012-08-09 07:47:30 +01003500 deleteAllValues( m_factories );
3501 }
3502
3503 virtual IReporter* create( const std::string& name, const ReporterConfig& config ) const {
3504 FactoryMap::const_iterator it = m_factories.find( name );
3505 if( it == m_factories.end() )
3506 return NULL;
3507 return it->second->create( config );
3508 }
3509
3510 void registerReporter( const std::string& name, IReporterFactory* factory ) {
3511 m_factories.insert( std::make_pair( name, factory ) );
3512 }
3513
3514 const FactoryMap& getFactories() const {
3515 return m_factories;
3516 }
3517
3518 private:
3519 FactoryMap m_factories;
3520 };
3521}
3522
3523// #included from: catch_exception_translator_registry.hpp
3524#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_HPP_INCLUDED
3525
3526#ifdef __OBJC__
3527#import "Foundation/Foundation.h"
3528#endif
3529
3530namespace Catch {
3531
3532 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
3533 public:
3534 ~ExceptionTranslatorRegistry() {
3535 deleteAll( m_translators );
3536 }
3537
3538 virtual void registerTranslator( const IExceptionTranslator* translator ) {
3539 m_translators.push_back( translator );
3540 }
3541
3542 virtual std::string translateActiveException() const {
3543 try {
3544#ifdef __OBJC__
3545 // In Objective-C try objective-c exceptions first
3546 @try {
3547 throw;
3548 }
3549 @catch (NSException *exception) {
3550 return toString( [exception description] );
3551 }
3552#else
3553 throw;
3554#endif
3555 }
3556 catch( std::exception& ex ) {
3557 return ex.what();
3558 }
3559 catch( std::string& msg ) {
3560 return msg;
3561 }
3562 catch( const char* msg ) {
3563 return msg;
3564 }
3565 catch(...) {
3566 return tryTranslators( m_translators.begin() );
3567 }
3568 }
3569
3570 std::string tryTranslators( std::vector<const IExceptionTranslator*>::const_iterator it ) const {
3571 if( it == m_translators.end() )
3572 return "Unknown exception";
3573
3574 try {
3575 return (*it)->translate();
3576 }
3577 catch(...) {
3578 return tryTranslators( it+1 );
3579 }
3580 }
3581
3582 private:
3583 std::vector<const IExceptionTranslator*> m_translators;
3584 };
3585}
3586
3587namespace Catch {
3588
3589 namespace {
3590
3591 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
3592
3593 RegistryHub( const RegistryHub& );
3594 void operator=( const RegistryHub& );
3595
3596 public: // IRegistryHub
3597 RegistryHub() {
3598 }
3599 virtual const IReporterRegistry& getReporterRegistry() const {
3600 return m_reporterRegistry;
3601 }
3602 virtual const ITestCaseRegistry& getTestCaseRegistry() const {
3603 return m_testCaseRegistry;
3604 }
3605 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
3606 return m_exceptionTranslatorRegistry;
3607 }
3608
3609 public: // IMutableRegistryHub
3610 virtual void registerReporter( const std::string& name, IReporterFactory* factory ) {
3611 m_reporterRegistry.registerReporter( name, factory );
3612 }
3613 virtual void registerTest( const TestCaseInfo& testInfo ) {
3614 m_testCaseRegistry.registerTest( testInfo );
3615 }
3616 virtual void registerTranslator( const IExceptionTranslator* translator ) {
3617 m_exceptionTranslatorRegistry.registerTranslator( translator );
3618 }
3619
3620 private:
3621 TestRegistry m_testCaseRegistry;
3622 ReporterRegistry m_reporterRegistry;
3623 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
3624 };
3625
3626 // Single, global, instance
3627 inline RegistryHub*& getTheRegistryHub() {
3628 static RegistryHub* theRegistryHub = NULL;
3629 if( !theRegistryHub )
3630 theRegistryHub = new RegistryHub();
3631 return theRegistryHub;
3632 }
3633 }
3634
3635 IRegistryHub& getRegistryHub() {
3636 return *getTheRegistryHub();
3637 }
3638 IMutableRegistryHub& getMutableRegistryHub() {
3639 return *getTheRegistryHub();
3640 }
3641 void cleanUp() {
3642 delete getTheRegistryHub();
3643 getTheRegistryHub() = NULL;
3644 cleanUpContext();
3645 }
3646
3647} // end namespace Catch
3648// #included from: catch_notimplemented_exception.hpp
3649#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
3650
3651#include <ostream>
3652
3653namespace Catch {
3654
3655 NotImplementedException::NotImplementedException( const SourceLineInfo& lineInfo )
3656 : m_lineInfo( lineInfo ) {
3657 std::ostringstream oss;
3658 oss << lineInfo << "function ";
3659 if( !lineInfo.function.empty() )
3660 oss << lineInfo.function << " ";
3661 oss << "not implemented";
3662 m_what = oss.str();
3663 }
3664
3665 const char* NotImplementedException::what() const throw() {
3666 return m_what.c_str();
3667 }
3668
3669} // end namespace Catch
3670
3671// #included from: catch_context_impl.hpp
3672
3673// #included from: catch_stream.hpp
3674#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
3675
3676#include <stdexcept>
3677#include <cstdio>
3678
3679namespace Catch {
3680
3681 template<typename WriterF, size_t bufferSize=256>
3682 class StreamBufImpl : public StreamBufBase {
3683 char data[bufferSize];
3684 WriterF m_writer;
3685
3686 public:
3687 StreamBufImpl() {
3688 setp( data, data + sizeof(data) );
3689 }
3690
3691 ~StreamBufImpl() {
3692 sync();
3693 }
3694
3695 private:
3696 int overflow( int c ) {
3697 sync();
3698
3699 if( c != EOF ) {
3700 if( pbase() == epptr() )
3701 m_writer( std::string( 1, static_cast<char>( c ) ) );
3702 else
3703 sputc( static_cast<char>( c ) );
3704 }
3705 return 0;
3706 }
3707
3708 int sync() {
3709 if( pbase() != pptr() ) {
3710 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
3711 setp( pbase(), epptr() );
3712 }
3713 return 0;
3714 }
3715 };
3716
3717 ///////////////////////////////////////////////////////////////////////////
3718
3719 struct OutputDebugWriter {
3720
3721 void operator()( const std::string &str ) {
3722 writeToDebugConsole( str );
3723 }
3724 };
3725}
3726
3727namespace Catch {
3728
3729 class Context : public IMutableContext {
3730
3731 Context() : m_config( NULL ) {}
3732 Context( const Context& );
3733 void operator=( const Context& );
3734
3735 public: // IContext
3736 virtual IResultCapture& getResultCapture() {
3737 return *m_resultCapture;
3738 }
3739 virtual IRunner& getRunner() {
3740 return *m_runner;
3741 }
3742 virtual size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ) {
3743 return getGeneratorsForCurrentTest()
3744 .getGeneratorInfo( fileInfo, totalSize )
3745 .getCurrentIndex();
3746 }
3747 virtual bool advanceGeneratorsForCurrentTest() {
3748 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
3749 return generators && generators->moveNext();
3750 }
3751
3752 virtual const IConfig* getConfig() const {
3753 return m_config;
3754 }
3755
3756 public: // IMutableContext
3757 virtual void setResultCapture( IResultCapture* resultCapture ) {
3758 m_resultCapture = resultCapture;
3759 }
3760 virtual void setRunner( IRunner* runner ) {
3761 m_runner = runner;
3762 }
3763 virtual void setConfig( const IConfig* config ) {
3764 m_config = config;
3765 }
3766
3767 friend IMutableContext& getCurrentMutableContext();
3768
3769 private:
3770 IGeneratorsForTest* findGeneratorsForCurrentTest() {
3771 std::string testName = getResultCapture().getCurrentTestName();
3772
3773 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
3774 m_generatorsByTestName.find( testName );
3775 return it != m_generatorsByTestName.end()
3776 ? it->second
3777 : NULL;
3778 }
3779
3780 IGeneratorsForTest& getGeneratorsForCurrentTest() {
3781 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
3782 if( !generators ) {
3783 std::string testName = getResultCapture().getCurrentTestName();
3784 generators = createGeneratorsForTest();
3785 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
3786 }
3787 return *generators;
3788 }
3789
3790 private:
3791 IRunner* m_runner;
3792 IResultCapture* m_resultCapture;
3793 const IConfig* m_config;
3794 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
3795 };
3796
3797 namespace {
3798 Context* currentContext = NULL;
3799 }
3800 IMutableContext& getCurrentMutableContext() {
3801 if( !currentContext )
3802 currentContext = new Context();
3803 return *currentContext;
3804 }
3805 IContext& getCurrentContext() {
3806 return getCurrentMutableContext();
3807 }
3808
3809 std::streambuf* createStreamBuf( const std::string& streamName ) {
3810 if( streamName == "stdout" ) return std::cout.rdbuf();
3811 if( streamName == "stderr" ) return std::cerr.rdbuf();
3812 if( streamName == "debug" ) return new StreamBufImpl<OutputDebugWriter>;
3813
3814 throw std::domain_error( "Unknown stream: " + streamName );
3815 }
3816
3817 void cleanUpContext() {
3818 delete currentContext;
3819 currentContext = NULL;
3820 }
3821}
3822// #included from: catch_console_colour_impl.hpp
3823#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
3824
Phil Nash56d5c422012-08-23 20:08:50 +01003825// #included from: catch_console_colour.hpp
3826#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
3827
3828namespace Catch {
3829
3830 struct ConsoleColourImpl;
3831
3832 class TextColour : NonCopyable {
3833 public:
3834
3835 enum Colours {
3836 None,
3837
3838 FileName,
3839 ResultError,
3840 ResultSuccess,
3841
3842 Error,
3843 Success,
3844
3845 OriginalExpression,
3846 ReconstructedExpression
3847 };
3848
3849 TextColour( Colours colour = None );
3850 void set( Colours colour );
3851 ~TextColour();
3852
3853 private:
3854 ConsoleColourImpl* m_impl;
3855 };
3856
3857} // end namespace Catch
3858
Phil Nash3b80af72012-08-09 07:47:30 +01003859#ifdef CATCH_PLATFORM_WINDOWS
3860
3861#include <windows.h>
3862
3863namespace Catch {
3864
3865 namespace {
3866
3867 WORD mapConsoleColour( TextColour::Colours colour ) {
3868 switch( colour ) {
3869 case TextColour::FileName:
3870 return FOREGROUND_INTENSITY; // greyed out
3871 case TextColour::ResultError:
3872 return FOREGROUND_RED | FOREGROUND_INTENSITY; // bright red
3873 case TextColour::ResultSuccess:
3874 return FOREGROUND_GREEN | FOREGROUND_INTENSITY; // bright green
3875 case TextColour::Error:
3876 return FOREGROUND_RED; // dark red
3877 case TextColour::Success:
3878 return FOREGROUND_GREEN; // dark green
3879 case TextColour::OriginalExpression:
3880 return FOREGROUND_BLUE | FOREGROUND_GREEN; // turquoise
3881 case TextColour::ReconstructedExpression:
3882 return FOREGROUND_RED | FOREGROUND_GREEN; // greeny-yellow
3883 default: return 0;
3884 }
3885 }
3886 }
3887
3888 struct ConsoleColourImpl {
3889
3890 ConsoleColourImpl()
3891 : hStdout( GetStdHandle(STD_OUTPUT_HANDLE) ),
3892 wOldColorAttrs( 0 )
3893 {
3894 GetConsoleScreenBufferInfo( hStdout, &csbiInfo );
3895 wOldColorAttrs = csbiInfo.wAttributes;
3896 }
3897
3898 ~ConsoleColourImpl() {
3899 SetConsoleTextAttribute( hStdout, wOldColorAttrs );
3900 }
3901
3902 void set( TextColour::Colours colour ) {
3903 WORD consoleColour = mapConsoleColour( colour );
3904 if( consoleColour > 0 )
3905 SetConsoleTextAttribute( hStdout, consoleColour );
3906 }
3907
3908 HANDLE hStdout;
3909 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
3910 WORD wOldColorAttrs;
3911 };
3912
3913 TextColour::TextColour( Colours colour )
3914 : m_impl( new ConsoleColourImpl() )
3915 {
3916 if( colour )
3917 m_impl->set( colour );
3918 }
3919
3920 TextColour::~TextColour() {
3921 delete m_impl;
3922 }
3923
3924 void TextColour::set( Colours colour ) {
3925 m_impl->set( colour );
3926 }
3927
3928} // end namespace Catch
3929
3930#else
3931
3932namespace Catch {
3933 TextColour::TextColour( Colours ){}
3934 TextColour::~TextColour(){}
3935 void TextColour::set( Colours ){}
3936
3937} // end namespace Catch
3938
3939#endif
3940
3941// #included from: catch_generators_impl.hpp
3942#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
3943
3944#include <vector>
3945#include <string>
3946#include <map>
3947
3948namespace Catch {
3949
3950 struct GeneratorInfo : IGeneratorInfo {
3951
3952 GeneratorInfo( std::size_t size )
3953 : m_size( size ),
3954 m_currentIndex( 0 )
3955 {}
3956
3957 bool moveNext() {
3958 if( ++m_currentIndex == m_size ) {
3959 m_currentIndex = 0;
3960 return false;
3961 }
3962 return true;
3963 }
3964
3965 std::size_t getCurrentIndex() const {
3966 return m_currentIndex;
3967 }
3968
3969 std::size_t m_size;
3970 std::size_t m_currentIndex;
3971 };
3972
3973 ///////////////////////////////////////////////////////////////////////////
3974
3975 class GeneratorsForTest : public IGeneratorsForTest {
3976
3977 public:
3978 ~GeneratorsForTest() {
3979 deleteAll( m_generatorsInOrder );
3980 }
3981
3982 IGeneratorInfo& getGeneratorInfo( const std::string& fileInfo, std::size_t size ) {
3983 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
3984 if( it == m_generatorsByName.end() ) {
3985 IGeneratorInfo* info = new GeneratorInfo( size );
3986 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
3987 m_generatorsInOrder.push_back( info );
3988 return *info;
3989 }
3990 return *it->second;
3991 }
3992
3993 bool moveNext() {
3994 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
3995 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
3996 for(; it != itEnd; ++it ) {
3997 if( (*it)->moveNext() )
3998 return true;
3999 }
4000 return false;
4001 }
4002
4003 private:
4004 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
4005 std::vector<IGeneratorInfo*> m_generatorsInOrder;
4006 };
4007
4008 IGeneratorsForTest* createGeneratorsForTest()
4009 {
4010 return new GeneratorsForTest();
4011 }
4012
4013} // end namespace Catch
4014
4015// #included from: catch_resultinfo.hpp
4016#define TWOBLUECUBES_CATCH_RESULT_INFO_HPP_INCLUDED
4017
4018namespace Catch {
4019
4020 ResultInfo::ResultInfo()
4021 : m_macroName(),
4022 m_expr(),
4023 m_lhs(),
4024 m_rhs(),
4025 m_op(),
4026 m_message(),
4027 m_result( ResultWas::Unknown ),
4028 m_isNot( false )
4029 {}
4030
4031 ResultInfo::ResultInfo(const char* expr,
4032 ResultWas::OfType result,
4033 bool isNot,
4034 const SourceLineInfo& lineInfo,
4035 const char* macroName,
4036 const char* message )
4037 : m_macroName( macroName ),
4038 m_lineInfo( lineInfo ),
4039 m_expr( expr ),
4040 m_lhs(),
4041 m_rhs(),
4042 m_op( isNotExpression( expr ) ? "!" : "" ),
4043 m_message( message ),
4044 m_result( result ),
4045 m_isNot( isNot )
4046 {
4047 if( isNot )
4048 m_expr = "!" + m_expr;
4049 }
4050
4051 ResultInfo::~ResultInfo() {}
4052
4053 bool ResultInfo::ok() const {
4054 return ( m_result & ResultWas::FailureBit ) != ResultWas::FailureBit;
4055 }
4056
4057 ResultWas::OfType ResultInfo::getResultType() const {
4058 return m_result;
4059 }
4060
4061 bool ResultInfo::hasExpression() const {
4062 return !m_expr.empty();
4063 }
4064
4065 bool ResultInfo::hasMessage() const {
4066 return !m_message.empty();
4067 }
4068
4069 std::string ResultInfo::getExpression() const {
4070 return m_expr;
4071 }
4072
4073 bool ResultInfo::hasExpandedExpression() const {
4074 return hasExpression() && getExpandedExpressionInternal() != m_expr;
4075 }
4076
4077 std::string ResultInfo::getExpandedExpression() const {
4078 return hasExpression() ? getExpandedExpressionInternal() : "";
4079 }
4080
4081 std::string ResultInfo::getMessage() const {
4082 return m_message;
4083 }
4084
4085 std::string ResultInfo::getFilename() const {
4086 return m_lineInfo.file;
4087 }
4088
4089 std::size_t ResultInfo::getLine() const {
4090 return m_lineInfo.line;
4091 }
4092
4093 std::string ResultInfo::getTestMacroName() const {
4094 return m_macroName;
4095 }
4096
4097 std::string ResultInfo::getExpandedExpressionInternal() const {
4098 if( m_op == "" || m_isNot )
4099 return m_lhs.empty() ? m_expr : m_op + m_lhs;
4100 else if( m_op == "matches" )
4101 return m_lhs + " " + m_rhs;
4102 else if( m_op != "!" )
4103 {
4104 if( m_lhs.size() + m_rhs.size() < 30 )
4105 return m_lhs + " " + m_op + " " + m_rhs;
4106 else if( m_lhs.size() < 70 && m_rhs.size() < 70 )
4107 return "\n\t" + m_lhs + "\n\t" + m_op + "\n\t" + m_rhs;
4108 else
4109 return "\n" + m_lhs + "\n" + m_op + "\n" + m_rhs + "\n\n";
4110 }
4111 else
4112 return "{can't expand - use " + m_macroName + "_FALSE( " + m_expr.substr(1) + " ) instead of " + m_macroName + "( " + m_expr + " ) for better diagnostics}";
4113 }
4114
4115 bool ResultInfo::isNotExpression( const char* expr ) {
4116 return expr && expr[0] == '!';
4117 }
4118
4119} // end namespace Catch
4120
4121// #included from: catch_resultinfo_builder.hpp
4122#define TWOBLUECUBES_CATCH_RESULTINFO_BUILDER_HPP_INCLUDED
4123
4124namespace Catch {
4125
4126 ResultInfoBuilder::ResultInfoBuilder() {}
4127
4128 ResultInfoBuilder::ResultInfoBuilder( const char* expr,
4129 bool isNot,
4130 const SourceLineInfo& lineInfo,
4131 const char* macroName,
4132 const char* message )
4133 : ResultInfo( expr, ResultWas::Unknown, isNot, lineInfo, macroName, message )
4134 {}
4135
4136 void ResultInfoBuilder::setResultType( ResultWas::OfType result ) {
4137 // Flip bool results if isNot is set
4138 if( m_isNot && result == ResultWas::Ok )
4139 m_result = ResultWas::ExpressionFailed;
4140 else if( m_isNot && result == ResultWas::ExpressionFailed )
4141 m_result = ResultWas::Ok;
4142 else
4143 m_result = result;
4144 }
4145
4146 void ResultInfoBuilder::setMessage( const std::string& message ) {
4147 m_message = message;
4148 }
4149
4150 void ResultInfoBuilder::setLineInfo( const SourceLineInfo& lineInfo ) {
4151 m_lineInfo = lineInfo;
4152 }
4153
4154 void ResultInfoBuilder::setLhs( const std::string& lhs ) {
4155 m_lhs = lhs;
4156 }
4157
4158 void ResultInfoBuilder::setRhs( const std::string& rhs ) {
4159 m_rhs = rhs;
4160 }
4161
4162 void ResultInfoBuilder::setOp( const std::string& op ) {
4163 m_op = op;
4164 }
4165
4166 ResultInfoBuilder& ResultInfoBuilder::captureBoolExpression( bool result ) {
4167 m_lhs = Catch::toString( result );
4168 m_op = m_isNot ? "!" : "";
4169 setResultType( result ? ResultWas::Ok : ResultWas::ExpressionFailed );
4170 return *this;
4171 }
4172
4173} // end namespace Catch
4174
Phil Nash5bc030d2012-08-16 18:48:50 +01004175// #included from: catch_test_case_info.hpp
4176#define TWOBLUECUBES_CATCH_TESTCASEINFO_HPP_INCLUDED
4177
4178namespace Catch {
4179
4180 TestCaseInfo::TestCaseInfo( ITestCase* testCase,
4181 const char* name,
4182 const char* description,
4183 const SourceLineInfo& lineInfo )
4184 : m_test( testCase ),
4185 m_name( name ),
4186 m_description( description ),
4187 m_lineInfo( lineInfo )
4188 {}
4189
4190 TestCaseInfo::TestCaseInfo()
4191 : m_test( NULL ),
4192 m_name(),
4193 m_description()
4194 {}
4195
4196 TestCaseInfo::TestCaseInfo( const TestCaseInfo& other, const std::string& name )
4197 : m_test( other.m_test ),
4198 m_name( name ),
4199 m_description( other.m_description ),
4200 m_lineInfo( other.m_lineInfo )
4201 {}
4202
Phil Nashd2ec8492012-08-23 19:48:57 +01004203 TestCaseInfo::TestCaseInfo( const TestCaseInfo& other )
4204 : m_test( other.m_test ),
4205 m_name( other.m_name ),
4206 m_description( other.m_description ),
4207 m_lineInfo( other.m_lineInfo )
4208 {}
4209
Phil Nash5bc030d2012-08-16 18:48:50 +01004210 void TestCaseInfo::invoke() const {
4211 m_test->invoke();
4212 }
4213
4214 const std::string& TestCaseInfo::getName() const {
4215 return m_name;
4216 }
4217
4218 const std::string& TestCaseInfo::getDescription() const {
4219 return m_description;
4220 }
4221
4222 const SourceLineInfo& TestCaseInfo::getLineInfo() const {
4223 return m_lineInfo;
4224 }
4225
4226 bool TestCaseInfo::isHidden() const {
4227 return m_name.size() >= 2 && m_name[0] == '.' && m_name[1] == '/';
4228 }
4229
4230 void TestCaseInfo::swap( TestCaseInfo& other ) {
4231 m_test.swap( other.m_test );
4232 m_name.swap( other.m_name );
4233 m_description.swap( other.m_description );
4234 m_lineInfo.swap( other.m_lineInfo );
4235 }
4236
4237 bool TestCaseInfo::operator == ( const TestCaseInfo& other ) const {
4238 return m_test.get() == other.m_test.get() && m_name == other.m_name;
4239 }
4240
4241 bool TestCaseInfo::operator < ( const TestCaseInfo& other ) const {
4242 return m_name < other.m_name;
4243 }
Phil Nashd2ec8492012-08-23 19:48:57 +01004244 TestCaseInfo& TestCaseInfo::operator = ( const TestCaseInfo& other ) {
4245 TestCaseInfo temp( other );
4246 swap( temp );
4247 return *this;
4248 }
Phil Nash5bc030d2012-08-16 18:48:50 +01004249}
4250
Phil Nash56d5c422012-08-23 20:08:50 +01004251// #included from: ../reporters/catch_reporter_basic.hpp
4252#define TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
4253
4254// #included from: ../internal/catch_reporter_registrars.hpp
4255#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
4256
4257namespace Catch {
4258
4259 template<typename T>
4260 class ReporterRegistrar {
4261
4262 class ReporterFactory : public IReporterFactory {
4263
4264 virtual IReporter* create( const ReporterConfig& config ) const {
4265 return new T( config );
4266 }
4267
4268 virtual std::string getDescription() const {
4269 return T::getDescription();
4270 }
4271 };
4272
4273 public:
4274
4275 ReporterRegistrar( const std::string& name ) {
4276 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
4277 }
4278 };
4279}
4280
4281#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
4282 Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name );
4283
4284namespace Catch {
4285
Phil Nash56d5c422012-08-23 20:08:50 +01004286 class BasicReporter : public SharedImpl<IReporter> {
4287
4288 struct SpanInfo {
4289
4290 SpanInfo()
4291 : emitted( false )
4292 {}
4293
4294 SpanInfo( const std::string& spanName )
4295 : name( spanName ),
4296 emitted( false )
4297 {}
4298
4299 SpanInfo( const SpanInfo& other )
4300 : name( other.name ),
4301 emitted( other.emitted )
4302 {}
4303
4304 std::string name;
4305 bool emitted;
4306 };
4307
4308 public:
4309 BasicReporter( const ReporterConfig& config )
4310 : m_config( config ),
4311 m_firstSectionInTestCase( true ),
4312 m_aborted( false )
4313 {}
4314
4315 virtual ~BasicReporter();
4316
4317 static std::string getDescription() {
4318 return "Reports test results as lines of text";
4319 }
4320
4321 private:
4322
4323 void ReportCounts( const std::string& label, const Counts& counts, const std::string& allPrefix = "All " ) {
4324 if( counts.passed )
4325 m_config.stream << counts.failed << " of " << counts.total() << " " << label << "s failed";
4326 else
4327 m_config.stream << ( counts.failed > 1 ? allPrefix : "" ) << pluralise( counts.failed, label ) << " failed";
4328 }
4329
4330 void ReportCounts( const Totals& totals, const std::string& allPrefix = "All " ) {
4331 if( totals.assertions.total() == 0 ) {
4332 m_config.stream << "No tests ran";
4333 }
4334 else if( totals.assertions.failed ) {
4335 TextColour colour( TextColour::ResultError );
4336 ReportCounts( "test case", totals.testCases, allPrefix );
4337 if( totals.testCases.failed > 0 ) {
4338 m_config.stream << " (";
4339 ReportCounts( "assertion", totals.assertions, allPrefix );
4340 m_config.stream << ")";
4341 }
4342 }
4343 else {
4344 TextColour colour( TextColour::ResultSuccess );
4345 m_config.stream << allPrefix << "tests passed ("
4346 << pluralise( totals.assertions.passed, "assertion" ) << " in "
4347 << pluralise( totals.testCases.passed, "test case" ) << ")";
4348 }
4349 }
4350
4351 private: // IReporter
4352
4353 virtual bool shouldRedirectStdout() const {
4354 return false;
4355 }
4356
4357 virtual void StartTesting() {
4358 m_testingSpan = SpanInfo();
4359 }
4360
4361 virtual void Aborted() {
4362 m_aborted = true;
4363 }
4364
4365 virtual void EndTesting( const Totals& totals ) {
4366 // Output the overall test results even if "Started Testing" was not emitted
4367 if( m_aborted ) {
4368 m_config.stream << "\n[Testing aborted. ";
4369 ReportCounts( totals, "The first " );
4370 }
4371 else {
4372 m_config.stream << "\n[Testing completed. ";
4373 ReportCounts( totals );
4374 }
4375 m_config.stream << "]\n" << std::endl;
4376 }
4377
4378 virtual void StartGroup( const std::string& groupName ) {
4379 m_groupSpan = groupName;
4380 }
4381
4382 virtual void EndGroup( const std::string& groupName, const Totals& totals ) {
4383 if( m_groupSpan.emitted && !groupName.empty() ) {
4384 m_config.stream << "[End of group: '" << groupName << "'. ";
4385 ReportCounts( totals );
4386 m_config.stream << "]\n" << std::endl;
4387 m_groupSpan = SpanInfo();
4388 }
4389 }
4390
4391 virtual void StartTestCase( const TestCaseInfo& testInfo ) {
4392 m_testSpan = testInfo.getName();
4393 }
4394
4395 virtual void StartSection( const std::string& sectionName, const std::string& ) {
4396 m_sectionSpans.push_back( SpanInfo( sectionName ) );
4397 }
4398
4399 virtual void EndSection( const std::string& sectionName, const Counts& assertions ) {
4400 SpanInfo& sectionSpan = m_sectionSpans.back();
4401 if( sectionSpan.emitted && !sectionSpan.name.empty() ) {
4402 m_config.stream << "[End of section: '" << sectionName << "' ";
4403
4404 if( assertions.failed ) {
4405 TextColour colour( TextColour::ResultError );
4406 ReportCounts( "assertion", assertions);
4407 }
4408 else {
4409 TextColour colour( TextColour::ResultSuccess );
4410 m_config.stream << ( assertions.passed > 1 ? "All " : "" )
4411 << pluralise( assertions.passed, "assertion" ) << " passed" ;
4412 }
4413 m_config.stream << "]\n" << std::endl;
4414 }
4415 m_sectionSpans.pop_back();
4416 }
4417
4418 virtual void Result( const ResultInfo& resultInfo ) {
4419 if( !m_config.includeSuccessfulResults && resultInfo.getResultType() == ResultWas::Ok )
4420 return;
4421
4422 StartSpansLazily();
4423
4424 if( !resultInfo.getFilename().empty() ) {
4425 TextColour colour( TextColour::FileName );
4426 m_config.stream << SourceLineInfo( resultInfo.getFilename(), resultInfo.getLine() );
4427 }
4428
4429 if( resultInfo.hasExpression() ) {
4430 TextColour colour( TextColour::OriginalExpression );
4431 m_config.stream << resultInfo.getExpression();
4432 if( resultInfo.ok() ) {
4433 TextColour successColour( TextColour::Success );
4434 m_config.stream << " succeeded";
4435 }
4436 else {
4437 TextColour errorColour( TextColour::Error );
4438 m_config.stream << " failed";
4439 }
4440 }
4441 switch( resultInfo.getResultType() ) {
4442 case ResultWas::ThrewException:
4443 {
4444 TextColour colour( TextColour::Error );
4445 if( resultInfo.hasExpression() )
4446 m_config.stream << " with unexpected";
4447 else
4448 m_config.stream << "Unexpected";
4449 m_config.stream << " exception with message: '" << resultInfo.getMessage() << "'";
4450 }
4451 break;
4452 case ResultWas::DidntThrowException:
4453 {
4454 TextColour colour( TextColour::Error );
4455 if( resultInfo.hasExpression() )
4456 m_config.stream << " because no exception was thrown where one was expected";
4457 else
4458 m_config.stream << "No exception thrown where one was expected";
4459 }
4460 break;
4461 case ResultWas::Info:
4462 streamVariableLengthText( "info", resultInfo.getMessage() );
4463 break;
4464 case ResultWas::Warning:
4465 m_config.stream << "warning:\n'" << resultInfo.getMessage() << "'";
4466 break;
4467 case ResultWas::ExplicitFailure:
4468 {
4469 TextColour colour( TextColour::Error );
4470 m_config.stream << "failed with message: '" << resultInfo.getMessage() << "'";
4471 }
4472 break;
4473 case ResultWas::Unknown: // These cases are here to prevent compiler warnings
4474 case ResultWas::Ok:
4475 case ResultWas::FailureBit:
4476 case ResultWas::ExpressionFailed:
4477 case ResultWas::Exception:
4478 if( !resultInfo.hasExpression() ) {
4479 if( resultInfo.ok() ) {
4480 TextColour colour( TextColour::Success );
4481 m_config.stream << " succeeded";
4482 }
4483 else {
4484 TextColour colour( TextColour::Error );
4485 m_config.stream << " failed";
4486 }
4487 }
4488 break;
4489 }
4490
4491 if( resultInfo.hasExpandedExpression() ) {
4492 m_config.stream << " for: ";
4493 TextColour colour( TextColour::ReconstructedExpression );
4494 m_config.stream << resultInfo.getExpandedExpression();
4495 }
4496 m_config.stream << std::endl;
4497 }
4498
4499 virtual void EndTestCase( const TestCaseInfo& testInfo,
4500 const Totals& totals,
4501 const std::string& stdOut,
4502 const std::string& stdErr ) {
4503 if( !stdOut.empty() ) {
4504 StartSpansLazily();
4505 streamVariableLengthText( "stdout", stdOut );
4506 }
4507
4508 if( !stdErr.empty() ) {
4509 StartSpansLazily();
4510 streamVariableLengthText( "stderr", stdErr );
4511 }
4512
4513 if( m_testSpan.emitted ) {
4514 m_config.stream << "[Finished: '" << testInfo.getName() << "' ";
4515 ReportCounts( totals );
4516 m_config.stream << "]" << std::endl;
4517 }
4518 }
4519
4520 private: // helpers
4521
4522 void StartSpansLazily() {
4523 if( !m_testingSpan.emitted ) {
4524 if( m_config.name.empty() )
4525 m_config.stream << "[Started testing]" << std::endl;
4526 else
4527 m_config.stream << "[Started testing: " << m_config.name << "]" << std::endl;
4528 m_testingSpan.emitted = true;
4529 }
4530
4531 if( !m_groupSpan.emitted && !m_groupSpan.name.empty() ) {
4532 m_config.stream << "[Started group: '" << m_groupSpan.name << "']" << std::endl;
4533 m_groupSpan.emitted = true;
4534 }
4535
4536 if( !m_testSpan.emitted ) {
4537 m_config.stream << std::endl << "[Running: " << m_testSpan.name << "]" << std::endl;
4538 m_testSpan.emitted = true;
4539 }
4540
4541 if( !m_sectionSpans.empty() ) {
4542 SpanInfo& sectionSpan = m_sectionSpans.back();
4543 if( !sectionSpan.emitted && !sectionSpan.name.empty() ) {
4544 if( m_firstSectionInTestCase ) {
4545 m_config.stream << "\n";
4546 m_firstSectionInTestCase = false;
4547 }
4548 std::vector<SpanInfo>::iterator it = m_sectionSpans.begin();
4549 std::vector<SpanInfo>::iterator itEnd = m_sectionSpans.end();
4550 for(; it != itEnd; ++it ) {
4551 SpanInfo& prevSpan = *it;
4552 if( !prevSpan.emitted && !prevSpan.name.empty() ) {
4553 m_config.stream << "[Started section: '" << prevSpan.name << "']" << std::endl;
4554 prevSpan.emitted = true;
4555 }
4556 }
4557 }
4558 }
4559 }
4560
4561 void streamVariableLengthText( const std::string& prefix, const std::string& text ) {
4562 std::string trimmed = trim( text );
4563 if( trimmed.find_first_of( "\r\n" ) == std::string::npos ) {
4564 m_config.stream << "[" << prefix << ": " << trimmed << "]\n";
4565 }
4566 else {
4567 m_config.stream << "\n[" << prefix << "] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" << trimmed
4568 << "\n[end of " << prefix << "] <<<<<<<<<<<<<<<<<<<<<<<<\n";
4569 }
4570 }
4571
4572 private:
4573 ReporterConfig m_config;
4574 bool m_firstSectionInTestCase;
4575
4576 SpanInfo m_testingSpan;
4577 SpanInfo m_groupSpan;
4578 SpanInfo m_testSpan;
4579 std::vector<SpanInfo> m_sectionSpans;
4580 bool m_aborted;
4581 };
4582
4583} // end namespace Catch
4584
4585// #included from: ../reporters/catch_reporter_xml.hpp
4586#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
4587
4588// #included from: ../internal/catch_xmlwriter.hpp
4589#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
4590
4591#include <sstream>
4592#include <string>
4593#include <vector>
4594
4595namespace Catch {
4596
4597 class XmlWriter {
4598 public:
4599
4600 class ScopedElement {
4601 public:
4602 ScopedElement( XmlWriter* writer )
4603 : m_writer( writer )
4604 {}
4605
4606 ScopedElement( const ScopedElement& other )
4607 : m_writer( other.m_writer ){
4608 other.m_writer = NULL;
4609 }
4610
4611 ~ScopedElement() {
4612 if( m_writer )
4613 m_writer->endElement();
4614 }
4615
4616 ScopedElement& writeText( const std::string& text ) {
4617 m_writer->writeText( text );
4618 return *this;
4619 }
4620
4621 template<typename T>
4622 ScopedElement& writeAttribute( const std::string& name, const T& attribute ) {
4623 m_writer->writeAttribute( name, attribute );
4624 return *this;
4625 }
4626
4627 private:
4628 mutable XmlWriter* m_writer;
4629 };
4630
4631 XmlWriter()
4632 : m_tagIsOpen( false ),
4633 m_needsNewline( false ),
4634 m_os( &std::cout )
4635 {}
4636
4637 XmlWriter( std::ostream& os )
4638 : m_tagIsOpen( false ),
4639 m_needsNewline( false ),
4640 m_os( &os )
4641 {}
4642
4643 ~XmlWriter() {
4644 while( !m_tags.empty() )
4645 endElement();
4646 }
4647
4648 XmlWriter& operator = ( const XmlWriter& other ) {
4649 XmlWriter temp( other );
4650 swap( temp );
4651 return *this;
4652 }
4653
4654 void swap( XmlWriter& other ) {
4655 std::swap( m_tagIsOpen, other.m_tagIsOpen );
4656 std::swap( m_needsNewline, other.m_needsNewline );
4657 std::swap( m_tags, other.m_tags );
4658 std::swap( m_indent, other.m_indent );
4659 std::swap( m_os, other.m_os );
4660 }
4661
4662 XmlWriter& startElement( const std::string& name ) {
4663 ensureTagClosed();
4664 newlineIfNecessary();
4665 stream() << m_indent << "<" << name;
4666 m_tags.push_back( name );
4667 m_indent += " ";
4668 m_tagIsOpen = true;
4669 return *this;
4670 }
4671
4672 ScopedElement scopedElement( const std::string& name ) {
4673 ScopedElement scoped( this );
4674 startElement( name );
4675 return scoped;
4676 }
4677
4678 XmlWriter& endElement() {
4679 newlineIfNecessary();
4680 m_indent = m_indent.substr( 0, m_indent.size()-2 );
4681 if( m_tagIsOpen ) {
4682 stream() << "/>\n";
4683 m_tagIsOpen = false;
4684 }
4685 else {
4686 stream() << m_indent << "</" << m_tags.back() << ">\n";
4687 }
4688 m_tags.pop_back();
4689 return *this;
4690 }
4691
4692 XmlWriter& writeAttribute( const std::string& name, const std::string& attribute ) {
4693 if( !name.empty() && !attribute.empty() ) {
4694 stream() << " " << name << "=\"";
4695 writeEncodedText( attribute );
4696 stream() << "\"";
4697 }
4698 return *this;
4699 }
4700
4701 XmlWriter& writeAttribute( const std::string& name, bool attribute ) {
4702 stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
4703 return *this;
4704 }
4705
4706 template<typename T>
4707 XmlWriter& writeAttribute( const std::string& name, const T& attribute ) {
4708 if( !name.empty() )
4709 stream() << " " << name << "=\"" << attribute << "\"";
4710 return *this;
4711 }
4712
4713 XmlWriter& writeText( const std::string& text ) {
4714 if( !text.empty() ){
4715 bool tagWasOpen = m_tagIsOpen;
4716 ensureTagClosed();
4717 if( tagWasOpen )
4718 stream() << m_indent;
4719 writeEncodedText( text );
4720 m_needsNewline = true;
4721 }
4722 return *this;
4723 }
4724
4725 XmlWriter& writeComment( const std::string& text ) {
4726 ensureTagClosed();
4727 stream() << m_indent << "<!--" << text << "-->";
4728 m_needsNewline = true;
4729 return *this;
4730 }
4731
4732 XmlWriter& writeBlankLine() {
4733 ensureTagClosed();
4734 stream() << "\n";
4735 return *this;
4736 }
4737
4738 private:
4739
4740 std::ostream& stream() {
4741 return *m_os;
4742 }
4743
4744 void ensureTagClosed() {
4745 if( m_tagIsOpen ) {
4746 stream() << ">\n";
4747 m_tagIsOpen = false;
4748 }
4749 }
4750
4751 void newlineIfNecessary() {
4752 if( m_needsNewline ) {
4753 stream() << "\n";
4754 m_needsNewline = false;
4755 }
4756 }
4757
4758 void writeEncodedText( const std::string& text ) {
4759 static const char* charsToEncode = "<&\"";
4760 std::string mtext = text;
4761 std::string::size_type pos = mtext.find_first_of( charsToEncode );
4762 while( pos != std::string::npos ) {
4763 stream() << mtext.substr( 0, pos );
4764
4765 switch( mtext[pos] ) {
4766 case '<':
4767 stream() << "&lt;";
4768 break;
4769 case '&':
4770 stream() << "&amp;";
4771 break;
4772 case '\"':
4773 stream() << "&quot;";
4774 break;
4775 }
4776 mtext = mtext.substr( pos+1 );
4777 pos = mtext.find_first_of( charsToEncode );
4778 }
4779 stream() << mtext;
4780 }
4781
4782 bool m_tagIsOpen;
4783 bool m_needsNewline;
4784 std::vector<std::string> m_tags;
4785 std::string m_indent;
4786 std::ostream* m_os;
4787 };
4788
4789}
4790namespace Catch {
4791 class XmlReporter : public SharedImpl<IReporter> {
4792 public:
4793 XmlReporter( const ReporterConfig& config ) : m_config( config ) {}
4794
4795 static std::string getDescription() {
4796 return "Reports test results as an XML document";
4797 }
4798 virtual ~XmlReporter();
4799
4800 private: // IReporter
4801
4802 virtual bool shouldRedirectStdout() const {
4803 return true;
4804 }
4805
4806 virtual void StartTesting() {
4807 m_xml = XmlWriter( m_config.stream );
4808 m_xml.startElement( "Catch" );
4809 if( !m_config.name.empty() )
4810 m_xml.writeAttribute( "name", m_config.name );
4811 }
4812
4813 virtual void EndTesting( const Totals& totals ) {
4814 m_xml.scopedElement( "OverallResults" )
4815 .writeAttribute( "successes", totals.assertions.passed )
4816 .writeAttribute( "failures", totals.assertions.failed );
4817 m_xml.endElement();
4818 }
4819
4820 virtual void StartGroup( const std::string& groupName ) {
4821 m_xml.startElement( "Group" )
4822 .writeAttribute( "name", groupName );
4823 }
4824
4825 virtual void EndGroup( const std::string&, const Totals& totals ) {
4826 m_xml.scopedElement( "OverallResults" )
4827 .writeAttribute( "successes", totals.assertions.passed )
4828 .writeAttribute( "failures", totals.assertions.failed );
4829 m_xml.endElement();
4830 }
4831
4832 virtual void StartSection( const std::string& sectionName, const std::string& description ) {
4833 m_xml.startElement( "Section" )
4834 .writeAttribute( "name", sectionName )
4835 .writeAttribute( "description", description );
4836 }
4837
4838 virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) {
4839 m_xml.scopedElement( "OverallResults" )
4840 .writeAttribute( "successes", assertions.passed )
4841 .writeAttribute( "failures", assertions.failed );
4842 m_xml.endElement();
4843 }
4844
4845 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) {
4846 m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.getName() );
4847 m_currentTestSuccess = true;
4848 }
4849
4850 virtual void Result( const Catch::ResultInfo& resultInfo ) {
4851 if( !m_config.includeSuccessfulResults && resultInfo.getResultType() == ResultWas::Ok )
4852 return;
4853
4854 if( resultInfo.hasExpression() ) {
4855 m_xml.startElement( "Expression" )
4856 .writeAttribute( "success", resultInfo.ok() )
4857 .writeAttribute( "filename", resultInfo.getFilename() )
4858 .writeAttribute( "line", resultInfo.getLine() );
4859
4860 m_xml.scopedElement( "Original" )
4861 .writeText( resultInfo.getExpression() );
4862 m_xml.scopedElement( "Expanded" )
4863 .writeText( resultInfo.getExpandedExpression() );
4864 m_currentTestSuccess &= resultInfo.ok();
4865 }
4866
4867 switch( resultInfo.getResultType() ) {
4868 case ResultWas::ThrewException:
4869 m_xml.scopedElement( "Exception" )
4870 .writeAttribute( "filename", resultInfo.getFilename() )
4871 .writeAttribute( "line", resultInfo.getLine() )
4872 .writeText( resultInfo.getMessage() );
4873 m_currentTestSuccess = false;
4874 break;
4875 case ResultWas::Info:
4876 m_xml.scopedElement( "Info" )
4877 .writeText( resultInfo.getMessage() );
4878 break;
4879 case ResultWas::Warning:
4880 m_xml.scopedElement( "Warning" )
4881 .writeText( resultInfo.getMessage() );
4882 break;
4883 case ResultWas::ExplicitFailure:
4884 m_xml.scopedElement( "Failure" )
4885 .writeText( resultInfo.getMessage() );
4886 m_currentTestSuccess = false;
4887 break;
4888 case ResultWas::Unknown:
4889 case ResultWas::Ok:
4890 case ResultWas::FailureBit:
4891 case ResultWas::ExpressionFailed:
4892 case ResultWas::Exception:
4893 case ResultWas::DidntThrowException:
4894 break;
4895 }
4896 if( resultInfo.hasExpression() )
4897 m_xml.endElement();
4898 }
4899
4900 virtual void Aborted() {
4901 // !TBD
4902 }
4903
4904 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) {
4905 m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess );
4906 m_xml.endElement();
4907 }
4908
4909 private:
4910 ReporterConfig m_config;
4911 bool m_currentTestSuccess;
4912 XmlWriter m_xml;
4913 };
4914
4915} // end namespace Catch
4916
4917// #included from: ../reporters/catch_reporter_junit.hpp
4918#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
4919
4920namespace Catch {
4921
4922 class JunitReporter : public SharedImpl<IReporter> {
4923
4924 struct TestStats {
4925 std::string m_element;
4926 std::string m_resultType;
4927 std::string m_message;
4928 std::string m_content;
4929 };
4930
4931 struct TestCaseStats {
4932
4933 TestCaseStats( const std::string& name = std::string() ) :m_name( name ){}
4934
4935 double m_timeInSeconds;
4936 std::string m_status;
4937 std::string m_className;
4938 std::string m_name;
4939 std::vector<TestStats> m_testStats;
4940 };
4941
4942 struct Stats {
4943
4944 Stats( const std::string& name = std::string() )
4945 : m_testsCount( 0 ),
4946 m_failuresCount( 0 ),
4947 m_disabledCount( 0 ),
4948 m_errorsCount( 0 ),
4949 m_timeInSeconds( 0 ),
4950 m_name( name )
4951 {}
4952
4953 std::size_t m_testsCount;
4954 std::size_t m_failuresCount;
4955 std::size_t m_disabledCount;
4956 std::size_t m_errorsCount;
4957 double m_timeInSeconds;
4958 std::string m_name;
4959
4960 std::vector<TestCaseStats> m_testCaseStats;
4961 };
4962
4963 public:
4964 JunitReporter( const ReporterConfig& config )
4965 : m_config( config ),
4966 m_testSuiteStats( "AllTests" ),
4967 m_currentStats( &m_testSuiteStats )
4968 {}
4969 virtual ~JunitReporter();
4970
4971 static std::string getDescription() {
4972 return "Reports test results in an XML format that looks like Ant's junitreport target";
4973 }
4974
4975 private: // IReporter
4976
4977 virtual bool shouldRedirectStdout() const {
4978 return true;
4979 }
4980
4981 virtual void StartTesting(){}
4982
4983 virtual void StartGroup( const std::string& groupName ) {
4984 m_statsForSuites.push_back( Stats( groupName ) );
4985 m_currentStats = &m_statsForSuites.back();
4986 }
4987
4988 virtual void EndGroup( const std::string&, const Totals& totals ) {
4989 m_currentStats->m_testsCount = totals.assertions.total();
4990 m_currentStats = &m_testSuiteStats;
4991 }
4992
4993 virtual void StartSection( const std::string&, const std::string& ){}
4994
4995 virtual void EndSection( const std::string&, const Counts& ){}
4996
4997 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) {
4998 m_currentStats->m_testCaseStats.push_back( TestCaseStats( testInfo.getName() ) );
4999 }
5000
5001 virtual void Result( const Catch::ResultInfo& resultInfo ) {
5002 if( resultInfo.getResultType() != ResultWas::Ok || m_config.includeSuccessfulResults ) {
5003 TestCaseStats& testCaseStats = m_currentStats->m_testCaseStats.back();
5004 TestStats stats;
5005 std::ostringstream oss;
5006 if( !resultInfo.getMessage().empty() )
5007 oss << resultInfo.getMessage() << " at ";
5008 oss << SourceLineInfo( resultInfo.getFilename(), resultInfo.getLine() );
5009 stats.m_content = oss.str();
5010 stats.m_message = resultInfo.getExpandedExpression();
5011 stats.m_resultType = resultInfo.getTestMacroName();
5012
5013 switch( resultInfo.getResultType() ) {
5014 case ResultWas::ThrewException:
5015 stats.m_element = "error";
5016 m_currentStats->m_errorsCount++;
5017 break;
5018 case ResultWas::Info:
5019 stats.m_element = "info"; // !TBD ?
5020 break;
5021 case ResultWas::Warning:
5022 stats.m_element = "warning"; // !TBD ?
5023 break;
5024 case ResultWas::ExplicitFailure:
5025 stats.m_element = "failure";
5026 m_currentStats->m_failuresCount++;
5027 break;
5028 case ResultWas::ExpressionFailed:
5029 stats.m_element = "failure";
5030 m_currentStats->m_failuresCount++;
5031 break;
5032 case ResultWas::Ok:
5033 stats.m_element = "success";
5034 break;
5035 case ResultWas::Unknown:
5036 case ResultWas::FailureBit:
5037 case ResultWas::Exception:
5038 case ResultWas::DidntThrowException:
5039 break;
5040 }
5041 testCaseStats.m_testStats.push_back( stats );
5042 }
5043 }
5044
5045 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string& stdOut, const std::string& stdErr ) {
5046 if( !stdOut.empty() )
5047 m_stdOut << stdOut << "\n";
5048 if( !stdErr.empty() )
5049 m_stdErr << stdErr << "\n";
5050 }
5051
5052 virtual void Aborted() {
5053 // !TBD
5054 }
5055
5056 virtual void EndTesting( const Totals& ) {
5057 std::ostream& str = m_config.stream;
5058 {
5059 XmlWriter xml( str );
5060
5061 if( m_statsForSuites.size() > 0 )
5062 xml.startElement( "testsuites" );
5063
5064 std::vector<Stats>::const_iterator it = m_statsForSuites.begin();
5065 std::vector<Stats>::const_iterator itEnd = m_statsForSuites.end();
5066
5067 for(; it != itEnd; ++it ) {
5068 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
5069 xml.writeAttribute( "name", it->m_name );
5070 xml.writeAttribute( "errors", it->m_errorsCount );
5071 xml.writeAttribute( "failures", it->m_failuresCount );
5072 xml.writeAttribute( "tests", it->m_testsCount );
5073 xml.writeAttribute( "hostname", "tbd" );
5074 xml.writeAttribute( "time", "tbd" );
5075 xml.writeAttribute( "timestamp", "tbd" );
5076
5077 OutputTestCases( xml, *it );
5078 }
5079
5080 xml.scopedElement( "system-out" ).writeText( trim( m_stdOut.str() ) );
5081 xml.scopedElement( "system-err" ).writeText( trim( m_stdErr.str() ) );
5082 }
5083 }
5084
5085 void OutputTestCases( XmlWriter& xml, const Stats& stats ) {
5086 std::vector<TestCaseStats>::const_iterator it = stats.m_testCaseStats.begin();
5087 std::vector<TestCaseStats>::const_iterator itEnd = stats.m_testCaseStats.end();
5088 for(; it != itEnd; ++it ) {
5089 xml.writeBlankLine();
5090 xml.writeComment( "Test case" );
5091
5092 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
5093 xml.writeAttribute( "classname", it->m_className );
5094 xml.writeAttribute( "name", it->m_name );
5095 xml.writeAttribute( "time", "tbd" );
5096
5097 OutputTestResult( xml, *it );
5098 }
5099 }
5100
5101 void OutputTestResult( XmlWriter& xml, const TestCaseStats& stats ) {
5102 std::vector<TestStats>::const_iterator it = stats.m_testStats.begin();
5103 std::vector<TestStats>::const_iterator itEnd = stats.m_testStats.end();
5104 for(; it != itEnd; ++it ) {
5105 if( it->m_element != "success" ) {
5106 XmlWriter::ScopedElement e = xml.scopedElement( it->m_element );
5107
5108 xml.writeAttribute( "message", it->m_message );
5109 xml.writeAttribute( "type", it->m_resultType );
5110 if( !it->m_content.empty() )
5111 xml.writeText( it->m_content );
5112 }
5113 }
5114 }
5115
5116 private:
5117 ReporterConfig m_config;
5118 bool m_currentTestSuccess;
5119
5120 Stats m_testSuiteStats;
5121 Stats* m_currentStats;
5122 std::vector<Stats> m_statsForSuites;
5123 std::ostringstream m_stdOut;
5124 std::ostringstream m_stdErr;
5125 };
5126
5127} // end namespace Catch
5128
Phil Nasha695eb92012-08-13 07:46:10 +01005129namespace Catch {
5130 NonCopyable::~NonCopyable() {}
5131 IShared::~IShared() {}
5132 StreamBufBase::~StreamBufBase() {}
5133 IContext::~IContext() {}
5134 IResultCapture::~IResultCapture() {}
5135 ITestCase::~ITestCase() {}
5136 ITestCaseRegistry::~ITestCaseRegistry() {}
5137 IRegistryHub::~IRegistryHub() {}
5138 IMutableRegistryHub::~IMutableRegistryHub() {}
5139 IExceptionTranslator::~IExceptionTranslator() {}
5140 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
5141 IReporter::~IReporter() {}
5142 IReporterFactory::~IReporterFactory() {}
5143 IReporterRegistry::~IReporterRegistry() {}
5144 BasicReporter::~BasicReporter() {}
5145 IRunner::~IRunner() {}
5146 IMutableContext::~IMutableContext() {}
5147 IConfig::~IConfig() {}
5148 XmlReporter::~XmlReporter() {}
5149 JunitReporter::~JunitReporter() {}
5150 TestRegistry::~TestRegistry() {}
5151 FreeFunctionTestCase::~FreeFunctionTestCase() {}
5152 IGeneratorInfo::~IGeneratorInfo() {}
5153 IGeneratorsForTest::~IGeneratorsForTest() {}
5154
5155 void Config::dummy() {}
5156
Phil Nash56d5c422012-08-23 20:08:50 +01005157 INTERNAL_CATCH_REGISTER_REPORTER( "basic", BasicReporter )
5158 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
5159 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
5160
Phil Nasha695eb92012-08-13 07:46:10 +01005161}
5162
Phil Nash5bc030d2012-08-16 18:48:50 +01005163#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01005164#pragma clang diagnostic pop
Phil Nash89d1e6c2011-05-24 08:23:02 +01005165#endif
Phil Nash5bc030d2012-08-16 18:48:50 +01005166#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01005167
5168#ifdef CATCH_CONFIG_MAIN
5169// #included from: internal/catch_default_main.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01005170#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01005171
Phil Nash176eb812012-05-11 08:17:16 +01005172#ifndef __OBJC__
Phil Nash89d1e6c2011-05-24 08:23:02 +01005173
Phil Nash176eb812012-05-11 08:17:16 +01005174// Standard C/C++ main entry point
5175int main (int argc, char * const argv[]) {
5176 return Catch::Main( argc, argv );
5177}
5178
5179#else // __OBJC__
5180
5181// Objective-C entry point
5182int main (int argc, char * const argv[]) {
Phil Nash53c990a2012-03-17 18:20:06 +00005183#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +01005184 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Phil Nash53c990a2012-03-17 18:20:06 +00005185#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01005186
5187 Catch::registerTestMethods();
Phil Nash89d1e6c2011-05-24 08:23:02 +01005188 int result = Catch::Main( argc, (char* const*)argv );
5189
Phil Nash53c990a2012-03-17 18:20:06 +00005190#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +01005191 [pool drain];
Phil Nash53c990a2012-03-17 18:20:06 +00005192#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01005193
Phil Nashdd5b9c22012-02-18 09:58:30 +00005194 return result;
Phil Nash89d1e6c2011-05-24 08:23:02 +01005195}
5196
Phil Nash176eb812012-05-11 08:17:16 +01005197#endif // __OBJC__
5198
Phil Nash89d1e6c2011-05-24 08:23:02 +01005199#endif
5200
Phil Nash89d1e6c2011-05-24 08:23:02 +01005201//////
5202
Phil Nash46bcd4b2012-07-20 18:43:48 +01005203// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
5204#ifdef CATCH_CONFIG_PREFIX_ALL
5205
5206#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, false, true, "CATCH_REQUIRE" )
5207#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, true, "CATCH_REQUIRE_FALSE" )
5208
5209#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., true, "CATCH_REQUIRE_THROWS" )
5210#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, true, "CATCH_REQUIRE_THROWS_AS" )
5211#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, true, "CATCH_REQUIRE_NOTHROW" )
5212
5213#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, false, false, "CATCH_CHECK" )
5214#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, false, "CATCH_CHECK_FALSE" )
5215#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, false, false, "CATCH_CHECKED_IF" )
5216#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, false, false, "CATCH_CHECKED_ELSE" )
5217
5218#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., false, "CATCH_CHECK_THROWS" )
5219#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, false, "CATCH_CHECK_THROWS_AS" )
5220#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, false, "CATCH_CHECK_NOTHROW" )
5221
5222#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, false, "CATCH_CHECK_THAT" )
5223#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, true, "CATCH_REQUIRE_THAT" )
5224
5225#define CATCH_INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, false, "CATCH_INFO" )
5226#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, false, "CATCH_WARN" )
5227#define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, true, "CATCH_FAIL" )
5228#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg )
5229#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, false, "CATCH_CAPTURE" )
5230
5231#define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
5232
5233#define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
5234#define CATCH_TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
5235#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" )
5236#define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
5237
5238#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
5239
5240#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
5241
5242///////////////
5243// Still to be implemented
5244//#define CHECK_NOFAIL( expr ) // !TBD - reports violation, but doesn't fail Test
5245
5246// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
5247#else
5248
Phil Nash89d1e6c2011-05-24 08:23:02 +01005249#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, false, true, "REQUIRE" )
5250#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, true, "REQUIRE_FALSE" )
5251
5252#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., true, "REQUIRE_THROWS" )
5253#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, true, "REQUIRE_THROWS_AS" )
5254#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, true, "REQUIRE_NOTHROW" )
5255
5256#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, false, false, "CHECK" )
5257#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, false, "CHECK_FALSE" )
Phil Nasha162e222012-02-10 08:30:13 +00005258#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, false, false, "CHECKED_IF" )
5259#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, false, false, "CHECKED_ELSE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01005260
5261#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., false, "CHECK_THROWS" )
5262#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, false, "CHECK_THROWS_AS" )
5263#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, false, "CHECK_NOTHROW" )
5264
Phil Nash78d95a02012-03-04 21:22:36 +00005265#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, false, "CHECK_THAT" )
5266#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, true, "REQUIRE_THAT" )
5267
Phil Nash89d1e6c2011-05-24 08:23:02 +01005268#define INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, false, "INFO" )
5269#define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, false, "WARN" )
5270#define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, true, "FAIL" )
5271#define SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg )
5272#define CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, false, "CAPTURE" )
5273
5274#define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
5275
5276#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
5277#define TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
5278#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01005279#define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
Phil Nash89d1e6c2011-05-24 08:23:02 +01005280
5281#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
Phil Nash89d1e6c2011-05-24 08:23:02 +01005282
5283#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
5284
Phil Nash46bcd4b2012-07-20 18:43:48 +01005285#endif
5286
5287#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
Phil Nash89d1e6c2011-05-24 08:23:02 +01005288
5289using Catch::Detail::Approx;
5290
Phil Nash5bc030d2012-08-16 18:48:50 +01005291#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01005292#pragma clang diagnostic pop
Phil Nash5bc030d2012-08-16 18:48:50 +01005293#endif
Phil Nasha695eb92012-08-13 07:46:10 +01005294
Phil Nashaec1e5e2012-05-09 19:37:51 +01005295#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01005296