blob: 4bca13ce5da2ec43f7ecb53d38ee5f06a0c15c31 [file] [log] [blame]
Phil Nash89d1e6c2011-05-24 08:23:02 +01001/*
Phil Nashaec1e5e2012-05-09 19:37:51 +01002 * This file has been merged from multiple headers. Please don't edit it directly
3 * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
Phil Nash89d1e6c2011-05-24 08:23:02 +01004 *
5 * Distributed under the Boost Software License, Version 1.0. (See accompanying
6 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Phil Nash89d1e6c2011-05-24 08:23:02 +01007 */
Phil Nashaec1e5e2012-05-09 19:37:51 +01008#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
9#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010010
Phil Nash176eb812012-05-11 08:17:16 +010011// #included from: internal/catch_context.h
Phil Nash89d1e6c2011-05-24 08:23:02 +010012
Phil Nash89d1e6c2011-05-24 08:23:02 +010013// #included from: catch_interfaces_reporter.h
14
Phil Nash89d1e6c2011-05-24 08:23:02 +010015// #included from: catch_common.h
16
Phil Nash89d1e6c2011-05-24 08:23:02 +010017#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
18#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
19#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
20
21#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
22#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
23
24#ifdef __GNUC__
25#define ATTRIBUTE_NORETURN __attribute__ ((noreturn))
26#else
27#define ATTRIBUTE_NORETURN
28#endif
29
30#include <sstream>
31#include <stdexcept>
32#include <algorithm>
33
34namespace Catch
35{
Phil Nashd31737f2012-05-09 19:04:00 +010036 class NonCopyable {
Phil Nash89d1e6c2011-05-24 08:23:02 +010037 NonCopyable( const NonCopyable& );
38 void operator = ( const NonCopyable& );
39 protected:
Phil Nashd31737f2012-05-09 19:04:00 +010040 NonCopyable() {}
Phil Nashf51d3162011-12-28 10:37:31 +000041 virtual ~NonCopyable() {}
Phil Nash89d1e6c2011-05-24 08:23:02 +010042 };
43
Phil Nash89d1e6c2011-05-24 08:23:02 +010044 template<typename ContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +010045 inline void deleteAll( ContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010046 typename ContainerT::const_iterator it = container.begin();
47 typename ContainerT::const_iterator itEnd = container.end();
48 for(; it != itEnd; ++it )
49 {
50 delete *it;
51 }
52 }
53 template<typename AssociativeContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +010054 inline void deleteAllValues( AssociativeContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010055 typename AssociativeContainerT::const_iterator it = container.begin();
56 typename AssociativeContainerT::const_iterator itEnd = container.end();
57 for(; it != itEnd; ++it )
58 {
59 delete it->second;
60 }
61 }
62
63 template<typename ContainerT, typename Function>
Phil Nashd31737f2012-05-09 19:04:00 +010064 inline void forEach( ContainerT& container, Function function ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010065 std::for_each( container.begin(), container.end(), function );
66 }
67
68 template<typename ContainerT, typename Function>
Phil Nashd31737f2012-05-09 19:04:00 +010069 inline void forEach( const ContainerT& container, Function function ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010070 std::for_each( container.begin(), container.end(), function );
71 }
72
Phil Nash6e0f58d2012-02-15 18:37:21 +000073 struct SourceLineInfo
74 {
Phil Nashd31737f2012-05-09 19:04:00 +010075 SourceLineInfo() : line( 0 ){}
Phil Nash62179662012-05-11 19:06:43 +010076 SourceLineInfo( const std::string& _file, std::size_t _line )
77 : file( _file ),
78 line( _line )
Phil Nash6e0f58d2012-02-15 18:37:21 +000079 {}
Phil Nashd31737f2012-05-09 19:04:00 +010080 SourceLineInfo( const SourceLineInfo& other )
81 : file( other.file ),
82 line( other.line )
83 {}
84 void swap( SourceLineInfo& other ){
85 file.swap( other.file );
86 std::swap( line, other.line );
87 }
Phil Nash6e0f58d2012-02-15 18:37:21 +000088
89 std::string file;
90 std::size_t line;
91 };
92
Phil Nashd31737f2012-05-09 19:04:00 +010093 inline std::ostream& operator << ( std::ostream& os, const SourceLineInfo& info ) {
Phil Nash6e0f58d2012-02-15 18:37:21 +000094#ifndef __GNUG__
95 os << info.file << "(" << info.line << "): ";
96#else
97 os << info.file << ":" << info.line << ": ";
98#endif
99 return os;
100 }
101
Phil Nash89d1e6c2011-05-24 08:23:02 +0100102 ATTRIBUTE_NORETURN
Phil Nashd31737f2012-05-09 19:04:00 +0100103 inline void throwLogicError( const std::string& message, const std::string& file, std::size_t line ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100104 std::ostringstream oss;
Phil Nash6e0f58d2012-02-15 18:37:21 +0000105 oss << "Internal Catch error: '" << message << "' at: " << SourceLineInfo( file, line );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100106 throw std::logic_error( oss.str() );
107 }
108}
109
110#define CATCH_INTERNAL_ERROR( msg ) throwLogicError( msg, __FILE__, __LINE__ );
Phil Nashd31737f2012-05-09 19:04:00 +0100111#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, __LINE__ )
Phil Nash89d1e6c2011-05-24 08:23:02 +0100112
Phil Nashf7299fc2012-02-25 09:39:45 +0000113// #included from: catch_totals.hpp
114
Phil Nashf7299fc2012-02-25 09:39:45 +0000115namespace Catch
116{
117 struct Counts
118 {
Phil Nash176eb812012-05-11 08:17:16 +0100119 Counts() : passed( 0 ), failed( 0 ) {}
Phil Nashf7299fc2012-02-25 09:39:45 +0000120
Phil Nash176eb812012-05-11 08:17:16 +0100121 Counts operator - ( const Counts& other ) const {
Phil Nashf7299fc2012-02-25 09:39:45 +0000122 Counts diff;
123 diff.passed = passed - other.passed;
124 diff.failed = failed - other.failed;
125 return diff;
126 }
127
Phil Nash176eb812012-05-11 08:17:16 +0100128 std::size_t total() const {
Phil Nashf7299fc2012-02-25 09:39:45 +0000129 return passed + failed;
130 }
Phil Nash176eb812012-05-11 08:17:16 +0100131
Phil Nashf7299fc2012-02-25 09:39:45 +0000132 std::size_t passed;
133 std::size_t failed;
134 };
135
136 struct Totals
137 {
Phil Nash176eb812012-05-11 08:17:16 +0100138 Totals operator - ( const Totals& other ) const {
Phil Nashf7299fc2012-02-25 09:39:45 +0000139 Totals diff;
140 diff.assertions = assertions - other.assertions;
141 diff.testCases = testCases - other.testCases;
142 return diff;
143 }
144
145 Counts assertions;
146 Counts testCases;
147 };
148}
149
Phil Nash49e6d532012-05-05 19:35:35 +0100150// #included from: catch_ptr.hpp
151
Phil Nash49e6d532012-05-05 19:35:35 +0100152namespace Catch
153{
154 // An intrusive reference counting smart pointer.
155 // T must implement addRef() and release() methods
156 // typically implementing the IShared interface
157 template<typename T>
158 class Ptr
159 {
160 public:
161 Ptr() : m_p( NULL ){}
162 Ptr( T* p ) : m_p( p ){
163 m_p->addRef();
164 }
165 Ptr( const Ptr& other ) : m_p( other.m_p ){
166 m_p->addRef();
167 }
168 ~Ptr(){
169 if( m_p )
170 m_p->release();
171 }
172 Ptr& operator = ( T* p ){
173 Ptr temp( p );
174 swap( temp );
175 return *this;
176 }
177 Ptr& operator = ( Ptr& other ){
178 Ptr temp( other );
179 swap( temp );
180 return *this;
181 }
182 void swap( Ptr& other ){
183 std::swap( m_p, other.m_p );
184 }
185
186 T* get(){
187 return m_p;
188 }
189 const T* get() const{
190 return m_p;
191 }
192
193 T& operator*(){
194 return *m_p;
195 }
196 const T& operator*() const{
197 return *m_p;
198 }
199
200 T* operator->(){
201 return m_p;
202 }
203 const T* operator->() const{
204 return m_p;
205 }
206
207 private:
208 T* m_p;
209 };
210
211 struct IShared : NonCopyable {
212 virtual ~IShared(){}
213 virtual void addRef() = 0;
214 virtual void release() = 0;
215 };
216
217 template<typename T>
218 struct SharedImpl : T {
219
220 SharedImpl() : m_rc( 0 ){}
221
222 virtual void addRef(){
223 ++m_rc;
224 }
225 virtual void release(){
226 if( --m_rc == 0 )
227 delete this;
228 }
229
230 int m_rc;
231 };
232
233} // end namespace Catch
234
Phil Nash89d1e6c2011-05-24 08:23:02 +0100235#include <string>
236#include <ostream>
237#include <map>
238
239namespace Catch
240{
Phil Nashd31737f2012-05-09 19:04:00 +0100241 struct IReporterConfig {
242 virtual ~IReporterConfig() {}
243 virtual std::ostream& stream () const = 0;
244 virtual bool includeSuccessfulResults () const = 0;
245 virtual std::string getName () const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100246 };
247
248 class TestCaseInfo;
249 class ResultInfo;
250
Phil Nashd31737f2012-05-09 19:04:00 +0100251 struct IReporter : IShared {
252 virtual ~IReporter() {}
253 virtual bool shouldRedirectStdout() const = 0;
254 virtual void StartTesting() = 0;
255 virtual void EndTesting( const Totals& totals ) = 0;
256 virtual void StartGroup( const std::string& groupName ) = 0;
257 virtual void EndGroup( const std::string& groupName, const Totals& totals ) = 0;
258 virtual void StartSection( const std::string& sectionName, const std::string description ) = 0;
259 virtual void EndSection( const std::string& sectionName, const Counts& assertions ) = 0;
260 virtual void StartTestCase( const TestCaseInfo& testInfo ) = 0;
261 virtual void EndTestCase( const TestCaseInfo& testInfo, const Totals& totals, const std::string& stdOut, const std::string& stdErr ) = 0;
262 virtual void Result( const ResultInfo& result ) = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100263 };
264
Phil Nashd31737f2012-05-09 19:04:00 +0100265 struct IReporterFactory {
266 virtual ~IReporterFactory() {}
267 virtual IReporter* create( const IReporterConfig& config ) const = 0;
268 virtual std::string getDescription() const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100269 };
270
Phil Nashd31737f2012-05-09 19:04:00 +0100271 struct IReporterRegistry {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100272 typedef std::map<std::string, IReporterFactory*> FactoryMap;
273
Phil Nashd31737f2012-05-09 19:04:00 +0100274 virtual ~IReporterRegistry() {}
275 virtual IReporter* create( const std::string& name, const IReporterConfig& config ) const = 0;
276 virtual void registerReporter( const std::string& name, IReporterFactory* factory ) = 0;
277 virtual const FactoryMap& getFactories() const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100278 };
279
Phil Nash89d1e6c2011-05-24 08:23:02 +0100280 inline std::string trim( const std::string& str )
281 {
282 std::string::size_type start = str.find_first_not_of( "\n\r\t " );
283 std::string::size_type end = str.find_last_not_of( "\n\r\t " );
284
Phil Nash918046a2012-02-28 20:04:42 +0000285 return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
Phil Nash89d1e6c2011-05-24 08:23:02 +0100286 }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100287}
288
Phil Nash89d1e6c2011-05-24 08:23:02 +0100289#include <memory>
290#include <vector>
291#include <stdlib.h>
292
293namespace Catch
294{
295 class TestCaseInfo;
296 struct IResultCapture;
297 struct ITestCaseRegistry;
298 struct IRunner;
299 struct IExceptionTranslatorRegistry;
300 class GeneratorsForTest;
301
Phil Nash176eb812012-05-11 08:17:16 +0100302 class StreamBufBase : public std::streambuf{};
303
304 class Context
Phil Nash89d1e6c2011-05-24 08:23:02 +0100305 {
Phil Nash176eb812012-05-11 08:17:16 +0100306 Context();
307 Context( const Context& );
308 void operator=( const Context& );
309 static Context& me();
Phil Nash89d1e6c2011-05-24 08:23:02 +0100310
311 public:
Phil Nash176eb812012-05-11 08:17:16 +0100312 static void setRunner( IRunner* runner );
313 static void setResultCapture( IResultCapture* resultCapture );
314 static IResultCapture& getResultCapture();
315 static IReporterRegistry& getReporterRegistry();
316 static ITestCaseRegistry& getTestCaseRegistry();
317 static IExceptionTranslatorRegistry& getExceptionTranslatorRegistry();
318 static std::streambuf* createStreamBuf( const std::string& streamName );
319 static IRunner& getRunner();
320 static size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize );
321 static bool advanceGeneratorsForCurrentTest();
322 static void cleanUp();
Phil Nashdd5b9c22012-02-18 09:58:30 +0000323
Phil Nash89d1e6c2011-05-24 08:23:02 +0100324 private:
Phil Nash176eb812012-05-11 08:17:16 +0100325 static Context*& singleInstance();
326 GeneratorsForTest* findGeneratorsForCurrentTest();
327 GeneratorsForTest& getGeneratorsForCurrentTest();
Phil Nashdd5b9c22012-02-18 09:58:30 +0000328
Phil Nash176eb812012-05-11 08:17:16 +0100329 private:
Phil Nash89d1e6c2011-05-24 08:23:02 +0100330 std::auto_ptr<IReporterRegistry> m_reporterRegistry;
331 std::auto_ptr<ITestCaseRegistry> m_testCaseRegistry;
332 std::auto_ptr<IExceptionTranslatorRegistry> m_exceptionTranslatorRegistry;
333 IRunner* m_runner;
334 IResultCapture* m_resultCapture;
335 std::map<std::string, GeneratorsForTest*> m_generatorsByTestName;
336 };
337}
338
339// #included from: internal/catch_test_registry.hpp
340
Phil Nash89d1e6c2011-05-24 08:23:02 +0100341// #included from: catch_interfaces_testcase.h
342
Phil Nash89d1e6c2011-05-24 08:23:02 +0100343#include <vector>
344
345namespace Catch
346{
347 struct ITestCase
348 {
349 virtual ~ITestCase
350 ()
351 {}
352
353 virtual void invoke
354 () const = 0;
355
356 virtual ITestCase* clone
357 () const = 0;
358
359 virtual bool operator ==
360 ( const ITestCase& other
361 ) const = 0;
362
363 virtual bool operator <
364 ( const ITestCase& other
365 ) const = 0;
366 };
367
368 class TestCaseInfo;
369
370 struct ITestCaseRegistry
371 {
372 virtual ~ITestCaseRegistry
373 ()
374 {}
375
376 virtual void registerTest
377 ( const TestCaseInfo& testInfo
378 ) = 0;
379
380 virtual const std::vector<TestCaseInfo>& getAllTests
381 () const = 0;
382
383 virtual std::vector<TestCaseInfo> getMatchingTestCases
384 ( const std::string& rawTestSpec
385 ) = 0;
386 };
387}
388
Phil Nash89d1e6c2011-05-24 08:23:02 +0100389namespace Catch
390{
391
392template<typename C>
Phil Nash176eb812012-05-11 08:17:16 +0100393class MethodTestCase : public ITestCase
Phil Nash89d1e6c2011-05-24 08:23:02 +0100394{
Phil Nash176eb812012-05-11 08:17:16 +0100395public:
396 MethodTestCase( void (C::*method)() ) : m_method( method ) {}
Phil Nash89d1e6c2011-05-24 08:23:02 +0100397
Phil Nash176eb812012-05-11 08:17:16 +0100398 virtual void invoke() const {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100399 C obj;
400 (obj.*m_method)();
401 }
402
Phil Nash176eb812012-05-11 08:17:16 +0100403 virtual ITestCase* clone() const {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100404 return new MethodTestCase<C>( m_method );
405 }
406
Phil Nash176eb812012-05-11 08:17:16 +0100407 virtual bool operator == ( const ITestCase& other ) const {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100408 const MethodTestCase* mtOther = dynamic_cast<const MethodTestCase*>( &other );
409 return mtOther && m_method == mtOther->m_method;
410 }
411
Phil Nash176eb812012-05-11 08:17:16 +0100412 virtual bool operator < ( const ITestCase& other ) const {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100413 const MethodTestCase* mtOther = dynamic_cast<const MethodTestCase*>( &other );
414 return mtOther && &m_method < &mtOther->m_method;
415 }
416
417private:
418 void (C::*m_method)();
419};
420
421typedef void(*TestFunction)();
422
423struct AutoReg
424{
Phil Nash176eb812012-05-11 08:17:16 +0100425 AutoReg( TestFunction function,
426 const char* name,
427 const char* description,
428 const SourceLineInfo& lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100429
Phil Nash89d1e6c2011-05-24 08:23:02 +0100430 template<typename C>
Phil Nash176eb812012-05-11 08:17:16 +0100431 AutoReg( void (C::*method)(),
432 const char* name,
433 const char* description,
434 const SourceLineInfo& lineInfo ) {
Phil Nashd31737f2012-05-09 19:04:00 +0100435 registerTestCase( new MethodTestCase<C>( method ), name, description, lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100436 }
437
Phil Nash176eb812012-05-11 08:17:16 +0100438 void registerTestCase( ITestCase* testCase,
439 const char* name,
440 const char* description,
441 const SourceLineInfo& lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100442
Phil Nash176eb812012-05-11 08:17:16 +0100443 ~AutoReg();
Phil Nash89d1e6c2011-05-24 08:23:02 +0100444
445private:
Phil Nash176eb812012-05-11 08:17:16 +0100446 AutoReg( const AutoReg& );
447 void operator= ( const AutoReg& );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100448};
449
450} // end namespace Catch
451
452///////////////////////////////////////////////////////////////////////////////
453#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
Phil Nashd31737f2012-05-09 19:04:00 +0100454 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )(); \
455 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ ), Name, Desc, CATCH_INTERNAL_LINEINFO ); }\
456 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100457
458///////////////////////////////////////////////////////////////////////////////
459#define INTERNAL_CATCH_TESTCASE_NORETURN( Name, Desc ) \
Phil Nashd31737f2012-05-09 19:04:00 +0100460 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )() ATTRIBUTE_NORETURN; \
461 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ ), Name, Desc, CATCH_INTERNAL_LINEINFO ); }\
462 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100463
464///////////////////////////////////////////////////////////////////////////////
465#define CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
Phil Nashd31737f2012-05-09 19:04:00 +0100466 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, Name, Desc, CATCH_INTERNAL_LINEINFO ); }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100467
468///////////////////////////////////////////////////////////////////////////////
469#define TEST_CASE_METHOD( ClassName, TestName, Desc )\
Phil Nashfd78e0f2011-12-28 19:56:39 +0000470 namespace{ \
Phil Nashd31737f2012-05-09 19:04:00 +0100471 struct INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ ) : ClassName{ \
Phil Nashfd78e0f2011-12-28 19:56:39 +0000472 void test(); \
473 }; \
Phil Nashd31737f2012-05-09 19:04:00 +0100474 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 +0000475 } \
Phil Nashd31737f2012-05-09 19:04:00 +0100476 void INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ )::test()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100477
478// #included from: internal/catch_capture.hpp
479
Phil Nash176eb812012-05-11 08:17:16 +0100480// #included from: catch_expression.hpp
481
Phil Nashd31737f2012-05-09 19:04:00 +0100482// #included from: catch_resultinfo_builder.hpp
483
Phil Nashd31737f2012-05-09 19:04:00 +0100484// #included from: catch_tostring.hpp
485
Phil Nashd31737f2012-05-09 19:04:00 +0100486#include <sstream>
487
488namespace Catch
489{
490namespace Detail
491{
492 struct NonStreamable {
493 template<typename T> NonStreamable( const T& ){}
494 };
495
496 // If the type does not have its own << overload for ostream then
497 // this one will be used instead
498 inline std::ostream& operator << ( std::ostream& ss, NonStreamable ){
499 return ss << "{?}";
500 }
501
502 template<typename T>
503 inline std::string makeString( const T& value ) {
504 std::ostringstream oss;
505 oss << value;
506 return oss.str();
507 }
508
509 template<typename T>
510 inline std::string makeString( T* p ) {
511 if( !p )
512 return INTERNAL_CATCH_STRINGIFY( NULL );
513 std::ostringstream oss;
514 oss << p;
515 return oss.str();
516 }
517
518 template<typename T>
519 inline std::string makeString( const T* p ) {
520 if( !p )
521 return INTERNAL_CATCH_STRINGIFY( NULL );
522 std::ostringstream oss;
523 oss << p;
524 return oss.str();
525 }
526
527} // end namespace Detail
528
529/// \brief converts any type to a string
530///
531/// The default template forwards on to ostringstream - except when an
532/// ostringstream overload does not exist - in which case it attempts to detect
533/// that and writes {?}.
534/// Overload (not specialise) this template for custom typs that you don't want
535/// to provide an ostream overload for.
536template<typename T>
537std::string toString( const T& value ) {
538 return Detail::makeString( value );
539}
540
541// Built in overloads
542
543inline std::string toString( const std::string& value ) {
544 return "\"" + value + "\"";
545}
546
547inline std::string toString( const std::wstring& value ) {
548 std::ostringstream oss;
549 oss << "\"";
550 for(size_t i = 0; i < value.size(); ++i )
551 oss << static_cast<char>( value[i] <= 0xff ? value[i] : '?');
552 oss << "\"";
553 return oss.str();
554}
555
556inline std::string toString( const char* const value ) {
557 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
558}
559
560inline std::string toString( char* const value ) {
561 return Catch::toString( static_cast<const char*>( value ) );
562}
563
564inline std::string toString( int value ) {
565 std::ostringstream oss;
566 oss << value;
567 return oss.str();
568}
569
570inline std::string toString( unsigned long value ) {
571 std::ostringstream oss;
572 if( value > 8192 )
573 oss << "0x" << std::hex << value;
574 else
575 oss << value;
576 return oss.str();
577}
578
579inline std::string toString( unsigned int value ) {
Phil Nash62179662012-05-11 19:06:43 +0100580 return toString( static_cast<unsigned long>( value ) );
Phil Nashd31737f2012-05-09 19:04:00 +0100581}
582
583inline std::string toString( const double value ) {
584 std::ostringstream oss;
585 oss << value;
586 return oss.str();
587}
588
589inline std::string toString( bool value ) {
590 return value ? "true" : "false";
591}
592
Phil Nash176eb812012-05-11 08:17:16 +0100593#ifdef CATCH_CONFIG_CPP11_NULLPTR
594inline std::string toString( std::nullptr_t null ) {
595 return "nullptr";
596}
597#endif
598
Phil Nashd31737f2012-05-09 19:04:00 +0100599} // end namespace Catch
600
Phil Nash89d1e6c2011-05-24 08:23:02 +0100601// #included from: catch_resultinfo.hpp
602
Phil Nash89d1e6c2011-05-24 08:23:02 +0100603#include <string>
604// #included from: catch_result_type.h
605
Phil Nash89d1e6c2011-05-24 08:23:02 +0100606namespace Catch
607{
608
609struct ResultWas{ enum OfType
610 {
611 Unknown = -1,
612 Ok = 0,
613 Info = 1,
614 Warning = 2,
615
616 FailureBit = 0x10,
617
618 ExpressionFailed = FailureBit | 1,
619 ExplicitFailure = FailureBit | 2,
620
621 Exception = 0x100 | FailureBit,
622
623 ThrewException = Exception | 1,
624 DidntThrowException = Exception | 2
625
626 }; };
627
628 struct ResultAction
629 {
630 enum Value
631 {
632 None,
633 Failed = 1, // Failure - but no debug break if Debug bit not set
634 DebugFailed = 3 // Indicates that the debugger should break, if possible
635 };
636 };
637
638}
639
640
Phil Nash89d1e6c2011-05-24 08:23:02 +0100641namespace Catch
642{
643 class ResultInfo
644 {
645 public:
646
647 ///////////////////////////////////////////////////////////////////////////
648 ResultInfo
649 ()
Phil Nashf51d3162011-12-28 10:37:31 +0000650 : m_macroName(),
Phil Nashf51d3162011-12-28 10:37:31 +0000651 m_expr(),
652 m_lhs(),
653 m_rhs(),
654 m_op(),
655 m_message(),
Phil Nash89d1e6c2011-05-24 08:23:02 +0100656 m_result( ResultWas::Unknown ),
657 m_isNot( false )
658 {}
659
660 ///////////////////////////////////////////////////////////////////////////
661 ResultInfo
662 (
663 const char* expr,
664 ResultWas::OfType result,
665 bool isNot,
Phil Nashd31737f2012-05-09 19:04:00 +0100666 const SourceLineInfo& lineInfo,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100667 const char* macroName,
668 const char* message
669 )
670 : m_macroName( macroName ),
Phil Nashd31737f2012-05-09 19:04:00 +0100671 m_lineInfo( lineInfo ),
Phil Nash89d1e6c2011-05-24 08:23:02 +0100672 m_expr( expr ),
Phil Nash78d95a02012-03-04 21:22:36 +0000673 m_lhs(),
674 m_rhs(),
Phil Nash89d1e6c2011-05-24 08:23:02 +0100675 m_op( isNotExpression( expr ) ? "!" : "" ),
676 m_message( message ),
677 m_result( result ),
678 m_isNot( isNot )
679 {
680 if( isNot )
681 m_expr = "!" + m_expr;
682 }
683
684 ///////////////////////////////////////////////////////////////////////////
Phil Nasha162e222012-02-10 08:30:13 +0000685 virtual ~ResultInfo
Phil Nashf51d3162011-12-28 10:37:31 +0000686 ()
Phil Nasha162e222012-02-10 08:30:13 +0000687 {
688 }
689
Phil Nashf51d3162011-12-28 10:37:31 +0000690 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +0100691 bool ok
692 ()
693 const
694 {
695 return ( m_result & ResultWas::FailureBit ) != ResultWas::FailureBit;
696 }
697
698 ///////////////////////////////////////////////////////////////////////////
699 ResultWas::OfType getResultType
700 ()
701 const
702 {
703 return m_result;
704 }
705
706 ///////////////////////////////////////////////////////////////////////////
707 bool hasExpression
708 ()
709 const
710 {
711 return !m_expr.empty();
712 }
713
714 ///////////////////////////////////////////////////////////////////////////
715 bool hasMessage
716 ()
717 const
718 {
719 return !m_message.empty();
720 }
721
722 ///////////////////////////////////////////////////////////////////////////
723 std::string getExpression
724 ()
725 const
726 {
727 return m_expr;
728 }
729
730 ///////////////////////////////////////////////////////////////////////////
Phil Nash49e6d532012-05-05 19:35:35 +0100731 bool hasExpandedExpression
732 ()
733 const
734 {
735 return hasExpression() && getExpandedExpressionInternal() != m_expr;
736 }
737
738 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +0100739 std::string getExpandedExpression
740 ()
741 const
742 {
743 return hasExpression() ? getExpandedExpressionInternal() : "";
744 }
745
746 ///////////////////////////////////////////////////////////////////////////
747 std::string getMessage
748 ()
749 const
750 {
751 return m_message;
752 }
753
754 ///////////////////////////////////////////////////////////////////////////
755 std::string getFilename
756 ()
757 const
758 {
Phil Nashd31737f2012-05-09 19:04:00 +0100759 return m_lineInfo.file;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100760 }
761
762 ///////////////////////////////////////////////////////////////////////////
763 std::size_t getLine
764 ()
765 const
766 {
Phil Nashd31737f2012-05-09 19:04:00 +0100767 return m_lineInfo.line;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100768 }
769
770 ///////////////////////////////////////////////////////////////////////////
771 std::string getTestMacroName
772 ()
773 const
774 {
775 return m_macroName;
776 }
777
778 protected:
779
780 ///////////////////////////////////////////////////////////////////////////
781 std::string getExpandedExpressionInternal
782 ()
783 const
784 {
785 if( m_op == "" || m_isNot )
786 return m_lhs.empty() ? m_expr : m_op + m_lhs;
Phil Nash78d95a02012-03-04 21:22:36 +0000787 else if( m_op == "matches" )
788 return m_lhs + " " + m_rhs;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100789 else if( m_op != "!" )
Phil Nash6f1543b2012-05-07 19:46:19 +0100790 {
791 if( m_lhs.size() + m_rhs.size() < 30 )
792 return m_lhs + " " + m_op + " " + m_rhs;
793 else if( m_lhs.size() < 70 && m_rhs.size() < 70 )
794 return "\n\t" + m_lhs + "\n\t" + m_op + "\n\t" + m_rhs;
795 else
796 return "\n" + m_lhs + "\n" + m_op + "\n" + m_rhs + "\n\n";
797 }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100798 else
Phil Nash49e6d532012-05-05 19:35:35 +0100799 return "{can't expand - use " + m_macroName + "_FALSE( " + m_expr.substr(1) + " ) instead of " + m_macroName + "( " + m_expr + " ) for better diagnostics}";
Phil Nash89d1e6c2011-05-24 08:23:02 +0100800 }
801
802 ///////////////////////////////////////////////////////////////////////////
803 bool isNotExpression
804 (
805 const char* expr
806 )
807 {
808 return expr && expr[0] == '!';
809 }
810
811 protected:
812 std::string m_macroName;
Phil Nashd31737f2012-05-09 19:04:00 +0100813 SourceLineInfo m_lineInfo;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100814 std::string m_expr, m_lhs, m_rhs, m_op;
815 std::string m_message;
816 ResultWas::OfType m_result;
817 bool m_isNot;
818 };
819
820} // end namespace Catch
821
Phil Nash89d1e6c2011-05-24 08:23:02 +0100822// #included from: catch_evaluate.hpp
823
Phil Nash89d1e6c2011-05-24 08:23:02 +0100824namespace Catch
825{
826namespace Internal
827{
828 enum Operator
829 {
830 IsEqualTo,
831 IsNotEqualTo,
832 IsLessThan,
833 IsGreaterThan,
834 IsLessThanOrEqualTo,
835 IsGreaterThanOrEqualTo
836 };
837
838 template<Operator Op>
839 struct OperatorTraits{ static const char* getName(){ return "*error - unknown operator*"; } };
840
841 template<>
842 struct OperatorTraits<IsEqualTo>{ static const char* getName(){ return "=="; } };
843
844 template<>
845 struct OperatorTraits<IsNotEqualTo>{ static const char* getName(){ return "!="; } };
846
847 template<>
848 struct OperatorTraits<IsLessThan>{ static const char* getName(){ return "<"; } };
849
850 template<>
851 struct OperatorTraits<IsGreaterThan>{ static const char* getName(){ return ">"; } };
852
853 template<>
854 struct OperatorTraits<IsLessThanOrEqualTo>{ static const char* getName(){ return "<="; } };
855
856 template<>
857 struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
858
859 // So the compare overloads can be operator agnostic we convey the operator as a template
860 // enum, which is used to specialise an Evaluator for doing the comparison.
861 template<typename T1, typename T2, Operator Op>
862 class Evaluator{};
863
864 template<typename T1, typename T2>
865 struct Evaluator<T1, T2, IsEqualTo>
866 {
867 static bool evaluate( const T1& lhs, const T2& rhs)
868 {
Phil Nashd31737f2012-05-09 19:04:00 +0100869 return const_cast<T1&>( lhs ) == const_cast<T2&>( rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100870 }
871 };
872 template<typename T1, typename T2>
873 struct Evaluator<T1, T2, IsNotEqualTo>
874 {
875 static bool evaluate( const T1& lhs, const T2& rhs )
876 {
877 return const_cast<T1&>( lhs ) != const_cast<T2&>( rhs );
878 }
879 };
880 template<typename T1, typename T2>
881 struct Evaluator<T1, T2, IsLessThan>
882 {
883 static bool evaluate( const T1& lhs, const T2& rhs )
884 {
885 return const_cast<T1&>( lhs ) < const_cast<T2&>( rhs );
886 }
887 };
888 template<typename T1, typename T2>
889 struct Evaluator<T1, T2, IsGreaterThan>
890 {
891 static bool evaluate( const T1& lhs, const T2& rhs )
892 {
893 return const_cast<T1&>( lhs ) > const_cast<T2&>( rhs );
894 }
895 };
896 template<typename T1, typename T2>
897 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo>
898 {
899 static bool evaluate( const T1& lhs, const T2& rhs )
900 {
901 return const_cast<T1&>( lhs ) >= const_cast<T2&>( rhs );
902 }
903 };
904 template<typename T1, typename T2>
905 struct Evaluator<T1, T2, IsLessThanOrEqualTo>
906 {
907 static bool evaluate( const T1& lhs, const T2& rhs )
908 {
909 return const_cast<T1&>( lhs ) <= const_cast<T2&>( rhs );
910 }
911 };
912
913 template<Operator Op, typename T1, typename T2>
914 bool applyEvaluator( const T1& lhs, const T2& rhs )
915 {
916 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
917 }
918
919 // "base" overload
920 template<Operator Op, typename T1, typename T2>
921 bool compare( const T1& lhs, const T2& rhs )
922 {
923 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
924 }
925
926 // unsigned X to int
927 template<Operator Op> bool compare( unsigned int lhs, int rhs )
928 {
929 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
930 }
931 template<Operator Op> bool compare( unsigned long lhs, int rhs )
932 {
933 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
934 }
935 template<Operator Op> bool compare( unsigned char lhs, int rhs )
936 {
937 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
938 }
939
940 // unsigned X to long
941 template<Operator Op> bool compare( unsigned int lhs, long rhs )
942 {
943 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
944 }
945 template<Operator Op> bool compare( unsigned long lhs, long rhs )
946 {
947 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
948 }
949 template<Operator Op> bool compare( unsigned char lhs, long rhs )
950 {
951 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
952 }
953
954 // int to unsigned X
955 template<Operator Op> bool compare( int lhs, unsigned int rhs )
956 {
957 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
958 }
959 template<Operator Op> bool compare( int lhs, unsigned long rhs )
960 {
961 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
962 }
963 template<Operator Op> bool compare( int lhs, unsigned char rhs )
964 {
965 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
966 }
967
968 // long to unsigned X
969 template<Operator Op> bool compare( long lhs, unsigned int rhs )
970 {
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 }
973 template<Operator Op> bool compare( long lhs, unsigned long rhs )
974 {
Jardel Weyrich11dca662012-04-27 14:42:40 -0300975 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100976 }
977 template<Operator Op> bool compare( long lhs, unsigned char rhs )
978 {
Jardel Weyrich11dca662012-04-27 14:42:40 -0300979 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100980 }
981
982 template<Operator Op, typename T>
983 bool compare( long lhs, const T* rhs )
984 {
Phil Nash6f1543b2012-05-07 19:46:19 +0100985 return Evaluator<const T*, const T*, Op>::evaluate( reinterpret_cast<const T*>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100986 }
987
988 template<Operator Op, typename T>
989 bool compare( long lhs, T* rhs )
990 {
991 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
Phil Nash6f1543b2012-05-07 19:46:19 +0100992 }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100993
Phil Nash6f1543b2012-05-07 19:46:19 +0100994 template<Operator Op, typename T>
995 bool compare( const T* lhs, long rhs )
996 {
997 return Evaluator<const T*, const T*, Op>::evaluate( lhs, reinterpret_cast<const T*>( rhs ) );
998 }
999
1000 template<Operator Op, typename T>
1001 bool compare( T* lhs, long rhs )
1002 {
1003 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001004 }
1005
1006} // end of namespace Internal
1007} // end of namespace Catch
1008
Phil Nash89d1e6c2011-05-24 08:23:02 +01001009namespace Catch
1010{
Phil Nashf51d3162011-12-28 10:37:31 +00001011
Phil Nash89d1e6c2011-05-24 08:23:02 +01001012struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
1013
Phil Nashd31737f2012-05-09 19:04:00 +01001014class ResultInfoBuilder : public ResultInfo
Phil Nash89d1e6c2011-05-24 08:23:02 +01001015{
1016public:
1017
Phil Nashd31737f2012-05-09 19:04:00 +01001018 ResultInfoBuilder() {}
1019
1020 ResultInfoBuilder( const char* expr,
1021 bool isNot,
1022 const SourceLineInfo& lineInfo,
1023 const char* macroName,
1024 const char* message = "" )
1025 : ResultInfo( expr, ResultWas::Unknown, isNot, lineInfo, macroName, message )
Phil Nash89d1e6c2011-05-24 08:23:02 +01001026 {}
1027
Phil Nashd31737f2012-05-09 19:04:00 +01001028 void setResultType( ResultWas::OfType result ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001029 // Flip bool results if isNot is set
1030 if( m_isNot && result == ResultWas::Ok )
1031 m_result = ResultWas::ExpressionFailed;
1032 else if( m_isNot && result == ResultWas::ExpressionFailed )
1033 m_result = ResultWas::Ok;
1034 else
1035 m_result = result;
1036 }
1037
Phil Nashd31737f2012-05-09 19:04:00 +01001038 void setMessage( const std::string& message ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001039 m_message = message;
1040 }
1041
Phil Nashd31737f2012-05-09 19:04:00 +01001042 void setLineInfo( const SourceLineInfo& lineInfo ) {
1043 m_lineInfo = lineInfo;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001044 }
1045
Phil Nashd31737f2012-05-09 19:04:00 +01001046 void setLhs( const std::string& lhs ) {
Phil Nash78d95a02012-03-04 21:22:36 +00001047 m_lhs = lhs;
1048 }
1049
Phil Nashd31737f2012-05-09 19:04:00 +01001050 void setRhs( const std::string& rhs ) {
Phil Nash78d95a02012-03-04 21:22:36 +00001051 m_rhs = rhs;
1052 }
1053
Phil Nashd31737f2012-05-09 19:04:00 +01001054 void setOp( const std::string& op ) {
Phil Nash78d95a02012-03-04 21:22:36 +00001055 m_op = op;
1056 }
1057
Phil Nash89d1e6c2011-05-24 08:23:02 +01001058 template<typename RhsT>
1059 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator ||
1060 (
1061 const RhsT&
1062 );
1063
Phil Nash89d1e6c2011-05-24 08:23:02 +01001064 template<typename RhsT>
1065 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator &&
1066 (
1067 const RhsT&
1068 );
1069
1070private:
1071 friend class ResultBuilder;
1072 template<typename T> friend class Expression;
1073
1074 template<typename T> friend class PtrExpression;
1075
Phil Nashd31737f2012-05-09 19:04:00 +01001076 ResultInfoBuilder& captureBoolExpression( bool result ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001077 m_lhs = Catch::toString( result );
1078 m_op = m_isNot ? "!" : "";
1079 setResultType( result ? ResultWas::Ok : ResultWas::ExpressionFailed );
1080 return *this;
1081 }
1082
Phil Nash89d1e6c2011-05-24 08:23:02 +01001083 template<Internal::Operator Op, typename T1, typename T2>
Phil Nashd31737f2012-05-09 19:04:00 +01001084 ResultInfoBuilder& captureExpression( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001085 setResultType( Internal::compare<Op>( lhs, rhs ) ? ResultWas::Ok : ResultWas::ExpressionFailed );
1086 m_lhs = Catch::toString( lhs );
1087 m_rhs = Catch::toString( rhs );
1088 m_op = Internal::OperatorTraits<Op>::getName();
1089 return *this;
1090 }
1091
Phil Nash4021d652011-07-15 08:12:10 +01001092 template<Internal::Operator Op, typename T>
Phil Nashd31737f2012-05-09 19:04:00 +01001093 ResultInfoBuilder& captureExpression( const T* lhs, int rhs ) {
Phil Nash4021d652011-07-15 08:12:10 +01001094 return captureExpression<Op>( lhs, reinterpret_cast<const T*>( rhs ) );
1095 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001096};
1097
Phil Nashd31737f2012-05-09 19:04:00 +01001098} // end namespace Catch
1099
Phil Nash176eb812012-05-11 08:17:16 +01001100namespace Catch
1101{
1102
1103template<typename T>
1104class Expression
1105{
1106 void operator = ( const Expression& );
1107
1108public:
1109 Expression( ResultInfoBuilder& result, T lhs )
1110 : m_result( result ),
1111 m_lhs( lhs )
1112 {}
1113
1114 template<typename RhsT>
1115 ResultInfoBuilder& operator == ( const RhsT& rhs ) {
1116 return m_result.captureExpression<Internal::IsEqualTo>( m_lhs, rhs );
1117 }
1118
1119 template<typename RhsT>
1120 ResultInfoBuilder& operator != ( const RhsT& rhs ) {
1121 return m_result.captureExpression<Internal::IsNotEqualTo>( m_lhs, rhs );
1122 }
1123
1124 template<typename RhsT>
1125 ResultInfoBuilder& operator < ( const RhsT& rhs ) {
1126 return m_result.captureExpression<Internal::IsLessThan>( m_lhs, rhs );
1127 }
1128
1129 template<typename RhsT>
1130 ResultInfoBuilder& operator > ( const RhsT& rhs ) {
1131 return m_result.captureExpression<Internal::IsGreaterThan>( m_lhs, rhs );
1132 }
1133
1134 template<typename RhsT>
1135 ResultInfoBuilder& operator <= ( const RhsT& rhs ) {
1136 return m_result.captureExpression<Internal::IsLessThanOrEqualTo>( m_lhs, rhs );
1137 }
1138
1139 template<typename RhsT>
1140 ResultInfoBuilder& operator >= ( const RhsT& rhs ) {
1141 return m_result.captureExpression<Internal::IsGreaterThanOrEqualTo>( m_lhs, rhs );
1142 }
1143
1144 ResultInfoBuilder& operator == ( bool rhs ) {
1145 return m_result.captureExpression<Internal::IsEqualTo>( m_lhs, rhs );
1146 }
1147
1148 ResultInfoBuilder& operator != ( bool rhs ) {
1149 return m_result.captureExpression<Internal::IsNotEqualTo>( m_lhs, rhs );
1150 }
1151
1152 operator ResultInfoBuilder& () {
1153 return m_result.captureBoolExpression( m_lhs );
1154 }
1155
1156 template<typename RhsT>
1157 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( const RhsT& );
1158
1159 template<typename RhsT>
1160 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( const RhsT& );
1161
1162private:
1163 ResultInfoBuilder& m_result;
1164 T m_lhs;
1165};
1166
1167template<typename LhsT>
1168class PtrExpression
1169{
1170public:
1171
1172 PtrExpression ( ResultInfoBuilder& result, const LhsT* lhs )
1173 : m_result( &result ),
1174 m_lhs( lhs )
1175 {}
1176
1177 template<typename RhsT>
1178 ResultInfoBuilder& operator == ( const RhsT* rhs ) {
1179 return m_result->captureExpression<Internal::IsEqualTo>( m_lhs, rhs );
1180 }
1181
1182 // This catches NULL
1183 ResultInfoBuilder& operator == ( LhsT* rhs ) {
1184 return m_result->captureExpression<Internal::IsEqualTo>( m_lhs, rhs );
1185 }
1186
1187 template<typename RhsT>
1188 ResultInfoBuilder& operator != ( const RhsT* rhs ) {
1189 return m_result->captureExpression<Internal::IsNotEqualTo>( m_lhs, rhs );
1190 }
1191
1192 // This catches NULL
1193 ResultInfoBuilder& operator != ( LhsT* rhs ) {
1194 return m_result->captureExpression<Internal::IsNotEqualTo>( m_lhs, rhs );
1195 }
1196
1197 operator ResultInfoBuilder& () {
1198 return m_result->captureBoolExpression( m_lhs );
1199 }
1200
1201private:
1202 ResultInfoBuilder* m_result;
1203 const LhsT* m_lhs;
1204};
1205
1206} // end namespace Catch
1207
Phil Nashd31737f2012-05-09 19:04:00 +01001208// #included from: catch_interfaces_capture.h
1209
Phil Nashd31737f2012-05-09 19:04:00 +01001210#include <string>
1211
1212namespace Catch
1213{
1214 class TestCaseInfo;
1215 class ScopedInfo;
1216 class ResultInfoBuilder;
1217 class ResultInfo;
1218
1219 struct IResultCapture
1220 {
1221 virtual ~IResultCapture
1222 ()
1223 {}
1224
1225 virtual void testEnded
1226 ( const ResultInfo& result
1227 ) = 0;
1228 virtual bool sectionStarted
1229 ( const std::string& name,
1230 const std::string& description,
1231 const SourceLineInfo& lineInfo,
1232 Counts& assertions
1233 ) = 0;
1234 virtual void sectionEnded
1235 ( const std::string& name,
1236 const Counts& assertions
1237 ) = 0;
1238 virtual void pushScopedInfo
1239 ( ScopedInfo* scopedInfo
1240 ) = 0;
1241 virtual void popScopedInfo
1242 ( ScopedInfo* scopedInfo
1243 ) = 0;
1244 virtual bool shouldDebugBreak
1245 () const = 0;
1246
1247 virtual ResultAction::Value acceptResult
1248 ( bool result
1249 ) = 0;
1250 virtual ResultAction::Value acceptResult
1251 ( ResultWas::OfType result
1252 ) = 0;
1253 virtual ResultAction::Value acceptExpression
1254 ( const ResultInfoBuilder& resultInfo
1255 ) = 0;
1256 virtual void acceptMessage
1257 ( const std::string& msg
1258 ) = 0;
1259
1260 virtual std::string getCurrentTestName
1261 () const = 0;
1262 virtual const ResultInfo* getLastResult
1263 () const = 0;
1264
1265 };
1266}
1267
1268// #included from: catch_debugger.hpp
1269
Phil Nashd31737f2012-05-09 19:04:00 +01001270#include <iostream>
1271
1272#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
1273#define CATCH_PLATFORM_MAC
1274#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
1275#define CATCH_PLATFORM_IPHONE
1276#elif defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
1277#define CATCH_PLATFORM_WINDOWS
1278#endif
1279
1280#ifdef CATCH_PLATFORM_MAC
1281
1282 #include <assert.h>
1283 #include <stdbool.h>
1284 #include <sys/types.h>
1285 #include <unistd.h>
1286 #include <sys/sysctl.h>
1287
1288 namespace Catch
1289 {
1290 // The following function is taken directly from the following technical note:
1291 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
1292
1293 inline bool isDebuggerActive()
1294 // Returns true if the current process is being debugged (either
1295 // running under the debugger or has a debugger attached post facto).
1296 {
1297 int junk;
1298 int mib[4];
1299 struct kinfo_proc info;
1300 size_t size;
1301
1302 // Initialize the flags so that, if sysctl fails for some bizarre
1303 // reason, we get a predictable result.
1304
1305 info.kp_proc.p_flag = 0;
1306
1307 // Initialize mib, which tells sysctl the info we want, in this case
1308 // we're looking for information about a specific process ID.
1309
1310 mib[0] = CTL_KERN;
1311 mib[1] = KERN_PROC;
1312 mib[2] = KERN_PROC_PID;
1313 mib[3] = getpid();
1314
1315 // Call sysctl.
1316
1317 size = sizeof(info);
1318 junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
1319 assert(junk == 0);
1320
1321 // We're being debugged if the P_TRACED flag is set.
1322
1323 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
1324 }
1325 }
1326
1327 // The following code snippet taken from:
1328 // http://cocoawithlove.com/2008/03/break-into-debugger.html
1329 #ifdef DEBUG
1330 #if defined(__ppc64__) || defined(__ppc__)
1331 #define BreakIntoDebugger() \
1332 if( Catch::isDebuggerActive() ) \
1333 { \
1334 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
1335 : : : "memory","r0","r3","r4" ); \
1336 }
1337 #else
1338 #define BreakIntoDebugger() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
1339 #endif
1340 #else
1341 inline void BreakIntoDebugger(){}
1342 #endif
1343
1344#elif defined(_MSC_VER)
1345 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
1346 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { __debugbreak(); }
1347 inline bool isDebuggerActive()
1348 {
1349 return IsDebuggerPresent() != 0;
1350 }
Phil Nash176eb812012-05-11 08:17:16 +01001351#elif defined(__MINGW32__)
1352 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
1353 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
1354 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { DebugBreak(); }
1355 inline bool isDebuggerActive()
1356 {
1357 return IsDebuggerPresent() != 0;
1358 }
Phil Nashd31737f2012-05-09 19:04:00 +01001359#else
1360 inline void BreakIntoDebugger(){}
1361 inline bool isDebuggerActive() { return false; }
1362#endif
1363
1364#ifdef CATCH_PLATFORM_WINDOWS
1365extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
1366inline void writeToDebugConsole( const std::string& text )
1367{
1368 ::OutputDebugStringA( text.c_str() );
1369}
1370#else
1371inline void writeToDebugConsole( const std::string& text )
1372{
1373 // !TBD: Need a version for Mac/ XCode and other IDEs
1374 std::cout << text;
1375}
1376#endif // CATCH_PLATFORM_WINDOWS
1377
1378#include <sstream>
1379
1380namespace Catch
1381{
1382
1383struct TestFailureException{};
1384struct DummyExceptionType_DontUse{};
1385
Phil Nash89d1e6c2011-05-24 08:23:02 +01001386class ResultBuilder
1387{
1388public:
1389
1390 ///////////////////////////////////////////////////////////////////////////
1391 ResultBuilder
1392 (
Phil Nashd31737f2012-05-09 19:04:00 +01001393 const SourceLineInfo& lineInfo,
Phil Nash89d1e6c2011-05-24 08:23:02 +01001394 const char* macroName,
1395 const char* expr = "",
1396 bool isNot = false
1397 )
Phil Nashd31737f2012-05-09 19:04:00 +01001398 : m_result( expr, isNot, lineInfo, macroName ),
Phil Nashf51d3162011-12-28 10:37:31 +00001399 m_messageStream()
Phil Nash89d1e6c2011-05-24 08:23:02 +01001400 {}
1401
1402 ///////////////////////////////////////////////////////////////////////////
1403 template<typename T>
Phil Nash98a21bc2011-09-19 18:23:07 +01001404 Expression<const T&> operator->*
Phil Nash89d1e6c2011-05-24 08:23:02 +01001405 (
1406 const T & operand
1407 )
1408 {
Phil Nash98a21bc2011-09-19 18:23:07 +01001409 Expression<const T&> expr( m_result, operand );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001410
1411 return expr;
1412 }
1413
1414 ///////////////////////////////////////////////////////////////////////////
Phil Nash62a5ddc2011-06-29 19:25:14 +01001415 Expression<const char*> operator->*
1416 (
Phil Nash4021d652011-07-15 08:12:10 +01001417 const char* const& operand
Phil Nash62a5ddc2011-06-29 19:25:14 +01001418 )
1419 {
1420 Expression<const char*> expr( m_result, operand );
1421
1422 return expr;
1423 }
1424
1425 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01001426 template<typename T>
1427 PtrExpression<T> operator->*
1428 (
1429 const T* operand
1430 )
1431 {
1432 PtrExpression<T> expr( m_result, operand );
1433
1434 return expr;
1435 }
1436
1437 ///////////////////////////////////////////////////////////////////////////
1438 template<typename T>
1439 PtrExpression<T> operator->*
1440 (
1441 T* operand
1442 )
1443 {
1444 PtrExpression<T> expr( m_result, operand );
1445
1446 return expr;
1447 }
1448
1449 ///////////////////////////////////////////////////////////////////////////
Phil Nash22545402011-08-09 18:41:01 +01001450 Expression<bool> operator->*
1451 (
1452 bool value
1453 )
1454 {
1455 Expression<bool> expr( m_result, value );
1456 return expr;
1457 }
1458
1459 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01001460 template<typename T>
1461 ResultBuilder& operator <<
1462 (
1463 const T & value
1464 )
1465 {
1466 m_messageStream << Catch::toString( value );
1467 return *this;
1468 }
1469
1470 ///////////////////////////////////////////////////////////////////////////
Phil Nash78d95a02012-03-04 21:22:36 +00001471 template<typename MatcherT, typename ArgT>
1472 ResultBuilder& acceptMatcher
1473 (
1474 const MatcherT& matcher,
1475 const ArgT& arg,
1476 const std::string& matcherCallAsString
1477 )
1478 {
1479 std::string matcherAsString = Catch::toString( matcher );
1480 if( matcherAsString == "{?}" )
1481 matcherAsString = matcherCallAsString;
1482 m_result.setLhs( Catch::toString( arg ) );
1483 m_result.setRhs( matcherAsString );
1484 m_result.setOp( "matches" );
1485 m_result.setResultType( matcher( arg ) ? ResultWas::Ok : ResultWas::ExpressionFailed );
1486 return *this;
1487 }
1488
1489 ///////////////////////////////////////////////////////////////////////////
Phil Nash53c990a2012-03-17 18:20:06 +00001490 template<typename MatcherT, typename ArgT>
1491 ResultBuilder& acceptMatcher
1492 (
1493 const MatcherT& matcher,
1494 ArgT* arg,
1495 const std::string& matcherCallAsString
1496 )
1497 {
1498 std::string matcherAsString = Catch::toString( matcher );
1499 if( matcherAsString == "{?}" )
1500 matcherAsString = matcherCallAsString;
1501 m_result.setLhs( Catch::toString( arg ) );
1502 m_result.setRhs( matcherAsString );
1503 m_result.setOp( "matches" );
1504 m_result.setResultType( matcher( arg ) ? ResultWas::Ok : ResultWas::ExpressionFailed );
1505 return *this;
1506 }
1507
1508 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01001509 ResultBuilder& setResultType
1510 (
1511 ResultWas::OfType resultType
1512 )
1513 {
1514 m_result.setResultType( resultType );
1515 return *this;
1516 }
1517
1518 ///////////////////////////////////////////////////////////////////////////
Phil Nashd31737f2012-05-09 19:04:00 +01001519 operator ResultInfoBuilder&
Phil Nash89d1e6c2011-05-24 08:23:02 +01001520 ()
1521 {
1522 m_result.setMessage( m_messageStream.str() );
1523 return m_result;
1524 }
1525
1526private:
Phil Nashd31737f2012-05-09 19:04:00 +01001527 ResultInfoBuilder m_result;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001528 std::ostringstream m_messageStream;
1529
1530};
1531
1532class ScopedInfo
1533{
1534public:
Phil Nashd31737f2012-05-09 19:04:00 +01001535 ScopedInfo() : m_oss() {
Phil Nash176eb812012-05-11 08:17:16 +01001536 Context::getResultCapture().pushScopedInfo( this );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001537 }
1538
Phil Nashd31737f2012-05-09 19:04:00 +01001539 ~ScopedInfo() {
Phil Nash176eb812012-05-11 08:17:16 +01001540 Context::getResultCapture().popScopedInfo( this );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001541 }
1542
Phil Nashd31737f2012-05-09 19:04:00 +01001543 template<typename T>
1544 ScopedInfo& operator << ( const T& value ) {
1545 m_oss << value;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001546 return *this;
1547 }
1548
Phil Nashd31737f2012-05-09 19:04:00 +01001549 std::string getInfo () const {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001550 return m_oss.str();
1551 }
1552
1553private:
1554 std::ostringstream m_oss;
1555};
1556
Phil Nash89d1e6c2011-05-24 08:23:02 +01001557// This is just here to avoid compiler warnings with macro constants
Phil Nashd31737f2012-05-09 19:04:00 +01001558inline bool isTrue( bool value ){ return value; }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001559
1560} // end namespace Catch
1561
1562///////////////////////////////////////////////////////////////////////////////
Phil Nashd31737f2012-05-09 19:04:00 +01001563#define INTERNAL_CATCH_ACCEPT_EXPR( expr, stopOnFailure, originalExpr ) \
Phil Nash176eb812012-05-11 08:17:16 +01001564 if( Catch::ResultAction::Value internal_catch_action = Catch::Context::getResultCapture().acceptExpression( expr ) ) \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001565 { \
Phil Nash3c20a752011-06-23 08:23:33 +01001566 if( internal_catch_action == Catch::ResultAction::DebugFailed ) BreakIntoDebugger(); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001567 if( Catch::isTrue( stopOnFailure ) ) throw Catch::TestFailureException(); \
Phil Nashd31737f2012-05-09 19:04:00 +01001568 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 +01001569 }
1570
1571///////////////////////////////////////////////////////////////////////////////
1572#define INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ) \
Phil Nash777b8af2012-02-29 08:39:46 +00001573 do{ try{ \
Phil Nashd31737f2012-05-09 19:04:00 +01001574 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr, isNot )->*expr ), stopOnFailure, expr ); \
Phil Nash777b8af2012-02-29 08:39:46 +00001575 }catch( Catch::TestFailureException& ){ \
Phil Nash333e6e62012-02-17 19:50:59 +00001576 throw; \
Phil Nash777b8af2012-02-29 08:39:46 +00001577 } catch( ... ){ \
Phil Nash176eb812012-05-11 08:17:16 +01001578 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::Context::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, expr ); \
Phil Nash333e6e62012-02-17 19:50:59 +00001579 throw; \
Phil Nash5ff4ab02012-02-29 08:47:18 +00001580 }}while( Catch::isTrue( false ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01001581
1582///////////////////////////////////////////////////////////////////////////////
Phil Nasha162e222012-02-10 08:30:13 +00001583#define INTERNAL_CATCH_IF( expr, isNot, stopOnFailure, macroName ) \
1584 INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \
Phil Nash176eb812012-05-11 08:17:16 +01001585 if( Catch::Context::getResultCapture().getLastResult()->ok() )
Phil Nasha162e222012-02-10 08:30:13 +00001586
1587///////////////////////////////////////////////////////////////////////////////
1588#define INTERNAL_CATCH_ELSE( expr, isNot, stopOnFailure, macroName ) \
1589 INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \
Phil Nash176eb812012-05-11 08:17:16 +01001590 if( !Catch::Context::getResultCapture().getLastResult()->ok() )
Phil Nasha162e222012-02-10 08:30:13 +00001591
1592///////////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01001593#define INTERNAL_CATCH_NO_THROW( expr, stopOnFailure, macroName ) \
1594 try \
1595 { \
1596 expr; \
Phil Nashd31737f2012-05-09 19:04:00 +01001597 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ResultBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure, false ); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001598 } \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001599 catch( ... ) \
1600 { \
Phil Nash176eb812012-05-11 08:17:16 +01001601 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::Context::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001602 }
1603
1604///////////////////////////////////////////////////////////////////////////////
1605#define INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \
1606 try \
1607 { \
1608 expr; \
Phil Nashd31737f2012-05-09 19:04:00 +01001609 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ResultBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::DidntThrowException ), stopOnFailure, false ); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001610 } \
1611 catch( Catch::TestFailureException& ) \
1612 { \
1613 throw; \
1614 } \
1615 catch( exceptionType ) \
1616 { \
Phil Nashd31737f2012-05-09 19:04:00 +01001617 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ResultBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure, false ); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001618 }
1619
1620///////////////////////////////////////////////////////////////////////////////
1621#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, stopOnFailure, macroName ) \
1622 INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \
1623 catch( ... ) \
1624 { \
Phil Nash176eb812012-05-11 08:17:16 +01001625 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::Context::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001626 }
1627
1628///////////////////////////////////////////////////////////////////////////////
1629#define INTERNAL_CATCH_MSG( reason, resultType, stopOnFailure, macroName ) \
Phil Nash176eb812012-05-11 08:17:16 +01001630 Catch::Context::getResultCapture().acceptExpression( ( Catch::ResultBuilder( CATCH_INTERNAL_LINEINFO, macroName ) << reason ).setResultType( resultType ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001631
1632///////////////////////////////////////////////////////////////////////////////
1633#define INTERNAL_CATCH_SCOPED_INFO( log ) \
1634 Catch::ScopedInfo INTERNAL_CATCH_UNIQUE_NAME( info ); \
1635 INTERNAL_CATCH_UNIQUE_NAME( info ) << log
1636
Phil Nash78d95a02012-03-04 21:22:36 +00001637///////////////////////////////////////////////////////////////////////////////
1638#define INTERNAL_CHECK_THAT( arg, matcher, stopOnFailure, macroName ) \
1639 do{ try{ \
Phil Nashd31737f2012-05-09 19:04:00 +01001640 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( CATCH_INTERNAL_LINEINFO, macroName, #arg " " #matcher, false ).acceptMatcher( matcher, arg, #matcher ) ), stopOnFailure, false ); \
Phil Nash78d95a02012-03-04 21:22:36 +00001641 }catch( Catch::TestFailureException& ){ \
1642 throw; \
1643 } catch( ... ){ \
Phil Nash176eb812012-05-11 08:17:16 +01001644 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( CATCH_INTERNAL_LINEINFO, macroName, #arg " " #matcher ) << Catch::Context::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, false ); \
Phil Nash78d95a02012-03-04 21:22:36 +00001645 throw; \
1646 }}while( Catch::isTrue( false ) )
1647
Phil Nash89d1e6c2011-05-24 08:23:02 +01001648// #included from: internal/catch_section.hpp
1649
Phil Nash89d1e6c2011-05-24 08:23:02 +01001650#include <string>
1651
1652namespace Catch
1653{
1654 class Section
1655 {
1656 public:
1657 ///////////////////////////////////////////////////////////////////////
1658 Section
1659 (
1660 const std::string& name,
1661 const std::string& description,
Phil Nashd31737f2012-05-09 19:04:00 +01001662 const SourceLineInfo& lineInfo
Phil Nash89d1e6c2011-05-24 08:23:02 +01001663 )
1664 : m_name( name ),
Phil Nash176eb812012-05-11 08:17:16 +01001665 m_sectionIncluded( Context::getResultCapture().sectionStarted( name, description, lineInfo, m_assertions ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01001666 {
1667 }
1668
1669 ///////////////////////////////////////////////////////////////////////
1670 ~Section
1671 ()
1672 {
1673 if( m_sectionIncluded )
Phil Nash176eb812012-05-11 08:17:16 +01001674 Context::getResultCapture().sectionEnded( m_name, m_assertions );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001675 }
1676
1677 ///////////////////////////////////////////////////////////////////////
1678 // This indicates whether the section should be executed or not
1679 operator bool
1680 ()
1681 {
1682 return m_sectionIncluded;
1683 }
1684
1685 private:
1686
1687 std::string m_name;
Phil Nashf7299fc2012-02-25 09:39:45 +00001688 Counts m_assertions;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001689 bool m_sectionIncluded;
1690 };
1691
1692} // end namespace Catch
1693
1694#define INTERNAL_CATCH_SECTION( name, desc ) \
Phil Nashd31737f2012-05-09 19:04:00 +01001695 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( name, desc, CATCH_INTERNAL_LINEINFO ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01001696
1697// #included from: internal/catch_generators.hpp
1698
Phil Nash89d1e6c2011-05-24 08:23:02 +01001699#include <iterator>
1700#include <vector>
1701#include <string>
1702#include <stdlib.h>
1703
1704namespace Catch
1705{
1706
1707template<typename T>
1708struct IGenerator
1709{
1710 virtual ~IGenerator
1711 ()
1712 {}
1713
1714 virtual T getValue
1715 ( std::size_t index
1716 ) const = 0;
1717
1718 virtual std::size_t size
1719 () const = 0;
1720};
1721
1722template<typename T>
1723class BetweenGenerator : public IGenerator<T>
1724{
1725public:
1726 ///////////////////////////////////////////////////////////////////////////
1727 BetweenGenerator
1728 (
1729 T from,
1730 T to
1731 )
1732 : m_from( from ),
1733 m_to( to )
1734 {
1735 }
1736
1737 ///////////////////////////////////////////////////////////////////////////
1738 virtual T getValue
1739 (
1740 std::size_t index
1741 )
1742 const
1743 {
1744 return m_from+static_cast<T>( index );
1745 }
1746
1747 ///////////////////////////////////////////////////////////////////////////
1748 virtual std::size_t size
1749 ()
1750 const
1751 {
Phil Nashd31737f2012-05-09 19:04:00 +01001752 return static_cast<std::size_t>( 1+m_to-m_from );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001753 }
1754
1755private:
1756
1757 T m_from;
1758 T m_to;
1759};
1760
1761template<typename T>
1762class ValuesGenerator : public IGenerator<T>
1763{
1764public:
1765 ///////////////////////////////////////////////////////////////////////////
1766 ValuesGenerator
1767 ()
1768 {
1769 }
1770
1771 ///////////////////////////////////////////////////////////////////////////
1772 void add
1773 (
1774 T value
1775 )
1776 {
1777 m_values.push_back( value );
1778 }
1779
1780 ///////////////////////////////////////////////////////////////////////////
1781 virtual T getValue
1782 (
1783 std::size_t index
1784 )
1785 const
1786 {
1787 return m_values[index];
1788 }
1789
1790 ///////////////////////////////////////////////////////////////////////////
1791 virtual std::size_t size
1792 ()
1793 const
1794 {
1795 return m_values.size();
1796 }
1797
1798private:
1799
1800 std::vector<T> m_values;
1801};
1802
1803template<typename T>
1804class CompositeGenerator
1805{
1806public:
1807 ///////////////////////////////////////////////////////////////////////////
1808 CompositeGenerator()
1809 : m_totalSize( 0 )
1810 {
1811 }
1812
1813 ///////////////////////////////////////////////////////////////////////////
1814 // *** Move semantics, similar to auto_ptr ***
1815 CompositeGenerator( CompositeGenerator& other )
1816 : m_fileInfo( other.m_fileInfo ),
1817 m_totalSize( 0 )
1818 {
1819 move( other );
1820 }
1821
1822 ///////////////////////////////////////////////////////////////////////////
1823 CompositeGenerator& setFileInfo
1824 (
1825 const char* fileInfo
1826 )
1827 {
1828 m_fileInfo = fileInfo;
1829 return *this;
1830 }
1831
1832 ///////////////////////////////////////////////////////////////////////////
1833 ~CompositeGenerator
1834 ()
1835 {
1836 deleteAll( m_composed );
1837 }
1838
1839 ///////////////////////////////////////////////////////////////////////////
1840 operator T
1841 ()
1842 const
1843 {
Phil Nash176eb812012-05-11 08:17:16 +01001844 size_t overallIndex = Context::getGeneratorIndex( m_fileInfo, m_totalSize );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001845
1846 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
1847 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
1848 for( size_t index = 0; it != itEnd; ++it )
1849 {
1850 const IGenerator<T>* generator = *it;
1851 if( overallIndex >= index && overallIndex < index + generator->size() )
1852 {
1853 return generator->getValue( overallIndex-index );
1854 }
1855 index += generator->size();
1856 }
1857 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
1858 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
1859 }
1860
1861 ///////////////////////////////////////////////////////////////////////////
1862 void add
1863 (
1864 const IGenerator<T>* generator
1865 )
1866 {
1867 m_totalSize += generator->size();
1868 m_composed.push_back( generator );
1869 }
1870
1871 ///////////////////////////////////////////////////////////////////////////
1872 CompositeGenerator& then
1873 (
1874 CompositeGenerator& other
1875 )
1876 {
1877 move( other );
1878 return *this;
1879 }
1880
1881 ///////////////////////////////////////////////////////////////////////////
1882 CompositeGenerator& then
1883 (
1884 T value
1885 )
1886 {
1887 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1888 valuesGen->add( value );
1889 add( valuesGen );
1890 return *this;
1891 }
1892
1893private:
1894
1895 ///////////////////////////////////////////////////////////////////////////
1896 void move
1897 (
1898 CompositeGenerator& other
1899 )
1900 {
1901 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
1902 m_totalSize += other.m_totalSize;
1903 other.m_composed.clear();
1904 }
1905
1906 std::vector<const IGenerator<T>*> m_composed;
1907 std::string m_fileInfo;
1908 size_t m_totalSize;
1909};
1910
1911namespace Generators
1912{
1913 ///////////////////////////////////////////////////////////////////////////
1914 template<typename T>
1915 CompositeGenerator<T> between
1916 (
1917 T from,
1918 T to
1919 )
1920 {
1921 CompositeGenerator<T> generators;
1922 generators.add( new BetweenGenerator<T>( from, to ) );
1923 return generators;
1924 }
1925
1926 ///////////////////////////////////////////////////////////////////////////
1927 template<typename T>
1928 CompositeGenerator<T> values
1929 (
1930 T val1,
1931 T val2
1932 )
1933 {
1934 CompositeGenerator<T> generators;
1935 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1936 valuesGen->add( val1 );
1937 valuesGen->add( val2 );
1938 generators.add( valuesGen );
1939 return generators;
1940 }
1941
1942 ///////////////////////////////////////////////////////////////////////////
1943 template<typename T>
1944 CompositeGenerator<T> values
1945 (
1946 T val1,
1947 T val2,
1948 T val3
1949 )
1950 {
1951 CompositeGenerator<T> generators;
1952 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1953 valuesGen->add( val1 );
1954 valuesGen->add( val2 );
1955 valuesGen->add( val3 );
1956 generators.add( valuesGen );
1957 return generators;
1958 }
1959
1960 ///////////////////////////////////////////////////////////////////////////
1961 template<typename T>
1962 CompositeGenerator<T> values
1963 (
1964 T val1,
1965 T val2,
1966 T val3,
1967 T val4
1968 )
1969 {
1970 CompositeGenerator<T> generators;
1971 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1972 valuesGen->add( val1 );
1973 valuesGen->add( val2 );
1974 valuesGen->add( val3 );
1975 valuesGen->add( val4 );
1976 generators.add( valuesGen );
1977 return generators;
1978 }
1979
1980} // end namespace Generators
1981
1982using namespace Generators;
1983
1984} // end namespace Catch
1985
1986#define INTERNAL_CATCH_LINESTR2( line ) #line
1987#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
1988
1989#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
1990
1991// #included from: internal/catch_interfaces_exception.h
1992
Phil Nash89d1e6c2011-05-24 08:23:02 +01001993#include <string>
1994
1995namespace Catch
1996{
1997 typedef std::string(*exceptionTranslateFunction)();
1998
1999 struct IExceptionTranslator
2000 {
2001 virtual ~IExceptionTranslator(){}
2002 virtual std::string translate() const = 0;
2003 };
2004
2005 struct IExceptionTranslatorRegistry
2006 {
2007 virtual ~IExceptionTranslatorRegistry
2008 ()
2009 {}
2010
2011 virtual void registerTranslator
2012 ( IExceptionTranslator* translator
2013 ) = 0;
2014 virtual std::string translateActiveException
2015 () const = 0;
2016
2017 };
2018
2019 class ExceptionTranslatorRegistrar
2020 {
2021 template<typename T>
2022 class ExceptionTranslator : public IExceptionTranslator
2023 {
2024 public:
2025
2026 ExceptionTranslator
2027 (
2028 std::string(*translateFunction)( T& )
2029 )
2030 : m_translateFunction( translateFunction )
2031 {}
2032
2033 virtual std::string translate
2034 ()
2035 const
2036 {
2037 try
2038 {
2039 throw;
2040 }
2041 catch( T& ex )
2042 {
2043 return m_translateFunction( ex );
2044 }
2045 }
2046
2047 protected:
2048 std::string(*m_translateFunction)( T& );
2049 };
2050
2051 public:
2052 template<typename T>
2053 ExceptionTranslatorRegistrar
2054 (
2055 std::string(*translateFunction)( T& )
2056 )
2057 {
Phil Nash176eb812012-05-11 08:17:16 +01002058 Catch::Context::getExceptionTranslatorRegistry().registerTranslator
Phil Nash89d1e6c2011-05-24 08:23:02 +01002059 ( new ExceptionTranslator<T>( translateFunction ) );
2060 }
2061 };
2062}
2063
2064///////////////////////////////////////////////////////////////////////////////
2065#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
2066 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
2067 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
2068 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
2069
2070// #included from: internal/catch_approx.hpp
2071
Phil Nash89d1e6c2011-05-24 08:23:02 +01002072#include <cmath>
2073#include <limits>
2074
2075namespace Catch
2076{
2077 namespace Detail
2078 {
2079 class Approx
2080 {
2081 public:
2082 ///////////////////////////////////////////////////////////////////////////
2083 explicit Approx
2084 (
Phil Nashf721a962011-06-07 14:13:57 +01002085 double value
Phil Nash89d1e6c2011-05-24 08:23:02 +01002086 )
Phil Nashf721a962011-06-07 14:13:57 +01002087 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
Phil Nash89d1e6c2011-05-24 08:23:02 +01002088 m_scale( 1.0 ),
Phil Nashf721a962011-06-07 14:13:57 +01002089 m_value( value )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002090 {
2091 }
2092
2093 ///////////////////////////////////////////////////////////////////////////
Phil Nashf721a962011-06-07 14:13:57 +01002094 Approx
2095 (
2096 const Approx& other
2097 )
2098 : m_epsilon( other.m_epsilon ),
2099 m_scale( other.m_scale ),
2100 m_value( other.m_value )
2101 {
2102 }
2103
2104 ///////////////////////////////////////////////////////////////////////////
2105 static Approx custom
2106 ()
2107 {
2108 return Approx( 0 );
2109 }
2110
2111 ///////////////////////////////////////////////////////////////////////////
2112 Approx operator()
2113 (
2114 double value
2115 )
2116 {
2117 Approx approx( value );
2118 approx.epsilon( m_epsilon );
2119 approx.scale( m_scale );
2120 return approx;
2121 }
2122
2123 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01002124 friend bool operator ==
2125 (
Phil Nash6b6143c2011-05-31 07:51:04 +01002126 double lhs,
Phil Nash89d1e6c2011-05-24 08:23:02 +01002127 const Approx& rhs
2128 )
2129 {
2130 // Thanks to Richard Harris for his help refining this formula
Phil Nashf721a962011-06-07 14:13:57 +01002131 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01002132 }
2133
2134 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01002135 friend bool operator ==
2136 (
2137 const Approx& lhs,
Phil Nash6b6143c2011-05-31 07:51:04 +01002138 double rhs
Phil Nash89d1e6c2011-05-24 08:23:02 +01002139 )
2140 {
2141 return operator==( rhs, lhs );
2142 }
2143
2144 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01002145 friend bool operator !=
2146 (
Phil Nash6b6143c2011-05-31 07:51:04 +01002147 double lhs,
Phil Nash89d1e6c2011-05-24 08:23:02 +01002148 const Approx& rhs
2149 )
2150 {
2151 return !operator==( lhs, rhs );
2152 }
2153
2154 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01002155 friend bool operator !=
2156 (
2157 const Approx& lhs,
Phil Nash6b6143c2011-05-31 07:51:04 +01002158 double rhs
Phil Nash89d1e6c2011-05-24 08:23:02 +01002159 )
2160 {
2161 return !operator==( rhs, lhs );
2162 }
2163
Phil Nash89d1e6c2011-05-24 08:23:02 +01002164 ///////////////////////////////////////////////////////////////////////////
2165 Approx& epsilon
2166 (
2167 double newEpsilon
2168 )
2169 {
2170 m_epsilon = newEpsilon;
2171 return *this;
2172 }
2173
2174 ///////////////////////////////////////////////////////////////////////////
2175 Approx& scale
2176 (
2177 double newScale
2178 )
2179 {
2180 m_scale = newScale;
2181 return *this;
2182 }
2183
2184 ///////////////////////////////////////////////////////////////////////////
2185 std::string toString() const
2186 {
2187 std::ostringstream oss;
Phil Nashf721a962011-06-07 14:13:57 +01002188 oss << "Approx( " << m_value << ")";
Phil Nash89d1e6c2011-05-24 08:23:02 +01002189 return oss.str();
2190 }
2191
2192 private:
2193 double m_epsilon;
2194 double m_scale;
Phil Nashf721a962011-06-07 14:13:57 +01002195 double m_value;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002196 };
2197 }
2198
2199 ///////////////////////////////////////////////////////////////////////////////
2200 template<>
2201 inline std::string toString<Detail::Approx>
2202 (
2203 const Detail::Approx& value
2204 )
2205 {
2206 return value.toString();
2207 }
2208
2209} // end namespace Catch
2210
Phil Nash83224e62011-08-12 18:53:28 +01002211// #included from: internal/catch_test_case_info.hpp
Phil Nash89d1e6c2011-05-24 08:23:02 +01002212
Phil Nash89d1e6c2011-05-24 08:23:02 +01002213#include <map>
2214#include <string>
2215
2216namespace Catch
2217{
2218 class TestCaseInfo
2219 {
2220 public:
2221 ///////////////////////////////////////////////////////////////////////
2222 TestCaseInfo
2223 (
2224 ITestCase* testCase,
2225 const char* name,
2226 const char* description,
Phil Nashd31737f2012-05-09 19:04:00 +01002227 const SourceLineInfo& lineInfo
Phil Nash89d1e6c2011-05-24 08:23:02 +01002228 )
2229 : m_test( testCase ),
2230 m_name( name ),
2231 m_description( description ),
Phil Nashd31737f2012-05-09 19:04:00 +01002232 m_lineInfo( lineInfo )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002233 {
2234 }
2235
2236 ///////////////////////////////////////////////////////////////////////
2237 TestCaseInfo
2238 ()
Phil Nashf51d3162011-12-28 10:37:31 +00002239 : m_test( NULL ),
2240 m_name(),
Phil Nashd31737f2012-05-09 19:04:00 +01002241 m_description()
Phil Nash89d1e6c2011-05-24 08:23:02 +01002242 {
2243 }
2244
2245 ///////////////////////////////////////////////////////////////////////
2246 TestCaseInfo
2247 (
2248 const TestCaseInfo& other
2249 )
2250 : m_test( other.m_test->clone() ),
2251 m_name( other.m_name ),
2252 m_description( other.m_description ),
Phil Nashd31737f2012-05-09 19:04:00 +01002253 m_lineInfo( other.m_lineInfo )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002254 {
2255 }
2256
2257 ///////////////////////////////////////////////////////////////////////
2258 TestCaseInfo
2259 (
2260 const TestCaseInfo& other,
2261 const std::string& name
2262 )
2263 : m_test( other.m_test->clone() ),
2264 m_name( name ),
2265 m_description( other.m_description ),
Phil Nashd31737f2012-05-09 19:04:00 +01002266 m_lineInfo( other.m_lineInfo )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002267 {
2268 }
2269
2270 ///////////////////////////////////////////////////////////////////////
2271 TestCaseInfo& operator =
2272 (
2273 const TestCaseInfo& other
2274 )
2275 {
2276 TestCaseInfo temp( other );
2277 swap( temp );
2278 return *this;
2279 }
2280
2281 ///////////////////////////////////////////////////////////////////////
2282 ~TestCaseInfo
2283 ()
2284 {
2285 delete m_test;
2286 }
2287
2288 ///////////////////////////////////////////////////////////////////////
2289 void invoke
2290 ()
2291 const
2292 {
2293 m_test->invoke();
2294 }
2295
2296 ///////////////////////////////////////////////////////////////////////
2297 const std::string& getName
2298 ()
2299 const
2300 {
2301 return m_name;
2302 }
2303
2304 ///////////////////////////////////////////////////////////////////////
2305 const std::string& getDescription
2306 ()
2307 const
2308 {
2309 return m_description;
2310 }
2311
2312 ///////////////////////////////////////////////////////////////////////
Phil Nashd31737f2012-05-09 19:04:00 +01002313 const SourceLineInfo& getLineInfo
Phil Nash89d1e6c2011-05-24 08:23:02 +01002314 ()
2315 const
2316 {
Phil Nashd31737f2012-05-09 19:04:00 +01002317 return m_lineInfo;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002318 }
2319
2320 ///////////////////////////////////////////////////////////////////////
2321 bool isHidden
2322 ()
2323 const
2324 {
2325 return m_name.size() >= 2 && m_name[0] == '.' && m_name[1] == '/';
2326 }
2327
2328 ///////////////////////////////////////////////////////////////////////
2329 void swap
2330 (
2331 TestCaseInfo& other
2332 )
2333 {
2334 std::swap( m_test, other.m_test );
2335 m_name.swap( other.m_name );
2336 m_description.swap( other.m_description );
Phil Nashd31737f2012-05-09 19:04:00 +01002337 m_lineInfo.swap( other.m_lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +01002338 }
2339
2340 ///////////////////////////////////////////////////////////////////////
2341 bool operator ==
2342 (
2343 const TestCaseInfo& other
2344 )
2345 const
2346 {
Phil Nash4a0a70a2012-02-09 08:37:02 +00002347 return *m_test == *other.m_test && m_name == other.m_name;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002348 }
2349
2350 ///////////////////////////////////////////////////////////////////////
2351 bool operator <
2352 (
2353 const TestCaseInfo& other
2354 )
2355 const
2356 {
Phil Nash4a0a70a2012-02-09 08:37:02 +00002357 return m_name < other.m_name;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002358 }
2359
2360 private:
2361 ITestCase* m_test;
2362 std::string m_name;
2363 std::string m_description;
Phil Nashd31737f2012-05-09 19:04:00 +01002364 SourceLineInfo m_lineInfo;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002365 };
2366
2367 ///////////////////////////////////////////////////////////////////////////
2368 ///////////////////////////////////////////////////////////////////////////
2369
2370 class TestSpec
2371 {
2372 public:
2373 ///////////////////////////////////////////////////////////////////////
2374 TestSpec
2375 (
2376 const std::string& rawSpec
2377 )
2378 : m_rawSpec( rawSpec ),
2379 m_isWildcarded( false )
2380 {
2381 if( m_rawSpec[m_rawSpec.size()-1] == '*' )
2382 {
2383 m_rawSpec = m_rawSpec.substr( 0, m_rawSpec.size()-1 );
2384 m_isWildcarded = true;
2385 }
2386 }
2387
2388 ///////////////////////////////////////////////////////////////////////
2389 bool matches
2390 (
2391 const std::string& testName
2392 )
2393 const
2394 {
2395 if( !m_isWildcarded )
2396 return m_rawSpec == testName;
2397 else
2398 return testName.size() >= m_rawSpec.size() && testName.substr( 0, m_rawSpec.size() ) == m_rawSpec;
2399 }
2400
2401 private:
2402 std::string m_rawSpec;
2403 bool m_isWildcarded;
2404 };
2405}
2406
Phil Nash78d95a02012-03-04 21:22:36 +00002407// #included from: internal/catch_matchers.hpp
2408
Phil Nash78d95a02012-03-04 21:22:36 +00002409namespace Catch
2410{
2411namespace Matchers
2412{
2413 namespace Impl
2414 {
2415 namespace StdString
2416 {
2417 struct Contains
2418 {
2419 Contains( const std::string& substr ) : m_substr( substr ){}
2420
2421 bool operator()( const std::string& str ) const
2422 {
2423 return str.find( m_substr ) != std::string::npos;
2424 }
2425
2426 friend std::ostream& operator<<( std::ostream& os, const Contains& matcher )
2427 {
2428 os << "contains: \"" << matcher.m_substr << "\"";
2429 return os;
2430 }
2431 std::string m_substr;
2432 };
2433
2434 struct StartsWith
2435 {
2436 StartsWith( const std::string& substr ) : m_substr( substr ){}
2437
2438 bool operator()( const std::string& str ) const
2439 {
2440 return str.find( m_substr ) == 0;
2441 }
2442
2443 friend std::ostream& operator<<( std::ostream& os, const StartsWith& matcher )
2444 {
2445 os << "starts with: \"" << matcher.m_substr << "\"";
2446 return os;
2447 }
2448 std::string m_substr;
2449 };
2450
2451 struct EndsWith
2452 {
2453 EndsWith( const std::string& substr ) : m_substr( substr ){}
2454
2455 bool operator()( const std::string& str ) const
2456 {
2457 return str.find( m_substr ) == str.size() - m_substr.size();
2458 }
2459
2460 friend std::ostream& operator<<( std::ostream& os, const EndsWith& matcher )
2461 {
2462 os << "ends with: \"" << matcher.m_substr << "\"";
2463 return os;
2464 }
2465 std::string m_substr;
2466 };
2467 } // namespace StdString
2468 } // namespace Impl
2469
2470 inline Impl::StdString::Contains Contains( const std::string& substr ){ return Impl::StdString::Contains( substr ); }
2471 inline Impl::StdString::StartsWith StartsWith( const std::string& substr ){ return Impl::StdString::StartsWith( substr ); }
2472 inline Impl::StdString::EndsWith EndsWith( const std::string& substr ){ return Impl::StdString::EndsWith( substr ); }
2473
2474} // namespace Matchers
2475
2476using namespace Matchers;
2477
2478} // namespace Catch
2479
Phil Nash81528252011-08-15 09:06:31 +01002480#ifdef __OBJC__
2481// #included from: internal/catch_objc.hpp
2482
Phil Nasha162e222012-02-10 08:30:13 +00002483#import <Foundation/Foundation.h>
Phil Nash81528252011-08-15 09:06:31 +01002484#import <objc/runtime.h>
Phil Nasha162e222012-02-10 08:30:13 +00002485
Phil Nash81528252011-08-15 09:06:31 +01002486#include <string>
2487
2488// NB. Any general catch headers included here must be included
2489// in catch.hpp first to make sure they are included by the single
2490// header for non obj-usage
2491
Phil Nash53c990a2012-03-17 18:20:06 +00002492#ifdef __has_feature
2493#define CATCH_ARC_ENABLED __has_feature(objc_arc)
2494#else
2495#define CATCH_ARC_ENABLED 0
2496#endif
2497
2498void arcSafeRelease( NSObject* obj );
2499id performOptionalSelector( id obj, SEL sel );
2500
2501#if !CATCH_ARC_ENABLED
Phil Nash861a1e72012-04-28 12:29:52 +01002502 inline void arcSafeRelease( NSObject* obj )
2503 {
2504 [obj release];
2505 }
2506 inline id performOptionalSelector( id obj, SEL sel )
2507 {
2508 if( [obj respondsToSelector: sel] )
2509 return [obj performSelector: sel];
2510 return nil;
2511 }
2512 #define CATCH_UNSAFE_UNRETAINED
Phil Nash53c990a2012-03-17 18:20:06 +00002513#else
Phil Nash861a1e72012-04-28 12:29:52 +01002514 inline void arcSafeRelease( NSObject* ){}
2515 inline id performOptionalSelector( id obj, SEL sel )
2516 {
2517 #pragma clang diagnostic push
2518 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
2519 if( [obj respondsToSelector: sel] )
2520 return [obj performSelector: sel];
2521 #pragma clang diagnostic pop
2522 return nil;
2523 }
2524 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
Phil Nash53c990a2012-03-17 18:20:06 +00002525#endif
2526
Phil Nash83224e62011-08-12 18:53:28 +01002527///////////////////////////////////////////////////////////////////////////////
2528// This protocol is really only here for (self) documenting purposes, since
2529// all its methods are optional.
2530@protocol OcFixture
2531
2532@optional
2533
2534-(void) setUp;
2535-(void) tearDown;
2536
2537@end
2538
2539namespace Catch
2540{
2541 class OcMethod : public ITestCase
2542 {
2543 public:
2544 ///////////////////////////////////////////////////////////////////////
2545 OcMethod
2546 (
2547 Class cls,
2548 SEL sel
2549 )
2550 : m_cls( cls ),
2551 m_sel( sel )
2552 {
2553 }
2554
2555 ///////////////////////////////////////////////////////////////////////
2556 virtual void invoke
2557 ()
2558 const
2559 {
Phil Nash53c990a2012-03-17 18:20:06 +00002560 id obj = [[m_cls alloc] init];
Phil Nash83224e62011-08-12 18:53:28 +01002561
Phil Nash53c990a2012-03-17 18:20:06 +00002562 performOptionalSelector( obj, @selector(setUp) );
2563 performOptionalSelector( obj, m_sel );
2564 performOptionalSelector( obj, @selector(tearDown) );
Phil Nash83224e62011-08-12 18:53:28 +01002565
Phil Nash53c990a2012-03-17 18:20:06 +00002566 arcSafeRelease( obj );
Phil Nash83224e62011-08-12 18:53:28 +01002567 }
2568
2569 ///////////////////////////////////////////////////////////////////////
2570 virtual ITestCase* clone
2571 ()
2572 const
2573 {
2574 return new OcMethod( m_cls, m_sel );
2575 }
2576
2577 ///////////////////////////////////////////////////////////////////////
2578 virtual bool operator ==
2579 (
2580 const ITestCase& other
2581 )
2582 const
2583 {
2584 const OcMethod* ocmOther = dynamic_cast<const OcMethod*> ( &other );
2585 return ocmOther && ocmOther->m_sel == m_sel;
2586 }
2587
2588 ///////////////////////////////////////////////////////////////////////
2589 virtual bool operator <
2590 (
2591 const ITestCase& other
2592 )
2593 const
2594 {
2595 const OcMethod* ocmOther = dynamic_cast<const OcMethod*> ( &other );
2596 return ocmOther && ocmOther->m_sel < m_sel;
2597 }
2598
2599 private:
2600 Class m_cls;
2601 SEL m_sel;
2602 };
2603
2604 namespace Detail
2605 {
2606
2607 ///////////////////////////////////////////////////////////////////////
2608 inline bool startsWith
2609 (
2610 const std::string& str,
2611 const std::string& sub
2612 )
2613 {
2614 return str.length() > sub.length() && str.substr( 0, sub.length() ) == sub;
2615 }
2616
2617 ///////////////////////////////////////////////////////////////////////
Phil Nash53c990a2012-03-17 18:20:06 +00002618 inline std::string getAnnotation
Phil Nash83224e62011-08-12 18:53:28 +01002619 (
2620 Class cls,
2621 const std::string& annotationName,
2622 const std::string& testCaseName
2623 )
2624 {
2625 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2626 SEL sel = NSSelectorFromString( selStr );
Phil Nash53c990a2012-03-17 18:20:06 +00002627 arcSafeRelease( selStr );
2628 id value = performOptionalSelector( cls, sel );
2629 if( value )
2630 return [(NSString*)value UTF8String];
Phil Nash83224e62011-08-12 18:53:28 +01002631 return "";
2632 }
2633 }
2634
2635 ///////////////////////////////////////////////////////////////////////////
2636 inline size_t registerTestMethods
2637 ()
2638 {
2639 size_t noTestMethods = 0;
2640 int noClasses = objc_getClassList( NULL, 0 );
2641
Phil Nash861a1e72012-04-28 12:29:52 +01002642 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
Phil Nash53c990a2012-03-17 18:20:06 +00002643 objc_getClassList( classes, noClasses );
Phil Nash83224e62011-08-12 18:53:28 +01002644
2645 for( int c = 0; c < noClasses; c++ )
2646 {
2647 Class cls = classes[c];
2648 {
2649 u_int count;
2650 Method* methods = class_copyMethodList( cls, &count );
2651 for( int m = 0; m < count ; m++ )
2652 {
2653 SEL selector = method_getName(methods[m]);
2654 std::string methodName = sel_getName(selector);
2655 if( Detail::startsWith( methodName, "Catch_TestCase_" ) )
2656 {
2657 std::string testCaseName = methodName.substr( 15 );
Phil Nash53c990a2012-03-17 18:20:06 +00002658 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
2659 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
Phil Nash83224e62011-08-12 18:53:28 +01002660
Phil Nash176eb812012-05-11 08:17:16 +01002661 Context::getTestCaseRegistry().registerTest( TestCaseInfo( new OcMethod( cls, selector ), name.c_str(), desc.c_str(), SourceLineInfo() ) );
Phil Nash83224e62011-08-12 18:53:28 +01002662 noTestMethods++;
2663
2664 }
2665 }
2666 free(methods);
2667 }
2668 }
2669 return noTestMethods;
2670 }
Phil Nash78d95a02012-03-04 21:22:36 +00002671
Phil Nash53c990a2012-03-17 18:20:06 +00002672 inline std::string toString( NSString* const& nsstring )
Phil Nash78d95a02012-03-04 21:22:36 +00002673 {
2674 return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
2675 }
2676
2677 namespace Matchers
2678 {
2679 namespace Impl
2680 {
2681 namespace NSStringMatchers
2682 {
2683 struct StringHolder
2684 {
2685 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
2686 StringHolder()
2687 {
Phil Nash53c990a2012-03-17 18:20:06 +00002688 arcSafeRelease( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00002689 }
2690
2691 NSString* m_substr;
2692 };
2693
Phil Nash8d18d162012-03-14 20:06:14 +00002694 struct Equals : StringHolder
2695 {
2696 Equals( NSString* substr ) : StringHolder( substr ){}
2697
2698 bool operator()( NSString* str ) const
2699 {
2700 return [str isEqualToString:m_substr];
2701 }
2702
2703 friend std::ostream& operator<<( std::ostream& os, const Equals& matcher )
2704 {
2705 os << "equals string: " << Catch::toString( matcher.m_substr );
2706 return os;
2707 }
2708 };
2709
Phil Nash78d95a02012-03-04 21:22:36 +00002710 struct Contains : StringHolder
2711 {
2712 Contains( NSString* substr ) : StringHolder( substr ){}
2713
2714 bool operator()( NSString* str ) const
2715 {
2716 return [str rangeOfString:m_substr].location != NSNotFound;
2717 }
2718
2719 friend std::ostream& operator<<( std::ostream& os, const Contains& matcher )
2720 {
2721 os << "contains: " << Catch::toString( matcher.m_substr );
2722 return os;
2723 }
2724 };
2725
2726 struct StartsWith : StringHolder
2727 {
2728 StartsWith( NSString* substr ) : StringHolder( substr ){}
2729
2730 bool operator()( NSString* str ) const
2731 {
2732 return [str rangeOfString:m_substr].location == 0;
2733 }
2734
2735 friend std::ostream& operator<<( std::ostream& os, const StartsWith& matcher )
2736 {
2737 os << "starts with: " << Catch::toString( matcher.m_substr );
2738 return os;
2739 }
2740 };
2741 struct EndsWith : StringHolder
2742 {
2743 EndsWith( NSString* substr ) : StringHolder( substr ){}
2744
2745 bool operator()( NSString* str ) const
2746 {
2747 return [str rangeOfString:m_substr].location == [str length] - [m_substr length];
2748 }
2749
2750 friend std::ostream& operator<<( std::ostream& os, const EndsWith& matcher )
2751 {
2752 os << "ends with: " << Catch::toString( matcher.m_substr );
2753 return os;
2754 }
2755 };
2756
2757 } // namespace NSStringMatchers
2758 } // namespace Impl
2759
Phil Nash8d18d162012-03-14 20:06:14 +00002760 inline Impl::NSStringMatchers::Equals
2761 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
2762
Phil Nash78d95a02012-03-04 21:22:36 +00002763 inline Impl::NSStringMatchers::Contains
2764 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00002765
Phil Nash78d95a02012-03-04 21:22:36 +00002766 inline Impl::NSStringMatchers::StartsWith
2767 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00002768
Phil Nash78d95a02012-03-04 21:22:36 +00002769 inline Impl::NSStringMatchers::EndsWith
2770 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
2771
2772 } // namespace Matchers
2773
2774 using namespace Matchers;
2775
2776} // namespace Catch
Phil Nash83224e62011-08-12 18:53:28 +01002777
2778///////////////////////////////////////////////////////////////////////////////
2779#define OC_TEST_CASE( name, desc )\
Phil Nash53c990a2012-03-17 18:20:06 +00002780+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01002781{\
Phil Nash53c990a2012-03-17 18:20:06 +00002782return @ name; \
Phil Nash83224e62011-08-12 18:53:28 +01002783}\
Phil Nash53c990a2012-03-17 18:20:06 +00002784+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01002785{ \
Phil Nash53c990a2012-03-17 18:20:06 +00002786return @ desc; \
Phil Nash83224e62011-08-12 18:53:28 +01002787} \
2788-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
2789
2790#endif
2791
2792#if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER )
2793// #included from: catch_runner.hpp
2794
Phil Nash176eb812012-05-11 08:17:16 +01002795// #included from: internal/catch_context_impl.hpp
Phil Nash83224e62011-08-12 18:53:28 +01002796// #included from: catch_test_case_registry_impl.hpp
2797
Phil Nash89d1e6c2011-05-24 08:23:02 +01002798#include <vector>
2799#include <set>
2800#include <sstream>
Phil Nash62179662012-05-11 19:06:43 +01002801#include <iostream>
Phil Nash89d1e6c2011-05-24 08:23:02 +01002802
Phil Nash89d1e6c2011-05-24 08:23:02 +01002803namespace Catch
2804{
Phil Nash176eb812012-05-11 08:17:16 +01002805 class TestRegistry : public ITestCaseRegistry {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002806 public:
Phil Nash176eb812012-05-11 08:17:16 +01002807 TestRegistry() : m_unnamedCount( 0 ) {}
Phil Nash89d1e6c2011-05-24 08:23:02 +01002808
Phil Nash176eb812012-05-11 08:17:16 +01002809 virtual void registerTest( const TestCaseInfo& testInfo ) {
2810 if( testInfo.getName() == "" ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002811 std::ostringstream oss;
2812 oss << testInfo.getName() << "unnamed/" << ++m_unnamedCount;
2813 return registerTest( TestCaseInfo( testInfo, oss.str() ) );
2814 }
Phil Nash176eb812012-05-11 08:17:16 +01002815
2816 if( m_functions.find( testInfo ) == m_functions.end() ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002817 m_functions.insert( testInfo );
2818 m_functionsInOrder.push_back( testInfo );
2819 }
Phil Nash176eb812012-05-11 08:17:16 +01002820 else {
Phil Nash4a0a70a2012-02-09 08:37:02 +00002821 const TestCaseInfo& prev = *m_functions.find( testInfo );
2822 std::cerr << "error: TEST_CASE( \"" << testInfo.getName() << "\" ) already defined.\n"
Phil Nashd31737f2012-05-09 19:04:00 +01002823 << "\tFirst seen at " << SourceLineInfo( prev.getLineInfo() ) << "\n"
2824 << "\tRedefined at " << SourceLineInfo( testInfo.getLineInfo() ) << std::endl;
Phil Nash4a0a70a2012-02-09 08:37:02 +00002825 exit(1);
2826 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002827 }
2828
Phil Nash176eb812012-05-11 08:17:16 +01002829 virtual const std::vector<TestCaseInfo>& getAllTests() const {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002830 return m_functionsInOrder;
2831 }
2832
Phil Nash176eb812012-05-11 08:17:16 +01002833 virtual std::vector<TestCaseInfo> getMatchingTestCases( const std::string& rawTestSpec ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002834 TestSpec testSpec( rawTestSpec );
2835
2836 std::vector<TestCaseInfo> testList;
2837 std::vector<TestCaseInfo>::const_iterator it = m_functionsInOrder.begin();
2838 std::vector<TestCaseInfo>::const_iterator itEnd = m_functionsInOrder.end();
Phil Nash176eb812012-05-11 08:17:16 +01002839 for(; it != itEnd; ++it ) {
2840 if( testSpec.matches( it->getName() ) ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002841 testList.push_back( *it );
Phil Nash89d1e6c2011-05-24 08:23:02 +01002842 }
2843 }
2844 return testList;
2845 }
2846
2847 private:
2848
2849 std::set<TestCaseInfo> m_functions;
2850 std::vector<TestCaseInfo> m_functionsInOrder;
2851 size_t m_unnamedCount;
2852 };
2853
2854 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01002855
Phil Nash176eb812012-05-11 08:17:16 +01002856 class FreeFunctionTestCase : public ITestCase {
2857 public:
Phil Nash89d1e6c2011-05-24 08:23:02 +01002858
Phil Nash176eb812012-05-11 08:17:16 +01002859 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
2860
2861 virtual void invoke() const {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002862 m_fun();
2863 }
2864
Phil Nash176eb812012-05-11 08:17:16 +01002865 virtual ITestCase* clone() const {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002866 return new FreeFunctionTestCase( m_fun );
2867 }
2868
Phil Nash176eb812012-05-11 08:17:16 +01002869 virtual bool operator == ( const ITestCase& other ) const {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002870 const FreeFunctionTestCase* ffOther = dynamic_cast<const FreeFunctionTestCase*> ( &other );
2871 return ffOther && m_fun == ffOther->m_fun;
2872 }
2873
Phil Nash176eb812012-05-11 08:17:16 +01002874 virtual bool operator < ( const ITestCase& other ) const {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002875 const FreeFunctionTestCase* ffOther = dynamic_cast<const FreeFunctionTestCase*> ( &other );
2876 return ffOther && m_fun < ffOther->m_fun;
2877 }
2878
2879 private:
2880 TestFunction m_fun;
2881 };
2882
2883 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01002884
Phil Nash176eb812012-05-11 08:17:16 +01002885 AutoReg::AutoReg( TestFunction function,
2886 const char* name,
2887 const char* description,
2888 const SourceLineInfo& lineInfo ) {
Phil Nashd31737f2012-05-09 19:04:00 +01002889 registerTestCase( new FreeFunctionTestCase( function ), name, description, lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +01002890 }
2891
Phil Nash176eb812012-05-11 08:17:16 +01002892 AutoReg::~AutoReg() {}
Phil Nash89d1e6c2011-05-24 08:23:02 +01002893
Phil Nash176eb812012-05-11 08:17:16 +01002894 void AutoReg::registerTestCase( ITestCase* testCase,
2895 const char* name,
2896 const char* description,
2897 const SourceLineInfo& lineInfo ) {
2898 Context::getTestCaseRegistry().registerTest( TestCaseInfo( testCase, name, description, lineInfo ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01002899 }
2900
2901} // end namespace Catch
2902
Phil Nash89d1e6c2011-05-24 08:23:02 +01002903// #included from: catch_runner_impl.hpp
2904
Phil Nash89d1e6c2011-05-24 08:23:02 +01002905// #included from: catch_interfaces_runner.h
2906
Phil Nash89d1e6c2011-05-24 08:23:02 +01002907#include <string>
2908
2909namespace Catch
2910{
2911 class TestCaseInfo;
2912
2913 struct IRunner
2914 {
2915 virtual ~IRunner
2916 ()
2917 {}
2918
2919 virtual void runAll
2920 ( bool runHiddenTests = false
2921 ) = 0;
2922
2923 virtual std::size_t runMatching
2924 ( const std::string& rawTestSpec
2925 ) = 0;
2926
Phil Nashf7299fc2012-02-25 09:39:45 +00002927 virtual Totals getTotals
Phil Nash89d1e6c2011-05-24 08:23:02 +01002928 () const = 0;
2929
2930 };
2931}
2932
2933// #included from: catch_config.hpp
2934
Phil Nash89d1e6c2011-05-24 08:23:02 +01002935#include <memory>
2936#include <vector>
2937#include <string>
2938#include <iostream>
2939
2940namespace Catch
2941{
2942
2943 class Config : public IReporterConfig
2944 {
2945 private:
2946 Config( const Config& other );
2947 Config& operator = ( const Config& other );
2948 public:
2949
2950 struct Include { enum What
2951 {
2952 FailedOnly,
2953 SuccessfulResults
2954 }; };
2955
2956 struct List{ enum What
2957 {
2958 None = 0,
2959
2960 Reports = 1,
2961 Tests = 2,
2962 All = 3,
2963
2964 WhatMask = 0xf,
2965
2966 AsText = 0x10,
2967 AsXml = 0x11,
2968
2969 AsMask = 0xf0
2970 }; };
2971
Phil Nash89d1e6c2011-05-24 08:23:02 +01002972 ///////////////////////////////////////////////////////////////////////////
2973 Config()
Phil Nash49e6d532012-05-05 19:35:35 +01002974 : m_listSpec( List::None ),
Phil Nash89d1e6c2011-05-24 08:23:02 +01002975 m_shouldDebugBreak( false ),
2976 m_showHelp( false ),
Phil Nash48112c22011-05-31 18:47:30 +01002977 m_streambuf( NULL ),
2978 m_os( std::cout.rdbuf() ),
Phil Nash89d1e6c2011-05-24 08:23:02 +01002979 m_includeWhat( Include::FailedOnly )
2980 {}
2981
2982 ///////////////////////////////////////////////////////////////////////////
2983 ~Config()
2984 {
Phil Nash48112c22011-05-31 18:47:30 +01002985 m_os.rdbuf( std::cout.rdbuf() );
2986 delete m_streambuf;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002987 }
2988
2989 ///////////////////////////////////////////////////////////////////////////
2990 void setReporter( const std::string& reporterName )
2991 {
2992 if( m_reporter.get() )
2993 return setError( "Only one reporter may be specified" );
Phil Nash176eb812012-05-11 08:17:16 +01002994 setReporter( Context::getReporterRegistry().create( reporterName, *this ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01002995 }
2996
2997 ///////////////////////////////////////////////////////////////////////////
2998 void addTestSpec( const std::string& testSpec )
2999 {
3000 m_testSpecs.push_back( testSpec );
3001 }
3002
3003 ///////////////////////////////////////////////////////////////////////////
3004 bool testsSpecified() const
3005 {
3006 return !m_testSpecs.empty();
3007 }
3008
3009 ///////////////////////////////////////////////////////////////////////////
3010 const std::vector<std::string>& getTestSpecs() const
3011 {
3012 return m_testSpecs;
3013 }
3014
3015 ///////////////////////////////////////////////////////////////////////////
3016 List::What getListSpec( void ) const
3017 {
3018 return m_listSpec;
3019 }
3020
3021 ///////////////////////////////////////////////////////////////////////////
3022 void setListSpec( List::What listSpec )
3023 {
3024 m_listSpec = listSpec;
3025 }
3026
3027 ///////////////////////////////////////////////////////////////////////////
3028 void setFilename( const std::string& filename )
3029 {
3030 m_filename = filename;
3031 }
3032
3033 ///////////////////////////////////////////////////////////////////////////
3034 const std::string& getFilename() const
3035 {
3036 return m_filename;
3037 }
3038
3039 ///////////////////////////////////////////////////////////////////////////
3040 const std::string& getMessage() const
3041 {
3042 return m_message;
3043 }
3044
3045 ///////////////////////////////////////////////////////////////////////////
3046 void setError( const std::string& errorMessage )
3047 {
3048 m_message = errorMessage + "\n\n" + "Usage: ...";
3049 }
3050
3051 ///////////////////////////////////////////////////////////////////////////
3052 void setReporter( IReporter* reporter )
3053 {
Phil Nash49e6d532012-05-05 19:35:35 +01003054 m_reporter = reporter;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003055 }
3056
3057 ///////////////////////////////////////////////////////////////////////////
Phil Nash49e6d532012-05-05 19:35:35 +01003058 Ptr<IReporter> getReporter()
Phil Nash89d1e6c2011-05-24 08:23:02 +01003059 {
3060 if( !m_reporter.get() )
Phil Nash176eb812012-05-11 08:17:16 +01003061 const_cast<Config*>( this )->setReporter( Context::getReporterRegistry().create( "basic", *this ) );
Phil Nash49e6d532012-05-05 19:35:35 +01003062 return m_reporter;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003063 }
3064
3065 ///////////////////////////////////////////////////////////////////////////
3066 List::What listWhat() const
3067 {
3068 return static_cast<List::What>( m_listSpec & List::WhatMask );
3069 }
3070
3071 ///////////////////////////////////////////////////////////////////////////
3072 List::What listAs() const
3073 {
3074 return static_cast<List::What>( m_listSpec & List::AsMask );
3075 }
3076
3077 ///////////////////////////////////////////////////////////////////////////
3078 void setIncludeWhat( Include::What includeWhat )
3079 {
3080 m_includeWhat = includeWhat;
3081 }
3082
3083 ///////////////////////////////////////////////////////////////////////////
3084 void setShouldDebugBreak( bool shouldDebugBreakFlag )
3085 {
3086 m_shouldDebugBreak = shouldDebugBreakFlag;
3087 }
3088
3089 ///////////////////////////////////////////////////////////////////////////
3090 void setName( const std::string& name )
3091 {
3092 m_name = name;
3093 }
3094
3095 ///////////////////////////////////////////////////////////////////////////
3096 std::string getName() const
3097 {
3098 return m_name;
3099 }
3100
3101 ///////////////////////////////////////////////////////////////////////////
3102 bool shouldDebugBreak() const
3103 {
3104 return m_shouldDebugBreak;
3105 }
3106
3107 ///////////////////////////////////////////////////////////////////////////
3108 void setShowHelp( bool showHelpFlag )
3109 {
3110 m_showHelp = showHelpFlag;
3111 }
3112
3113 ///////////////////////////////////////////////////////////////////////////
3114 bool showHelp() const
3115 {
3116 return m_showHelp;
3117 }
3118
3119 ///////////////////////////////////////////////////////////////////////////
3120 virtual std::ostream& stream() const
3121 {
3122 return m_os;
3123 }
3124
3125 ///////////////////////////////////////////////////////////////////////////
3126 void setStreamBuf( std::streambuf* buf )
3127 {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003128 m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
3129 }
3130
3131 ///////////////////////////////////////////////////////////////////////////
3132 void useStream( const std::string& streamName )
3133 {
Phil Nash176eb812012-05-11 08:17:16 +01003134 std::streambuf* newBuf = Context::createStreamBuf( streamName );
Phil Nash48112c22011-05-31 18:47:30 +01003135 setStreamBuf( newBuf );
3136 delete m_streambuf;
3137 m_streambuf = newBuf;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003138 }
3139
3140 ///////////////////////////////////////////////////////////////////////////
3141 virtual bool includeSuccessfulResults() const
3142 {
3143 return m_includeWhat == Include::SuccessfulResults;
3144 }
3145
3146 private:
Phil Nash49e6d532012-05-05 19:35:35 +01003147 Ptr<IReporter> m_reporter;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003148 std::string m_filename;
3149 std::string m_message;
3150 List::What m_listSpec;
3151 std::vector<std::string> m_testSpecs;
3152 bool m_shouldDebugBreak;
3153 bool m_showHelp;
3154 std::streambuf* m_streambuf;
3155 mutable std::ostream m_os;
3156 Include::What m_includeWhat;
3157 std::string m_name;
3158
3159 };
3160
3161} // end namespace Catch
3162
Phil Nash49e6d532012-05-05 19:35:35 +01003163// #included from: catch_running_test.hpp
Phil Nash89d1e6c2011-05-24 08:23:02 +01003164
Phil Nash49e6d532012-05-05 19:35:35 +01003165// #included from: catch_section_info.hpp
3166
Phil Nash49e6d532012-05-05 19:35:35 +01003167#include <map>
Phil Nash89d1e6c2011-05-24 08:23:02 +01003168#include <string>
3169
3170namespace Catch
3171{
Phil Nash89d1e6c2011-05-24 08:23:02 +01003172 ///////////////////////////////////////////////////////////////////////////
3173 ///////////////////////////////////////////////////////////////////////////
3174 class SectionInfo
3175 {
3176 public:
3177 enum Status
3178 {
3179 Root,
3180 Unknown,
Phil Nash49e6d532012-05-05 19:35:35 +01003181 Branch,
3182 TestedBranch,
Phil Nash89d1e6c2011-05-24 08:23:02 +01003183 TestedLeaf
3184 };
3185
3186 ///////////////////////////////////////////////////////////////////////
3187 SectionInfo
3188 (
3189 SectionInfo* parent
3190 )
3191 : m_status( Unknown ),
3192 m_parent( parent )
3193 {
3194 }
3195
3196 ///////////////////////////////////////////////////////////////////////
3197 SectionInfo
3198 ()
3199 : m_status( Root ),
3200 m_parent( NULL )
3201 {
3202 }
3203
3204 ///////////////////////////////////////////////////////////////////////
3205 ~SectionInfo
3206 ()
3207 {
3208 deleteAllValues( m_subSections );
3209 }
3210
3211 ///////////////////////////////////////////////////////////////////////
3212 bool shouldRun
3213 ()
3214 const
3215 {
Phil Nash49e6d532012-05-05 19:35:35 +01003216 return m_status < TestedBranch;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003217 }
3218
3219 ///////////////////////////////////////////////////////////////////////
3220 bool ran
3221 ()
3222 {
Phil Nash49e6d532012-05-05 19:35:35 +01003223 if( m_status < Branch )
Phil Nash89d1e6c2011-05-24 08:23:02 +01003224 {
3225 m_status = TestedLeaf;
3226 return true;
3227 }
3228 return false;
3229 }
Phil Nash49e6d532012-05-05 19:35:35 +01003230 ///////////////////////////////////////////////////////////////////////
3231 void ranToCompletion
3232 ()
3233 {
3234 if( m_status == Branch && !hasUntestedSections() )
3235 {
3236 m_status = TestedBranch;
3237 }
3238 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003239
3240 ///////////////////////////////////////////////////////////////////////
Phil Nash3c20a752011-06-23 08:23:33 +01003241 SectionInfo* findSubSection
Phil Nash89d1e6c2011-05-24 08:23:02 +01003242 (
3243 const std::string& name
3244 )
3245 {
3246 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.find( name );
Phil Nash3c20a752011-06-23 08:23:33 +01003247 return it != m_subSections.end()
Phil Nash49e6d532012-05-05 19:35:35 +01003248 ? it->second
3249 : NULL;
Phil Nash3c20a752011-06-23 08:23:33 +01003250 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003251
Phil Nash3c20a752011-06-23 08:23:33 +01003252 ///////////////////////////////////////////////////////////////////////
3253 SectionInfo* addSubSection
3254 (
3255 const std::string& name
3256 )
3257 {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003258 SectionInfo* subSection = new SectionInfo( this );
3259 m_subSections.insert( std::make_pair( name, subSection ) );
Phil Nash49e6d532012-05-05 19:35:35 +01003260 m_status = Branch;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003261 return subSection;
3262 }
3263
3264 ///////////////////////////////////////////////////////////////////////
3265 SectionInfo* getParent
3266 ()
3267 {
3268 return m_parent;
3269 }
3270
3271 ///////////////////////////////////////////////////////////////////////
3272 bool hasUntestedSections
3273 ()
3274 const
3275 {
Phil Nash3c20a752011-06-23 08:23:33 +01003276 if( m_status == Unknown )
Phil Nash89d1e6c2011-05-24 08:23:02 +01003277 return true;
3278
3279 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.begin();
3280 std::map<std::string, SectionInfo*>::const_iterator itEnd = m_subSections.end();
3281 for(; it != itEnd; ++it )
3282 {
3283 if( it->second->hasUntestedSections() )
3284 return true;
3285 }
3286 return false;
3287 }
3288
3289 private:
3290 Status m_status;
3291 std::map<std::string, SectionInfo*> m_subSections;
3292 SectionInfo* m_parent;
3293 };
Phil Nash49e6d532012-05-05 19:35:35 +01003294}
Phil Nash89d1e6c2011-05-24 08:23:02 +01003295
Phil Nash49e6d532012-05-05 19:35:35 +01003296namespace Catch
3297{
Phil Nash89d1e6c2011-05-24 08:23:02 +01003298 class RunningTest
3299 {
3300 enum RunStatus
3301 {
3302 NothingRun,
3303 EncounteredASection,
3304 RanAtLeastOneSection,
3305 RanToCompletionWithSections,
3306 RanToCompletionWithNoSections
3307 };
3308
3309 public:
3310 ///////////////////////////////////////////////////////////////////////
3311 explicit RunningTest
3312 (
3313 const TestCaseInfo* info = NULL
3314 )
3315 : m_info( info ),
3316 m_runStatus( RanAtLeastOneSection ),
Phil Nash3c20a752011-06-23 08:23:33 +01003317 m_currentSection( &m_rootSection ),
3318 m_changed( false )
Phil Nash89d1e6c2011-05-24 08:23:02 +01003319 {
3320 }
3321
3322 ///////////////////////////////////////////////////////////////////////
3323 bool wasSectionSeen
3324 ()
3325 const
3326 {
3327 return m_runStatus == RanAtLeastOneSection ||
3328 m_runStatus == RanToCompletionWithSections;
3329 }
3330
3331 ///////////////////////////////////////////////////////////////////////
3332 void reset
3333 ()
3334 {
3335 m_runStatus = NothingRun;
Phil Nash3c20a752011-06-23 08:23:33 +01003336 m_changed = false;
Phil Nash49e6d532012-05-05 19:35:35 +01003337 m_lastSectionToRun = NULL;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003338 }
3339
3340 ///////////////////////////////////////////////////////////////////////
3341 void ranToCompletion
3342 ()
3343 {
Phil Nash49e6d532012-05-05 19:35:35 +01003344 if( m_runStatus == RanAtLeastOneSection ||
3345 m_runStatus == EncounteredASection )
3346 {
3347 m_runStatus = RanToCompletionWithSections;
3348 if( m_lastSectionToRun )
3349 {
3350 m_lastSectionToRun->ranToCompletion();
3351 m_changed = true;
3352 }
3353 }
3354 else
3355 {
3356 m_runStatus = RanToCompletionWithNoSections;
3357 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003358 }
3359
3360 ///////////////////////////////////////////////////////////////////////
3361 bool addSection
3362 (
3363 const std::string& name
3364 )
3365 {
3366 if( m_runStatus == NothingRun )
3367 m_runStatus = EncounteredASection;
3368
Phil Nash3c20a752011-06-23 08:23:33 +01003369 SectionInfo* thisSection = m_currentSection->findSubSection( name );
3370 if( !thisSection )
3371 {
3372 thisSection = m_currentSection->addSubSection( name );
3373 m_changed = true;
3374 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003375
3376 if( !wasSectionSeen() && thisSection->shouldRun() )
3377 {
3378 m_currentSection = thisSection;
Phil Nash49e6d532012-05-05 19:35:35 +01003379 m_lastSectionToRun = NULL;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003380 return true;
3381 }
3382 return false;
3383 }
3384
3385 ///////////////////////////////////////////////////////////////////////
3386 void endSection
3387 (
3388 const std::string&
3389 )
3390 {
3391 if( m_currentSection->ran() )
Phil Nash3c20a752011-06-23 08:23:33 +01003392 {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003393 m_runStatus = RanAtLeastOneSection;
Phil Nash3c20a752011-06-23 08:23:33 +01003394 m_changed = true;
3395 }
Phil Nash49e6d532012-05-05 19:35:35 +01003396 else if( m_runStatus == EncounteredASection )
3397 {
3398 m_runStatus = RanAtLeastOneSection;
3399 m_lastSectionToRun = m_currentSection;
3400 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003401 m_currentSection = m_currentSection->getParent();
3402 }
3403
3404 ///////////////////////////////////////////////////////////////////////
3405 const TestCaseInfo& getTestCaseInfo
3406 ()
3407 const
3408 {
3409 return *m_info;
3410 }
3411
3412 ///////////////////////////////////////////////////////////////////////
3413 bool hasUntestedSections
3414 ()
3415 const
3416 {
Phil Nash3c20a752011-06-23 08:23:33 +01003417 return m_runStatus == RanAtLeastOneSection ||
3418 ( m_rootSection.hasUntestedSections() && m_changed );
Phil Nash89d1e6c2011-05-24 08:23:02 +01003419 }
3420
3421 private:
3422 const TestCaseInfo* m_info;
3423 RunStatus m_runStatus;
3424 SectionInfo m_rootSection;
3425 SectionInfo* m_currentSection;
Phil Nash49e6d532012-05-05 19:35:35 +01003426 SectionInfo* m_lastSectionToRun;
Phil Nash3c20a752011-06-23 08:23:33 +01003427 bool m_changed;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003428 };
Phil Nash49e6d532012-05-05 19:35:35 +01003429}
3430
Phil Nash49e6d532012-05-05 19:35:35 +01003431#include <set>
3432#include <string>
3433
3434namespace Catch
3435{
Phil Nash49e6d532012-05-05 19:35:35 +01003436 class StreamRedirect
3437 {
3438 public:
3439 ///////////////////////////////////////////////////////////////////////
3440 StreamRedirect
3441 (
3442 std::ostream& stream,
3443 std::string& targetString
3444 )
3445 : m_stream( stream ),
3446 m_prevBuf( stream.rdbuf() ),
3447 m_targetString( targetString )
3448 {
3449 stream.rdbuf( m_oss.rdbuf() );
3450 }
3451
3452 ///////////////////////////////////////////////////////////////////////
3453 ~StreamRedirect
3454 ()
3455 {
3456 m_targetString += m_oss.str();
3457 m_stream.rdbuf( m_prevBuf );
3458 }
3459
3460 private:
3461 std::ostream& m_stream;
3462 std::streambuf* m_prevBuf;
3463 std::ostringstream m_oss;
3464 std::string& m_targetString;
3465 };
Phil Nash89d1e6c2011-05-24 08:23:02 +01003466
3467 ///////////////////////////////////////////////////////////////////////////
3468 ///////////////////////////////////////////////////////////////////////////
3469 class Runner : public IResultCapture, public IRunner
3470 {
3471 Runner( const Runner& );
3472 void operator =( const Runner& );
3473
3474 public:
3475
3476 ///////////////////////////////////////////////////////////////////////////
3477 explicit Runner
3478 (
Phil Nash49e6d532012-05-05 19:35:35 +01003479 Config& config
Phil Nash89d1e6c2011-05-24 08:23:02 +01003480 )
3481 : m_runningTest( NULL ),
3482 m_config( config ),
Phil Nash49e6d532012-05-05 19:35:35 +01003483 m_reporter( config.getReporter() ),
Phil Nash176eb812012-05-11 08:17:16 +01003484 m_prevRunner( &Context::getRunner() ),
3485 m_prevResultCapture( &Context::getResultCapture() )
Phil Nash89d1e6c2011-05-24 08:23:02 +01003486 {
Phil Nash176eb812012-05-11 08:17:16 +01003487 Context::setRunner( this );
3488 Context::setResultCapture( this );
Phil Nash89d1e6c2011-05-24 08:23:02 +01003489 m_reporter->StartTesting();
3490 }
3491
3492 ///////////////////////////////////////////////////////////////////////////
3493 ~Runner
3494 ()
3495 {
Phil Nashf7299fc2012-02-25 09:39:45 +00003496 m_reporter->EndTesting( m_totals );
Phil Nash176eb812012-05-11 08:17:16 +01003497 Context::setRunner( m_prevRunner );
3498 Context::setResultCapture( m_prevResultCapture );
Phil Nash89d1e6c2011-05-24 08:23:02 +01003499 }
3500
3501 ///////////////////////////////////////////////////////////////////////////
3502 virtual void runAll
3503 (
3504 bool runHiddenTests = false
3505 )
3506 {
Phil Nash176eb812012-05-11 08:17:16 +01003507 std::vector<TestCaseInfo> allTests = Context::getTestCaseRegistry().getAllTests();
Phil Nash89d1e6c2011-05-24 08:23:02 +01003508 for( std::size_t i=0; i < allTests.size(); ++i )
3509 {
3510 if( runHiddenTests || !allTests[i].isHidden() )
3511 runTest( allTests[i] );
3512 }
3513 }
3514
3515 ///////////////////////////////////////////////////////////////////////////
3516 virtual std::size_t runMatching
3517 (
3518 const std::string& rawTestSpec
3519 )
3520 {
3521 TestSpec testSpec( rawTestSpec );
3522
Phil Nash176eb812012-05-11 08:17:16 +01003523 std::vector<TestCaseInfo> allTests = Context::getTestCaseRegistry().getAllTests();
Phil Nash89d1e6c2011-05-24 08:23:02 +01003524 std::size_t testsRun = 0;
3525 for( std::size_t i=0; i < allTests.size(); ++i )
3526 {
3527 if( testSpec.matches( allTests[i].getName() ) )
3528 {
3529 runTest( allTests[i] );
3530 testsRun++;
3531 }
3532 }
3533 return testsRun;
3534 }
3535
3536 ///////////////////////////////////////////////////////////////////////////
3537 void runTest
3538 (
3539 const TestCaseInfo& testInfo
3540 )
3541 {
Phil Nashf7299fc2012-02-25 09:39:45 +00003542 Totals prevTotals = m_totals;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003543
3544 std::string redirectedCout;
3545 std::string redirectedCerr;
3546
3547 m_reporter->StartTestCase( testInfo );
3548
3549 m_runningTest = new RunningTest( &testInfo );
3550
3551 do
3552 {
3553 do
3554 {
Phil Nash49e6d532012-05-05 19:35:35 +01003555 m_reporter->StartGroup( "test case run" );
Phil Nashd31737f2012-05-09 19:04:00 +01003556 m_currentResult.setLineInfo( m_runningTest->getTestCaseInfo().getLineInfo() );
Phil Nash89d1e6c2011-05-24 08:23:02 +01003557 runCurrentTest( redirectedCout, redirectedCerr );
Phil Nash49e6d532012-05-05 19:35:35 +01003558 m_reporter->EndGroup( "test case run", m_totals - prevTotals );
Phil Nash89d1e6c2011-05-24 08:23:02 +01003559 }
3560 while( m_runningTest->hasUntestedSections() );
3561 }
Phil Nash176eb812012-05-11 08:17:16 +01003562 while( Context::advanceGeneratorsForCurrentTest() );
Phil Nash89d1e6c2011-05-24 08:23:02 +01003563
3564 delete m_runningTest;
3565 m_runningTest = NULL;
3566
Phil Nashf7299fc2012-02-25 09:39:45 +00003567 if( m_totals.assertions.failed > prevTotals.assertions.failed )
3568 ++m_totals.testCases.failed;
3569 else
3570 ++m_totals.testCases.passed;
3571
3572 m_reporter->EndTestCase( testInfo, m_totals - prevTotals, redirectedCout, redirectedCerr );
Phil Nash89d1e6c2011-05-24 08:23:02 +01003573 }
3574
3575 ///////////////////////////////////////////////////////////////////////////
Phil Nashf7299fc2012-02-25 09:39:45 +00003576 virtual Totals getTotals
Phil Nash89d1e6c2011-05-24 08:23:02 +01003577 ()
3578 const
3579 {
Phil Nashf7299fc2012-02-25 09:39:45 +00003580 return m_totals;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003581 }
3582
3583 private: // IResultCapture
3584
3585 ///////////////////////////////////////////////////////////////////////////
3586 virtual ResultAction::Value acceptResult
3587 (
3588 bool result
3589 )
3590 {
3591 return acceptResult( result ? ResultWas::Ok : ResultWas::ExpressionFailed );
3592 }
3593
3594 ///////////////////////////////////////////////////////////////////////////
3595 virtual ResultAction::Value acceptResult
3596 (
3597 ResultWas::OfType result
3598 )
3599 {
3600 m_currentResult.setResultType( result );
3601 return actOnCurrentResult();
3602 }
3603
3604 ///////////////////////////////////////////////////////////////////////////
3605 virtual ResultAction::Value acceptExpression
3606 (
Phil Nashd31737f2012-05-09 19:04:00 +01003607 const ResultInfoBuilder& resultInfo
Phil Nash89d1e6c2011-05-24 08:23:02 +01003608 )
3609 {
3610 m_currentResult = resultInfo;
3611 return actOnCurrentResult();
3612 }
3613
3614 ///////////////////////////////////////////////////////////////////////////
3615 virtual void acceptMessage
3616 (
3617 const std::string& msg
3618 )
3619 {
3620 m_currentResult.setMessage( msg );
3621 }
3622
3623 ///////////////////////////////////////////////////////////////////////////
3624 virtual void testEnded
3625 (
3626 const ResultInfo& result
3627 )
3628 {
3629 if( result.getResultType() == ResultWas::Ok )
3630 {
Phil Nashf7299fc2012-02-25 09:39:45 +00003631 m_totals.assertions.passed++;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003632 }
3633 else if( !result.ok() )
3634 {
Phil Nashf7299fc2012-02-25 09:39:45 +00003635 m_totals.assertions.failed++;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003636
3637 std::vector<ResultInfo>::const_iterator it = m_info.begin();
3638 std::vector<ResultInfo>::const_iterator itEnd = m_info.end();
3639 for(; it != itEnd; ++it )
3640 m_reporter->Result( *it );
3641 m_info.clear();
3642 }
3643
3644 if( result.getResultType() == ResultWas::Info )
3645 m_info.push_back( result );
3646 else
3647 m_reporter->Result( result );
3648 }
3649
3650 ///////////////////////////////////////////////////////////////////////////
3651 virtual bool sectionStarted
3652 (
3653 const std::string& name,
3654 const std::string& description,
Phil Nashd31737f2012-05-09 19:04:00 +01003655 const SourceLineInfo& lineInfo,
Phil Nashf7299fc2012-02-25 09:39:45 +00003656 Counts& assertions
Phil Nash89d1e6c2011-05-24 08:23:02 +01003657 )
3658 {
3659 std::ostringstream oss;
Phil Nashd31737f2012-05-09 19:04:00 +01003660 oss << name << "@" << lineInfo;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003661
3662 if( !m_runningTest->addSection( oss.str() ) )
3663 return false;
3664
Phil Nashd31737f2012-05-09 19:04:00 +01003665 m_currentResult.setLineInfo( lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +01003666 m_reporter->StartSection( name, description );
Phil Nashf7299fc2012-02-25 09:39:45 +00003667 assertions = m_totals.assertions;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003668
3669 return true;
3670 }
3671
3672 ///////////////////////////////////////////////////////////////////////////
3673 virtual void sectionEnded
3674 (
3675 const std::string& name,
Phil Nashf7299fc2012-02-25 09:39:45 +00003676 const Counts& prevAssertions
Phil Nash89d1e6c2011-05-24 08:23:02 +01003677 )
3678 {
3679 m_runningTest->endSection( name );
Phil Nashf7299fc2012-02-25 09:39:45 +00003680 m_reporter->EndSection( name, m_totals.assertions - prevAssertions );
Phil Nash89d1e6c2011-05-24 08:23:02 +01003681 }
3682
3683 ///////////////////////////////////////////////////////////////////////////
3684 virtual void pushScopedInfo
3685 (
3686 ScopedInfo* scopedInfo
3687 )
3688 {
3689 m_scopedInfos.push_back( scopedInfo );
3690 }
3691
3692 ///////////////////////////////////////////////////////////////////////////
3693 virtual void popScopedInfo
3694 (
3695 ScopedInfo* scopedInfo
3696 )
3697 {
3698 if( m_scopedInfos.back() == scopedInfo )
3699 m_scopedInfos.pop_back();
3700 }
3701
3702 ///////////////////////////////////////////////////////////////////////////
3703 virtual bool shouldDebugBreak
3704 ()
3705 const
3706 {
3707 return m_config.shouldDebugBreak();
3708 }
3709
3710 ///////////////////////////////////////////////////////////////////////////
3711 virtual std::string getCurrentTestName
3712 ()
3713 const
3714 {
3715 return m_runningTest
3716 ? m_runningTest->getTestCaseInfo().getName()
3717 : "";
3718 }
3719
Phil Nasha162e222012-02-10 08:30:13 +00003720 ///////////////////////////////////////////////////////////////////////////
3721 virtual const ResultInfo* getLastResult
3722 ()
3723 const
3724 {
3725 return &m_lastResult;
3726 }
3727
Phil Nash89d1e6c2011-05-24 08:23:02 +01003728 private:
3729
3730 ///////////////////////////////////////////////////////////////////////////
3731 ResultAction::Value actOnCurrentResult
3732 ()
3733 {
3734 testEnded( m_currentResult );
Phil Nasha162e222012-02-10 08:30:13 +00003735 m_lastResult = m_currentResult;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003736
Phil Nashd31737f2012-05-09 19:04:00 +01003737 m_currentResult = ResultInfoBuilder();
Phil Nasha162e222012-02-10 08:30:13 +00003738 if( m_lastResult.ok() )
Phil Nash89d1e6c2011-05-24 08:23:02 +01003739 return ResultAction::None;
3740 else if( shouldDebugBreak() )
3741 return ResultAction::DebugFailed;
3742 else
3743 return ResultAction::Failed;
3744 }
3745
3746 ///////////////////////////////////////////////////////////////////////////
3747 void runCurrentTest
3748 (
3749 std::string& redirectedCout,
3750 std::string& redirectedCerr
3751 )
3752 {
3753 try
3754 {
3755 m_runningTest->reset();
Phil Nash333e6e62012-02-17 19:50:59 +00003756 if( m_reporter->shouldRedirectStdout() )
3757 {
3758 StreamRedirect coutRedir( std::cout, redirectedCout );
3759 StreamRedirect cerrRedir( std::cerr, redirectedCerr );
3760 m_runningTest->getTestCaseInfo().invoke();
3761 }
3762 else
3763 {
3764 m_runningTest->getTestCaseInfo().invoke();
3765 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003766 m_runningTest->ranToCompletion();
3767 }
3768 catch( TestFailureException& )
3769 {
3770 // This just means the test was aborted due to failure
3771 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003772 catch(...)
3773 {
Phil Nash176eb812012-05-11 08:17:16 +01003774 acceptMessage( Catch::Context::getExceptionTranslatorRegistry().translateActiveException() );
Phil Nash89d1e6c2011-05-24 08:23:02 +01003775 acceptResult( ResultWas::ThrewException );
3776 }
3777 m_info.clear();
3778 }
3779
3780 private:
3781 RunningTest* m_runningTest;
Phil Nashd31737f2012-05-09 19:04:00 +01003782 ResultInfoBuilder m_currentResult;
Phil Nasha162e222012-02-10 08:30:13 +00003783 ResultInfo m_lastResult;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003784
3785 const Config& m_config;
Phil Nashf7299fc2012-02-25 09:39:45 +00003786 Totals m_totals;
Phil Nash49e6d532012-05-05 19:35:35 +01003787 Ptr<IReporter> m_reporter;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003788 std::vector<ScopedInfo*> m_scopedInfos;
3789 std::vector<ResultInfo> m_info;
3790 IRunner* m_prevRunner;
3791 IResultCapture* m_prevResultCapture;
3792 };
3793}
3794
3795// #included from: catch_generators_impl.hpp
3796
Phil Nash89d1e6c2011-05-24 08:23:02 +01003797#include <vector>
3798#include <string>
3799#include <map>
3800
3801namespace Catch
3802{
3803 struct GeneratorInfo
3804 {
3805 ///////////////////////////////////////////////////////////////////////
3806 GeneratorInfo
3807 (
3808 std::size_t size
3809 )
3810 : m_size( size ),
3811 m_currentIndex( 0 )
3812 {
3813 }
3814
3815 ///////////////////////////////////////////////////////////////////////
3816 bool moveNext
3817 ()
3818 {
3819 if( ++m_currentIndex == m_size )
3820 {
3821 m_currentIndex = 0;
3822 return false;
3823 }
3824 return true;
3825 }
3826
3827 ///////////////////////////////////////////////////////////////////////
3828 std::size_t getCurrentIndex
3829 ()
3830 const
3831 {
3832 return m_currentIndex;
3833 }
3834
3835 std::size_t m_size;
3836 std::size_t m_currentIndex;
3837 };
3838
3839 ///////////////////////////////////////////////////////////////////////////
3840 ///////////////////////////////////////////////////////////////////////////
3841
3842 class GeneratorsForTest
3843 {
3844
3845 public:
3846 ///////////////////////////////////////////////////////////////////////
3847 ~GeneratorsForTest
3848 ()
3849 {
3850 deleteAll( m_generatorsInOrder );
3851 }
3852
3853 ///////////////////////////////////////////////////////////////////////
3854 GeneratorInfo& getGeneratorInfo
3855 (
3856 const std::string& fileInfo,
3857 std::size_t size
3858 )
3859 {
3860 std::map<std::string, GeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
3861 if( it == m_generatorsByName.end() )
3862 {
3863 GeneratorInfo* info = new GeneratorInfo( size );
3864 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
3865 m_generatorsInOrder.push_back( info );
3866 return *info;
3867 }
3868 return *it->second;
3869 }
3870
3871 ///////////////////////////////////////////////////////////////////////
3872 bool moveNext
3873 ()
3874 {
3875 std::vector<GeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
3876 std::vector<GeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
3877 for(; it != itEnd; ++it )
3878 {
3879 if( (*it)->moveNext() )
3880 return true;
3881 }
3882 return false;
3883 }
3884
3885 private:
3886 std::map<std::string, GeneratorInfo*> m_generatorsByName;
3887 std::vector<GeneratorInfo*> m_generatorsInOrder;
3888 };
3889
3890} // end namespace Catch
3891
3892#define INTERNAL_CATCH_LINESTR2( line ) #line
3893#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
3894
3895#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
3896
Phil Nash918046a2012-02-28 20:04:42 +00003897// #included from: catch_console_colour_impl.hpp
3898
Phil Nash918046a2012-02-28 20:04:42 +00003899// #included from: catch_console_colour.hpp
3900
Phil Nash918046a2012-02-28 20:04:42 +00003901namespace Catch
3902{
3903 struct ConsoleColourImpl;
3904
3905 class TextColour : NonCopyable
3906 {
3907 public:
3908
3909 enum Colours
3910 {
3911 None,
3912
3913 FileName,
3914 ResultError,
3915 ResultSuccess,
3916
3917 Error,
3918 Success,
3919
3920 OriginalExpression,
3921 ReconstructedExpression
3922 };
3923
3924 TextColour( Colours colour = None );
3925 void set( Colours colour );
3926 ~TextColour();
3927
3928 private:
3929 ConsoleColourImpl* m_impl;
3930 };
3931
3932} // end namespace Catch
3933
Phil Nash918046a2012-02-28 20:04:42 +00003934#ifdef CATCH_PLATFORM_WINDOWS
3935
3936#include <windows.h>
3937
3938namespace Catch
3939{
3940 namespace
3941 {
3942 WORD mapConsoleColour( TextColour::Colours colour )
3943 {
3944 switch( colour )
3945 {
3946 case TextColour::FileName:
3947 return FOREGROUND_INTENSITY; // greyed out
3948 case TextColour::ResultError:
3949 return FOREGROUND_RED | FOREGROUND_INTENSITY; // bright red
3950 case TextColour::ResultSuccess:
3951 return FOREGROUND_GREEN | FOREGROUND_INTENSITY; // bright green
3952 case TextColour::Error:
3953 return FOREGROUND_RED; // dark red
3954 case TextColour::Success:
3955 return FOREGROUND_GREEN; // dark green
3956 case TextColour::OriginalExpression:
3957 return FOREGROUND_BLUE | FOREGROUND_GREEN; // turquoise
3958 case TextColour::ReconstructedExpression:
3959 return FOREGROUND_RED | FOREGROUND_GREEN; // greeny-yellow
3960 default: return 0;
3961 }
3962 }
3963 }
3964
3965 struct ConsoleColourImpl
3966 {
3967 ConsoleColourImpl()
3968 : hStdout( GetStdHandle(STD_OUTPUT_HANDLE) ),
3969 wOldColorAttrs( 0 )
3970 {
3971 GetConsoleScreenBufferInfo( hStdout, &csbiInfo );
3972 wOldColorAttrs = csbiInfo.wAttributes;
3973 }
3974 ~ConsoleColourImpl()
3975 {
3976 SetConsoleTextAttribute( hStdout, wOldColorAttrs );
3977 }
3978 void set( TextColour::Colours colour )
3979 {
3980 WORD consoleColour = mapConsoleColour( colour );
3981 if( consoleColour > 0 )
3982 SetConsoleTextAttribute( hStdout, consoleColour );
3983 }
3984
3985 HANDLE hStdout;
3986 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
3987 WORD wOldColorAttrs;
3988 };
3989
3990 TextColour::TextColour( Colours colour )
3991 : m_impl( new ConsoleColourImpl() )
3992 {
3993 if( colour )
3994 m_impl->set( colour );
3995 }
3996 TextColour::~TextColour()
3997 {
3998 delete m_impl;
3999 }
4000 void TextColour::set( Colours colour )
4001 {
4002 m_impl->set( colour );
4003 }
4004
4005} // end namespace Catch
4006
4007#else
4008
4009namespace Catch
4010{
4011 TextColour::TextColour( Colours ){}
4012 TextColour::~TextColour(){}
4013 void TextColour::set( Colours ){}
4014
4015} // end namespace Catch
4016
4017#endif
4018
Phil Nash176eb812012-05-11 08:17:16 +01004019
4020// #included from: catch_exception_translator_registry.hpp
4021
4022namespace Catch
4023{
4024 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry
4025 {
4026 ///////////////////////////////////////////////////////////////////////
4027 ~ExceptionTranslatorRegistry
4028 ()
4029 {
4030 deleteAll( m_translators );
4031 }
4032
4033 ///////////////////////////////////////////////////////////////////////
4034 virtual void registerTranslator
4035 (
4036 IExceptionTranslator* translator
4037 )
4038 {
4039 m_translators.push_back( translator );
4040 }
4041
4042 ///////////////////////////////////////////////////////////////////////
4043 virtual std::string translateActiveException
4044 ()
4045 const
4046 {
4047 try
4048 {
4049 throw;
4050 }
4051 catch( std::exception& ex )
4052 {
4053 return ex.what();
4054 }
4055 catch( std::string& msg )
4056 {
4057 return msg;
4058 }
4059 catch( const char* msg )
4060 {
4061 return msg;
4062 }
4063 catch(...)
4064 {
4065 return tryTranslators( m_translators.begin() );
4066 }
4067 }
4068
4069 ///////////////////////////////////////////////////////////////////////
4070 std::string tryTranslators
4071 (
4072 std::vector<IExceptionTranslator*>::const_iterator it
4073 )
4074 const
4075 {
4076 if( it == m_translators.end() )
4077 return "Unknown exception";
4078
4079 try
4080 {
4081 return (*it)->translate();
4082 }
4083 catch(...)
4084 {
4085 return tryTranslators( it+1 );
4086 }
4087 }
4088
4089 private:
4090 std::vector<IExceptionTranslator*> m_translators;
4091 };
4092}
4093
4094// #included from: catch_reporter_registry.hpp
4095
4096#include <map>
4097
4098namespace Catch
4099{
4100 class ReporterRegistry : public IReporterRegistry
4101 {
4102 public:
4103
4104 ///////////////////////////////////////////////////////////////////////
4105 ~ReporterRegistry
4106 ()
4107 {
4108 deleteAllValues( m_factories );
4109 }
4110
4111 ///////////////////////////////////////////////////////////////////////
4112 virtual IReporter* create
4113 (
4114 const std::string& name,
4115 const IReporterConfig& config
4116 )
4117 const
4118 {
4119 FactoryMap::const_iterator it = m_factories.find( name );
4120 if( it == m_factories.end() )
4121 return NULL;
4122 return it->second->create( config );
4123 }
4124
4125 ///////////////////////////////////////////////////////////////////////
4126 void registerReporter
4127 (
4128 const std::string& name,
4129 IReporterFactory* factory
4130 )
4131 {
4132 m_factories.insert( std::make_pair( name, factory ) );
4133 }
4134
4135 ///////////////////////////////////////////////////////////////////////
4136 const FactoryMap& getFactories
4137 ()
4138 const
4139 {
4140 return m_factories;
4141 }
4142
4143 private:
4144 FactoryMap m_factories;
4145 };
4146}
4147
Phil Nash89d1e6c2011-05-24 08:23:02 +01004148// #included from: catch_stream.hpp
4149
Phil Nash89d1e6c2011-05-24 08:23:02 +01004150#include <stdexcept>
4151#include <cstdio>
4152
4153namespace Catch
4154{
4155 template<typename WriterF, size_t bufferSize=256>
4156 class StreamBufImpl : public StreamBufBase
4157 {
4158 char data[bufferSize];
4159 WriterF m_writer;
4160
4161 public:
4162 ///////////////////////////////////////////////////////////////////////
4163 StreamBufImpl
4164 ()
4165 {
4166 setp( data, data + sizeof(data) );
4167 }
4168
4169 ///////////////////////////////////////////////////////////////////////
4170 ~StreamBufImpl
4171 ()
4172 {
4173 sync();
4174 }
4175
4176 private:
4177 ///////////////////////////////////////////////////////////////////////
4178 int overflow
4179 (
4180 int c
4181 )
4182 {
4183 sync();
4184
4185 if( c != EOF )
4186 {
4187 if( pbase() == epptr() )
4188 m_writer( std::string( 1, static_cast<char>( c ) ) );
4189 else
4190 sputc( static_cast<char>( c ) );
4191 }
4192 return 0;
4193 }
4194
4195 ///////////////////////////////////////////////////////////////////////
4196 int sync
4197 ()
4198 {
4199 if( pbase() != pptr() )
4200 {
Phil Nashd31737f2012-05-09 19:04:00 +01004201 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004202 setp( pbase(), epptr() );
4203 }
4204 return 0;
4205 }
4206 };
4207
4208 ///////////////////////////////////////////////////////////////////////////
4209 ///////////////////////////////////////////////////////////////////////////
4210
4211 struct OutputDebugWriter
4212 {
4213 ///////////////////////////////////////////////////////////////////////
4214 void operator()
4215 (
4216 const std::string &str
4217 )
4218 {
4219 writeToDebugConsole( str );
4220 }
4221 };
4222}
4223
Phil Nash89d1e6c2011-05-24 08:23:02 +01004224namespace Catch
4225{
Phil Nash176eb812012-05-11 08:17:16 +01004226 Context::Context()
Phil Nash89d1e6c2011-05-24 08:23:02 +01004227 : m_reporterRegistry( new ReporterRegistry ),
4228 m_testCaseRegistry( new TestRegistry ),
4229 m_exceptionTranslatorRegistry( new ExceptionTranslatorRegistry )
Phil Nash176eb812012-05-11 08:17:16 +01004230 {}
Phil Nash89d1e6c2011-05-24 08:23:02 +01004231
Phil Nash176eb812012-05-11 08:17:16 +01004232 Context& Context::me() {
4233 Context*& hub = singleInstance();
Phil Nashdd5b9c22012-02-18 09:58:30 +00004234 if( !hub )
Phil Nash176eb812012-05-11 08:17:16 +01004235 hub = new Context();
Phil Nashdd5b9c22012-02-18 09:58:30 +00004236 return *hub;
4237 }
4238
Phil Nash176eb812012-05-11 08:17:16 +01004239 void Context::cleanUp() {
4240 Context*& hub = singleInstance();
Phil Nashdd5b9c22012-02-18 09:58:30 +00004241 delete hub;
4242 hub = NULL;
4243 }
4244
Phil Nash176eb812012-05-11 08:17:16 +01004245 Context*& Context::singleInstance() {
4246 static Context* hub = NULL;
Phil Nash89d1e6c2011-05-24 08:23:02 +01004247 return hub;
4248 }
4249
Phil Nash176eb812012-05-11 08:17:16 +01004250 void Context::setRunner( IRunner* runner ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01004251 me().m_runner = runner;
4252 }
Phil Nash176eb812012-05-11 08:17:16 +01004253
4254 void Context::setResultCapture( IResultCapture* resultCapture ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01004255 me().m_resultCapture = resultCapture;
4256 }
4257
Phil Nash176eb812012-05-11 08:17:16 +01004258 IResultCapture& Context::getResultCapture() {
Phil Nash89d1e6c2011-05-24 08:23:02 +01004259 return *me().m_resultCapture;
4260 }
4261
Phil Nash176eb812012-05-11 08:17:16 +01004262 IRunner& Context::getRunner() {
Phil Nash89d1e6c2011-05-24 08:23:02 +01004263 return *me().m_runner;
4264 }
4265
Phil Nash176eb812012-05-11 08:17:16 +01004266 IReporterRegistry& Context::getReporterRegistry() {
Phil Nash89d1e6c2011-05-24 08:23:02 +01004267 return *me().m_reporterRegistry.get();
4268 }
4269
Phil Nash176eb812012-05-11 08:17:16 +01004270 ITestCaseRegistry& Context::getTestCaseRegistry() {
Phil Nash89d1e6c2011-05-24 08:23:02 +01004271 return *me().m_testCaseRegistry.get();
4272 }
4273
Phil Nash176eb812012-05-11 08:17:16 +01004274 IExceptionTranslatorRegistry& Context::getExceptionTranslatorRegistry() {
Phil Nash89d1e6c2011-05-24 08:23:02 +01004275 return *me().m_exceptionTranslatorRegistry.get();
4276 }
4277
Phil Nash176eb812012-05-11 08:17:16 +01004278 std::streambuf* Context::createStreamBuf( const std::string& streamName ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01004279 if( streamName == "stdout" ) return std::cout.rdbuf();
4280 if( streamName == "stderr" ) return std::cerr.rdbuf();
4281 if( streamName == "debug" ) return new StreamBufImpl<OutputDebugWriter>;
4282
4283 throw std::domain_error( "Unknown stream: " + streamName );
4284 }
4285
Phil Nash176eb812012-05-11 08:17:16 +01004286 GeneratorsForTest* Context::findGeneratorsForCurrentTest() {
Phil Nash89d1e6c2011-05-24 08:23:02 +01004287 std::string testName = getResultCapture().getCurrentTestName();
4288
4289 std::map<std::string, GeneratorsForTest*>::const_iterator it =
4290 m_generatorsByTestName.find( testName );
4291 return it != m_generatorsByTestName.end()
4292 ? it->second
4293 : NULL;
4294 }
Phil Nash176eb812012-05-11 08:17:16 +01004295
4296 GeneratorsForTest& Context::getGeneratorsForCurrentTest() {
Phil Nash89d1e6c2011-05-24 08:23:02 +01004297 GeneratorsForTest* generators = findGeneratorsForCurrentTest();
4298 if( !generators )
4299 {
4300 std::string testName = getResultCapture().getCurrentTestName();
4301 generators = new GeneratorsForTest();
4302 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
4303 }
4304 return *generators;
4305 }
4306
Phil Nash176eb812012-05-11 08:17:16 +01004307 size_t Context::getGeneratorIndex( const std::string& fileInfo, size_t totalSize )
Phil Nash89d1e6c2011-05-24 08:23:02 +01004308 {
4309 return me().getGeneratorsForCurrentTest()
4310 .getGeneratorInfo( fileInfo, totalSize )
4311 .getCurrentIndex();
4312 }
4313
Phil Nash176eb812012-05-11 08:17:16 +01004314 bool Context::advanceGeneratorsForCurrentTest() {
Phil Nash89d1e6c2011-05-24 08:23:02 +01004315 GeneratorsForTest* generators = me().findGeneratorsForCurrentTest();
4316 return generators && generators->moveNext();
4317 }
4318}
Phil Nash89d1e6c2011-05-24 08:23:02 +01004319// #included from: internal/catch_commandline.hpp
4320
Phil Nash89d1e6c2011-05-24 08:23:02 +01004321namespace Catch
4322{
4323 // !TBD: This could be refactored to be more "declarative"
4324 // have a table up front that relates the mode, option strings, # arguments, names of arguments
4325 // - may not be worth it at this scale
4326
4327 // -l, --list tests [xml] lists available tests (optionally in xml)
4328 // -l, --list reporters [xml] lists available reports (optionally in xml)
4329 // -l, --list all [xml] lists available tests and reports (optionally in xml)
4330 // -t, --test "testspec" ["testspec", ...]
4331 // -r, --reporter <type>
4332 // -o, --out filename to write to
4333 // -s, --success report successful cases too
4334 // -b, --break breaks into debugger on test failure
4335 // -n, --name specifies an optional name for the test run
4336 class ArgParser : NonCopyable
4337 {
4338 enum Mode
4339 {
4340 modeNone,
4341 modeList,
4342 modeTest,
4343 modeReport,
4344 modeOutput,
4345 modeSuccess,
4346 modeBreak,
4347 modeName,
4348 modeHelp,
4349
4350 modeError
4351 };
4352
4353 public:
4354 ///////////////////////////////////////////////////////////////////////
4355 ArgParser
4356 (
4357 int argc,
4358 char * const argv[],
4359 Config& config
4360 )
4361 : m_mode( modeNone ),
4362 m_config( config )
4363 {
4364 for( int i=1; i < argc; ++i )
4365 {
4366 if( argv[i][0] == '-' )
4367 {
4368 std::string cmd = ( argv[i] );
4369 if( cmd == "-l" || cmd == "--list" )
4370 changeMode( cmd, modeList );
4371 else if( cmd == "-t" || cmd == "--test" )
4372 changeMode( cmd, modeTest );
4373 else if( cmd == "-r" || cmd == "--reporter" )
4374 changeMode( cmd, modeReport );
4375 else if( cmd == "-o" || cmd == "--out" )
4376 changeMode( cmd, modeOutput );
4377 else if( cmd == "-s" || cmd == "--success" )
4378 changeMode( cmd, modeSuccess );
4379 else if( cmd == "-b" || cmd == "--break" )
4380 changeMode( cmd, modeBreak );
4381 else if( cmd == "-n" || cmd == "--name" )
4382 changeMode( cmd, modeName );
4383 else if( cmd == "-h" || cmd == "-?" || cmd == "--help" )
4384 changeMode( cmd, modeHelp );
4385 }
4386 else
4387 {
4388 m_args.push_back( argv[i] );
4389 }
4390 if( m_mode == modeError )
4391 return;
4392 }
4393 changeMode( "", modeNone );
4394 }
4395
4396 private:
4397 ///////////////////////////////////////////////////////////////////////
4398 std::string argsAsString
4399 ()
4400 {
4401 std::ostringstream oss;
4402 std::vector<std::string>::const_iterator it = m_args.begin();
4403 std::vector<std::string>::const_iterator itEnd = m_args.end();
4404 for( bool first = true; it != itEnd; ++it, first = false )
4405 {
4406 if( !first )
4407 oss << " ";
4408 oss << *it;
4409 }
4410 return oss.str();
4411 }
4412
4413 ///////////////////////////////////////////////////////////////////////
4414 void changeMode
4415 (
4416 const std::string& cmd,
4417 Mode mode
4418 )
4419 {
4420 m_command = cmd;
4421 switch( m_mode )
4422 {
4423 case modeNone:
4424 if( m_args.size() > 0 )
4425 return setErrorMode( "Unexpected arguments before " + m_command + ": " + argsAsString() );
4426 break;
4427 case modeList:
4428 if( m_args.size() > 2 )
4429 {
4430 return setErrorMode( m_command + " expected upto 2 arguments but recieved: " + argsAsString() );
4431 }
4432 else
4433 {
4434 Config::List::What listSpec = Config::List::All;
4435 if( m_args.size() >= 1 )
4436 {
4437 if( m_args[0] == "tests" )
4438 listSpec = Config::List::Tests;
4439 else if( m_args[0] == "reporters" )
4440 listSpec = Config::List::Reports;
4441 else
4442 return setErrorMode( m_command + " expected [tests] or [reporters] but recieved: [" + m_args[0] + "]" );
4443 }
4444 if( m_args.size() >= 2 )
4445 {
4446 if( m_args[1] == "xml" )
4447 listSpec = static_cast<Config::List::What>( listSpec | Config::List::AsXml );
4448 else if( m_args[1] == "text" )
4449 listSpec = static_cast<Config::List::What>( listSpec | Config::List::AsText );
4450 else
4451 return setErrorMode( m_command + " expected [xml] or [text] but recieved: [" + m_args[1] + "]" );
4452 }
4453 m_config.setListSpec( static_cast<Config::List::What>( m_config.getListSpec() | listSpec ) );
4454 }
4455 break;
4456 case modeTest:
4457 if( m_args.size() == 0 )
4458 return setErrorMode( m_command + " expected at least 1 argument but recieved none" );
4459 {
4460 std::vector<std::string>::const_iterator it = m_args.begin();
4461 std::vector<std::string>::const_iterator itEnd = m_args.end();
4462 for(; it != itEnd; ++it )
4463 m_config.addTestSpec( *it );
4464 }
4465 break;
4466 case modeReport:
4467 if( m_args.size() != 1 )
4468 return setErrorMode( m_command + " expected one argument, recieved: " + argsAsString() );
4469 m_config.setReporter( m_args[0] );
4470 break;
4471 case modeOutput:
4472 if( m_args.size() == 0 )
4473 return setErrorMode( m_command + " expected filename" );
4474 if( m_args[0][0] == '%' )
4475 m_config.useStream( m_args[0].substr( 1 ) );
4476 else
4477 m_config.setFilename( m_args[0] );
4478 break;
4479 case modeSuccess:
4480 if( m_args.size() != 0 )
4481 return setErrorMode( m_command + " does not accept arguments" );
4482 m_config.setIncludeWhat( Config::Include::SuccessfulResults );
4483 break;
4484 case modeBreak:
4485 if( m_args.size() != 0 )
4486 return setErrorMode( m_command + " does not accept arguments" );
4487 m_config.setShouldDebugBreak( true );
4488 break;
4489 case modeName:
4490 if( m_args.size() != 1 )
4491 return setErrorMode( m_command + " requires exactly one argument (a name)" );
4492 m_config.setName( m_args[0] );
4493 break;
4494 case modeHelp:
4495 if( m_args.size() != 0 )
4496 return setErrorMode( m_command + " does not accept arguments" );
4497 m_config.setShowHelp( true );
4498 break;
Phil Nashf51d3162011-12-28 10:37:31 +00004499 case modeError:
Phil Nash89d1e6c2011-05-24 08:23:02 +01004500 default:
4501 break;
4502 }
4503 m_args.clear();
4504 m_mode = mode;
4505 }
4506
4507 ///////////////////////////////////////////////////////////////////////
4508 void setErrorMode
4509 (
4510 const std::string& errorMessage
4511 )
4512 {
4513 m_mode = modeError;
4514 m_command = "";
4515 m_config.setError( errorMessage );
4516 }
4517
4518 private:
4519
4520 Mode m_mode;
4521 std::string m_command;
4522 std::vector<std::string> m_args;
4523 Config& m_config;
4524 };
4525
Phil Nash89d1e6c2011-05-24 08:23:02 +01004526} // end namespace Catch
4527
4528// #included from: internal/catch_list.hpp
4529
Phil Nash89d1e6c2011-05-24 08:23:02 +01004530#include <limits>
4531
4532namespace Catch
4533{
4534 ///////////////////////////////////////////////////////////////////////////
4535 inline int List
4536 (
Phil Nash49e6d532012-05-05 19:35:35 +01004537 Config& config
Phil Nash89d1e6c2011-05-24 08:23:02 +01004538 )
4539 {
4540 if( config.listWhat() & Config::List::Reports )
4541 {
4542 std::cout << "Available reports:\n";
Phil Nash176eb812012-05-11 08:17:16 +01004543 IReporterRegistry::FactoryMap::const_iterator it = Context::getReporterRegistry().getFactories().begin();
4544 IReporterRegistry::FactoryMap::const_iterator itEnd = Context::getReporterRegistry().getFactories().end();
Phil Nash89d1e6c2011-05-24 08:23:02 +01004545 for(; it != itEnd; ++it )
4546 {
4547 // !TBD: consider listAs()
4548 std::cout << "\t" << it->first << "\n\t\t'" << it->second->getDescription() << "'\n";
4549 }
4550 std::cout << std::endl;
4551 }
4552 if( config.listWhat() & Config::List::Tests )
4553 {
4554 std::cout << "Available tests:\n";
Phil Nash176eb812012-05-11 08:17:16 +01004555 std::vector<TestCaseInfo>::const_iterator it = Context::getTestCaseRegistry().getAllTests().begin();
4556 std::vector<TestCaseInfo>::const_iterator itEnd = Context::getTestCaseRegistry().getAllTests().end();
Phil Nash89d1e6c2011-05-24 08:23:02 +01004557 for(; it != itEnd; ++it )
4558 {
4559 // !TBD: consider listAs()
4560 std::cout << "\t" << it->getName() << "\n\t\t '" << it->getDescription() << "'\n";
4561 }
4562 std::cout << std::endl;
4563 }
4564 if( ( config.listWhat() & Config::List::All ) == 0 )
4565 {
4566 std::cerr << "Unknown list type" << std::endl;
4567 return (std::numeric_limits<int>::max)();
4568 }
4569
Phil Nash49e6d532012-05-05 19:35:35 +01004570 if( config.getReporter().get() )
Phil Nash89d1e6c2011-05-24 08:23:02 +01004571 {
4572 std::cerr << "Reporters ignored when listing" << std::endl;
4573 }
4574 if( !config.testsSpecified() )
4575 {
4576 std::cerr << "Test specs ignored when listing" << std::endl;
4577 }
4578 return 0;
4579
4580 }
4581
4582} // end namespace Catch
4583
4584// #included from: reporters/catch_reporter_basic.hpp
4585
Phil Nashf721a962011-06-07 14:13:57 +01004586// #included from: ../internal/catch_reporter_registrars.hpp
Phil Nash89d1e6c2011-05-24 08:23:02 +01004587
Phil Nash89d1e6c2011-05-24 08:23:02 +01004588namespace Catch
4589{
4590 template<typename T>
4591 class ReporterRegistrar
4592 {
4593 class ReporterFactory : public IReporterFactory
4594 {
4595 ///////////////////////////////////////////////////////////////////
4596 virtual IReporter* create
4597 (
4598 const IReporterConfig& config
4599 )
4600 const
4601 {
4602 return new T( config );
4603 }
4604 ///////////////////////////////////////////////////////////////////
4605 virtual std::string getDescription
4606 ()
4607 const
4608 {
4609 return T::getDescription();
4610 }
4611 };
4612
4613 public:
4614
4615 ///////////////////////////////////////////////////////////////////////
4616 ReporterRegistrar
4617 (
4618 const std::string& name
4619 )
4620 {
Phil Nash176eb812012-05-11 08:17:16 +01004621 Context::getReporterRegistry().registerReporter( name, new ReporterFactory() );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004622 }
4623 };
4624}
4625
4626///////////////////////////////////////////////////////////////////////////////
4627#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
4628 Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name );
4629
Phil Nash89d1e6c2011-05-24 08:23:02 +01004630namespace Catch
4631{
Phil Nashf7299fc2012-02-25 09:39:45 +00004632 struct pluralise
4633 {
4634 pluralise( std::size_t count, const std::string& label )
4635 : m_count( count ),
4636 m_label( label )
4637 {}
4638
4639 friend std::ostream& operator << ( std::ostream& os, const pluralise& pluraliser )
4640 {
4641 os << pluraliser.m_count << " " << pluraliser.m_label;
4642 if( pluraliser.m_count != 1 )
4643 os << "s";
4644 return os;
4645 }
4646
4647 std::size_t m_count;
4648 std::string m_label;
4649 };
4650
Phil Nash49e6d532012-05-05 19:35:35 +01004651 class BasicReporter : public SharedImpl<IReporter>
Phil Nash89d1e6c2011-05-24 08:23:02 +01004652 {
4653 struct SpanInfo
4654 {
4655 SpanInfo()
4656 : emitted( false )
4657 {}
4658
4659 SpanInfo( const std::string& spanName )
4660 : name( spanName ),
4661 emitted( false )
4662 {}
4663
4664 SpanInfo( const SpanInfo& other )
4665 : name( other.name ),
4666 emitted( other.emitted )
4667 {}
4668
4669 std::string name;
4670 bool emitted;
4671 };
4672
4673 public:
4674 ///////////////////////////////////////////////////////////////////////////
4675 BasicReporter
4676 (
4677 const IReporterConfig& config
4678 )
Phil Nashf51d3162011-12-28 10:37:31 +00004679 : m_config( config ),
4680 m_firstSectionInTestCase( true )
Phil Nash89d1e6c2011-05-24 08:23:02 +01004681 {
4682 }
4683
4684 ///////////////////////////////////////////////////////////////////////////
4685 static std::string getDescription
4686 ()
4687 {
4688 return "Reports test results as lines of text";
4689 }
4690
4691 private:
4692
4693 ///////////////////////////////////////////////////////////////////////////
4694 void ReportCounts
4695 (
Phil Nashf7299fc2012-02-25 09:39:45 +00004696 const std::string& label,
4697 const Counts& counts
Phil Nash89d1e6c2011-05-24 08:23:02 +01004698 )
4699 {
Phil Nash918046a2012-02-28 20:04:42 +00004700 if( counts.passed )
4701 m_config.stream() << counts.failed << " of " << counts.total() << " " << label << "s failed";
Phil Nash89d1e6c2011-05-24 08:23:02 +01004702 else
Phil Nash918046a2012-02-28 20:04:42 +00004703 m_config.stream() << ( counts.failed > 1 ? "All " : "" ) << pluralise( counts.failed, label ) << " failed";
Phil Nashf7299fc2012-02-25 09:39:45 +00004704 }
Phil Nash2cc9b0d2012-02-22 09:44:06 +00004705
Phil Nashf7299fc2012-02-25 09:39:45 +00004706 ///////////////////////////////////////////////////////////////////////////
4707 void ReportCounts
4708 (
4709 const Totals& totals
4710 )
4711 {
4712 if( totals.assertions.total() == 0 )
4713 {
4714 m_config.stream() << "No tests ran";
Phil Nashf7299fc2012-02-25 09:39:45 +00004715 }
Phil Nash918046a2012-02-28 20:04:42 +00004716 else if( totals.assertions.failed )
Phil Nashf7299fc2012-02-25 09:39:45 +00004717 {
Phil Nash918046a2012-02-28 20:04:42 +00004718 TextColour colour( TextColour::ResultError );
4719 ReportCounts( "test case", totals.testCases );
4720 if( totals.testCases.failed > 0 )
4721 {
4722 m_config.stream() << " (";
4723 ReportCounts( "assertion", totals.assertions );
4724 m_config.stream() << ")";
4725 }
4726 }
4727 else
4728 {
4729 TextColour colour( TextColour::ResultSuccess );
4730 m_config.stream() << "All tests passed ("
Phil Nash78d95a02012-03-04 21:22:36 +00004731 << pluralise( totals.assertions.passed, "assertion" ) << " in "
4732 << pluralise( totals.testCases.passed, "test case" ) << ")";
Phil Nash2cc9b0d2012-02-22 09:44:06 +00004733 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01004734 }
4735
4736 private: // IReporter
4737
4738 ///////////////////////////////////////////////////////////////////////////
Phil Nash333e6e62012-02-17 19:50:59 +00004739 virtual bool shouldRedirectStdout
4740 ()
4741 const
4742 {
4743 return false;
4744 }
4745
4746 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01004747 virtual void StartTesting
4748 ()
4749 {
4750 m_testingSpan = SpanInfo();
4751 }
4752
4753 ///////////////////////////////////////////////////////////////////////////
4754 virtual void EndTesting
4755 (
Phil Nashf7299fc2012-02-25 09:39:45 +00004756 const Totals& totals
Phil Nash89d1e6c2011-05-24 08:23:02 +01004757 )
4758 {
4759 // Output the overall test results even if "Started Testing" was not emitted
Phil Nash2cc9b0d2012-02-22 09:44:06 +00004760 m_config.stream() << "\n[Testing completed. ";
Phil Nashf7299fc2012-02-25 09:39:45 +00004761 ReportCounts( totals);
Phil Nash89d1e6c2011-05-24 08:23:02 +01004762 m_config.stream() << "]\n" << std::endl;
4763 }
4764
4765 ///////////////////////////////////////////////////////////////////////////
4766 virtual void StartGroup
4767 (
4768 const std::string& groupName
4769 )
4770 {
4771 m_groupSpan = groupName;
4772 }
4773
4774 ///////////////////////////////////////////////////////////////////////////
4775 virtual void EndGroup
4776 (
4777 const std::string& groupName,
Phil Nashf7299fc2012-02-25 09:39:45 +00004778 const Totals& totals
Phil Nash89d1e6c2011-05-24 08:23:02 +01004779 )
4780 {
4781 if( m_groupSpan.emitted && !groupName.empty() )
4782 {
4783 m_config.stream() << "[End of group: '" << groupName << "'. ";
Phil Nashf7299fc2012-02-25 09:39:45 +00004784 ReportCounts( totals );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004785 m_config.stream() << "]\n" << std::endl;
4786 m_groupSpan = SpanInfo();
4787 }
4788 }
4789
4790 ///////////////////////////////////////////////////////////////////////////
4791 virtual void StartTestCase
4792 (
4793 const TestCaseInfo& testInfo
4794 )
4795 {
4796 m_testSpan = testInfo.getName();
4797 }
4798
4799 ///////////////////////////////////////////////////////////////////////////
4800 virtual void StartSection
4801 (
4802 const std::string& sectionName,
4803 const std::string /*description*/
4804 )
4805 {
4806 m_sectionSpans.push_back( SpanInfo( sectionName ) );
4807 }
4808
4809 ///////////////////////////////////////////////////////////////////////////
4810 virtual void EndSection
4811 (
4812 const std::string& sectionName,
Phil Nashf7299fc2012-02-25 09:39:45 +00004813 const Counts& assertions
Phil Nash89d1e6c2011-05-24 08:23:02 +01004814 )
4815 {
4816 SpanInfo& sectionSpan = m_sectionSpans.back();
4817 if( sectionSpan.emitted && !sectionSpan.name.empty() )
4818 {
Phil Nash78d95a02012-03-04 21:22:36 +00004819 m_config.stream() << "[End of section: '" << sectionName << "' ";
Phil Nash918046a2012-02-28 20:04:42 +00004820
4821 if( assertions.failed )
4822 {
4823 TextColour colour( TextColour::ResultError );
4824 ReportCounts( "assertion", assertions);
4825 }
4826 else
4827 {
4828 TextColour colour( TextColour::ResultSuccess );
4829 m_config.stream() << ( assertions.passed > 1 ? "All " : "" )
Phil Nash78d95a02012-03-04 21:22:36 +00004830 << pluralise( assertions.passed, "assertion" ) << "passed" ;
Phil Nash918046a2012-02-28 20:04:42 +00004831 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01004832 m_config.stream() << "]\n" << std::endl;
4833 }
4834 m_sectionSpans.pop_back();
4835 }
4836
4837 ///////////////////////////////////////////////////////////////////////////
4838 virtual void Result
4839 (
4840 const ResultInfo& resultInfo
4841 )
4842 {
4843 if( !m_config.includeSuccessfulResults() && resultInfo.getResultType() == ResultWas::Ok )
4844 return;
4845
4846 StartSpansLazily();
4847
4848 if( !resultInfo.getFilename().empty() )
Phil Nash918046a2012-02-28 20:04:42 +00004849 {
4850 TextColour colour( TextColour::FileName );
Phil Nash6e0f58d2012-02-15 18:37:21 +00004851 m_config.stream() << SourceLineInfo( resultInfo.getFilename(), resultInfo.getLine() );
Phil Nash918046a2012-02-28 20:04:42 +00004852 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01004853
4854 if( resultInfo.hasExpression() )
4855 {
Phil Nash918046a2012-02-28 20:04:42 +00004856 TextColour colour( TextColour::OriginalExpression );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004857 m_config.stream() << resultInfo.getExpression();
4858 if( resultInfo.ok() )
Phil Nash918046a2012-02-28 20:04:42 +00004859 {
Phil Nash62179662012-05-11 19:06:43 +01004860 TextColour successColour( TextColour::Success );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004861 m_config.stream() << " succeeded";
Phil Nash918046a2012-02-28 20:04:42 +00004862 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01004863 else
Phil Nash918046a2012-02-28 20:04:42 +00004864 {
Phil Nash62179662012-05-11 19:06:43 +01004865 TextColour errorColour( TextColour::Error );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004866 m_config.stream() << " failed";
Phil Nash918046a2012-02-28 20:04:42 +00004867 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01004868 }
4869 switch( resultInfo.getResultType() )
4870 {
4871 case ResultWas::ThrewException:
Phil Nash918046a2012-02-28 20:04:42 +00004872 {
4873 TextColour colour( TextColour::Error );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004874 if( resultInfo.hasExpression() )
4875 m_config.stream() << " with unexpected";
4876 else
4877 m_config.stream() << "Unexpected";
4878 m_config.stream() << " exception with message: '" << resultInfo.getMessage() << "'";
Phil Nash918046a2012-02-28 20:04:42 +00004879 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01004880 break;
4881 case ResultWas::DidntThrowException:
Phil Nash918046a2012-02-28 20:04:42 +00004882 {
4883 TextColour colour( TextColour::Error );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004884 if( resultInfo.hasExpression() )
4885 m_config.stream() << " because no exception was thrown where one was expected";
4886 else
4887 m_config.stream() << "No exception thrown where one was expected";
Phil Nash918046a2012-02-28 20:04:42 +00004888 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01004889 break;
4890 case ResultWas::Info:
4891 streamVariableLengthText( "info", resultInfo.getMessage() );
4892 break;
4893 case ResultWas::Warning:
4894 m_config.stream() << "warning:\n'" << resultInfo.getMessage() << "'";
4895 break;
4896 case ResultWas::ExplicitFailure:
Phil Nash918046a2012-02-28 20:04:42 +00004897 {
4898 TextColour colour( TextColour::Error );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004899 m_config.stream() << "failed with message: '" << resultInfo.getMessage() << "'";
Phil Nash918046a2012-02-28 20:04:42 +00004900 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01004901 break;
Phil Nashf51d3162011-12-28 10:37:31 +00004902 case ResultWas::Unknown: // These cases are here to prevent compiler warnings
4903 case ResultWas::Ok:
4904 case ResultWas::FailureBit:
4905 case ResultWas::ExpressionFailed:
4906 case ResultWas::Exception:
Phil Nash89d1e6c2011-05-24 08:23:02 +01004907 default:
4908 if( !resultInfo.hasExpression() )
4909 {
4910 if( resultInfo.ok() )
Phil Nash918046a2012-02-28 20:04:42 +00004911 {
4912 TextColour colour( TextColour::Success );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004913 m_config.stream() << " succeeded";
Phil Nash918046a2012-02-28 20:04:42 +00004914 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01004915 else
Phil Nash918046a2012-02-28 20:04:42 +00004916 {
4917 TextColour colour( TextColour::Error );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004918 m_config.stream() << " failed";
Phil Nash918046a2012-02-28 20:04:42 +00004919 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01004920 }
4921 break;
4922 }
4923
Phil Nash49e6d532012-05-05 19:35:35 +01004924 if( resultInfo.hasExpandedExpression() )
Phil Nash89d1e6c2011-05-24 08:23:02 +01004925 {
Phil Nash918046a2012-02-28 20:04:42 +00004926 m_config.stream() << " for: ";
4927 TextColour colour( TextColour::ReconstructedExpression );
4928 m_config.stream() << resultInfo.getExpandedExpression();
Phil Nash89d1e6c2011-05-24 08:23:02 +01004929 }
4930 m_config.stream() << std::endl;
4931 }
4932
4933 ///////////////////////////////////////////////////////////////////////////
4934 virtual void EndTestCase
4935 (
4936 const TestCaseInfo& testInfo,
Phil Nashf7299fc2012-02-25 09:39:45 +00004937 const Totals& totals,
Phil Nash89d1e6c2011-05-24 08:23:02 +01004938 const std::string& stdOut,
4939 const std::string& stdErr
4940 )
4941 {
4942 if( !stdOut.empty() )
4943 {
4944 StartSpansLazily();
4945 streamVariableLengthText( "stdout", stdOut );
4946 }
4947
4948 if( !stdErr.empty() )
4949 {
4950 StartSpansLazily();
4951 streamVariableLengthText( "stderr", stdErr );
4952 }
4953
4954 if( m_testSpan.emitted )
4955 {
Phil Nash918046a2012-02-28 20:04:42 +00004956 m_config.stream() << "[Finished: '" << testInfo.getName() << "' ";
Phil Nashf7299fc2012-02-25 09:39:45 +00004957 ReportCounts( totals );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004958 m_config.stream() << "]" << std::endl;
4959 }
4960 }
4961
4962 private: // helpers
4963
4964 ///////////////////////////////////////////////////////////////////////////
4965 void StartSpansLazily()
4966 {
4967 if( !m_testingSpan.emitted )
4968 {
4969 if( m_config.getName().empty() )
4970 m_config.stream() << "[Started testing]" << std::endl;
4971 else
4972 m_config.stream() << "[Started testing: " << m_config.getName() << "]" << std::endl;
4973 m_testingSpan.emitted = true;
4974 }
4975
4976 if( !m_groupSpan.emitted && !m_groupSpan.name.empty() )
4977 {
4978 m_config.stream() << "[Started group: '" << m_groupSpan.name << "']" << std::endl;
4979 m_groupSpan.emitted = true;
4980 }
4981
4982 if( !m_testSpan.emitted )
4983 {
4984 m_config.stream() << std::endl << "[Running: " << m_testSpan.name << "]" << std::endl;
4985 m_testSpan.emitted = true;
4986 }
4987
4988 if( !m_sectionSpans.empty() )
4989 {
4990 SpanInfo& sectionSpan = m_sectionSpans.back();
4991 if( !sectionSpan.emitted && !sectionSpan.name.empty() )
4992 {
4993 if( m_firstSectionInTestCase )
4994 {
4995 m_config.stream() << "\n";
4996 m_firstSectionInTestCase = false;
4997 }
4998 std::vector<SpanInfo>::iterator it = m_sectionSpans.begin();
4999 std::vector<SpanInfo>::iterator itEnd = m_sectionSpans.end();
5000 for(; it != itEnd; ++it )
5001 {
5002 SpanInfo& prevSpan = *it;
5003 if( !prevSpan.emitted && !prevSpan.name.empty() )
5004 {
5005 m_config.stream() << "[Started section: '" << prevSpan.name << "']" << std::endl;
5006 prevSpan.emitted = true;
5007 }
5008 }
5009 }
5010 }
5011 }
5012
5013 ///////////////////////////////////////////////////////////////////////////
5014 void streamVariableLengthText
5015 (
5016 const std::string& prefix,
5017 const std::string& text
5018 )
5019 {
5020 std::string trimmed = trim( text );
5021 if( trimmed.find_first_of( "\r\n" ) == std::string::npos )
5022 {
5023 m_config.stream() << "[" << prefix << ": " << trimmed << "]\n";
5024 }
5025 else
5026 {
Phil Nash918046a2012-02-28 20:04:42 +00005027 m_config.stream() << "\n[" << prefix << "] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" << trimmed
5028 << "\n[end of " << prefix << "] <<<<<<<<<<<<<<<<<<<<<<<<\n";
Phil Nash89d1e6c2011-05-24 08:23:02 +01005029 }
5030 }
5031
5032 private:
5033 const IReporterConfig& m_config;
5034 bool m_firstSectionInTestCase;
5035
5036 SpanInfo m_testingSpan;
5037 SpanInfo m_groupSpan;
5038 SpanInfo m_testSpan;
5039 std::vector<SpanInfo> m_sectionSpans;
5040 };
5041
5042 INTERNAL_CATCH_REGISTER_REPORTER( "basic", BasicReporter )
5043
5044} // end namespace Catch
5045
5046// #included from: reporters/catch_reporter_xml.hpp
5047
Phil Nashf721a962011-06-07 14:13:57 +01005048// #included from: ../internal/catch_xmlwriter.hpp
Phil Nash89d1e6c2011-05-24 08:23:02 +01005049
Phil Nash89d1e6c2011-05-24 08:23:02 +01005050#include <sstream>
5051#include <string>
5052#include <vector>
5053
5054namespace Catch
5055{
5056 class XmlWriter
5057 {
5058 public:
5059
5060 class ScopedElement
5061 {
5062 public:
5063 ///////////////////////////////////////////////////////////////////
5064 ScopedElement
5065 (
5066 XmlWriter* writer
5067 )
5068 : m_writer( writer )
5069 {
5070 }
5071
5072 ///////////////////////////////////////////////////////////////////
5073 ScopedElement
5074 (
5075 const ScopedElement& other
5076 )
5077 : m_writer( other.m_writer )
5078 {
5079 other.m_writer = NULL;
5080 }
5081
5082 ///////////////////////////////////////////////////////////////////
5083 ~ScopedElement
5084 ()
5085 {
5086 if( m_writer )
5087 m_writer->endElement();
5088 }
5089
5090 ///////////////////////////////////////////////////////////////////
5091 ScopedElement& writeText
5092 (
5093 const std::string& text
5094 )
5095 {
5096 m_writer->writeText( text );
5097 return *this;
5098 }
5099
5100 ///////////////////////////////////////////////////////////////////
5101 template<typename T>
5102 ScopedElement& writeAttribute
5103 (
5104 const std::string& name,
5105 const T& attribute
5106 )
5107 {
5108 m_writer->writeAttribute( name, attribute );
5109 return *this;
5110 }
5111
5112 private:
5113 mutable XmlWriter* m_writer;
5114 };
5115
5116 ///////////////////////////////////////////////////////////////////////
5117 XmlWriter
5118 ()
5119 : m_tagIsOpen( false ),
5120 m_needsNewline( false ),
5121 m_os( &std::cout )
5122 {
5123 }
5124
5125 ///////////////////////////////////////////////////////////////////////
5126 XmlWriter
5127 (
5128 std::ostream& os
5129 )
5130 : m_tagIsOpen( false ),
5131 m_needsNewline( false ),
5132 m_os( &os )
5133 {
5134 }
5135
5136 ///////////////////////////////////////////////////////////////////////
5137 ~XmlWriter
5138 ()
5139 {
5140 while( !m_tags.empty() )
5141 {
5142 endElement();
5143 }
5144 }
5145
5146 ///////////////////////////////////////////////////////////////////////
5147 XmlWriter& operator =
5148 (
5149 const XmlWriter& other
5150 )
5151 {
5152 XmlWriter temp( other );
5153 swap( temp );
5154 return *this;
5155 }
5156
5157 ///////////////////////////////////////////////////////////////////////
5158 void swap
5159 (
5160 XmlWriter& other
5161 )
5162 {
5163 std::swap( m_tagIsOpen, other.m_tagIsOpen );
5164 std::swap( m_needsNewline, other.m_needsNewline );
5165 std::swap( m_tags, other.m_tags );
5166 std::swap( m_indent, other.m_indent );
5167 std::swap( m_os, other.m_os );
5168 }
5169
5170 ///////////////////////////////////////////////////////////////////////
5171 XmlWriter& startElement
5172 (
5173 const std::string& name
5174 )
5175 {
5176 ensureTagClosed();
5177 newlineIfNecessary();
5178 stream() << m_indent << "<" << name;
5179 m_tags.push_back( name );
5180 m_indent += " ";
5181 m_tagIsOpen = true;
5182 return *this;
5183 }
5184
5185 ///////////////////////////////////////////////////////////////////////
5186 ScopedElement scopedElement
5187 (
5188 const std::string& name
5189 )
5190 {
5191 ScopedElement scoped( this );
5192 startElement( name );
5193 return scoped;
5194 }
5195
5196 ///////////////////////////////////////////////////////////////////////
5197 XmlWriter& endElement
5198 ()
5199 {
5200 newlineIfNecessary();
5201 m_indent = m_indent.substr( 0, m_indent.size()-2 );
5202 if( m_tagIsOpen )
5203 {
5204 stream() << "/>\n";
5205 m_tagIsOpen = false;
5206 }
5207 else
5208 {
5209 stream() << m_indent << "</" << m_tags.back() << ">\n";
5210 }
5211 m_tags.pop_back();
5212 return *this;
5213 }
5214
5215 ///////////////////////////////////////////////////////////////////////
5216 XmlWriter& writeAttribute
5217 (
5218 const std::string& name,
5219 const std::string& attribute
5220 )
5221 {
5222 if( !name.empty() && !attribute.empty() )
5223 {
5224 stream() << " " << name << "=\"";
5225 writeEncodedText( attribute );
5226 stream() << "\"";
5227 }
5228 return *this;
5229 }
5230
5231 ///////////////////////////////////////////////////////////////////////
5232 XmlWriter& writeAttribute
5233 (
5234 const std::string& name,
5235 bool attribute
5236 )
5237 {
5238 stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
5239 return *this;
5240 }
5241
5242 ///////////////////////////////////////////////////////////////////////
5243 template<typename T>
5244 XmlWriter& writeAttribute
5245 (
5246 const std::string& name,
5247 const T& attribute
5248 )
5249 {
5250 if( !name.empty() )
5251 {
5252 stream() << " " << name << "=\"" << attribute << "\"";
5253 }
5254 return *this;
5255 }
5256
5257 ///////////////////////////////////////////////////////////////////////
5258 XmlWriter& writeText
5259 (
5260 const std::string& text
5261 )
5262 {
5263 if( !text.empty() )
5264 {
5265 bool tagWasOpen = m_tagIsOpen;
5266 ensureTagClosed();
5267 if( tagWasOpen )
5268 stream() << m_indent;
5269 writeEncodedText( text );
5270 m_needsNewline = true;
5271 }
5272 return *this;
5273 }
5274
5275 ///////////////////////////////////////////////////////////////////////
5276 XmlWriter& writeComment
5277 (
5278 const std::string& text
5279 )
5280 {
5281 ensureTagClosed();
5282 stream() << m_indent << "<!--" << text << "-->";
5283 m_needsNewline = true;
5284 return *this;
5285 }
5286
5287 ///////////////////////////////////////////////////////////////////////
5288 XmlWriter& writeBlankLine
5289 ()
5290 {
5291 ensureTagClosed();
5292 stream() << "\n";
5293 return *this;
5294 }
5295
5296 private:
5297
5298 ///////////////////////////////////////////////////////////////////////
5299 std::ostream& stream
5300 ()
5301 {
5302 return *m_os;
5303 }
5304
5305 ///////////////////////////////////////////////////////////////////////
5306 void ensureTagClosed
5307 ()
5308 {
5309 if( m_tagIsOpen )
5310 {
5311 stream() << ">\n";
5312 m_tagIsOpen = false;
5313 }
5314 }
5315
5316 ///////////////////////////////////////////////////////////////////////
5317 void newlineIfNecessary
5318 ()
5319 {
5320 if( m_needsNewline )
5321 {
5322 stream() << "\n";
5323 m_needsNewline = false;
5324 }
5325 }
5326
5327 ///////////////////////////////////////////////////////////////////////
5328 void writeEncodedText
5329 (
5330 const std::string& text
5331 )
5332 {
Phil Nash6e0f58d2012-02-15 18:37:21 +00005333 static const char* charsToEncode = "<&\"";
5334 std::string mtext = text;
5335 std::string::size_type pos = mtext.find_first_of( charsToEncode );
5336 while( pos != std::string::npos )
Phil Nash89d1e6c2011-05-24 08:23:02 +01005337 {
Phil Nash6e0f58d2012-02-15 18:37:21 +00005338 stream() << mtext.substr( 0, pos );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005339
Phil Nash6e0f58d2012-02-15 18:37:21 +00005340 switch( mtext[pos] )
5341 {
5342 case '<':
5343 stream() << "&lt;";
5344 break;
5345 case '&':
5346 stream() << "&amp;";
5347 break;
5348 case '\"':
5349 stream() << "&quot;";
5350 break;
5351 }
5352 mtext = mtext.substr( pos+1 );
5353 pos = mtext.find_first_of( charsToEncode );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005354 }
Phil Nash6e0f58d2012-02-15 18:37:21 +00005355 stream() << mtext;
Phil Nash89d1e6c2011-05-24 08:23:02 +01005356 }
5357
5358 bool m_tagIsOpen;
5359 bool m_needsNewline;
5360 std::vector<std::string> m_tags;
5361 std::string m_indent;
5362 std::ostream* m_os;
5363 };
5364
5365}
Phil Nash89d1e6c2011-05-24 08:23:02 +01005366namespace Catch
5367{
Phil Nash49e6d532012-05-05 19:35:35 +01005368 class XmlReporter : public SharedImpl<IReporter>
Phil Nash89d1e6c2011-05-24 08:23:02 +01005369 {
5370 public:
5371 ///////////////////////////////////////////////////////////////////////////
5372 XmlReporter
5373 (
5374 const IReporterConfig& config
5375 )
5376 : m_config( config )
5377 {
5378 }
5379
5380 ///////////////////////////////////////////////////////////////////////////
5381 static std::string getDescription
5382 ()
5383 {
5384 return "Reports test results as an XML document";
5385 }
5386
5387 private: // IReporter
5388
5389 ///////////////////////////////////////////////////////////////////////////
Phil Nash333e6e62012-02-17 19:50:59 +00005390 virtual bool shouldRedirectStdout
5391 ()
5392 const
5393 {
5394 return true;
5395 }
5396
5397 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01005398 virtual void StartTesting
5399 ()
5400 {
5401 m_xml = XmlWriter( m_config.stream() );
5402 m_xml.startElement( "Catch" );
5403 if( !m_config.getName().empty() )
5404 m_xml.writeAttribute( "name", m_config.getName() );
5405 }
5406
5407 ///////////////////////////////////////////////////////////////////////////
5408 virtual void EndTesting
5409 (
Phil Nashf7299fc2012-02-25 09:39:45 +00005410 const Totals& totals
Phil Nash89d1e6c2011-05-24 08:23:02 +01005411 )
5412 {
5413 m_xml.scopedElement( "OverallResults" )
Phil Nashf7299fc2012-02-25 09:39:45 +00005414 .writeAttribute( "successes", totals.assertions.passed )
5415 .writeAttribute( "failures", totals.assertions.failed );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005416 m_xml.endElement();
5417 }
5418
5419 ///////////////////////////////////////////////////////////////////////////
5420 virtual void StartGroup
5421 (
5422 const std::string& groupName
5423 )
5424 {
5425 m_xml.startElement( "Group" )
5426 .writeAttribute( "name", groupName );
5427 }
5428
5429 ///////////////////////////////////////////////////////////////////////////
5430 virtual void EndGroup
5431 (
5432 const std::string& /*groupName*/,
Phil Nashf7299fc2012-02-25 09:39:45 +00005433 const Totals& totals
Phil Nash89d1e6c2011-05-24 08:23:02 +01005434 )
5435 {
5436 m_xml.scopedElement( "OverallResults" )
Phil Nashf7299fc2012-02-25 09:39:45 +00005437 .writeAttribute( "successes", totals.assertions.passed )
5438 .writeAttribute( "failures", totals.assertions.failed );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005439 m_xml.endElement();
5440 }
5441
5442 ///////////////////////////////////////////////////////////////////////////
5443 virtual void StartSection( const std::string& sectionName, const std::string description )
5444 {
5445 m_xml.startElement( "Section" )
5446 .writeAttribute( "name", sectionName )
5447 .writeAttribute( "description", description );
5448 }
5449
5450 ///////////////////////////////////////////////////////////////////////////
Phil Nashf7299fc2012-02-25 09:39:45 +00005451 virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions )
Phil Nash89d1e6c2011-05-24 08:23:02 +01005452 {
5453 m_xml.scopedElement( "OverallResults" )
Phil Nashf7299fc2012-02-25 09:39:45 +00005454 .writeAttribute( "successes", assertions.passed )
5455 .writeAttribute( "failures", assertions.failed );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005456 m_xml.endElement();
5457 }
5458
5459 ///////////////////////////////////////////////////////////////////////////
5460 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo )
5461 {
5462 m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.getName() );
5463 m_currentTestSuccess = true;
5464 }
5465
5466 ///////////////////////////////////////////////////////////////////////////
5467 virtual void Result( const Catch::ResultInfo& resultInfo )
5468 {
5469 if( !m_config.includeSuccessfulResults() && resultInfo.getResultType() == ResultWas::Ok )
5470 return;
5471
5472 if( resultInfo.hasExpression() )
5473 {
5474 m_xml.startElement( "Expression" )
5475 .writeAttribute( "success", resultInfo.ok() )
5476 .writeAttribute( "filename", resultInfo.getFilename() )
5477 .writeAttribute( "line", resultInfo.getLine() );
5478
5479 m_xml.scopedElement( "Original" )
5480 .writeText( resultInfo.getExpression() );
5481 m_xml.scopedElement( "Expanded" )
5482 .writeText( resultInfo.getExpandedExpression() );
5483 m_currentTestSuccess &= resultInfo.ok();
5484 }
5485
5486 switch( resultInfo.getResultType() )
5487 {
5488 case ResultWas::ThrewException:
5489 m_xml.scopedElement( "Exception" )
5490 .writeAttribute( "filename", resultInfo.getFilename() )
5491 .writeAttribute( "line", resultInfo.getLine() )
5492 .writeText( resultInfo.getMessage() );
5493 m_currentTestSuccess = false;
5494 break;
5495 case ResultWas::Info:
5496 m_xml.scopedElement( "Info" )
5497 .writeText( resultInfo.getMessage() );
5498 break;
5499 case ResultWas::Warning:
5500 m_xml.scopedElement( "Warning" )
5501 .writeText( resultInfo.getMessage() );
5502 break;
5503 case ResultWas::ExplicitFailure:
5504 m_xml.scopedElement( "Failure" )
5505 .writeText( resultInfo.getMessage() );
5506 m_currentTestSuccess = false;
5507 break;
Phil Nashf51d3162011-12-28 10:37:31 +00005508 case ResultWas::Unknown:
5509 case ResultWas::Ok:
5510 case ResultWas::FailureBit:
5511 case ResultWas::ExpressionFailed:
5512 case ResultWas::Exception:
5513 case ResultWas::DidntThrowException:
Phil Nash89d1e6c2011-05-24 08:23:02 +01005514 default:
5515 break;
5516 }
5517 if( resultInfo.hasExpression() )
5518 m_xml.endElement();
5519 }
5520
5521 ///////////////////////////////////////////////////////////////////////////
Phil Nashf7299fc2012-02-25 09:39:45 +00005522 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals& /* totals */, const std::string& /*stdOut*/, const std::string& /*stdErr*/ )
Phil Nash89d1e6c2011-05-24 08:23:02 +01005523 {
5524 m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess );
5525 m_xml.endElement();
5526 }
5527
5528 private:
5529 const IReporterConfig& m_config;
5530 bool m_currentTestSuccess;
5531 XmlWriter m_xml;
5532 };
5533
5534 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
5535
5536} // end namespace Catch
5537
5538// #included from: reporters/catch_reporter_junit.hpp
5539
Phil Nash89d1e6c2011-05-24 08:23:02 +01005540namespace Catch
5541{
Phil Nash49e6d532012-05-05 19:35:35 +01005542 class JunitReporter : public SharedImpl<IReporter>
Phil Nash89d1e6c2011-05-24 08:23:02 +01005543 {
5544 struct TestStats
5545 {
5546 std::string m_element;
5547 std::string m_resultType;
5548 std::string m_message;
5549 std::string m_content;
5550 };
5551
5552 struct TestCaseStats
5553 {
5554 TestCaseStats( const std::string& name = std::string() )
5555 : m_name( name )
5556 {
5557 }
5558
5559 double m_timeInSeconds;
5560 std::string m_status;
5561 std::string m_className;
5562 std::string m_name;
5563 std::vector<TestStats> m_testStats;
5564 };
5565
5566 struct Stats
5567 {
5568 Stats( const std::string& name = std::string() )
5569 : m_testsCount( 0 ),
5570 m_failuresCount( 0 ),
5571 m_disabledCount( 0 ),
5572 m_errorsCount( 0 ),
5573 m_timeInSeconds( 0 ),
5574 m_name( name )
5575 {
5576 }
5577
5578 std::size_t m_testsCount;
5579 std::size_t m_failuresCount;
5580 std::size_t m_disabledCount;
5581 std::size_t m_errorsCount;
5582 double m_timeInSeconds;
5583 std::string m_name;
5584
5585 std::vector<TestCaseStats> m_testCaseStats;
5586 };
5587
5588 public:
5589 ///////////////////////////////////////////////////////////////////////////
5590 JunitReporter( const IReporterConfig& config )
5591 : m_config( config ),
5592 m_testSuiteStats( "AllTests" ),
5593 m_currentStats( &m_testSuiteStats )
5594 {
5595 }
5596
5597 ///////////////////////////////////////////////////////////////////////////
5598 static std::string getDescription()
5599 {
5600 return "Reports test results in an XML format that looks like Ant's junitreport target";
5601 }
5602
5603 private: // IReporter
5604
5605 ///////////////////////////////////////////////////////////////////////////
Phil Nash333e6e62012-02-17 19:50:59 +00005606 virtual bool shouldRedirectStdout
5607 ()
5608 const
5609 {
5610 return true;
5611 }
5612
5613 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01005614 virtual void StartTesting()
5615 {
5616 }
5617
5618 ///////////////////////////////////////////////////////////////////////////
5619 virtual void StartGroup( const std::string& groupName )
5620 {
5621
5622 m_statsForSuites.push_back( Stats( groupName ) );
5623 m_currentStats = &m_statsForSuites.back();
5624 }
5625
5626 ///////////////////////////////////////////////////////////////////////////
Phil Nashf7299fc2012-02-25 09:39:45 +00005627 virtual void EndGroup( const std::string&, const Totals& totals )
Phil Nash89d1e6c2011-05-24 08:23:02 +01005628 {
Phil Nashf7299fc2012-02-25 09:39:45 +00005629 m_currentStats->m_testsCount = totals.assertions.total();
Phil Nash89d1e6c2011-05-24 08:23:02 +01005630 m_currentStats = &m_testSuiteStats;
5631 }
5632
5633 virtual void StartSection( const std::string& /*sectionName*/, const std::string /*description*/ )
5634 {
5635 }
5636
Phil Nashf7299fc2012-02-25 09:39:45 +00005637 virtual void EndSection( const std::string& /*sectionName*/, const Counts& /* assertions */ )
Phil Nash89d1e6c2011-05-24 08:23:02 +01005638 {
5639 }
5640
5641 ///////////////////////////////////////////////////////////////////////////
5642 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo )
5643 {
5644 m_currentStats->m_testCaseStats.push_back( TestCaseStats( testInfo.getName() ) );
5645
5646 }
5647
5648 ///////////////////////////////////////////////////////////////////////////
5649 virtual void Result( const Catch::ResultInfo& resultInfo )
5650 {
5651 if( resultInfo.getResultType() != ResultWas::Ok || m_config.includeSuccessfulResults() )
5652 {
5653 TestCaseStats& testCaseStats = m_currentStats->m_testCaseStats.back();
5654 TestStats stats;
5655 std::ostringstream oss;
5656 if( !resultInfo.getMessage().empty() )
5657 {
5658 oss << resultInfo.getMessage() << " at ";
5659 }
Phil Nash6e0f58d2012-02-15 18:37:21 +00005660 oss << SourceLineInfo( resultInfo.getFilename(), resultInfo.getLine() );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005661 stats.m_content = oss.str();
5662 stats.m_message = resultInfo.getExpandedExpression();
5663 stats.m_resultType = resultInfo.getTestMacroName();
5664 switch( resultInfo.getResultType() )
5665 {
5666 case ResultWas::ThrewException:
5667 stats.m_element = "error";
5668 m_currentStats->m_errorsCount++;
5669 break;
5670 case ResultWas::Info:
5671 stats.m_element = "info"; // !TBD ?
5672 break;
5673 case ResultWas::Warning:
5674 stats.m_element = "warning"; // !TBD ?
5675 break;
5676 case ResultWas::ExplicitFailure:
5677 stats.m_element = "failure";
5678 m_currentStats->m_failuresCount++;
5679 break;
5680 case ResultWas::ExpressionFailed:
5681 stats.m_element = "failure";
5682 m_currentStats->m_failuresCount++;
5683 break;
5684 case ResultWas::Ok:
5685 stats.m_element = "success";
5686 break;
Phil Nashf51d3162011-12-28 10:37:31 +00005687 case ResultWas::Unknown:
5688 case ResultWas::FailureBit:
5689 case ResultWas::Exception:
5690 case ResultWas::DidntThrowException:
Phil Nash89d1e6c2011-05-24 08:23:02 +01005691 default:
5692 stats.m_element = "unknown";
5693 break;
5694 }
5695 testCaseStats.m_testStats.push_back( stats );
5696
5697 }
5698 }
5699
5700 ///////////////////////////////////////////////////////////////////////////
Phil Nashf7299fc2012-02-25 09:39:45 +00005701 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals& /* totals */, const std::string& stdOut, const std::string& stdErr )
Phil Nash89d1e6c2011-05-24 08:23:02 +01005702 {
5703 if( !stdOut.empty() )
5704 m_stdOut << stdOut << "\n";
5705 if( !stdErr.empty() )
5706 m_stdErr << stdErr << "\n";
5707 }
5708
5709 ///////////////////////////////////////////////////////////////////////////
Phil Nashf7299fc2012-02-25 09:39:45 +00005710 virtual void EndTesting( const Totals& /* totals */ )
Phil Nash89d1e6c2011-05-24 08:23:02 +01005711 {
5712 std::ostream& str = m_config.stream();
5713 {
5714 XmlWriter xml( str );
5715
5716 if( m_statsForSuites.size() > 0 )
5717 xml.startElement( "testsuites" );
5718
5719 std::vector<Stats>::const_iterator it = m_statsForSuites.begin();
5720 std::vector<Stats>::const_iterator itEnd = m_statsForSuites.end();
5721
5722 for(; it != itEnd; ++it )
5723 {
5724 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
5725 xml.writeAttribute( "name", it->m_name );
5726 xml.writeAttribute( "errors", it->m_errorsCount );
5727 xml.writeAttribute( "failures", it->m_failuresCount );
5728 xml.writeAttribute( "tests", it->m_testsCount );
5729 xml.writeAttribute( "hostname", "tbd" );
5730 xml.writeAttribute( "time", "tbd" );
5731 xml.writeAttribute( "timestamp", "tbd" );
5732
5733 OutputTestCases( xml, *it );
5734 }
5735
5736 xml.scopedElement( "system-out" ).writeText( trim( m_stdOut.str() ) );
5737 xml.scopedElement( "system-err" ).writeText( trim( m_stdOut.str() ) );
5738 }
5739 }
5740
5741 ///////////////////////////////////////////////////////////////////////////
5742 void OutputTestCases( XmlWriter& xml, const Stats& stats )
5743 {
5744 std::vector<TestCaseStats>::const_iterator it = stats.m_testCaseStats.begin();
5745 std::vector<TestCaseStats>::const_iterator itEnd = stats.m_testCaseStats.end();
5746 for(; it != itEnd; ++it )
5747 {
5748 xml.writeBlankLine();
5749 xml.writeComment( "Test case" );
5750
5751 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
5752 xml.writeAttribute( "classname", it->m_className );
5753 xml.writeAttribute( "name", it->m_name );
5754 xml.writeAttribute( "time", "tbd" );
5755
5756 OutputTestResult( xml, *it );
5757 }
5758 }
5759
Phil Nash89d1e6c2011-05-24 08:23:02 +01005760 ///////////////////////////////////////////////////////////////////////////
5761 void OutputTestResult( XmlWriter& xml, const TestCaseStats& stats )
5762 {
5763 std::vector<TestStats>::const_iterator it = stats.m_testStats.begin();
5764 std::vector<TestStats>::const_iterator itEnd = stats.m_testStats.end();
5765 for(; it != itEnd; ++it )
5766 {
5767 if( it->m_element != "success" )
5768 {
5769 XmlWriter::ScopedElement e = xml.scopedElement( it->m_element );
5770
5771 xml.writeAttribute( "message", it->m_message );
5772 xml.writeAttribute( "type", it->m_resultType );
5773 if( !it->m_content.empty() )
5774 xml.writeText( it->m_content );
5775 }
5776 }
5777 }
5778
5779 private:
5780 const IReporterConfig& m_config;
5781 bool m_currentTestSuccess;
5782
5783 Stats m_testSuiteStats;
5784 Stats* m_currentStats;
5785 std::vector<Stats> m_statsForSuites;
5786 std::ostringstream m_stdOut;
5787 std::ostringstream m_stdErr;
5788 };
5789
5790 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
5791
5792} // end namespace Catch
5793
Phil Nash89d1e6c2011-05-24 08:23:02 +01005794#include <fstream>
5795#include <stdlib.h>
5796#include <limits>
5797
5798namespace Catch
5799{
5800 //////////////////////////////////////////////////////////////////////////
5801 inline int Main
5802 (
5803 Config& config
5804 )
5805 {
5806 // Handle list request
5807 if( config.listWhat() != Config::List::None )
5808 return List( config );
5809
5810 // Open output file, if specified
5811 std::ofstream ofs;
5812 if( !config.getFilename().empty() )
5813 {
5814 ofs.open( config.getFilename().c_str() );
5815 if( ofs.fail() )
5816 {
5817 std::cerr << "Unable to open file: '" << config.getFilename() << "'" << std::endl;
5818 return (std::numeric_limits<int>::max)();
5819 }
5820 config.setStreamBuf( ofs.rdbuf() );
5821 }
5822
5823 Runner runner( config );
5824
5825 // Run test specs specified on the command line - or default to all
5826 if( !config.testsSpecified() )
5827 {
5828 config.getReporter()->StartGroup( "" );
5829 runner.runAll();
Phil Nashf7299fc2012-02-25 09:39:45 +00005830 config.getReporter()->EndGroup( "", runner.getTotals() );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005831 }
5832 else
5833 {
5834 // !TBD We should get all the testcases upfront, report any missing,
5835 // then just run them
5836 std::vector<std::string>::const_iterator it = config.getTestSpecs().begin();
5837 std::vector<std::string>::const_iterator itEnd = config.getTestSpecs().end();
5838 for(; it != itEnd; ++it )
5839 {
Phil Nashf7299fc2012-02-25 09:39:45 +00005840 Totals prevTotals = runner.getTotals();
Phil Nash89d1e6c2011-05-24 08:23:02 +01005841 config.getReporter()->StartGroup( *it );
5842 if( runner.runMatching( *it ) == 0 )
5843 {
5844 // Use reporter?
5845// std::cerr << "\n[Unable to match any test cases with: " << *it << "]" << std::endl;
5846 }
Phil Nashf7299fc2012-02-25 09:39:45 +00005847 config.getReporter()->EndGroup( *it, runner.getTotals() - prevTotals );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005848 }
5849 }
Phil Nash6e0f58d2012-02-15 18:37:21 +00005850
Phil Nashf7299fc2012-02-25 09:39:45 +00005851 return static_cast<int>( runner.getTotals().assertions.failed );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005852 }
5853
5854 //////////////////////////////////////////////////////////////////////////
Phil Nashf51d3162011-12-28 10:37:31 +00005855 inline void showHelp
Phil Nash89d1e6c2011-05-24 08:23:02 +01005856 (
5857 std::string exeName
5858 )
5859 {
5860 std::string::size_type pos = exeName.find_last_of( "/\\" );
5861 if( pos != std::string::npos )
5862 {
5863 exeName = exeName.substr( pos+1 );
5864 }
5865
5866 std::cout << exeName << " is a CATCH host application. Options are as follows:\n\n"
5867 << "\t-l, --list <tests | reporters> [xml]\n"
5868 << "\t-t, --test <testspec> [<testspec>...]\n"
5869 << "\t-r, --reporter <reporter name>\n"
5870 << "\t-o, --out <file name>|<%stream name>\n"
5871 << "\t-s, --success\n"
5872 << "\t-b, --break\n"
5873 << "\t-n, --name <name>\n\n"
5874 << "For more detail usage please see: https://github.com/philsquared/Catch/wiki/Command-line" << std::endl;
5875 }
5876
5877 //////////////////////////////////////////////////////////////////////////
5878 inline int Main
5879 (
5880 int argc,
5881 char* const argv[],
5882 Config& config
5883 )
5884 {
5885 ArgParser( argc, argv, config );
5886
5887 if( !config.getMessage().empty() )
5888 {
5889 std::cerr << config.getMessage() << std::endl;
5890 return (std::numeric_limits<int>::max)();
5891 }
5892
5893 // Handle help
5894 if( config.showHelp() )
5895 {
5896 showHelp( argv[0] );
5897 return 0;
5898 }
5899
5900 return Main( config );
5901 }
5902
5903 //////////////////////////////////////////////////////////////////////////
5904 inline int Main
5905 (
5906 int argc,
5907 char* const argv[]
5908 )
5909 {
5910 Config config;
5911// if( isDebuggerActive() )
5912// config.useStream( "debug" );
Phil Nash176eb812012-05-11 08:17:16 +01005913 int result = Main( argc, argv, config );
5914 Catch::Context::cleanUp();
5915 return result;
Phil Nash89d1e6c2011-05-24 08:23:02 +01005916 }
5917
5918} // end namespace Catch
5919
5920#endif
5921
5922#ifdef CATCH_CONFIG_MAIN
5923// #included from: internal/catch_default_main.hpp
5924
Phil Nash176eb812012-05-11 08:17:16 +01005925#ifndef __OBJC__
Phil Nash89d1e6c2011-05-24 08:23:02 +01005926
Phil Nash176eb812012-05-11 08:17:16 +01005927// Standard C/C++ main entry point
5928int main (int argc, char * const argv[]) {
5929 return Catch::Main( argc, argv );
5930}
5931
5932#else // __OBJC__
5933
5934// Objective-C entry point
5935int main (int argc, char * const argv[]) {
Phil Nash53c990a2012-03-17 18:20:06 +00005936#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +01005937 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Phil Nash53c990a2012-03-17 18:20:06 +00005938#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01005939
5940 Catch::registerTestMethods();
Phil Nash89d1e6c2011-05-24 08:23:02 +01005941 int result = Catch::Main( argc, (char* const*)argv );
5942
Phil Nash53c990a2012-03-17 18:20:06 +00005943#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +01005944 [pool drain];
Phil Nash53c990a2012-03-17 18:20:06 +00005945#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01005946
Phil Nashdd5b9c22012-02-18 09:58:30 +00005947 return result;
Phil Nash89d1e6c2011-05-24 08:23:02 +01005948}
5949
Phil Nash176eb812012-05-11 08:17:16 +01005950#endif // __OBJC__
5951
Phil Nash89d1e6c2011-05-24 08:23:02 +01005952#endif
5953
Phil Nash89d1e6c2011-05-24 08:23:02 +01005954//////
5955
5956#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, false, true, "REQUIRE" )
5957#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, true, "REQUIRE_FALSE" )
5958
5959#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., true, "REQUIRE_THROWS" )
5960#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, true, "REQUIRE_THROWS_AS" )
5961#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, true, "REQUIRE_NOTHROW" )
5962
5963#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, false, false, "CHECK" )
5964#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, false, "CHECK_FALSE" )
Phil Nasha162e222012-02-10 08:30:13 +00005965#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, false, false, "CHECKED_IF" )
5966#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, false, false, "CHECKED_ELSE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01005967
5968#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., false, "CHECK_THROWS" )
5969#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, false, "CHECK_THROWS_AS" )
5970#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, false, "CHECK_NOTHROW" )
5971
Phil Nash78d95a02012-03-04 21:22:36 +00005972#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, false, "CHECK_THAT" )
5973#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, true, "REQUIRE_THAT" )
5974
Phil Nash89d1e6c2011-05-24 08:23:02 +01005975#define INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, false, "INFO" )
5976#define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, false, "WARN" )
5977#define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, true, "FAIL" )
5978#define SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg )
5979#define CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, false, "CAPTURE" )
5980
5981#define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
5982
5983#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
5984#define TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
5985#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" )
5986#define METHOD_AS_TEST_CASE( method, name, description ) CATCH_METHOD_AS_TEST_CASE( method, name, description )
5987
5988#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
5989#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
5990
5991#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
5992
5993///////////////
5994// Still to be implemented
5995#define CHECK_NOFAIL( expr ) // !TBD - reports violation, but doesn't fail Test
5996
5997using Catch::Detail::Approx;
5998
Phil Nashaec1e5e2012-05-09 19:37:51 +01005999#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01006000