aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--test/unit/catch.hpp5037
1 files changed, 3048 insertions, 1989 deletions
diff --git a/test/unit/catch.hpp b/test/unit/catch.hpp
index 2fc6b728e..03665c43f 100644
--- a/test/unit/catch.hpp
+++ b/test/unit/catch.hpp
@@ -1,6 +1,6 @@
/*
- * CATCH v1.0 build 13 (master branch)
- * Generated: 2013-11-13 08:10:05.836093
+ * CATCH v1.0 build 43 (master branch)
+ * Generated: 2014-05-04 09:22:51.466832
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
@@ -16,9 +16,22 @@
#ifdef __clang__
#pragma clang diagnostic ignored "-Wglobal-constructors"
#pragma clang diagnostic ignored "-Wvariadic-macros"
-
+#pragma clang diagnostic ignored "-Wc99-extensions"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpadded"
+#pragma clang diagnostic ignored "-Wc++98-compat"
+#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
+#endif
+
+#ifdef CATCH_CONFIG_MAIN
+# define CATCH_CONFIG_RUNNER
+#endif
+
+#ifdef CATCH_CONFIG_RUNNER
+# ifndef CLARA_CONFIG_MAIN
+# define CLARA_CONFIG_MAIN_NOT_DEFINED
+# define CLARA_CONFIG_MAIN
+# endif
#endif
// #included from: internal/catch_notimplemented_exception.h
@@ -43,6 +56,18 @@
// Much of the following code is based on Boost (1.53)
+#ifdef __clang__
+
+# if __has_feature(cxx_nullptr)
+# define CATCH_CONFIG_CPP11_NULLPTR
+# endif
+
+# if __has_feature(cxx_noexcept)
+# define CATCH_CONFIG_CPP11_NOEXCEPT
+# endif
+
+#endif // __clang__
+
////////////////////////////////////////////////////////////////////////////////
// Borland
#ifdef __BORLANDC__
@@ -89,6 +114,11 @@
#endif // __GNUC__ < 3
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) )
+
+#define CATCH_CONFIG_CPP11_NULLPTR
+#endif
+
#endif // __GNUC__
////////////////////////////////////////////////////////////////////////////////
@@ -113,6 +143,26 @@
#endif
+////////////////////////////////////////////////////////////////////////////////
+// C++ language feature support
+
+// detect language version:
+#if (__cplusplus == 201103L)
+# define CATCH_CPP11
+# define CATCH_CPP11_OR_GREATER
+#elif (__cplusplus >= 201103L)
+# define CATCH_CPP11_OR_GREATER
+#endif
+
+// noexcept support:
+#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
+# define CATCH_NOEXCEPT noexcept
+# define CATCH_NOEXCEPT_IS(x) noexcept(x)
+#else
+# define CATCH_NOEXCEPT throw()
+# define CATCH_NOEXCEPT_IS(x)
+#endif
+
namespace Catch {
class NonCopyable {
@@ -149,46 +199,17 @@ namespace Catch {
delete it->second;
}
- template<typename ContainerT, typename Function>
- inline void forEach( ContainerT& container, Function function ) {
- std::for_each( container.begin(), container.end(), function );
- }
-
- template<typename ContainerT, typename Function>
- inline void forEach( ContainerT const& container, Function function ) {
- std::for_each( container.begin(), container.end(), function );
- }
-
- inline bool startsWith( std::string const& s, std::string const& prefix ) {
- return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
- }
- inline bool endsWith( std::string const& s, std::string const& suffix ) {
- return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
- }
- inline bool contains( std::string const& s, std::string const& infix ) {
- return s.find( infix ) != std::string::npos;
- }
- inline void toLowerInPlace( std::string& s ) {
- std::transform( s.begin(), s.end(), s.begin(), ::tolower );
- }
- inline std::string toLower( std::string const& s ) {
- std::string lc = s;
- toLowerInPlace( lc );
- return lc;
- }
+ bool startsWith( std::string const& s, std::string const& prefix );
+ bool endsWith( std::string const& s, std::string const& suffix );
+ bool contains( std::string const& s, std::string const& infix );
+ void toLowerInPlace( std::string& s );
+ std::string toLower( std::string const& s );
+ std::string trim( std::string const& str );
struct pluralise {
- pluralise( std::size_t count, std::string const& label )
- : m_count( count ),
- m_label( label )
- {}
+ pluralise( std::size_t count, std::string const& label );
- friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
- os << pluraliser.m_count << " " << pluraliser.m_label;
- if( pluraliser.m_count != 1 )
- os << "s";
- return os;
- }
+ friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
std::size_t m_count;
std::string m_label;
@@ -196,42 +217,40 @@ namespace Catch {
struct SourceLineInfo {
- SourceLineInfo() : line( 0 ){}
- SourceLineInfo( std::string const& _file, std::size_t _line )
- : file( _file ),
- line( _line )
- {}
- SourceLineInfo( SourceLineInfo const& other )
- : file( other.file ),
- line( other.line )
- {}
- bool empty() const {
- return file.empty();
- }
- bool operator == ( SourceLineInfo const& other ) const {
- return line == other.line && file == other.file;
- }
+ SourceLineInfo();
+ SourceLineInfo( char const* _file, std::size_t _line );
+ SourceLineInfo( SourceLineInfo const& other );
+# ifdef CATCH_CPP11_OR_GREATER
+ SourceLineInfo( SourceLineInfo && ) = default;
+ SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
+ SourceLineInfo& operator = ( SourceLineInfo && ) = default;
+# endif
+ bool empty() const;
+ bool operator == ( SourceLineInfo const& other ) const;
+
std::string file;
std::size_t line;
};
- inline std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
-#ifndef __GNUG__
- os << info.file << "(" << info.line << ")";
-#else
- os << info.file << ":" << info.line;
-#endif
- return os;
- }
+ std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
// This is just here to avoid compiler warnings with macro constants and boolean literals
inline bool isTrue( bool value ){ return value; }
- inline void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
- std::ostringstream oss;
- oss << locationInfo << ": Internal Catch error: '" << message << "'";
- if( isTrue( true ))
- throw std::logic_error( oss.str() );
+ void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
+
+ // Use this in variadic streaming macros to allow
+ // >> +StreamEndStop
+ // as well as
+ // >> stuff +StreamEndStop
+ struct StreamEndStop {
+ std::string operator+() {
+ return std::string();
+ }
+ };
+ template<typename T>
+ T const& operator + ( T const& value, StreamEndStop ) {
+ return value;
}
}
@@ -247,9 +266,9 @@ namespace Catch {
public:
NotImplementedException( SourceLineInfo const& lineInfo );
- virtual ~NotImplementedException() throw() {}
+ virtual ~NotImplementedException() CATCH_NOEXCEPT {}
- virtual const char* what() const throw();
+ virtual const char* what() const CATCH_NOEXCEPT;
private:
std::string m_what;
@@ -430,11 +449,14 @@ namespace Catch {
};
class TestCase;
+ struct IConfig;
struct ITestCaseRegistry {
virtual ~ITestCaseRegistry();
virtual std::vector<TestCase> const& getAllTests() const = 0;
- virtual std::vector<TestCase> getMatchingTestCases( std::string const& rawTestSpec ) const = 0;
+ virtual void getFilteredTests( TestCaseFilters const& filters, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const = 0;
+ virtual void getFilteredTests( IConfig const& config, std::vector<TestCase>& matchingTestCases ) const = 0;
+
};
}
@@ -555,8 +577,8 @@ private:
// #included from: catch_expressionresult_builder.h
#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_BUILDER_H_INCLUDED
-// #included from: catch_tostring.hpp
-#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
+// #included from: catch_tostring.h
+#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
// #included from: catch_sfinae.hpp
#define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED
@@ -596,6 +618,7 @@ namespace Catch {
#include <iomanip>
#include <limits>
#include <vector>
+#include <cstddef>
#ifdef __OBJC__
// #included from: catch_objc_arc.hpp
@@ -702,6 +725,43 @@ namespace Detail {
}
};
+ struct Endianness {
+ enum Arch { Big, Little };
+
+ static Arch which() {
+ union {
+ int asInt;
+ char asChar[sizeof (int)];
+ };
+
+ asInt = 1;
+ return ( asChar[sizeof(int)-1] == 1 ) ? Big : Little;
+ }
+ };
+
+ // Writes the raw memory into a string, considering endianness
+ template<typename T>
+ std::string rawMemoryToString( T value ) {
+ union {
+ T typedValue;
+ unsigned char bytes[sizeof(T)];
+ };
+
+ typedValue = value;
+
+ std::ostringstream oss;
+ oss << "0x";
+
+ int i = 0, end = sizeof(T), inc = 1;
+ if( Endianness::which() == Endianness::Little ) {
+ i = end-1;
+ end = inc = -1;
+ }
+ for( ; i != end; i += inc )
+ oss << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)bytes[i];
+ return oss.str();
+ }
+
} // end namespace Detail
template<typename T>
@@ -717,9 +777,18 @@ struct StringMaker<T*> {
static std::string convert( U* p ) {
if( !p )
return INTERNAL_CATCH_STRINGIFY( NULL );
- std::ostringstream oss;
- oss << p;
- return oss.str();
+ else
+ return Detail::rawMemoryToString( p );
+ }
+};
+
+template<typename R, typename C>
+struct StringMaker<R C::*> {
+ static std::string convert( R C::* p ) {
+ if( !p )
+ return INTERNAL_CATCH_STRINGIFY( NULL );
+ else
+ return Detail::rawMemoryToString( p );
}
};
@@ -737,7 +806,7 @@ struct StringMaker<std::vector<T, Allocator> > {
namespace Detail {
template<typename T>
- inline std::string makeString( T const& value ) {
+ std::string makeString( T const& value ) {
return StringMaker<T>::convert( value );
}
} // end namespace Detail
@@ -756,99 +825,27 @@ std::string toString( T const& value ) {
// Built in overloads
-inline std::string toString( std::string const& value ) {
- return "\"" + value + "\"";
-}
-
-inline std::string toString( std::wstring const& value ) {
- std::ostringstream oss;
- oss << "\"";
- for(size_t i = 0; i < value.size(); ++i )
- oss << static_cast<char>( value[i] <= 0xff ? value[i] : '?');
- oss << "\"";
- return oss.str();
-}
-
-inline std::string toString( const char* const value ) {
- return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
-}
-
-inline std::string toString( char* const value ) {
- return Catch::toString( static_cast<const char*>( value ) );
-}
-
-inline std::string toString( int value ) {
- std::ostringstream oss;
- oss << value;
- return oss.str();
-}
-
-inline std::string toString( unsigned long value ) {
- std::ostringstream oss;
- if( value > 8192 )
- oss << "0x" << std::hex << value;
- else
- oss << value;
- return oss.str();
-}
-
-inline std::string toString( unsigned int value ) {
- return toString( static_cast<unsigned long>( value ) );
-}
-
-inline std::string toString( const double value ) {
- std::ostringstream oss;
- oss << std::setprecision( 10 )
- << std::fixed
- << value;
- std::string d = oss.str();
- std::size_t i = d.find_last_not_of( '0' );
- if( i != std::string::npos && i != d.size()-1 ) {
- if( d[i] == '.' )
- i++;
- d = d.substr( 0, i+1 );
- }
- return d;
-}
-
-inline std::string toString( bool value ) {
- return value ? "true" : "false";
-}
-
-inline std::string toString( char value ) {
- return value < ' '
- ? toString( static_cast<unsigned int>( value ) )
- : Detail::makeString( value );
-}
-
-inline std::string toString( signed char value ) {
- return toString( static_cast<char>( value ) );
-}
-
-inline std::string toString( unsigned char value ) {
- return toString( static_cast<char>( value ) );
-}
+std::string toString( std::string const& value );
+std::string toString( std::wstring const& value );
+std::string toString( const char* const value );
+std::string toString( char* const value );
+std::string toString( int value );
+std::string toString( unsigned long value );
+std::string toString( unsigned int value );
+std::string toString( const double value );
+std::string toString( bool value );
+std::string toString( char value );
+std::string toString( signed char value );
+std::string toString( unsigned char value );
#ifdef CATCH_CONFIG_CPP11_NULLPTR
-inline std::string toString( std::nullptr_t ) {
- return "nullptr";
-}
+std::string toString( std::nullptr_t );
#endif
#ifdef __OBJC__
- inline std::string toString( NSString const * const& nsstring ) {
- if( !nsstring )
- return "nil";
- return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
- }
- inline std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
- if( !nsstring )
- return "nil";
- return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
- }
- inline std::string toString( NSObject* const& nsObject ) {
- return toString( [nsObject description] );
- }
+ std::string toString( NSString const * const& nsstring );
+ std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
+ std::string toString( NSObject* const& nsObject );
#endif
namespace Detail {
@@ -962,6 +959,12 @@ namespace Catch {
AssertionResult();
AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
~AssertionResult();
+# ifdef CATCH_CPP11_OR_GREATER
+ AssertionResult( AssertionResult const& ) = default;
+ AssertionResult( AssertionResult && ) = default;
+ AssertionResult& operator = ( AssertionResult const& ) = default;
+ AssertionResult& operator = ( AssertionResult && ) = default;
+# endif
bool isOk() const;
bool succeeded() const;
@@ -991,6 +994,8 @@ namespace Catch {
#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
#endif
+#include <cstddef>
+
namespace Catch {
namespace Internal {
@@ -1200,14 +1205,21 @@ private:
namespace Catch {
-// Wraps the LHS of an expression and captures the operator and RHS (if any) - wrapping them all
-// in an ExpressionResultBuilder object
+// Wraps the LHS of an expression and captures the operator and RHS (if any) -
+// wrapping them all in an ExpressionResultBuilder object
template<typename T>
class ExpressionLhs {
- void operator = ( ExpressionLhs const& );
+ ExpressionLhs& operator = ( ExpressionLhs const& );
+# ifdef CATCH_CPP11_OR_GREATER
+ ExpressionLhs& operator = ( ExpressionLhs && ) = delete;
+# endif
public:
ExpressionLhs( T lhs ) : m_lhs( lhs ) {}
+# ifdef CATCH_CPP11_OR_GREATER
+ ExpressionLhs( ExpressionLhs const& ) = default;
+ ExpressionLhs( ExpressionLhs && ) = default;
+# endif
template<typename RhsT>
ExpressionResultBuilder& operator == ( RhsT const& rhs ) {
@@ -1358,65 +1370,6 @@ namespace Catch {
#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
#include <string>
-// #included from: catch_totals.hpp
-#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
-
-#include <cstddef>
-
-namespace Catch {
-
- struct Counts {
- Counts() : passed( 0 ), failed( 0 ) {}
-
- Counts operator - ( Counts const& other ) const {
- Counts diff;
- diff.passed = passed - other.passed;
- diff.failed = failed - other.failed;
- return diff;
- }
- Counts& operator += ( Counts const& other ) {
- passed += other.passed;
- failed += other.failed;
- return *this;
- }
-
- std::size_t total() const {
- return passed + failed;
- }
-
- std::size_t passed;
- std::size_t failed;
- };
-
- struct Totals {
-
- Totals operator - ( Totals const& other ) const {
- Totals diff;
- diff.assertions = assertions - other.assertions;
- diff.testCases = testCases - other.testCases;
- return diff;
- }
-
- Totals delta( Totals const& prevTotals ) const {
- Totals diff = *this - prevTotals;
- if( diff.assertions.failed > 0 )
- ++diff.testCases.failed;
- else
- ++diff.testCases.passed;
- return diff;
- }
-
- Totals& operator += ( Totals const& other ) {
- assertions += other.assertions;
- testCases += other.testCases;
- return *this;
- }
-
- Counts assertions;
- Counts testCases;
- };
-}
-
namespace Catch {
@@ -1427,6 +1380,7 @@ namespace Catch {
struct SectionInfo;
struct MessageInfo;
class ScopedMessageBuilder;
+ struct Counts;
struct IResultCapture {
@@ -1448,10 +1402,8 @@ namespace Catch {
};
}
-// #included from: catch_debugger.hpp
-#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
-
-#include <iostream>
+// #included from: catch_debugger.h
+#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
// #included from: catch_platform.h
#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
@@ -1464,516 +1416,74 @@ namespace Catch {
#define CATCH_PLATFORM_WINDOWS
#endif
-#ifdef CATCH_PLATFORM_MAC
-
- #include <assert.h>
- #include <stdbool.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <sys/sysctl.h>
-
- namespace Catch{
-
- // The following function is taken directly from the following technical note:
- // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
-
- // Returns true if the current process is being debugged (either
- // running under the debugger or has a debugger attached post facto).
- inline bool isDebuggerActive(){
-
- int junk;
- int mib[4];
- struct kinfo_proc info;
- size_t size;
-
- // Initialize the flags so that, if sysctl fails for some bizarre
- // reason, we get a predictable result.
-
- info.kp_proc.p_flag = 0;
-
- // Initialize mib, which tells sysctl the info we want, in this case
- // we're looking for information about a specific process ID.
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_PID;
- mib[3] = getpid();
+#include <string>
- // Call sysctl.
+namespace Catch{
- size = sizeof(info);
- junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
- assert(junk == 0);
-
- // We're being debugged if the P_TRACED flag is set.
+ bool isDebuggerActive();
+ void writeToDebugConsole( std::string const& text );
+}
- return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
- }
- }
+#ifdef CATCH_PLATFORM_MAC
- // The following code snippet taken from:
+ // The following code snippet based on:
// http://cocoawithlove.com/2008/03/break-into-debugger.html
#ifdef DEBUG
#if defined(__ppc64__) || defined(__ppc__)
- #define BreakIntoDebugger() \
- if( Catch::isDebuggerActive() ) { \
- __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
- : : : "memory","r0","r3","r4" ); \
- }
+ #define CATCH_BREAK_INTO_DEBUGGER() \
+ if( Catch::isDebuggerActive() ) { \
+ __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
+ : : : "memory","r0","r3","r4" ); \
+ }
#else
- #define BreakIntoDebugger() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
+ #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
#endif
- #else
- inline void BreakIntoDebugger(){}
#endif
#elif defined(_MSC_VER)
- extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
- #define BreakIntoDebugger() if (IsDebuggerPresent() ) { __debugbreak(); }
- inline bool isDebuggerActive() {
- return IsDebuggerPresent() != 0;
- }
+ #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
#elif defined(__MINGW32__)
- extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
extern "C" __declspec(dllimport) void __stdcall DebugBreak();
- #define BreakIntoDebugger() if (IsDebuggerPresent() ) { DebugBreak(); }
- inline bool isDebuggerActive() {
- return IsDebuggerPresent() != 0;
- }
-#else
- inline void BreakIntoDebugger(){}
- inline bool isDebuggerActive() { return false; }
+ #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
#endif
-#ifdef CATCH_PLATFORM_WINDOWS
-extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
-inline void writeToDebugConsole( std::string const& text ) {
- ::OutputDebugStringA( text.c_str() );
-}
-#else
-inline void writeToDebugConsole( std::string const& text ) {
- // !TBD: Need a version for Mac/ XCode and other IDEs
- std::cout << text;
-}
-#endif // CATCH_PLATFORM_WINDOWS
+#ifndef CATCH_BREAK_INTO_DEBUGGER
+#define CATCH_BREAK_INTO_DEBUGGER() Catch::isTrue( true );
+#endif
// #included from: catch_interfaces_registry_hub.h
#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
-// #included from: catch_interfaces_reporter.h
-#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
-
-// #included from: catch_config.hpp
-#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
-
-// #included from: catch_test_spec.h
-#define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED
-
-// #included from: catch_test_case_info.h
-#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
-
#include <string>
-#include <set>
-
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wpadded"
-#endif
namespace Catch {
- struct ITestCase;
-
- struct TestCaseInfo {
- TestCaseInfo( std::string const& _name,
- std::string const& _className,
- std::string const& _description,
- std::set<std::string> const& _tags,
- bool _isHidden,
- SourceLineInfo const& _lineInfo );
-
- TestCaseInfo( TestCaseInfo const& other );
-
- std::string name;
- std::string className;
- std::string description;
- std::set<std::string> tags;
- std::string tagsAsString;
- SourceLineInfo lineInfo;
- bool isHidden;
- };
-
- class TestCase : protected TestCaseInfo {
- public:
-
- TestCase( ITestCase* testCase, TestCaseInfo const& info );
- TestCase( TestCase const& other );
-
- TestCase withName( std::string const& _newName ) const;
-
- void invoke() const;
-
- TestCaseInfo const& getTestCaseInfo() const;
-
- bool isHidden() const;
- bool hasTag( std::string const& tag ) const;
- bool matchesTags( std::string const& tagPattern ) const;
- std::set<std::string> const& getTags() const;
-
- void swap( TestCase& other );
- bool operator == ( TestCase const& other ) const;
- bool operator < ( TestCase const& other ) const;
- TestCase& operator = ( TestCase const& other );
-
- private:
- Ptr<ITestCase> test;
- };
-
- TestCase makeTestCase( ITestCase* testCase,
- std::string const& className,
- std::string const& name,
- std::string const& description,
- SourceLineInfo const& lineInfo );
-}
-
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
-
-// #included from: catch_tags.hpp
-#define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED
-
-#include <string>
-#include <set>
-#include <map>
-#include <vector>
-
-#ifdef __clang__
-#pragma clang diagnostic ignored "-Wpadded"
-#endif
-
-namespace Catch {
- class TagParser {
- public:
- virtual ~TagParser();
-
- void parse( std::string const& str ) {
- std::size_t pos = 0;
- while( pos < str.size() ) {
- char c = str[pos];
- if( c == '[' ) {
- std::size_t end = str.find_first_of( ']', pos );
- if( end != std::string::npos ) {
- acceptTag( str.substr( pos+1, end-pos-1 ) );
- pos = end+1;
- }
- else {
- acceptChar( c );
- pos++;
- }
- }
- else {
- acceptChar( c );
- pos++;
- }
- }
- endParse();
- }
-
- protected:
- virtual void acceptTag( std::string const& tag ) = 0;
- virtual void acceptChar( char c ) = 0;
- virtual void endParse() {}
-
- private:
- };
-
- class TagExtracter : public TagParser {
- public:
-
- TagExtracter( std::set<std::string>& tags )
- : m_tags( tags )
- {}
- virtual ~TagExtracter();
-
- void parse( std::string& description ) {
- TagParser::parse( description );
- description = m_remainder;
- }
-
- private:
- virtual void acceptTag( std::string const& tag ) {
- m_tags.insert( toLower( tag ) );
- }
- virtual void acceptChar( char c ) {
- m_remainder += c;
- }
-
- TagExtracter& operator=(TagExtracter const&);
-
- std::set<std::string>& m_tags;
- std::string m_remainder;
- };
-
- class Tag {
- public:
- Tag()
- : m_isNegated( false )
- {}
-
- Tag( std::string const& name, bool isNegated )
- : m_name( name ),
- m_isNegated( isNegated )
- {}
-
- std::string getName() const {
- return m_name;
- }
- bool isNegated() const {
- return m_isNegated;
- }
-
- bool operator ! () const {
- return m_name.empty();
- }
-
- private:
- std::string m_name;
- bool m_isNegated;
- };
-
- class TagSet {
- typedef std::map<std::string, Tag> TagMap;
- public:
- void add( Tag const& tag ) {
- m_tags.insert( std::make_pair( toLower( tag.getName() ), tag ) );
- }
-
- bool empty() const {
- return m_tags.empty();
- }
-
- bool matches( std::set<std::string> const& tags ) const {
- for( TagMap::const_iterator
- it = m_tags.begin(), itEnd = m_tags.end();
- it != itEnd;
- ++it ) {
- bool found = tags.find( it->first ) != tags.end();
- if( found == it->second.isNegated() )
- return false;
- }
- return true;
- }
-
- private:
- TagMap m_tags;
- };
-
- class TagExpression {
- public:
- bool matches( std::set<std::string> const& tags ) const {
- for( std::vector<TagSet>::const_iterator
- it = m_tagSets.begin(), itEnd = m_tagSets.end();
- it != itEnd;
- ++it )
- if( it->matches( tags ) )
- return true;
- return false;
- }
-
- private:
- friend class TagExpressionParser;
-
- std::vector<TagSet> m_tagSets;
- };
-
- class TagExpressionParser : public TagParser {
- public:
- TagExpressionParser( TagExpression& exp )
- : m_isNegated( false ),
- m_exp( exp )
- {}
-
- ~TagExpressionParser();
-
- private:
- virtual void acceptTag( std::string const& tag ) {
- m_currentTagSet.add( Tag( tag, m_isNegated ) );
- m_isNegated = false;
- }
- virtual void acceptChar( char c ) {
- switch( c ) {
- case '~':
- m_isNegated = true;
- break;
- case ',':
- m_exp.m_tagSets.push_back( m_currentTagSet );
- m_currentTagSet = TagSet();
- break;
- }
- }
- virtual void endParse() {
- if( !m_currentTagSet.empty() )
- m_exp.m_tagSets.push_back( m_currentTagSet );
- }
+ class TestCase;
+ struct ITestCaseRegistry;
+ struct IExceptionTranslatorRegistry;
+ struct IExceptionTranslator;
+ struct IReporterRegistry;
+ struct IReporterFactory;
- TagExpressionParser& operator=(TagExpressionParser const&);
+ struct IRegistryHub {
+ virtual ~IRegistryHub();
- bool m_isNegated;
- TagSet m_currentTagSet;
- TagExpression& m_exp;
+ virtual IReporterRegistry const& getReporterRegistry() const = 0;
+ virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
+ virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
};
-} // end namespace Catch
-
-#include <string>
-#include <vector>
-
-namespace Catch {
-
- struct IfFilterMatches{ enum DoWhat {
- AutoDetectBehaviour,
- IncludeTests,
- ExcludeTests
- }; };
-
- class TestCaseFilter {
- enum WildcardPosition {
- NoWildcard = 0,
- WildcardAtStart = 1,
- WildcardAtEnd = 2,
- WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
- };
-
- public:
- TestCaseFilter( std::string const& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::AutoDetectBehaviour )
- : m_stringToMatch( toLower( testSpec ) ),
- m_filterType( matchBehaviour ),
- m_wildcardPosition( NoWildcard )
- {
- if( m_filterType == IfFilterMatches::AutoDetectBehaviour ) {
- if( startsWith( m_stringToMatch, "exclude:" ) ) {
- m_stringToMatch = m_stringToMatch.substr( 8 );
- m_filterType = IfFilterMatches::ExcludeTests;
- }
- else if( startsWith( m_stringToMatch, "~" ) ) {
- m_stringToMatch = m_stringToMatch.substr( 1 );
- m_filterType = IfFilterMatches::ExcludeTests;
- }
- else {
- m_filterType = IfFilterMatches::IncludeTests;
- }
- }
-
- if( startsWith( m_stringToMatch, "*" ) ) {
- m_stringToMatch = m_stringToMatch.substr( 1 );
- m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtStart );
- }
- if( endsWith( m_stringToMatch, "*" ) ) {
- m_stringToMatch = m_stringToMatch.substr( 0, m_stringToMatch.size()-1 );
- m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtEnd );
- }
- }
-
- IfFilterMatches::DoWhat getFilterType() const {
- return m_filterType;
- }
-
- bool shouldInclude( TestCase const& testCase ) const {
- return isMatch( testCase ) == (m_filterType == IfFilterMatches::IncludeTests);
- }
- private:
-
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunreachable-code"
-#endif
-
- bool isMatch( TestCase const& testCase ) const {
- std::string name = testCase.getTestCaseInfo().name;
- toLowerInPlace( name );
-
- switch( m_wildcardPosition ) {
- case NoWildcard:
- return m_stringToMatch == name;
- case WildcardAtStart:
- return endsWith( name, m_stringToMatch );
- case WildcardAtEnd:
- return startsWith( name, m_stringToMatch );
- case WildcardAtBothEnds:
- return contains( name, m_stringToMatch );
- }
- throw std::logic_error( "Unhandled wildcard type" );
- }
-
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
-
- std::string m_stringToMatch;
- IfFilterMatches::DoWhat m_filterType;
- WildcardPosition m_wildcardPosition;
+ struct IMutableRegistryHub {
+ virtual ~IMutableRegistryHub();
+ virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0;
+ virtual void registerTest( TestCase const& testInfo ) = 0;
+ virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
};
- class TestCaseFilters {
- public:
- TestCaseFilters( std::string const& name ) : m_name( name ) {}
-
- std::string getName() const {
- return m_name;
- }
-
- void addFilter( TestCaseFilter const& filter ) {
- if( filter.getFilterType() == IfFilterMatches::ExcludeTests )
- m_exclusionFilters.push_back( filter );
- else
- m_inclusionFilters.push_back( filter );
- }
-
- void addTags( std::string const& tagPattern ) {
- TagExpression exp;
- TagExpressionParser( exp ).parse( tagPattern );
-
- m_tagExpressions.push_back( exp );
- }
-
- bool shouldInclude( TestCase const& testCase ) const {
- if( !m_tagExpressions.empty() ) {
- std::vector<TagExpression>::const_iterator it = m_tagExpressions.begin();
- std::vector<TagExpression>::const_iterator itEnd = m_tagExpressions.end();
- for(; it != itEnd; ++it )
- if( it->matches( testCase.getTags() ) )
- break;
- if( it == itEnd )
- return false;
- }
-
- if( !m_inclusionFilters.empty() ) {
- std::vector<TestCaseFilter>::const_iterator it = m_inclusionFilters.begin();
- std::vector<TestCaseFilter>::const_iterator itEnd = m_inclusionFilters.end();
- for(; it != itEnd; ++it )
- if( it->shouldInclude( testCase ) )
- break;
- if( it == itEnd )
- return false;
- }
- else if( m_exclusionFilters.empty() && m_tagExpressions.empty() ) {
- return !testCase.isHidden();
- }
-
- std::vector<TestCaseFilter>::const_iterator it = m_exclusionFilters.begin();
- std::vector<TestCaseFilter>::const_iterator itEnd = m_exclusionFilters.end();
- for(; it != itEnd; ++it )
- if( !it->shouldInclude( testCase ) )
- return false;
- return true;
- }
- private:
- std::vector<TagExpression> m_tagExpressions;
- std::vector<TestCaseFilter> m_inclusionFilters;
- std::vector<TestCaseFilter> m_exclusionFilters;
- std::string m_name;
- };
+ IRegistryHub& getRegistryHub();
+ IMutableRegistryHub& getMutableRegistryHub();
+ void cleanUp();
+ std::string translateActiveException();
}
@@ -1982,6 +1492,7 @@ namespace Catch {
#include <iostream>
#include <string>
+#include <vector>
namespace Catch {
@@ -2002,6 +1513,8 @@ namespace Catch {
Never
}; };
+ class TestCaseFilters;
+
struct IConfig : IShared {
virtual ~IConfig();
@@ -2013,774 +1526,12 @@ namespace Catch {
virtual bool shouldDebugBreak() const = 0;
virtual bool warnAboutMissingAssertions() const = 0;
virtual int abortAfter() const = 0;
+ virtual bool showInvisibles() const = 0;
virtual ShowDurations::OrNot showDurations() const = 0;
+ virtual std::vector<TestCaseFilters> const& filters() const = 0;
};
}
-// #included from: catch_stream.hpp
-#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
-
-// #included from: catch_streambuf.h
-#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
-
-#include <streambuf>
-
-namespace Catch {
-
- class StreamBufBase : public std::streambuf {
- public:
- virtual ~StreamBufBase() throw();
- };
-}
-
-#include <stdexcept>
-#include <cstdio>
-
-namespace Catch {
-
- template<typename WriterF, size_t bufferSize=256>
- class StreamBufImpl : public StreamBufBase {
- char data[bufferSize];
- WriterF m_writer;
-
- public:
- StreamBufImpl() {
- setp( data, data + sizeof(data) );
- }
-
- ~StreamBufImpl() throw() {
- sync();
- }
-
- private:
- int overflow( int c ) {
- sync();
-
- if( c != EOF ) {
- if( pbase() == epptr() )
- m_writer( std::string( 1, static_cast<char>( c ) ) );
- else
- sputc( static_cast<char>( c ) );
- }
- return 0;
- }
-
- int sync() {
- if( pbase() != pptr() ) {
- m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
- setp( pbase(), epptr() );
- }
- return 0;
- }
- };
-
- ///////////////////////////////////////////////////////////////////////////
-
- struct OutputDebugWriter {
-
- void operator()( std::string const&str ) {
- writeToDebugConsole( str );
- }
- };
-
- class Stream {
- public:
- Stream()
- : streamBuf( NULL ), isOwned( false )
- {}
-
- Stream( std::streambuf* _streamBuf, bool _isOwned )
- : streamBuf( _streamBuf ), isOwned( _isOwned )
- {}
-
- void release() {
- if( isOwned ) {
- delete streamBuf;
- streamBuf = NULL;
- isOwned = false;
- }
- }
-
- std::streambuf* streamBuf;
-
- private:
- bool isOwned;
- };
-}
-
-#include <memory>
-#include <vector>
-#include <string>
-#include <iostream>
-
-#ifndef CATCH_CONFIG_CONSOLE_WIDTH
-#define CATCH_CONFIG_CONSOLE_WIDTH 80
-#endif
-
-namespace Catch {
-
- struct ConfigData {
-
- ConfigData()
- : listTests( false ),
- listTags( false ),
- listReporters( false ),
- showSuccessfulTests( false ),
- shouldDebugBreak( false ),
- noThrow( false ),
- showHelp( false ),
- abortAfter( -1 ),
- verbosity( Verbosity::Normal ),
- warnings( WarnAbout::Nothing ),
- showDurations( ShowDurations::DefaultForReporter )
- {}
-
- bool listTests;
- bool listTags;
- bool listReporters;
-
- bool showSuccessfulTests;
- bool shouldDebugBreak;
- bool noThrow;
- bool showHelp;
-
- int abortAfter;
-
- Verbosity::Level verbosity;
- WarnAbout::What warnings;
- ShowDurations::OrNot showDurations;
-
- std::string reporterName;
- std::string outputFilename;
- std::string name;
- std::string processName;
-
- std::vector<std::string> testsOrTags;
- };
-
- class Config : public SharedImpl<IConfig> {
- private:
- Config( Config const& other );
- Config& operator = ( Config const& other );
- virtual void dummy();
- public:
-
- Config()
- : m_os( std::cout.rdbuf() )
- {}
-
- Config( ConfigData const& data )
- : m_data( data ),
- m_os( std::cout.rdbuf() )
- {
- if( !data.testsOrTags.empty() ) {
- std::string groupName;
- for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) {
- if( i != 0 )
- groupName += " ";
- groupName += data.testsOrTags[i];
- }
- TestCaseFilters filters( groupName );
- for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) {
- std::string filter = data.testsOrTags[i];
- if( startsWith( filter, "[" ) || startsWith( filter, "~[" ) )
- filters.addTags( filter );
- else
- filters.addFilter( TestCaseFilter( filter ) );
- }
- m_filterSets.push_back( filters );
- }
- }
-
- virtual ~Config() {
- m_os.rdbuf( std::cout.rdbuf() );
- m_stream.release();
- }
-
- void setFilename( std::string const& filename ) {
- m_data.outputFilename = filename;
- }
-
- std::string const& getFilename() const {
- return m_data.outputFilename ;
- }
-
- bool listTests() const { return m_data.listTests; }
- bool listTags() const { return m_data.listTags; }
- bool listReporters() const { return m_data.listReporters; }
-
- std::string getProcessName() const {
- return m_data.processName;
- }
-
- bool shouldDebugBreak() const {
- return m_data.shouldDebugBreak;
- }
-
- void setStreamBuf( std::streambuf* buf ) {
- m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
- }
-
- void useStream( std::string const& streamName ) {
- Stream stream = createStream( streamName );
- setStreamBuf( stream.streamBuf );
- m_stream.release();
- m_stream = stream;
- }
-
- std::string getReporterName() const { return m_data.reporterName; }
-
- void addTestSpec( std::string const& testSpec ) {
- TestCaseFilters filters( testSpec );
- filters.addFilter( TestCaseFilter( testSpec ) );
- m_filterSets.push_back( filters );
- }
-
- int abortAfter() const {
- return m_data.abortAfter;
- }
-
- std::vector<TestCaseFilters> const& filters() const {
- return m_filterSets;
- }
-
- bool showHelp() const { return m_data.showHelp; }
-
- // IConfig interface
- virtual bool allowThrows() const { return !m_data.noThrow; }
- virtual std::ostream& stream() const { return m_os; }
- virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
- virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
- virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
- virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
-
- private:
- ConfigData m_data;
-
- Stream m_stream;
- mutable std::ostream m_os;
- std::vector<TestCaseFilters> m_filterSets;
- };
-
-} // end namespace Catch
-
-// #included from: catch_option.hpp
-#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
-
-namespace Catch {
-
- // An optional type
- template<typename T>
- class Option {
- public:
- Option() : nullableValue( NULL ) {}
- Option( T const& _value )
- : nullableValue( new( storage ) T( _value ) )
- {}
- Option( Option const& _other )
- : nullableValue( _other ? new( storage ) T( *_other ) : NULL )
- {}
-
- ~Option() {
- reset();
- }
-
- Option& operator= ( Option const& _other ) {
- reset();
- if( _other )
- nullableValue = new( storage ) T( *_other );
- return *this;
- }
- Option& operator = ( T const& _value ) {
- reset();
- nullableValue = new( storage ) T( _value );
- return *this;
- }
-
- void reset() {
- if( nullableValue )
- nullableValue->~T();
- nullableValue = NULL;
- }
-
- T& operator*() { return *nullableValue; }
- T const& operator*() const { return *nullableValue; }
- T* operator->() { return nullableValue; }
- const T* operator->() const { return nullableValue; }
-
- T valueOr( T const& defaultValue ) const {
- return nullableValue ? *nullableValue : defaultValue;
- }
-
- bool some() const { return nullableValue != NULL; }
- bool none() const { return nullableValue == NULL; }
-
- bool operator !() const { return nullableValue == NULL; }
- operator SafeBool::type() const {
- return SafeBool::makeSafe( some() );
- }
-
- private:
- T* nullableValue;
- char storage[sizeof(T)];
- };
-
-} // end namespace Catch
-
-#include <string>
-#include <ostream>
-#include <map>
-#include <assert.h>
-
-namespace Catch
-{
- struct ReporterConfig {
- explicit ReporterConfig( Ptr<IConfig> const& _fullConfig )
- : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
-
- ReporterConfig( Ptr<IConfig> const& _fullConfig, std::ostream& _stream )
- : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
-
- std::ostream& stream() const { return *m_stream; }
- Ptr<IConfig> fullConfig() const { return m_fullConfig; }
-
- private:
- std::ostream* m_stream;
- Ptr<IConfig> m_fullConfig;
- };
-
- struct ReporterPreferences {
- ReporterPreferences()
- : shouldRedirectStdOut( false )
- {}
-
- bool shouldRedirectStdOut;
- };
-
- template<typename T>
- struct LazyStat : Option<T> {
- LazyStat() : used( false ) {}
- LazyStat& operator=( T const& _value ) {
- Option<T>::operator=( _value );
- used = false;
- return *this;
- }
- void reset() {
- Option<T>::reset();
- used = false;
- }
- bool used;
- };
-
- struct TestRunInfo {
- TestRunInfo( std::string const& _name ) : name( _name ) {}
- std::string name;
- };
- struct GroupInfo {
- GroupInfo( std::string const& _name,
- std::size_t _groupIndex,
- std::size_t _groupsCount )
- : name( _name ),
- groupIndex( _groupIndex ),
- groupsCounts( _groupsCount )
- {}
-
- std::string name;
- std::size_t groupIndex;
- std::size_t groupsCounts;
- };
-
- struct SectionInfo {
- SectionInfo( std::string const& _name,
- std::string const& _description,
- SourceLineInfo const& _lineInfo )
- : name( _name ),
- description( _description ),
- lineInfo( _lineInfo )
- {}
-
- std::string name;
- std::string description;
- SourceLineInfo lineInfo;
- };
-
- struct AssertionStats {
- AssertionStats( AssertionResult const& _assertionResult,
- std::vector<MessageInfo> const& _infoMessages,
- Totals const& _totals )
- : assertionResult( _assertionResult ),
- infoMessages( _infoMessages ),
- totals( _totals )
- {
- if( assertionResult.hasMessage() ) {
- // Copy message into messages list.
- // !TBD This should have been done earlier, somewhere
- MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
- builder << assertionResult.getMessage();
- builder.m_info.message = builder.m_stream.str();
-
- infoMessages.push_back( builder.m_info );
- }
- }
- virtual ~AssertionStats();
-
- AssertionResult assertionResult;
- std::vector<MessageInfo> infoMessages;
- Totals totals;
- };
-
- struct SectionStats {
- SectionStats( SectionInfo const& _sectionInfo,
- Counts const& _assertions,
- double _durationInSeconds,
- bool _missingAssertions )
- : sectionInfo( _sectionInfo ),
- assertions( _assertions ),
- durationInSeconds( _durationInSeconds ),
- missingAssertions( _missingAssertions )
- {}
- virtual ~SectionStats();
-
- SectionInfo sectionInfo;
- Counts assertions;
- double durationInSeconds;
- bool missingAssertions;
- };
-
- struct TestCaseStats {
- TestCaseStats( TestCaseInfo const& _testInfo,
- Totals const& _totals,
- std::string const& _stdOut,
- std::string const& _stdErr,
- bool _aborting )
- : testInfo( _testInfo ),
- totals( _totals ),
- stdOut( _stdOut ),
- stdErr( _stdErr ),
- aborting( _aborting )
- {}
- virtual ~TestCaseStats();
-
- TestCaseInfo testInfo;
- Totals totals;
- std::string stdOut;
- std::string stdErr;
- bool aborting;
- };
-
- struct TestGroupStats {
- TestGroupStats( GroupInfo const& _groupInfo,
- Totals const& _totals,
- bool _aborting )
- : groupInfo( _groupInfo ),
- totals( _totals ),
- aborting( _aborting )
- {}
- TestGroupStats( GroupInfo const& _groupInfo )
- : groupInfo( _groupInfo ),
- aborting( false )
- {}
- virtual ~TestGroupStats();
-
- GroupInfo groupInfo;
- Totals totals;
- bool aborting;
- };
-
- struct TestRunStats {
- TestRunStats( TestRunInfo const& _runInfo,
- Totals const& _totals,
- bool _aborting )
- : runInfo( _runInfo ),
- totals( _totals ),
- aborting( _aborting )
- {}
- TestRunStats( TestRunStats const& _other )
- : runInfo( _other.runInfo ),
- totals( _other.totals ),
- aborting( _other.aborting )
- {}
- virtual ~TestRunStats();
-
- TestRunInfo runInfo;
- Totals totals;
- bool aborting;
- };
-
- struct IStreamingReporter : IShared {
- virtual ~IStreamingReporter();
-
- // Implementing class must also provide the following static method:
- // static std::string getDescription();
-
- virtual ReporterPreferences getPreferences() const = 0;
-
- virtual void noMatchingTestCases( std::string const& spec ) = 0;
-
- virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
- virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
-
- virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
- virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
-
- virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
-
- virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
- virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
- virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
- virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
- virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
- };
-
- struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
-
- StreamingReporterBase( ReporterConfig const& _config )
- : m_config( _config.fullConfig() ),
- stream( _config.stream() )
- {}
-
- virtual ~StreamingReporterBase();
-
- virtual void noMatchingTestCases( std::string const& ) {}
-
- virtual void testRunStarting( TestRunInfo const& _testRunInfo ) {
- currentTestRunInfo = _testRunInfo;
- }
- virtual void testGroupStarting( GroupInfo const& _groupInfo ) {
- currentGroupInfo = _groupInfo;
- }
-
- virtual void testCaseStarting( TestCaseInfo const& _testInfo ) {
- currentTestCaseInfo = _testInfo;
- }
- virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
- m_sectionStack.push_back( _sectionInfo );
- }
-
- virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) {
- m_sectionStack.pop_back();
- }
- virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) {
- currentTestCaseInfo.reset();
- assert( m_sectionStack.empty() );
- }
- virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) {
- currentGroupInfo.reset();
- }
- virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) {
- currentTestCaseInfo.reset();
- currentGroupInfo.reset();
- currentTestRunInfo.reset();
- }
-
- Ptr<IConfig> m_config;
- std::ostream& stream;
-
- LazyStat<TestRunInfo> currentTestRunInfo;
- LazyStat<GroupInfo> currentGroupInfo;
- LazyStat<TestCaseInfo> currentTestCaseInfo;
-
- std::vector<SectionInfo> m_sectionStack;
- };
-
- struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
- template<typename T, typename ChildNodeT>
- struct Node : SharedImpl<> {
- explicit Node( T const& _value ) : value( _value ) {}
- virtual ~Node() {}
-
- typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
- T value;
- ChildNodes children;
- };
- struct SectionNode : SharedImpl<> {
- explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {}
- virtual ~SectionNode();
-
- bool operator == ( SectionNode const& other ) const {
- return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
- }
- bool operator == ( Ptr<SectionNode> const& other ) const {
- return operator==( *other );
- }
-
- SectionStats stats;
- typedef std::vector<Ptr<SectionNode> > ChildSections;
- typedef std::vector<AssertionStats> Assertions;
- ChildSections childSections;
- Assertions assertions;
- std::string stdOut;
- std::string stdErr;
- };
- friend bool operator == ( Ptr<SectionNode> const& node, SectionInfo const& other ) {
- return node->stats.sectionInfo.lineInfo == other.lineInfo;
- }
-
- typedef Node<TestCaseStats, SectionNode> TestCaseNode;
- typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
- typedef Node<TestRunStats, TestGroupNode> TestRunNode;
-
- CumulativeReporterBase( ReporterConfig const& _config )
- : m_config( _config.fullConfig() ),
- stream( _config.stream() )
- {}
- ~CumulativeReporterBase();
-
- virtual void testRunStarting( TestRunInfo const& ) {}
- virtual void testGroupStarting( GroupInfo const& ) {}
-
- virtual void testCaseStarting( TestCaseInfo const& ) {}
-
- virtual void sectionStarting( SectionInfo const& sectionInfo ) {
- SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
- Ptr<SectionNode> node;
- if( m_sectionStack.empty() ) {
- if( !m_rootSection )
- m_rootSection = new SectionNode( incompleteStats );
- node = m_rootSection;
- }
- else {
- SectionNode& parentNode = *m_sectionStack.back();
- SectionNode::ChildSections::const_iterator it =
- std::find( parentNode.childSections.begin(), parentNode.childSections.end(), sectionInfo );
- if( it == parentNode.childSections.end() ) {
- node = new SectionNode( incompleteStats );
- parentNode.childSections.push_back( node );
- }
- else
- node = *it;
- }
- m_sectionStack.push_back( node );
- m_deepestSection = node;
- }
-
- virtual void assertionStarting( AssertionInfo const& ) {}
-
- virtual bool assertionEnded( AssertionStats const& assertionStats ) {
- assert( !m_sectionStack.empty() );
- SectionNode& sectionNode = *m_sectionStack.back();
- sectionNode.assertions.push_back( assertionStats );
- return true;
- }
- virtual void sectionEnded( SectionStats const& sectionStats ) {
- assert( !m_sectionStack.empty() );
- SectionNode& node = *m_sectionStack.back();
- node.stats = sectionStats;
- m_sectionStack.pop_back();
- }
- virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
- Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
- assert( m_sectionStack.size() == 0 );
- node->children.push_back( m_rootSection );
- m_testCases.push_back( node );
- m_rootSection.reset();
-
- assert( m_deepestSection );
- m_deepestSection->stdOut = testCaseStats.stdOut;
- m_deepestSection->stdErr = testCaseStats.stdErr;
- }
- virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
- Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
- node->children.swap( m_testCases );
- m_testGroups.push_back( node );
- }
- virtual void testRunEnded( TestRunStats const& testRunStats ) {
- Ptr<TestRunNode> node = new TestRunNode( testRunStats );
- node->children.swap( m_testGroups );
- m_testRuns.push_back( node );
- testRunEnded();
- }
- virtual void testRunEnded() = 0;
-
- Ptr<IConfig> m_config;
- std::ostream& stream;
- std::vector<AssertionStats> m_assertions;
- std::vector<std::vector<Ptr<SectionNode> > > m_sections;
- std::vector<Ptr<TestCaseNode> > m_testCases;
- std::vector<Ptr<TestGroupNode> > m_testGroups;
-
- std::vector<Ptr<TestRunNode> > m_testRuns;
-
- Ptr<SectionNode> m_rootSection;
- Ptr<SectionNode> m_deepestSection;
- std::vector<Ptr<SectionNode> > m_sectionStack;
-
- };
-
- // Deprecated
- struct IReporter : IShared {
- virtual ~IReporter();
-
- virtual bool shouldRedirectStdout() const = 0;
-
- virtual void StartTesting() = 0;
- virtual void EndTesting( Totals const& totals ) = 0;
- virtual void StartGroup( std::string const& groupName ) = 0;
- virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
- virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
- virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
- virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
- virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
- virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
- virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
- virtual void Aborted() = 0;
- virtual void Result( AssertionResult const& result ) = 0;
- };
-
- struct IReporterFactory {
- virtual ~IReporterFactory();
- virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
- virtual std::string getDescription() const = 0;
- };
-
- struct IReporterRegistry {
- typedef std::map<std::string, IReporterFactory*> FactoryMap;
-
- virtual ~IReporterRegistry();
- virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const = 0;
- virtual FactoryMap const& getFactories() const = 0;
- };
-
- inline std::string trim( std::string const& str ) {
- static char const* whitespaceChars = "\n\r\t ";
- std::string::size_type start = str.find_first_not_of( whitespaceChars );
- std::string::size_type end = str.find_last_not_of( whitespaceChars );
-
- return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
- }
-}
-
-#include <vector>
-
-namespace Catch {
-
- class TestCase;
- struct ITestCaseRegistry;
- struct IExceptionTranslatorRegistry;
- struct IExceptionTranslator;
-
- struct IRegistryHub {
- virtual ~IRegistryHub();
-
- virtual IReporterRegistry const& getReporterRegistry() const = 0;
- virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
- virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
- };
-
- struct IMutableRegistryHub {
- virtual ~IMutableRegistryHub();
- virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0;
- virtual void registerTest( TestCase const& testInfo ) = 0;
- virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
- };
-
- IRegistryHub& getRegistryHub();
- IMutableRegistryHub& getMutableRegistryHub();
- void cleanUp();
- std::string translateActiveException();
-
-}
-
#include <ostream>
namespace Catch {
@@ -2823,32 +1574,25 @@ struct TestFailureException{};
} // end namespace Catch
///////////////////////////////////////////////////////////////////////////////
-#define INTERNAL_CATCH_ASSERTIONINFO_NAME INTERNAL_CATCH_UNIQUE_NAME( __assertionInfo )
-
-///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_ACCEPT_EXPR( evaluatedExpr, resultDisposition, originalExpr ) \
- if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, INTERNAL_CATCH_ASSERTIONINFO_NAME ) ) { \
- if( internal_catch_action & Catch::ResultAction::Debug ) BreakIntoDebugger(); \
+ if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, __assertionInfo ) ) { \
+ if( internal_catch_action & Catch::ResultAction::Debug ) CATCH_BREAK_INTO_DEBUGGER(); \
if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \
if( !Catch::shouldContinueOnFailure( resultDisposition ) ) throw Catch::TestFailureException(); \
Catch::isTrue( false && originalExpr ); \
}
///////////////////////////////////////////////////////////////////////////////
-#define INTERNAL_CATCH_ACCEPT_INFO( expr, macroName, resultDisposition ) \
- Catch::AssertionInfo INTERNAL_CATCH_ASSERTIONINFO_NAME( macroName, CATCH_INTERNAL_LINEINFO, expr, resultDisposition );
-
-///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
do { \
- INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
+ Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
try { \
INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \
} catch( Catch::TestFailureException& ) { \
throw; \
} catch( ... ) { \
INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \
- resultDisposition | Catch::ResultDisposition::ContinueOnFailure, expr ); \
+ Catch::ResultDisposition::Normal, expr ); \
} \
} while( Catch::isTrue( false ) )
@@ -2865,7 +1609,7 @@ struct TestFailureException{};
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
do { \
- INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
+ Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
try { \
expr; \
INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \
@@ -2893,14 +1637,14 @@ struct TestFailureException{};
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_THROWS( expr, exceptionType, resultDisposition, macroName ) \
do { \
- INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
+ Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
} while( Catch::isTrue( false ) )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
do { \
- INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
+ Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
catch( ... ) { \
INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
@@ -2909,11 +1653,19 @@ struct TestFailureException{};
} while( Catch::isTrue( false ) )
///////////////////////////////////////////////////////////////////////////////
-#define INTERNAL_CATCH_MSG( log, messageType, resultDisposition, macroName ) \
- do { \
- INTERNAL_CATCH_ACCEPT_INFO( "", macroName, resultDisposition ); \
- INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << log, resultDisposition, true ) \
- } while( Catch::isTrue( false ) )
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+ #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
+ do { \
+ Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
+ INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << __VA_ARGS__ +::Catch::StreamEndStop(), resultDisposition, true ) \
+ } while( Catch::isTrue( false ) )
+#else
+ #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
+ do { \
+ Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
+ INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << log, resultDisposition, true ) \
+ } while( Catch::isTrue( false ) )
+#endif
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_INFO( log, macroName ) \
@@ -2922,7 +1674,7 @@ struct TestFailureException{};
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
do { \
- INTERNAL_CATCH_ACCEPT_INFO( #arg " " #matcher, macroName, resultDisposition ); \
+ Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \
try { \
INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \
} catch( Catch::TestFailureException& ) { \
@@ -2933,8 +1685,88 @@ struct TestFailureException{};
} \
} while( Catch::isTrue( false ) )
-// #included from: internal/catch_section.hpp
-#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
+// #included from: internal/catch_section.h
+#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
+
+// #included from: catch_section_info.h
+#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
+
+namespace Catch {
+
+ struct SectionInfo {
+ SectionInfo( std::string const& _name,
+ std::string const& _description,
+ SourceLineInfo const& _lineInfo )
+ : name( _name ),
+ description( _description ),
+ lineInfo( _lineInfo )
+ {}
+
+ std::string name;
+ std::string description;
+ SourceLineInfo lineInfo;
+ };
+
+} // end namespace Catch
+
+// #included from: catch_totals.hpp
+#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
+
+#include <cstddef>
+
+namespace Catch {
+
+ struct Counts {
+ Counts() : passed( 0 ), failed( 0 ) {}
+
+ Counts operator - ( Counts const& other ) const {
+ Counts diff;
+ diff.passed = passed - other.passed;
+ diff.failed = failed - other.failed;
+ return diff;
+ }
+ Counts& operator += ( Counts const& other ) {
+ passed += other.passed;
+ failed += other.failed;
+ return *this;
+ }
+
+ std::size_t total() const {
+ return passed + failed;
+ }
+
+ std::size_t passed;
+ std::size_t failed;
+ };
+
+ struct Totals {
+
+ Totals operator - ( Totals const& other ) const {
+ Totals diff;
+ diff.assertions = assertions - other.assertions;
+ diff.testCases = testCases - other.testCases;
+ return diff;
+ }
+
+ Totals delta( Totals const& prevTotals ) const {
+ Totals diff = *this - prevTotals;
+ if( diff.assertions.failed > 0 )
+ ++diff.testCases.failed;
+ else
+ ++diff.testCases.passed;
+ return diff;
+ }
+
+ Totals& operator += ( Totals const& other ) {
+ assertions += other.assertions;
+ testCases += other.testCases;
+ return *this;
+ }
+
+ Counts assertions;
+ Counts testCases;
+ };
+}
// #included from: catch_timer.h
#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
@@ -2969,24 +1801,20 @@ namespace Catch {
public:
Section( SourceLineInfo const& lineInfo,
std::string const& name,
- std::string const& description = "" )
- : m_info( name, description, lineInfo ),
- m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( m_info, m_assertions ) )
- {
- m_timer.start();
- }
-
- ~Section() {
- if( m_sectionIncluded )
- getCurrentContext().getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() );
- }
+ std::string const& description = "" );
+ ~Section();
+# ifdef CATCH_CPP11_OR_GREATER
+ Section( Section const& ) = default;
+ Section( Section && ) = default;
+ Section& operator = ( Section const& ) = default;
+ Section& operator = ( Section && ) = default;
+# endif
// This indicates whether the section should be executed or not
- operator bool() {
- return m_sectionIncluded;
- }
+ operator bool();
private:
+
SectionInfo m_info;
std::string m_name;
@@ -3305,7 +2133,7 @@ namespace Detail {
std::string toString() const {
std::ostringstream oss;
- oss << "Approx( " << m_value << " )";
+ oss << "Approx( " << Catch::toString( m_value ) << " )";
return oss.str();
}
@@ -3550,10 +2378,81 @@ using namespace Matchers;
// These files are included here so the single_include script doesn't put them
// in the conditionally compiled sections
-// #included from: internal/catch_interfaces_runner.h
-#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
+// #included from: internal/catch_test_case_info.h
+#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
#include <string>
+#include <set>
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpadded"
+#endif
+
+namespace Catch {
+
+ struct ITestCase;
+
+ struct TestCaseInfo {
+ TestCaseInfo( std::string const& _name,
+ std::string const& _className,
+ std::string const& _description,
+ std::set<std::string> const& _tags,
+ bool _isHidden,
+ SourceLineInfo const& _lineInfo );
+
+ TestCaseInfo( TestCaseInfo const& other );
+
+ std::string name;
+ std::string className;
+ std::string description;
+ std::set<std::string> tags;
+ std::string tagsAsString;
+ SourceLineInfo lineInfo;
+ bool isHidden;
+ bool throws;
+ };
+
+ class TestCase : protected TestCaseInfo {
+ public:
+
+ TestCase( ITestCase* testCase, TestCaseInfo const& info );
+ TestCase( TestCase const& other );
+
+ TestCase withName( std::string const& _newName ) const;
+
+ void invoke() const;
+
+ TestCaseInfo const& getTestCaseInfo() const;
+
+ bool isHidden() const;
+ bool throws() const;
+ bool hasTag( std::string const& tag ) const;
+ bool matchesTags( std::string const& tagPattern ) const;
+ std::set<std::string> const& getTags() const;
+
+ void swap( TestCase& other );
+ bool operator == ( TestCase const& other ) const;
+ bool operator < ( TestCase const& other ) const;
+ TestCase& operator = ( TestCase const& other );
+
+ private:
+ Ptr<ITestCase> test;
+ };
+
+ TestCase makeTestCase( ITestCase* testCase,
+ std::string const& className,
+ std::string const& name,
+ std::string const& description,
+ SourceLineInfo const& lineInfo );
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+// #included from: internal/catch_interfaces_runner.h
+#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
namespace Catch {
class TestCase;
@@ -3613,10 +2512,6 @@ namespace Catch {
namespace Detail{
- inline bool startsWith( std::string const& str, std::string const& sub ) {
- return str.length() > sub.length() && str.substr( 0, sub.length() ) == sub;
- }
-
inline std::string getAnnotation( Class cls,
std::string const& annotationName,
std::string const& testCaseName ) {
@@ -3645,7 +2540,7 @@ namespace Catch {
for( u_int m = 0; m < count ; m++ ) {
SEL selector = method_getName(methods[m]);
std::string methodName = sel_getName(selector);
- if( Detail::startsWith( methodName, "Catch_TestCase_" ) ) {
+ if( startsWith( methodName, "Catch_TestCase_" ) ) {
std::string testCaseName = methodName.substr( 15 );
std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
@@ -3762,7 +2657,7 @@ return @ desc; \
#endif
-#if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER )
+#ifdef CATCH_CONFIG_RUNNER
// #included from: internal/catch_impl.hpp
#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
@@ -3780,22 +2675,405 @@ return @ desc; \
// #included from: internal/catch_commandline.hpp
#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
-// #included from: clara.h
-#define TWOBLUECUBES_CLARA_H_INCLUDED
+// #included from: catch_config.hpp
+#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
-// #included from: catch_text.h
-#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
+// #included from: catch_test_spec.h
+#define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED
+
+// #included from: catch_tags.h
+#define TWOBLUECUBES_CATCH_TAGS_H_INCLUDED
+
+#include <string>
+#include <set>
+#include <map>
+#include <vector>
+
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wpadded"
+#endif
+
+namespace Catch {
+ class TagParser {
+ public:
+ virtual ~TagParser();
+
+ void parse( std::string const& str );
+
+ protected:
+ virtual void acceptTag( std::string const& tag ) = 0;
+ virtual void acceptChar( char c ) = 0;
+ virtual void endParse() {}
+
+ private:
+ };
+
+ class TagExtracter : public TagParser {
+ public:
+
+ TagExtracter( std::set<std::string>& tags );
+ virtual ~TagExtracter();
+
+ void parse( std::string& description );
+
+ private:
+ virtual void acceptTag( std::string const& tag );
+ virtual void acceptChar( char c );
+
+ TagExtracter& operator=(TagExtracter const&);
+
+ std::set<std::string>& m_tags;
+ std::string m_remainder;
+ };
+
+ class Tag {
+ public:
+ Tag();
+ Tag( std::string const& name, bool isNegated );
+ std::string getName() const;
+ bool isNegated() const;
+ bool operator ! () const;
+
+ private:
+ std::string m_name;
+ bool m_isNegated;
+ };
+
+ class TagSet {
+ typedef std::map<std::string, Tag> TagMap;
+ public:
+ void add( Tag const& tag );
+ bool empty() const;
+ bool matches( std::set<std::string> const& tags ) const;
+
+ private:
+ TagMap m_tags;
+ };
+
+ class TagExpression {
+ public:
+ bool matches( std::set<std::string> const& tags ) const;
+
+ private:
+ friend class TagExpressionParser;
+
+ std::vector<TagSet> m_tagSets;
+ };
+
+ class TagExpressionParser : public TagParser {
+ public:
+ TagExpressionParser( TagExpression& exp );
+ ~TagExpressionParser();
+
+ private:
+ virtual void acceptTag( std::string const& tag );
+ virtual void acceptChar( char c );
+ virtual void endParse();
+
+ TagExpressionParser& operator=(TagExpressionParser const&);
+
+ bool m_isNegated;
+ TagSet m_currentTagSet;
+ TagExpression& m_exp;
+ };
+
+} // end namespace Catch
#include <string>
#include <vector>
namespace Catch {
+ class TestCase;
+
+ struct IfFilterMatches{ enum DoWhat {
+ AutoDetectBehaviour,
+ IncludeTests,
+ ExcludeTests
+ }; };
+
+ class TestCaseFilter {
+ enum WildcardPosition {
+ NoWildcard = 0,
+ WildcardAtStart = 1,
+ WildcardAtEnd = 2,
+ WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
+ };
+
+ public:
+ TestCaseFilter( std::string const& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::AutoDetectBehaviour );
+
+ IfFilterMatches::DoWhat getFilterType() const;
+ bool shouldInclude( TestCase const& testCase ) const;
+
+ private:
+ bool isMatch( TestCase const& testCase ) const;
+
+ std::string m_stringToMatch;
+ IfFilterMatches::DoWhat m_filterType;
+ WildcardPosition m_wildcardPosition;
+ };
+
+ class TestCaseFilters {
+ public:
+ TestCaseFilters( std::string const& name );
+ std::string getName() const;
+ void addFilter( TestCaseFilter const& filter );
+ void addTags( std::string const& tagPattern );
+ bool shouldInclude( TestCase const& testCase ) const;
+
+ private:
+ std::vector<TagExpression> m_tagExpressions;
+ std::vector<TestCaseFilter> m_inclusionFilters;
+ std::vector<TestCaseFilter> m_exclusionFilters;
+ std::string m_name;
+ };
+
+}
+
+// #included from: catch_stream.h
+#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
+
+#include <streambuf>
+
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wpadded"
+#endif
+
+namespace Catch {
+
+ class Stream {
+ public:
+ Stream();
+ Stream( std::streambuf* _streamBuf, bool _isOwned );
+ void release();
+
+ std::streambuf* streamBuf;
+
+ private:
+ bool isOwned;
+ };
+}
+
+#include <memory>
+#include <vector>
+#include <string>
+#include <iostream>
+
+#ifndef CATCH_CONFIG_CONSOLE_WIDTH
+#define CATCH_CONFIG_CONSOLE_WIDTH 80
+#endif
+
+namespace Catch {
+
+ struct ConfigData {
+
+ ConfigData()
+ : listTests( false ),
+ listTags( false ),
+ listReporters( false ),
+ listTestNamesOnly( false ),
+ showSuccessfulTests( false ),
+ shouldDebugBreak( false ),
+ noThrow( false ),
+ showHelp( false ),
+ showInvisibles( false ),
+ abortAfter( -1 ),
+ verbosity( Verbosity::Normal ),
+ warnings( WarnAbout::Nothing ),
+ showDurations( ShowDurations::DefaultForReporter )
+ {}
+
+ bool listTests;
+ bool listTags;
+ bool listReporters;
+ bool listTestNamesOnly;
+
+ bool showSuccessfulTests;
+ bool shouldDebugBreak;
+ bool noThrow;
+ bool showHelp;
+ bool showInvisibles;
+
+ int abortAfter;
+
+ Verbosity::Level verbosity;
+ WarnAbout::What warnings;
+ ShowDurations::OrNot showDurations;
+
+ std::string reporterName;
+ std::string outputFilename;
+ std::string name;
+ std::string processName;
+
+ std::vector<std::string> testsOrTags;
+ };
+
+ class Config : public SharedImpl<IConfig> {
+ private:
+ Config( Config const& other );
+ Config& operator = ( Config const& other );
+ virtual void dummy();
+ public:
+
+ Config()
+ : m_os( std::cout.rdbuf() )
+ {}
+
+ Config( ConfigData const& data )
+ : m_data( data ),
+ m_os( std::cout.rdbuf() )
+ {
+ if( !data.testsOrTags.empty() ) {
+ std::string groupName;
+ for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) {
+ if( i != 0 )
+ groupName += " ";
+ groupName += data.testsOrTags[i];
+ }
+ TestCaseFilters filters( groupName );
+ for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) {
+ std::string filter = data.testsOrTags[i];
+ if( startsWith( filter, "[" ) || startsWith( filter, "~[" ) )
+ filters.addTags( filter );
+ else
+ filters.addFilter( TestCaseFilter( filter ) );
+ }
+ m_filterSets.push_back( filters );
+ }
+ }
+
+ virtual ~Config() {
+ m_os.rdbuf( std::cout.rdbuf() );
+ m_stream.release();
+ }
+
+ void setFilename( std::string const& filename ) {
+ m_data.outputFilename = filename;
+ }
+
+ std::string const& getFilename() const {
+ return m_data.outputFilename ;
+ }
+
+ bool listTests() const { return m_data.listTests; }
+ bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
+ bool listTags() const { return m_data.listTags; }
+ bool listReporters() const { return m_data.listReporters; }
+
+ std::string getProcessName() const {
+ return m_data.processName;
+ }
+
+ bool shouldDebugBreak() const {
+ return m_data.shouldDebugBreak;
+ }
+
+ void setStreamBuf( std::streambuf* buf ) {
+ m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
+ }
+
+ void useStream( std::string const& streamName ) {
+ Stream stream = createStream( streamName );
+ setStreamBuf( stream.streamBuf );
+ m_stream.release();
+ m_stream = stream;
+ }
+
+ std::string getReporterName() const { return m_data.reporterName; }
+
+ void addTestSpec( std::string const& testSpec ) {
+ TestCaseFilters filters( testSpec );
+ filters.addFilter( TestCaseFilter( testSpec ) );
+ m_filterSets.push_back( filters );
+ }
+
+ int abortAfter() const {
+ return m_data.abortAfter;
+ }
+
+ std::vector<TestCaseFilters> const& filters() const {
+ return m_filterSets;
+ }
+
+ bool showHelp() const { return m_data.showHelp; }
+ bool showInvisibles() const { return m_data.showInvisibles; }
+
+ // IConfig interface
+ virtual bool allowThrows() const { return !m_data.noThrow; }
+ virtual std::ostream& stream() const { return m_os; }
+ virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
+ virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
+ virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
+ virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
+
+ private:
+ ConfigData m_data;
+
+ Stream m_stream;
+ mutable std::ostream m_os;
+ std::vector<TestCaseFilters> m_filterSets;
+ };
+
+} // end namespace Catch
+
+// #included from: catch_clara.h
+#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
+
+// Use Catch's value for console width (store Clara's off to the side, if present)
+#ifdef CLARA_CONFIG_CONSOLE_WIDTH
+#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
+#undef CLARA_CONFIG_CONSOLE_WIDTH
+#endif
+#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
+
+// Declare Clara inside the Catch namespace
+#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
+// #included from: ../external/clara.h
+
+// Only use header guard if we are not using an outer namespace
+#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
+
+#ifndef STITCH_CLARA_OPEN_NAMESPACE
+#define TWOBLUECUBES_CLARA_H_INCLUDED
+#define STITCH_CLARA_OPEN_NAMESPACE
+#define STITCH_CLARA_CLOSE_NAMESPACE
+#else
+#define STITCH_CLARA_CLOSE_NAMESPACE }
+#endif
+
+#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
+
+// ----------- #included from tbc_text_format.h -----------
+
+// Only use header guard if we are not using an outer namespace
+#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
+#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+#define TBC_TEXT_FORMAT_H_INCLUDED
+#endif
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+// Use optional outer namespace
+#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
+#endif
+
+namespace Tbc {
+
+#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
+ const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
+#else
+ const unsigned int consoleWidth = 80;
+#endif
+
struct TextAttributes {
TextAttributes()
: initialIndent( std::string::npos ),
indent( 0 ),
- width( CATCH_CONFIG_CONSOLE_WIDTH-1 ),
+ width( consoleWidth-1 ),
tabChar( '\t' )
{}
@@ -3812,8 +3090,66 @@ namespace Catch {
class Text {
public:
- Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() );
- void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos );
+ Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
+ : attr( _attr )
+ {
+ std::string wrappableChars = " [({.,/|\\-";
+ std::size_t indent = _attr.initialIndent != std::string::npos
+ ? _attr.initialIndent
+ : _attr.indent;
+ std::string remainder = _str;
+
+ while( !remainder.empty() ) {
+ if( lines.size() >= 1000 ) {
+ lines.push_back( "... message truncated due to excessive size" );
+ return;
+ }
+ std::size_t tabPos = std::string::npos;
+ std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
+ std::size_t pos = remainder.find_first_of( '\n' );
+ if( pos <= width ) {
+ width = pos;
+ }
+ pos = remainder.find_last_of( _attr.tabChar, width );
+ if( pos != std::string::npos ) {
+ tabPos = pos;
+ if( remainder[width] == '\n' )
+ width--;
+ remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
+ }
+
+ if( width == remainder.size() ) {
+ spliceLine( indent, remainder, width );
+ }
+ else if( remainder[width] == '\n' ) {
+ spliceLine( indent, remainder, width );
+ if( width <= 1 || remainder.size() != 1 )
+ remainder = remainder.substr( 1 );
+ indent = _attr.indent;
+ }
+ else {
+ pos = remainder.find_last_of( wrappableChars, width );
+ if( pos != std::string::npos && pos > 0 ) {
+ spliceLine( indent, remainder, pos );
+ if( remainder[0] == ' ' )
+ remainder = remainder.substr( 1 );
+ }
+ else {
+ spliceLine( indent, remainder, width-1 );
+ lines.back() += "-";
+ }
+ if( lines.size() == 1 )
+ indent = _attr.indent;
+ if( tabPos != std::string::npos )
+ indent += tabPos;
+ }
+ }
+ }
+
+ void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
+ lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
+ _remainder = _remainder.substr( _pos );
+ }
typedef std::vector<std::string>::const_iterator const_iterator;
@@ -3822,9 +3158,21 @@ namespace Catch {
std::string const& last() const { return lines.back(); }
std::size_t size() const { return lines.size(); }
std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
- std::string toString() const;
+ std::string toString() const {
+ std::ostringstream oss;
+ oss << *this;
+ return oss.str();
+ }
- friend std::ostream& operator << ( std::ostream& _stream, Text const& _text );
+ inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
+ for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
+ it != itEnd; ++it ) {
+ if( it != _text.begin() )
+ _stream << "\n";
+ _stream << *it;
+ }
+ return _stream;
+ }
private:
std::string str;
@@ -3832,10 +3180,53 @@ namespace Catch {
std::vector<std::string> lines;
};
-} // end namespace Catch
+} // end namespace Tbc
+
+#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+} // end outer namespace
+#endif
+
+#endif // TBC_TEXT_FORMAT_H_INCLUDED
+
+// ----------- end of #include from tbc_text_format.h -----------
+// ........... back in /Users/philnash/Dev/OSS/Clara/srcs/clara.h
+
+#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
+
+#include <map>
+#include <algorithm>
+#include <stdexcept>
+#include <memory>
+
+// Use optional outer namespace
+#ifdef STITCH_CLARA_OPEN_NAMESPACE
+STITCH_CLARA_OPEN_NAMESPACE
+#endif
namespace Clara {
+
+ struct UnpositionalTag {};
+
+ extern UnpositionalTag _;
+
+#ifdef CLARA_CONFIG_MAIN
+ UnpositionalTag _;
+#endif
+
namespace Detail {
+
+#ifdef CLARA_CONSOLE_WIDTH
+ const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
+#else
+ const unsigned int consoleWidth = 80;
+#endif
+
+ using namespace Tbc;
+
+ inline bool startsWith( std::string const& str, std::string const& prefix ) {
+ return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
+ }
+
template<typename T> struct RemoveConstRef{ typedef T type; };
template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
@@ -3876,6 +3267,10 @@ namespace Clara {
template<typename ConfigT>
struct IArgFunction {
virtual ~IArgFunction() {}
+# ifdef CATCH_CPP11_OR_GREATER
+ IArgFunction() = default;
+ IArgFunction( IArgFunction const& ) = default;
+# endif
virtual void set( ConfigT& config, std::string const& value ) const = 0;
virtual void setFlag( ConfigT& config ) const = 0;
virtual bool takesArg() const = 0;
@@ -3885,10 +3280,11 @@ namespace Clara {
template<typename ConfigT>
class BoundArgFunction {
public:
+ BoundArgFunction() : functionObj( NULL ) {}
BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
- BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj->clone() ) {}
+ BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {}
BoundArgFunction& operator = ( BoundArgFunction const& other ) {
- IArgFunction<ConfigT>* newFunctionObj = other.functionObj->clone();
+ IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL;
delete functionObj;
functionObj = newFunctionObj;
return *this;
@@ -3902,6 +3298,10 @@ namespace Clara {
functionObj->setFlag( config );
}
bool takesArg() const { return functionObj->takesArg(); }
+
+ bool isSet() const {
+ return functionObj != NULL;
+ }
private:
IArgFunction<ConfigT>* functionObj;
};
@@ -3996,26 +3396,6 @@ namespace Clara {
void (*function)( C&, T );
};
- template<typename C, typename M>
- BoundArgFunction<C> makeBoundField( M C::* _member ) {
- return BoundArgFunction<C>( new BoundDataMember<C,M>( _member ) );
- }
- template<typename C, typename M>
- BoundArgFunction<C> makeBoundField( void (C::*_member)( M ) ) {
- return BoundArgFunction<C>( new BoundUnaryMethod<C,M>( _member ) );
- }
- template<typename C>
- BoundArgFunction<C> makeBoundField( void (C::*_member)() ) {
- return BoundArgFunction<C>( new BoundNullaryMethod<C>( _member ) );
- }
- template<typename C>
- BoundArgFunction<C> makeBoundField( void (*_function)( C& ) ) {
- return BoundArgFunction<C>( new BoundUnaryFunction<C>( _function ) );
- }
- template<typename C, typename T>
- BoundArgFunction<C> makeBoundField( void (*_function)( C&, T ) ) {
- return BoundArgFunction<C>( new BoundBinaryFunction<C, T>( _function ) );
- }
} // namespace Detail
struct Parser {
@@ -4029,7 +3409,8 @@ namespace Clara {
};
void parseIntoTokens( int argc, char const * const * argv, std::vector<Parser::Token>& tokens ) const {
- for( int i = 1; i < argc; ++i )
+ const std::string doubleDash = "--";
+ for( int i = 1; i < argc && argv[i] != doubleDash; ++i )
parseIntoTokens( argv[i] , tokens);
}
void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens ) const {
@@ -4062,32 +3443,52 @@ namespace Clara {
};
template<typename ConfigT>
+ struct CommonArgProperties {
+ CommonArgProperties() {}
+ CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
+
+ Detail::BoundArgFunction<ConfigT> boundField;
+ std::string description;
+ std::string detail;
+ std::string placeholder; // Only value if boundField takes an arg
+
+ bool takesArg() const {
+ return !placeholder.empty();
+ }
+ void validate() const {
+ if( !boundField.isSet() )
+ throw std::logic_error( "option not bound" );
+ }
+ };
+ struct OptionArgProperties {
+ std::vector<std::string> shortNames;
+ std::string longName;
+
+ bool hasShortName( std::string const& shortName ) const {
+ return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
+ }
+ bool hasLongName( std::string const& _longName ) const {
+ return _longName == longName;
+ }
+ };
+ struct PositionalArgProperties {
+ PositionalArgProperties() : position( -1 ) {}
+ int position; // -1 means non-positional (floating)
+
+ bool isFixedPositional() const {
+ return position != -1;
+ }
+ };
+
+ template<typename ConfigT>
class CommandLine {
- struct Arg {
- Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ), position( -1 ) {}
+ struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
+ Arg() {}
+ Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
+
+ using CommonArgProperties<ConfigT>::placeholder; // !TBD
- bool hasShortName( std::string const& shortName ) const {
- for( std::vector<std::string>::const_iterator
- it = shortNames.begin(), itEnd = shortNames.end();
- it != itEnd;
- ++it )
- if( *it == shortName )
- return true;
- return false;
- }
- bool hasLongName( std::string const& _longName ) const {
- return _longName == longName;
- }
- bool takesArg() const {
- return !hint.empty();
- }
- bool isFixedPositional() const {
- return position != -1;
- }
- bool isAnyPositional() const {
- return position == -1 && shortNames.empty() && longName.empty();
- }
std::string dbgName() const {
if( !longName.empty() )
return "--" + longName;
@@ -4095,10 +3496,6 @@ namespace Clara {
return "-" + shortNames[0];
return "positional args";
}
- void validate() const {
- if( boundField.takesArg() && !takesArg() )
- throw std::logic_error( dbgName() + " must specify an arg name" );
- }
std::string commands() const {
std::ostringstream oss;
bool first = true;
@@ -4115,113 +3512,182 @@ namespace Clara {
oss << ", ";
oss << "--" << longName;
}
- if( !hint.empty() )
- oss << " <" << hint << ">";
+ if( !placeholder.empty() )
+ oss << " <" << placeholder << ">";
return oss.str();
}
-
- Detail::BoundArgFunction<ConfigT> boundField;
- std::vector<std::string> shortNames;
- std::string longName;
- std::string description;
- std::string hint;
- int position;
};
- class ArgBinder {
+ // NOTE: std::auto_ptr is deprecated in c++11/c++0x
+#if defined(__cplusplus) && __cplusplus > 199711L
+ typedef std::unique_ptr<Arg> ArgAutoPtr;
+#else
+ typedef std::auto_ptr<Arg> ArgAutoPtr;
+#endif
+
+ friend void addOptName( Arg& arg, std::string const& optName )
+ {
+ if( optName.empty() )
+ return;
+ if( Detail::startsWith( optName, "--" ) ) {
+ if( !arg.longName.empty() )
+ throw std::logic_error( "Only one long opt may be specified. '"
+ + arg.longName
+ + "' already specified, now attempting to add '"
+ + optName + "'" );
+ arg.longName = optName.substr( 2 );
+ }
+ else if( Detail::startsWith( optName, "-" ) )
+ arg.shortNames.push_back( optName.substr( 1 ) );
+ else
+ throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" );
+ }
+ friend void setPositionalArg( Arg& arg, int position )
+ {
+ arg.position = position;
+ }
+
+ class ArgBuilder {
public:
- template<typename F>
- ArgBinder( CommandLine* cl, F f )
- : m_cl( cl ),
- m_arg( Detail::makeBoundField( f ) )
- {}
- ArgBinder( ArgBinder& other )
- : m_cl( other.m_cl ),
- m_arg( other.m_arg )
- {
- other.m_cl = NULL;
- }
- ~ArgBinder() {
- if( m_cl ) {
- m_arg.validate();
- if( m_arg.isFixedPositional() ) {
- m_cl->m_positionalArgs.insert( std::make_pair( m_arg.position, m_arg ) );
- if( m_arg.position > m_cl->m_highestSpecifiedArgPosition )
- m_cl->m_highestSpecifiedArgPosition = m_arg.position;
- }
- else if( m_arg.isAnyPositional() ) {
- if( m_cl->m_arg.get() )
- throw std::logic_error( "Only one unpositional argument can be added" );
- m_cl->m_arg = std::auto_ptr<Arg>( new Arg( m_arg ) );
- }
- else
- m_cl->m_options.push_back( m_arg );
- }
+ ArgBuilder( Arg* arg ) : m_arg( arg ) {}
+
+ // Bind a non-boolean data member (requires placeholder string)
+ template<typename C, typename M>
+ void bind( M C::* field, std::string const& placeholder ) {
+ m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
+ m_arg->placeholder = placeholder;
}
- ArgBinder& shortOpt( std::string const& name ) {
- m_arg.shortNames.push_back( name );
- return *this;
+ // Bind a boolean data member (no placeholder required)
+ template<typename C>
+ void bind( bool C::* field ) {
+ m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
}
- ArgBinder& longOpt( std::string const& name ) {
- m_arg.longName = name;
- return *this;
+
+ // Bind a method taking a single, non-boolean argument (requires a placeholder string)
+ template<typename C, typename M>
+ void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
+ m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
+ m_arg->placeholder = placeholder;
}
- ArgBinder& describe( std::string const& description ) {
- m_arg.description = description;
+
+ // Bind a method taking a single, boolean argument (no placeholder string required)
+ template<typename C>
+ void bind( void (C::* unaryMethod)( bool ) ) {
+ m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
+ }
+
+ // Bind a method that takes no arguments (will be called if opt is present)
+ template<typename C>
+ void bind( void (C::* nullaryMethod)() ) {
+ m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
+ }
+
+ // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
+ template<typename C>
+ void bind( void (* unaryFunction)( C& ) ) {
+ m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
+ }
+
+ // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
+ template<typename C, typename T>
+ void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
+ m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction );
+ m_arg->placeholder = placeholder;
+ }
+
+ ArgBuilder& describe( std::string const& description ) {
+ m_arg->description = description;
return *this;
}
- ArgBinder& hint( std::string const& hint ) {
- m_arg.hint = hint;
+ ArgBuilder& detail( std::string const& detail ) {
+ m_arg->detail = detail;
return *this;
}
- ArgBinder& position( int position ) {
- m_arg.position = position;
+
+ protected:
+ Arg* m_arg;
+ };
+
+ class OptBuilder : public ArgBuilder {
+ public:
+ OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
+ OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
+
+ OptBuilder& operator[]( std::string const& optName ) {
+ addOptName( *ArgBuilder::m_arg, optName );
return *this;
}
- private:
- CommandLine* m_cl;
- Arg m_arg;
};
public:
CommandLine()
: m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
- m_highestSpecifiedArgPosition( 0 )
+ m_highestSpecifiedArgPosition( 0 ),
+ m_throwOnUnrecognisedTokens( false )
{}
CommandLine( CommandLine const& other )
: m_boundProcessName( other.m_boundProcessName ),
m_options ( other.m_options ),
m_positionalArgs( other.m_positionalArgs ),
- m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition )
+ m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
+ m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
{
- if( other.m_arg.get() )
- m_arg = std::auto_ptr<Arg>( new Arg( *other.m_arg ) );
+ if( other.m_floatingArg.get() )
+ m_floatingArg = ArgAutoPtr( new Arg( *other.m_floatingArg ) );
}
- template<typename F>
- ArgBinder bind( F f ) {
- ArgBinder binder( this, f );
- return binder;
+ CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
+ m_throwOnUnrecognisedTokens = shouldThrow;
+ return *this;
}
- template<typename F>
- void bindProcessName( F f ) {
- m_boundProcessName = Detail::makeBoundField( f );
+
+ OptBuilder operator[]( std::string const& optName ) {
+ m_options.push_back( Arg() );
+ addOptName( m_options.back(), optName );
+ OptBuilder builder( &m_options.back() );
+ return builder;
+ }
+
+ ArgBuilder operator[]( int position ) {
+ m_positionalArgs.insert( std::make_pair( position, Arg() ) );
+ if( position > m_highestSpecifiedArgPosition )
+ m_highestSpecifiedArgPosition = position;
+ setPositionalArg( m_positionalArgs[position], position );
+ ArgBuilder builder( &m_positionalArgs[position] );
+ return builder;
}
- void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = CATCH_CONFIG_CONSOLE_WIDTH ) const {
+ // Invoke this with the _ instance
+ ArgBuilder operator[]( UnpositionalTag ) {
+ if( m_floatingArg.get() )
+ throw std::logic_error( "Only one unpositional argument can be added" );
+ m_floatingArg = ArgAutoPtr( new Arg() );
+ ArgBuilder builder( m_floatingArg.get() );
+ return builder;
+ }
+
+ template<typename C, typename M>
+ void bindProcessName( M C::* field ) {
+ m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
+ }
+ template<typename C, typename M>
+ void bindProcessName( void (C::*_unaryMethod)( M ) ) {
+ m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
+ }
+
+ void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
std::size_t maxWidth = 0;
for( it = itBegin; it != itEnd; ++it )
maxWidth = (std::max)( maxWidth, it->commands().size() );
for( it = itBegin; it != itEnd; ++it ) {
- Catch::Text usage( it->commands(), Catch::TextAttributes()
+ Detail::Text usage( it->commands(), Detail::TextAttributes()
.setWidth( maxWidth+indent )
.setIndent( indent ) );
- // !TBD handle longer usage strings
- Catch::Text desc( it->description, Catch::TextAttributes()
- .setWidth( width - maxWidth -3 ) );
+ Detail::Text desc( it->description, Detail::TextAttributes()
+ .setWidth( width - maxWidth - 3 ) );
for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
std::string usageCol = i < usage.size() ? usage[i] : "";
@@ -4246,17 +3712,17 @@ namespace Clara {
os << " ";
typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
if( it != m_positionalArgs.end() )
- os << "<" << it->second.hint << ">";
- else if( m_arg.get() )
- os << "<" << m_arg->hint << ">";
+ os << "<" << it->second.placeholder << ">";
+ else if( m_floatingArg.get() )
+ os << "<" << m_floatingArg->placeholder << ">";
else
throw std::logic_error( "non consecutive positional arguments with no floating args" );
}
// !TBD No indication of mandatory args
- if( m_arg.get() ) {
+ if( m_floatingArg.get() ) {
if( m_highestSpecifiedArgPosition > 1 )
os << " ";
- os << "[<" << m_arg->hint << "> ...]";
+ os << "[<" << m_floatingArg->placeholder << "> ...]";
}
}
std::string argSynopsis() const {
@@ -4266,6 +3732,7 @@ namespace Clara {
}
void usage( std::ostream& os, std::string const& procName ) const {
+ validate();
os << "usage:\n " << procName << " ";
argSynopsis( os );
if( !m_options.empty() ) {
@@ -4280,6 +3747,12 @@ namespace Clara {
return oss.str();
}
+ ConfigT parse( int argc, char const * const * argv ) const {
+ ConfigT config;
+ parseInto( argc, argv, config );
+ return config;
+ }
+
std::vector<Parser::Token> parseInto( int argc, char const * const * argv, ConfigT& config ) const {
std::string processName = argv[0];
std::size_t lastSlash = processName.find_last_of( "/\\" );
@@ -4293,9 +3766,7 @@ namespace Clara {
}
std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
- if( m_options.empty() && m_positionalArgs.empty() )
- throw std::logic_error( "No options or arguments specified" );
-
+ validate();
std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
unusedTokens = populateFixedArgs( unusedTokens, config );
unusedTokens = populateFloatingArgs( unusedTokens, config );
@@ -4304,6 +3775,7 @@ namespace Clara {
std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
std::vector<Parser::Token> unusedTokens;
+ std::vector<std::string> errors;
for( std::size_t i = 0; i < tokens.size(); ++i ) {
Parser::Token const& token = tokens[i];
typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
@@ -4315,8 +3787,9 @@ namespace Clara {
( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
if( arg.takesArg() ) {
if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
- throw std::domain_error( "Expected argument to option " + token.data );
- arg.boundField.set( config, tokens[++i].data );
+ errors.push_back( "Expected argument to option: " + token.data );
+ else
+ arg.boundField.set( config, tokens[++i].data );
}
else {
arg.boundField.setFlag( config );
@@ -4325,11 +3798,26 @@ namespace Clara {
}
}
catch( std::exception& ex ) {
- throw std::runtime_error( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
+ errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
}
}
- if( it == itEnd )
- unusedTokens.push_back( token );
+ if( it == itEnd ) {
+ if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
+ unusedTokens.push_back( token );
+ else if( m_throwOnUnrecognisedTokens )
+ errors.push_back( "unrecognised option: " + token.data );
+ }
+ }
+ if( !errors.empty() ) {
+ std::ostringstream oss;
+ for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
+ it != itEnd;
+ ++it ) {
+ if( it != errors.begin() )
+ oss << "\n";
+ oss << *it;
+ }
+ throw std::runtime_error( oss.str() );
}
return unusedTokens;
}
@@ -4349,29 +3837,56 @@ namespace Clara {
return unusedTokens;
}
std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
- if( !m_arg.get() )
+ if( !m_floatingArg.get() )
return tokens;
std::vector<Parser::Token> unusedTokens;
for( std::size_t i = 0; i < tokens.size(); ++i ) {
Parser::Token const& token = tokens[i];
if( token.type == Parser::Token::Positional )
- m_arg->boundField.set( config, token.data );
+ m_floatingArg->boundField.set( config, token.data );
else
unusedTokens.push_back( token );
}
return unusedTokens;
}
+ void validate() const
+ {
+ if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
+ throw std::logic_error( "No options or arguments specified" );
+
+ for( typename std::vector<Arg>::const_iterator it = m_options.begin(),
+ itEnd = m_options.end();
+ it != itEnd; ++it )
+ it->validate();
+ }
+
private:
Detail::BoundArgFunction<ConfigT> m_boundProcessName;
std::vector<Arg> m_options;
std::map<int, Arg> m_positionalArgs;
- std::auto_ptr<Arg> m_arg;
+ ArgAutoPtr m_floatingArg;
int m_highestSpecifiedArgPosition;
+ bool m_throwOnUnrecognisedTokens;
};
} // end namespace Clara
+STITCH_CLARA_CLOSE_NAMESPACE
+#undef STITCH_CLARA_OPEN_NAMESPACE
+#undef STITCH_CLARA_CLOSE_NAMESPACE
+
+#endif // TWOBLUECUBES_CLARA_H_INCLUDED
+#undef STITCH_CLARA_OPEN_NAMESPACE
+
+// Restore Clara's value for console width, if present
+#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
+#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
+#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
+#endif
+
+#include <fstream>
+
namespace Catch {
inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
@@ -4398,99 +3913,106 @@ namespace Catch {
? ShowDurations::Always
: ShowDurations::Never;
}
+ inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
+ std::ifstream f( _filename.c_str() );
+ if( !f.is_open() )
+ throw std::domain_error( "Unable to load input file: " + _filename );
+
+ std::string line;
+ while( std::getline( f, line ) ) {
+ line = trim(line);
+ if( !line.empty() && !startsWith( line, "#" ) )
+ addTestOrTags( config, line );
+ }
+ }
inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
- Clara::CommandLine<ConfigData> cli;
+ using namespace Clara;
+ CommandLine<ConfigData> cli;
cli.bindProcessName( &ConfigData::processName );
- cli.bind( &ConfigData::showHelp )
+ cli["-?"]["-h"]["--help"]
.describe( "display usage information" )
- .shortOpt( "?")
- .shortOpt( "h")
- .longOpt( "help" );
-
- cli.bind( &ConfigData::listTests )
- .describe( "list all (or matching) test cases" )
- .shortOpt( "l")
- .longOpt( "list-tests" );
+ .bind( &ConfigData::showHelp );
- cli.bind( &ConfigData::listTags )
- .describe( "list all (or matching) tags" )
- .shortOpt( "t")
- .longOpt( "list-tags" );
+ cli["-l"]["--list-tests"]
+ .describe( "list all/matching test cases" )
+ .bind( &ConfigData::listTests );
- cli.bind( &ConfigData::listReporters )
- .describe( "list all reporters" )
- .longOpt( "list-reporters" );
+ cli["-t"]["--list-tags"]
+ .describe( "list all/matching tags" )
+ .bind( &ConfigData::listTags );
- cli.bind( &ConfigData::showSuccessfulTests )
+ cli["-s"]["--success"]
.describe( "include successful tests in output" )
- .shortOpt( "s")
- .longOpt( "success" );
+ .bind( &ConfigData::showSuccessfulTests );
- cli.bind( &ConfigData::shouldDebugBreak )
+ cli["-b"]["--break"]
.describe( "break into debugger on failure" )
- .shortOpt( "b")
- .longOpt( "break" );
+ .bind( &ConfigData::shouldDebugBreak );
- cli.bind( &ConfigData::noThrow )
+ cli["-e"]["--nothrow"]
.describe( "skip exception tests" )
- .shortOpt( "e")
- .longOpt( "nothrow" );
+ .bind( &ConfigData::noThrow );
- cli.bind( &ConfigData::outputFilename )
+ cli["-i"]["--invisibles"]
+ .describe( "show invisibles (tabs, newlines)" )
+ .bind( &ConfigData::showInvisibles );
+
+ cli["-o"]["--out"]
.describe( "output filename" )
- .shortOpt( "o")
- .longOpt( "out" )
- .hint( "filename" );
-
- cli.bind( &ConfigData::reporterName )
- .describe( "reporter to use - defaults to console" )
- .shortOpt( "r")
- .longOpt( "reporter" )
-// .hint( "name[:filename]" );
- .hint( "name" );
-
- cli.bind( &ConfigData::name )
+ .bind( &ConfigData::outputFilename, "filename" );
+
+ cli["-r"]["--reporter"]
+// .placeholder( "name[:filename]" )
+ .describe( "reporter to use (defaults to console)" )
+ .bind( &ConfigData::reporterName, "name" );
+
+ cli["-n"]["--name"]
.describe( "suite name" )
- .shortOpt( "n")
- .longOpt( "name" )
- .hint( "name" );
+ .bind( &ConfigData::name, "name" );
- cli.bind( &abortAfterFirst )
+ cli["-a"]["--abort"]
.describe( "abort at first failure" )
- .shortOpt( "a")
- .longOpt( "abort" );
+ .bind( &abortAfterFirst );
- cli.bind( &abortAfterX )
+ cli["-x"]["--abortx"]
.describe( "abort after x failures" )
- .shortOpt( "x")
- .longOpt( "abortx" )
- .hint( "number of failures" );
+ .bind( &abortAfterX, "no. failures" );
- cli.bind( &addWarning )
+ cli["-w"]["--warn"]
.describe( "enable warnings" )
- .shortOpt( "w")
- .longOpt( "warn" )
- .hint( "warning name" );
+ .bind( &addWarning, "warning name" );
-// cli.bind( &setVerbosity )
+// - needs updating if reinstated
+// cli.into( &setVerbosity )
// .describe( "level of verbosity (0=no output)" )
// .shortOpt( "v")
// .longOpt( "verbosity" )
-// .hint( "level" );
+// .placeholder( "level" );
- cli.bind( &addTestOrTags )
+ cli[_]
.describe( "which test or tests to use" )
- .hint( "test name, pattern or tags" );
+ .bind( &addTestOrTags, "test name, pattern or tags" );
- cli.bind( &setShowDurations )
+ cli["-d"]["--durations"]
.describe( "show test durations" )
- .shortOpt( "d")
- .longOpt( "durations" )
- .hint( "yes/no" );
+ .bind( &setShowDurations, "yes/no" );
+
+ cli["-f"]["--input-file"]
+ .describe( "load test names to run from a file" )
+ .bind( &loadTestNamesFromFile, "filename" );
+
+ // Less common commands which don't have a short form
+ cli["--list-test-names-only"]
+ .describe( "list all/matching test cases names only" )
+ .bind( &ConfigData::listTestNamesOnly );
+
+ cli["--list-reporters"]
+ .describe( "list all reporters" )
+ .bind( &ConfigData::listReporters );
return cli;
}
@@ -4500,6 +4022,166 @@ namespace Catch {
// #included from: internal/catch_list.hpp
#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
+// #included from: catch_text.h
+#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
+
+#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
+
+#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
+// #included from: ../external/tbc_text_format.h
+// Only use header guard if we are not using an outer namespace
+#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
+# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
+# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
+# endif
+# else
+# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
+# endif
+#endif
+#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
+#include <string>
+#include <vector>
+#include <sstream>
+
+// Use optional outer namespace
+#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
+#endif
+
+namespace Tbc {
+
+#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
+ const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
+#else
+ const unsigned int consoleWidth = 80;
+#endif
+
+ struct TextAttributes {
+ TextAttributes()
+ : initialIndent( std::string::npos ),
+ indent( 0 ),
+ width( consoleWidth-1 ),
+ tabChar( '\t' )
+ {}
+
+ TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
+ TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
+ TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
+ TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
+
+ std::size_t initialIndent; // indent of first line, or npos
+ std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
+ std::size_t width; // maximum width of text, including indent. Longer text will wrap
+ char tabChar; // If this char is seen the indent is changed to current pos
+ };
+
+ class Text {
+ public:
+ Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
+ : attr( _attr )
+ {
+ std::string wrappableChars = " [({.,/|\\-";
+ std::size_t indent = _attr.initialIndent != std::string::npos
+ ? _attr.initialIndent
+ : _attr.indent;
+ std::string remainder = _str;
+
+ while( !remainder.empty() ) {
+ if( lines.size() >= 1000 ) {
+ lines.push_back( "... message truncated due to excessive size" );
+ return;
+ }
+ std::size_t tabPos = std::string::npos;
+ std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
+ std::size_t pos = remainder.find_first_of( '\n' );
+ if( pos <= width ) {
+ width = pos;
+ }
+ pos = remainder.find_last_of( _attr.tabChar, width );
+ if( pos != std::string::npos ) {
+ tabPos = pos;
+ if( remainder[width] == '\n' )
+ width--;
+ remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
+ }
+
+ if( width == remainder.size() ) {
+ spliceLine( indent, remainder, width );
+ }
+ else if( remainder[width] == '\n' ) {
+ spliceLine( indent, remainder, width );
+ if( width <= 1 || remainder.size() != 1 )
+ remainder = remainder.substr( 1 );
+ indent = _attr.indent;
+ }
+ else {
+ pos = remainder.find_last_of( wrappableChars, width );
+ if( pos != std::string::npos && pos > 0 ) {
+ spliceLine( indent, remainder, pos );
+ if( remainder[0] == ' ' )
+ remainder = remainder.substr( 1 );
+ }
+ else {
+ spliceLine( indent, remainder, width-1 );
+ lines.back() += "-";
+ }
+ if( lines.size() == 1 )
+ indent = _attr.indent;
+ if( tabPos != std::string::npos )
+ indent += tabPos;
+ }
+ }
+ }
+
+ void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
+ lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
+ _remainder = _remainder.substr( _pos );
+ }
+
+ typedef std::vector<std::string>::const_iterator const_iterator;
+
+ const_iterator begin() const { return lines.begin(); }
+ const_iterator end() const { return lines.end(); }
+ std::string const& last() const { return lines.back(); }
+ std::size_t size() const { return lines.size(); }
+ std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
+ std::string toString() const {
+ std::ostringstream oss;
+ oss << *this;
+ return oss.str();
+ }
+
+ inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
+ for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
+ it != itEnd; ++it ) {
+ if( it != _text.begin() )
+ _stream << "\n";
+ _stream << *it;
+ }
+ return _stream;
+ }
+
+ private:
+ std::string str;
+ TextAttributes attr;
+ std::vector<std::string> lines;
+ };
+
+} // end namespace Tbc
+
+#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+} // end outer namespace
+#endif
+
+#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
+#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+
+namespace Catch {
+ using Tbc::Text;
+ using Tbc::TextAttributes;
+}
+
// #included from: catch_console_colour.hpp
#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
@@ -4551,23 +4233,325 @@ namespace Catch {
static void use( Code _colourCode );
private:
- static Detail::IColourImpl* impl;
+ static Detail::IColourImpl* impl();
};
} // end namespace Catch
+// #included from: catch_interfaces_reporter.h
+#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
+
+// #included from: catch_option.hpp
+#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
+
+namespace Catch {
+
+ // An optional type
+ template<typename T>
+ class Option {
+ public:
+ Option() : nullableValue( NULL ) {}
+ Option( T const& _value )
+ : nullableValue( new( storage ) T( _value ) )
+ {}
+ Option( Option const& _other )
+ : nullableValue( _other ? new( storage ) T( *_other ) : NULL )
+ {}
+
+ ~Option() {
+ reset();
+ }
+
+ Option& operator= ( Option const& _other ) {
+ if( &_other != this ) {
+ reset();
+ if( _other )
+ nullableValue = new( storage ) T( *_other );
+ }
+ return *this;
+ }
+ Option& operator = ( T const& _value ) {
+ reset();
+ nullableValue = new( storage ) T( _value );
+ return *this;
+ }
+
+ void reset() {
+ if( nullableValue )
+ nullableValue->~T();
+ nullableValue = NULL;
+ }
+
+ T& operator*() { return *nullableValue; }
+ T const& operator*() const { return *nullableValue; }
+ T* operator->() { return nullableValue; }
+ const T* operator->() const { return nullableValue; }
+
+ T valueOr( T const& defaultValue ) const {
+ return nullableValue ? *nullableValue : defaultValue;
+ }
+
+ bool some() const { return nullableValue != NULL; }
+ bool none() const { return nullableValue == NULL; }
+
+ bool operator !() const { return nullableValue == NULL; }
+ operator SafeBool::type() const {
+ return SafeBool::makeSafe( some() );
+ }
+
+ private:
+ T* nullableValue;
+ char storage[sizeof(T)];
+ };
+
+} // end namespace Catch
+
+#include <string>
+#include <ostream>
+#include <map>
+#include <assert.h>
+
+namespace Catch
+{
+ struct ReporterConfig {
+ explicit ReporterConfig( Ptr<IConfig> const& _fullConfig )
+ : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
+
+ ReporterConfig( Ptr<IConfig> const& _fullConfig, std::ostream& _stream )
+ : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
+
+ std::ostream& stream() const { return *m_stream; }
+ Ptr<IConfig> fullConfig() const { return m_fullConfig; }
+
+ private:
+ std::ostream* m_stream;
+ Ptr<IConfig> m_fullConfig;
+ };
+
+ struct ReporterPreferences {
+ ReporterPreferences()
+ : shouldRedirectStdOut( false )
+ {}
+
+ bool shouldRedirectStdOut;
+ };
+
+ template<typename T>
+ struct LazyStat : Option<T> {
+ LazyStat() : used( false ) {}
+ LazyStat& operator=( T const& _value ) {
+ Option<T>::operator=( _value );
+ used = false;
+ return *this;
+ }
+ void reset() {
+ Option<T>::reset();
+ used = false;
+ }
+ bool used;
+ };
+
+ struct TestRunInfo {
+ TestRunInfo( std::string const& _name ) : name( _name ) {}
+ std::string name;
+ };
+ struct GroupInfo {
+ GroupInfo( std::string const& _name,
+ std::size_t _groupIndex,
+ std::size_t _groupsCount )
+ : name( _name ),
+ groupIndex( _groupIndex ),
+ groupsCounts( _groupsCount )
+ {}
+
+ std::string name;
+ std::size_t groupIndex;
+ std::size_t groupsCounts;
+ };
+
+ struct AssertionStats {
+ AssertionStats( AssertionResult const& _assertionResult,
+ std::vector<MessageInfo> const& _infoMessages,
+ Totals const& _totals )
+ : assertionResult( _assertionResult ),
+ infoMessages( _infoMessages ),
+ totals( _totals )
+ {
+ if( assertionResult.hasMessage() ) {
+ // Copy message into messages list.
+ // !TBD This should have been done earlier, somewhere
+ MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
+ builder << assertionResult.getMessage();
+ builder.m_info.message = builder.m_stream.str();
+
+ infoMessages.push_back( builder.m_info );
+ }
+ }
+ virtual ~AssertionStats();
+
+# ifdef CATCH_CPP11_OR_GREATER
+ AssertionStats( AssertionStats const& ) = default;
+ AssertionStats( AssertionStats && ) = default;
+ AssertionStats& operator = ( AssertionStats const& ) = default;
+ AssertionStats& operator = ( AssertionStats && ) = default;
+# endif
+
+ AssertionResult assertionResult;
+ std::vector<MessageInfo> infoMessages;
+ Totals totals;
+ };
+
+ struct SectionStats {
+ SectionStats( SectionInfo const& _sectionInfo,
+ Counts const& _assertions,
+ double _durationInSeconds,
+ bool _missingAssertions )
+ : sectionInfo( _sectionInfo ),
+ assertions( _assertions ),
+ durationInSeconds( _durationInSeconds ),
+ missingAssertions( _missingAssertions )
+ {}
+ virtual ~SectionStats();
+# ifdef CATCH_CPP11_OR_GREATER
+ SectionStats( SectionStats const& ) = default;
+ SectionStats( SectionStats && ) = default;
+ SectionStats& operator = ( SectionStats const& ) = default;
+ SectionStats& operator = ( SectionStats && ) = default;
+# endif
+
+ SectionInfo sectionInfo;
+ Counts assertions;
+ double durationInSeconds;
+ bool missingAssertions;
+ };
+
+ struct TestCaseStats {
+ TestCaseStats( TestCaseInfo const& _testInfo,
+ Totals const& _totals,
+ std::string const& _stdOut,
+ std::string const& _stdErr,
+ bool _aborting )
+ : testInfo( _testInfo ),
+ totals( _totals ),
+ stdOut( _stdOut ),
+ stdErr( _stdErr ),
+ aborting( _aborting )
+ {}
+ virtual ~TestCaseStats();
+
+# ifdef CATCH_CPP11_OR_GREATER
+ TestCaseStats( TestCaseStats const& ) = default;
+ TestCaseStats( TestCaseStats && ) = default;
+ TestCaseStats& operator = ( TestCaseStats const& ) = default;
+ TestCaseStats& operator = ( TestCaseStats && ) = default;
+# endif
+
+ TestCaseInfo testInfo;
+ Totals totals;
+ std::string stdOut;
+ std::string stdErr;
+ bool aborting;
+ };
+
+ struct TestGroupStats {
+ TestGroupStats( GroupInfo const& _groupInfo,
+ Totals const& _totals,
+ bool _aborting )
+ : groupInfo( _groupInfo ),
+ totals( _totals ),
+ aborting( _aborting )
+ {}
+ TestGroupStats( GroupInfo const& _groupInfo )
+ : groupInfo( _groupInfo ),
+ aborting( false )
+ {}
+ virtual ~TestGroupStats();
+
+# ifdef CATCH_CPP11_OR_GREATER
+ TestGroupStats( TestGroupStats const& ) = default;
+ TestGroupStats( TestGroupStats && ) = default;
+ TestGroupStats& operator = ( TestGroupStats const& ) = default;
+ TestGroupStats& operator = ( TestGroupStats && ) = default;
+# endif
+
+ GroupInfo groupInfo;
+ Totals totals;
+ bool aborting;
+ };
+
+ struct TestRunStats {
+ TestRunStats( TestRunInfo const& _runInfo,
+ Totals const& _totals,
+ bool _aborting )
+ : runInfo( _runInfo ),
+ totals( _totals ),
+ aborting( _aborting )
+ {}
+ virtual ~TestRunStats();
+
+# ifndef CATCH_CPP11_OR_GREATER
+ TestRunStats( TestRunStats const& _other )
+ : runInfo( _other.runInfo ),
+ totals( _other.totals ),
+ aborting( _other.aborting )
+ {}
+# else
+ TestRunStats( TestRunStats const& ) = default;
+ TestRunStats( TestRunStats && ) = default;
+ TestRunStats& operator = ( TestRunStats const& ) = default;
+ TestRunStats& operator = ( TestRunStats && ) = default;
+# endif
+
+ TestRunInfo runInfo;
+ Totals totals;
+ bool aborting;
+ };
+
+ struct IStreamingReporter : IShared {
+ virtual ~IStreamingReporter();
+
+ // Implementing class must also provide the following static method:
+ // static std::string getDescription();
+
+ virtual ReporterPreferences getPreferences() const = 0;
+
+ virtual void noMatchingTestCases( std::string const& spec ) = 0;
+
+ virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
+ virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
+
+ virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
+ virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
+
+ virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
+
+ virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
+ virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
+ virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
+ virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
+ virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
+ };
+
+ struct IReporterFactory {
+ virtual ~IReporterFactory();
+ virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
+ virtual std::string getDescription() const = 0;
+ };
+
+ struct IReporterRegistry {
+ typedef std::map<std::string, IReporterFactory*> FactoryMap;
+
+ virtual ~IReporterRegistry();
+ virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const = 0;
+ virtual FactoryMap const& getFactories() const = 0;
+ };
+
+}
+
#include <limits>
#include <algorithm>
namespace Catch {
- inline bool matchesFilters( std::vector<TestCaseFilters> const& filters, TestCase const& testCase ) {
- std::vector<TestCaseFilters>::const_iterator it = filters.begin();
- std::vector<TestCaseFilters>::const_iterator itEnd = filters.end();
- for(; it != itEnd; ++it )
- if( !it->shouldInclude( testCase ) )
- return false;
- return true;
- }
inline std::size_t listTests( Config const& config ) {
if( config.filters().empty() )
@@ -4580,22 +4564,22 @@ namespace Catch {
nameAttr.setInitialIndent( 2 ).setIndent( 4 );
tagsAttr.setIndent( 6 );
- std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests();
- for( std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end();
+ std::vector<TestCase> matchedTestCases;
+ getRegistryHub().getTestCaseRegistry().getFilteredTests( config, matchedTestCases );
+ for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
it != itEnd;
- ++it )
- if( matchesFilters( config.filters(), *it ) ) {
- matchedTests++;
- TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
- Colour::Code colour = testCaseInfo.isHidden
- ? Colour::SecondaryText
- : Colour::None;
- Colour colourGuard( colour );
+ ++it ) {
+ matchedTests++;
+ TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
+ Colour::Code colour = testCaseInfo.isHidden
+ ? Colour::SecondaryText
+ : Colour::None;
+ Colour colourGuard( colour );
- std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl;
- if( !testCaseInfo.tags.empty() )
- std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
- }
+ std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl;
+ if( !testCaseInfo.tags.empty() )
+ std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
+ }
if( config.filters().empty() )
std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl;
@@ -4604,6 +4588,20 @@ namespace Catch {
return matchedTests;
}
+ inline std::size_t listTestsNamesOnly( Config const& config ) {
+ std::size_t matchedTests = 0;
+ std::vector<TestCase> matchedTestCases;
+ getRegistryHub().getTestCaseRegistry().getFilteredTests( config, matchedTestCases );
+ for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
+ it != itEnd;
+ ++it ) {
+ matchedTests++;
+ TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
+ std::cout << testCaseInfo.name << std::endl;
+ }
+ return matchedTests;
+ }
+
inline std::size_t listTags( Config const& config ) {
if( config.filters().empty() )
std::cout << "All available tags:\n";
@@ -4612,23 +4610,21 @@ namespace Catch {
std::map<std::string, int> tagCounts;
- std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests();
- for( std::vector<TestCase>::const_iterator it = allTests.begin(),
- itEnd = allTests.end();
+ std::vector<TestCase> matchedTestCases;
+ getRegistryHub().getTestCaseRegistry().getFilteredTests( config, matchedTestCases );
+ for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
it != itEnd;
++it ) {
- if( matchesFilters( config.filters(), *it ) ) {
- for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
- tagItEnd = it->getTestCaseInfo().tags.end();
- tagIt != tagItEnd;
- ++tagIt ) {
- std::string tagName = *tagIt;
- std::map<std::string, int>::iterator countIt = tagCounts.find( tagName );
- if( countIt == tagCounts.end() )
- tagCounts.insert( std::make_pair( tagName, 1 ) );
- else
- countIt->second++;
- }
+ for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
+ tagItEnd = it->getTestCaseInfo().tags.end();
+ tagIt != tagItEnd;
+ ++tagIt ) {
+ std::string tagName = *tagIt;
+ std::map<std::string, int>::iterator countIt = tagCounts.find( tagName );
+ if( countIt == tagCounts.end() )
+ tagCounts.insert( std::make_pair( tagName, 1 ) );
+ else
+ countIt->second++;
}
}
@@ -4675,6 +4671,8 @@ namespace Catch {
Option<std::size_t> listedCount;
if( config.listTests() )
listedCount = listedCount.valueOr(0) + listTests( config );
+ if( config.listTestNamesOnly() )
+ listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
if( config.listTags() )
listedCount = listedCount.valueOr(0) + listTags( config );
if( config.listReporters() )
@@ -4715,13 +4713,18 @@ namespace SectionTracking {
RunState runState() const { return m_runState; }
- void addChild( std::string const& childName ) {
- m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) );
+ TrackedSection* findChild( std::string const& childName ) {
+ TrackedSections::iterator it = m_children.find( childName );
+ return it != m_children.end()
+ ? &it->second
+ : NULL;
}
- TrackedSection* getChild( std::string const& childName ) {
- return &m_children.find( childName )->second;
+ TrackedSection* acquireChild( std::string const& childName ) {
+ if( TrackedSection* child = findChild( childName ) )
+ return child;
+ m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) );
+ return findChild( childName );
}
-
void enter() {
if( m_runState == NotStarted )
m_runState = Executing;
@@ -4760,21 +4763,13 @@ namespace SectionTracking {
{}
bool enterSection( std::string const& name ) {
- if( m_completedASectionThisRun )
+ TrackedSection* child = m_currentSection->acquireChild( name );
+ if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed )
return false;
- if( m_currentSection->runState() == TrackedSection::Executing ) {
- m_currentSection->addChild( name );
- return false;
- }
- else {
- TrackedSection* child = m_currentSection->getChild( name );
- if( child->runState() != TrackedSection::Completed ) {
- m_currentSection = child;
- m_currentSection->enter();
- return true;
- }
- return false;
- }
+
+ m_currentSection = child;
+ m_currentSection->enter();
+ return true;
}
void leaveSection() {
m_currentSection->leave();
@@ -4792,9 +4787,7 @@ namespace SectionTracking {
class Guard {
public:
- Guard( TestCaseTracker& tracker )
- : m_tracker( tracker )
- {
+ Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) {
m_tracker.enterTestCase();
}
~Guard() {
@@ -4895,23 +4888,6 @@ namespace Catch {
m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
}
- Totals runMatching( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
-
- std::vector<TestCase> matchingTests = getRegistryHub().getTestCaseRegistry().getMatchingTestCases( testSpec );
-
- Totals totals;
-
- testGroupStarting( testSpec, groupIndex, groupsCount );
-
- std::vector<TestCase>::const_iterator it = matchingTests.begin();
- std::vector<TestCase>::const_iterator itEnd = matchingTests.end();
- for(; it != itEnd; ++it )
- totals += runTest( *it );
-
- testGroupEnded( testSpec, totals, groupIndex, groupsCount );
- return totals;
- }
-
Totals runTest( TestCase const& testCase ) {
Totals prevTotals = m_totals;
@@ -5095,8 +5071,8 @@ namespace Catch {
}
// If sections ended prematurely due to an exception we stored their
// infos here so we can tear them down outside the unwind process.
- for( std::vector<UnfinishedSections>::const_iterator it = m_unfinishedSections.begin(),
- itEnd = m_unfinishedSections.end();
+ for( std::vector<UnfinishedSections>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
+ itEnd = m_unfinishedSections.rend();
it != itEnd;
++it )
sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
@@ -5150,17 +5126,17 @@ namespace Catch {
Version( unsigned int _majorVersion,
unsigned int _minorVersion,
unsigned int _buildNumber,
- std::string const& _branchName )
+ char const* const _branchName )
: majorVersion( _majorVersion ),
minorVersion( _minorVersion ),
buildNumber( _buildNumber ),
branchName( _branchName )
{}
- const unsigned int majorVersion;
- const unsigned int minorVersion;
- const unsigned int buildNumber;
- const std::string branchName;
+ unsigned int const majorVersion;
+ unsigned int const minorVersion;
+ unsigned int const buildNumber;
+ char const* const branchName;
private:
void operator=( Version const& );
@@ -5204,29 +5180,29 @@ namespace Catch {
}
return totals;
}
-
- Totals runTestsForGroup( RunContext& context, const TestCaseFilters& filterGroup ) {
+ Totals runTestsForGroup( RunContext& context, TestCaseFilters const& filterGroup ) {
Totals totals;
- std::vector<TestCase>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin();
- std::vector<TestCase>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end();
+
+ std::vector<TestCase> testCases;
+ getRegistryHub().getTestCaseRegistry().getFilteredTests( filterGroup, *m_config, testCases );
+
int testsRunForGroup = 0;
- for(; it != itEnd; ++it ) {
- if( filterGroup.shouldInclude( *it ) ) {
- testsRunForGroup++;
- if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
+ for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
+ it != itEnd;
+ ++it ) {
+ testsRunForGroup++;
+ if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
- if( context.aborting() )
- break;
+ if( context.aborting() )
+ break;
- totals += context.runTest( *it );
- m_testsAlreadyRun.insert( *it );
- }
+ totals += context.runTest( *it );
+ m_testsAlreadyRun.insert( *it );
}
}
if( testsRunForGroup == 0 && !filterGroup.getName().empty() )
m_reporter->noMatchingTestCases( filterGroup.getName() );
return totals;
-
}
private:
@@ -5286,7 +5262,7 @@ namespace Catch {
std::cout << "\nCatch v" << libraryVersion.majorVersion << "."
<< libraryVersion.minorVersion << " build "
<< libraryVersion.buildNumber;
- if( libraryVersion.branchName != "master" )
+ if( libraryVersion.branchName != std::string( "master" ) )
std::cout << " (" << libraryVersion.branchName << " branch)";
std::cout << "\n";
@@ -5296,9 +5272,8 @@ namespace Catch {
int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
try {
+ m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
m_unusedTokens = m_cli.parseInto( argc, argv, m_configData );
- if( unusedOptionBehaviour == OnUnusedOptions::Fail )
- enforceNoUsedTokens();
if( m_configData.showHelp )
showHelp( m_configData.processName );
m_config.reset();
@@ -5306,7 +5281,7 @@ namespace Catch {
catch( std::exception& ex ) {
{
Colour colourGuard( Colour::Red );
- std::cerr << "\nError in input:\n"
+ std::cerr << "\nError(s) in input:\n"
<< Text( ex.what(), TextAttributes().setIndent(2) )
<< "\n\n";
}
@@ -5321,18 +5296,6 @@ namespace Catch {
m_config.reset();
}
- void enforceNoUsedTokens() const {
- if( !m_unusedTokens.empty() ) {
- std::vector<Clara::Parser::Token>::const_iterator
- it = m_unusedTokens.begin(),
- itEnd = m_unusedTokens.end();
- std::string msg;
- for(; it != itEnd; ++it )
- msg += " unrecognised option: " + it->data + "\n";
- throw std::runtime_error( msg.substr( 0, msg.size()-1 ) );
- }
- }
-
int run( int argc, char* const argv[] ) {
int returnCode = applyCommandLine( argc, argv );
@@ -5422,9 +5385,12 @@ namespace Catch {
}
else {
TestCase const& prev = *m_functions.find( testCase );
- std::cerr << "error: TEST_CASE( \"" << name << "\" ) already defined.\n"
- << "\tFirst seen at " << SourceLineInfo( prev.getTestCaseInfo().lineInfo ) << "\n"
- << "\tRedefined at " << SourceLineInfo( testCase.getTestCaseInfo().lineInfo ) << std::endl;
+ {
+ Colour colourGuard( Colour::Red );
+ std::cerr << "error: TEST_CASE( \"" << name << "\" ) already defined.\n"
+ << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n"
+ << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl;
+ }
exit(1);
}
}
@@ -5437,32 +5403,24 @@ namespace Catch {
return m_nonHiddenFunctions;
}
- // !TBD deprecated
- virtual std::vector<TestCase> getMatchingTestCases( std::string const& rawTestSpec ) const {
- std::vector<TestCase> matchingTests;
- getMatchingTestCases( rawTestSpec, matchingTests );
- return matchingTests;
- }
-
- // !TBD deprecated
- virtual void getMatchingTestCases( std::string const& rawTestSpec, std::vector<TestCase>& matchingTestsOut ) const {
- TestCaseFilter filter( rawTestSpec );
-
- std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin();
- std::vector<TestCase>::const_iterator itEnd = m_functionsInOrder.end();
- for(; it != itEnd; ++it ) {
- if( filter.shouldInclude( *it ) ) {
- matchingTestsOut.push_back( *it );
- }
+ virtual void getFilteredTests( TestCaseFilters const& filters, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const {
+ for( std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin(),
+ itEnd = m_functionsInOrder.end();
+ it != itEnd;
+ ++it ) {
+ if( filters.shouldInclude( *it ) && ( config.allowThrows() || !it->throws() ) )
+ matchingTestCases.push_back( *it );
}
}
- virtual void getMatchingTestCases( TestCaseFilters const& filters, std::vector<TestCase>& matchingTestsOut ) const {
- std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin();
- std::vector<TestCase>::const_iterator itEnd = m_functionsInOrder.end();
- // !TBD: replace with algorithm
- for(; it != itEnd; ++it )
- if( filters.shouldInclude( *it ) )
- matchingTestsOut.push_back( *it );
+ virtual void getFilteredTests( IConfig const& config, std::vector<TestCase>& matchingTestCases ) const {
+ if( config.filters().empty() )
+ return getFilteredTests( TestCaseFilters( "empty" ), config, matchingTestCases );
+
+ for( std::vector<TestCaseFilters>::const_iterator it = config.filters().begin(),
+ itEnd = config.filters().end();
+ it != itEnd;
+ ++it )
+ getFilteredTests( *it, config, matchingTestCases );
}
private:
@@ -5707,7 +5665,7 @@ namespace Catch {
m_what = oss.str();
}
- const char* NotImplementedException::what() const throw() {
+ const char* NotImplementedException::what() const CATCH_NOEXCEPT {
return m_what.c_str();
}
@@ -5716,6 +5674,89 @@ namespace Catch {
// #included from: catch_context_impl.hpp
#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
+// #included from: catch_stream.hpp
+#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
+
+// #included from: catch_streambuf.h
+#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
+
+#include <streambuf>
+
+namespace Catch {
+
+ class StreamBufBase : public std::streambuf {
+ public:
+ virtual ~StreamBufBase() CATCH_NOEXCEPT;
+ };
+}
+
+#include <stdexcept>
+#include <cstdio>
+
+namespace Catch {
+
+ template<typename WriterF, size_t bufferSize=256>
+ class StreamBufImpl : public StreamBufBase {
+ char data[bufferSize];
+ WriterF m_writer;
+
+ public:
+ StreamBufImpl() {
+ setp( data, data + sizeof(data) );
+ }
+
+ ~StreamBufImpl() CATCH_NOEXCEPT {
+ sync();
+ }
+
+ private:
+ int overflow( int c ) {
+ sync();
+
+ if( c != EOF ) {
+ if( pbase() == epptr() )
+ m_writer( std::string( 1, static_cast<char>( c ) ) );
+ else
+ sputc( static_cast<char>( c ) );
+ }
+ return 0;
+ }
+
+ int sync() {
+ if( pbase() != pptr() ) {
+ m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
+ setp( pbase(), epptr() );
+ }
+ return 0;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ struct OutputDebugWriter {
+
+ void operator()( std::string const&str ) {
+ writeToDebugConsole( str );
+ }
+ };
+
+ Stream::Stream()
+ : streamBuf( NULL ), isOwned( false )
+ {}
+
+ Stream::Stream( std::streambuf* _streamBuf, bool _isOwned )
+ : streamBuf( _streamBuf ), isOwned( _isOwned )
+ {}
+
+ void Stream::release() {
+ if( isOwned ) {
+ delete streamBuf;
+ streamBuf = NULL;
+ isOwned = false;
+ }
+ }
+}
+
namespace Catch {
class Context : public IMutableContext {
@@ -5878,7 +5919,10 @@ namespace {
return true;
}
- Win32ColourImpl platformColourImpl;
+ static Detail::IColourImpl* platformColourInstance() {
+ static Win32ColourImpl s_instance;
+ return &s_instance;
+ }
} // end anon namespace
} // end namespace Catch
@@ -5922,10 +5966,13 @@ namespace {
};
inline bool shouldUseColourForPlatform() {
- return isatty( fileno(stdout) );
+ return isatty(STDOUT_FILENO);
}
- PosixColourImpl platformColourImpl;
+ static Detail::IColourImpl* platformColourInstance() {
+ static PosixColourImpl s_instance;
+ return &s_instance;
+ }
} // end anon namespace
} // end namespace Catch
@@ -5937,21 +5984,28 @@ namespace Catch {
namespace {
struct NoColourImpl : Detail::IColourImpl {
void use( Colour::Code ) {}
+
+ static IColourImpl* instance() {
+ static NoColourImpl s_instance;
+ return &s_instance;
+ }
};
- NoColourImpl noColourImpl;
- static const bool shouldUseColour = shouldUseColourForPlatform() &&
- !isDebuggerActive();
+ static bool shouldUseColour() {
+ return shouldUseColourForPlatform() && !isDebuggerActive();
+ }
}
Colour::Colour( Code _colourCode ){ use( _colourCode ); }
Colour::~Colour(){ use( None ); }
void Colour::use( Code _colourCode ) {
- impl->use( _colourCode );
+ impl()->use( _colourCode );
}
- Detail::IColourImpl* Colour::impl = shouldUseColour
- ? static_cast<Detail::IColourImpl*>( &platformColourImpl )
- : static_cast<Detail::IColourImpl*>( &noColourImpl );
+ Detail::IColourImpl* Colour::impl() {
+ return shouldUseColour()
+ ? platformColourInstance()
+ : NoColourImpl::instance();
+ }
} // end namespace Catch
@@ -6202,6 +6256,16 @@ namespace Catch {
namespace Catch {
+ inline bool isSpecialTag( std::string const& tag ) {
+ return tag == "." ||
+ tag == "hide" ||
+ tag == "!hide" ||
+ tag == "!throws";
+ }
+ inline bool isReservedTag( std::string const& tag ) {
+ return !isSpecialTag( tag ) && tag.size() > 0 && !isalnum( tag[0] );
+ }
+
TestCase makeTestCase( ITestCase* _testCase,
std::string const& _className,
std::string const& _name,
@@ -6209,12 +6273,33 @@ namespace Catch {
SourceLineInfo const& _lineInfo )
{
std::string desc = _descOrTags;
- bool isHidden( startsWith( _name, "./" ) );
+ bool isHidden( startsWith( _name, "./" ) ); // Legacy support
std::set<std::string> tags;
TagExtracter( tags ).parse( desc );
+ for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end();
+ it != itEnd;
+ ++it )
+ if( isReservedTag( *it ) ) {
+ {
+ Colour colourGuard( Colour::Red );
+ std::cerr
+ << "Tag name [" << *it << "] not allowed.\n"
+ << "Tag names starting with non alpha-numeric characters are reserved\n";
+ }
+ {
+ Colour colourGuard( Colour::FileName );
+ std::cerr << _lineInfo << std::endl;
+ }
+ exit(1);
+ }
+
if( tags.find( "hide" ) != tags.end() || tags.find( "." ) != tags.end() )
isHidden = true;
+ if( isHidden ) {
+ tags.insert( "hide" );
+ tags.insert( "." );
+ }
TestCaseInfo info( _name, _className, desc, tags, isHidden, _lineInfo );
return TestCase( _testCase, info );
}
@@ -6230,11 +6315,15 @@ namespace Catch {
description( _description ),
tags( _tags ),
lineInfo( _lineInfo ),
- isHidden( _isHidden )
+ isHidden( _isHidden ),
+ throws( false )
{
std::ostringstream oss;
- for( std::set<std::string>::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it )
+ for( std::set<std::string>::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) {
oss << "[" << *it << "]";
+ if( *it == "!throws" )
+ throws = true;
+ }
tagsAsString = oss.str();
}
@@ -6245,7 +6334,8 @@ namespace Catch {
tags( other.tags ),
tagsAsString( other.tagsAsString ),
lineInfo( other.lineInfo ),
- isHidden( other.isHidden )
+ isHidden( other.isHidden ),
+ throws( other.throws )
{}
TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
@@ -6268,6 +6358,9 @@ namespace Catch {
bool TestCase::isHidden() const {
return TestCaseInfo::isHidden;
}
+ bool TestCase::throws() const {
+ return TestCaseInfo::throws;
+ }
bool TestCase::hasTag( std::string const& tag ) const {
return tags.find( toLower( tag ) ) != tags.end();
@@ -6311,101 +6404,260 @@ namespace Catch {
} // end namespace Catch
-// #included from: catch_version.hpp
-#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
+// #included from: catch_tags.hpp
+#define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED
namespace Catch {
+ TagParser::~TagParser() {}
- // These numbers are maintained by a script
- Version libraryVersion( 1, 0, 13, "master" );
-}
+ void TagParser::parse( std::string const& str ) {
+ std::size_t pos = 0;
+ while( pos < str.size() ) {
+ char c = str[pos];
+ if( c == '[' ) {
+ std::size_t end = str.find_first_of( ']', pos );
+ if( end != std::string::npos ) {
+ acceptTag( str.substr( pos+1, end-pos-1 ) );
+ pos = end+1;
+ }
+ else {
+ acceptChar( c );
+ pos++;
+ }
+ }
+ else {
+ acceptChar( c );
+ pos++;
+ }
+ }
+ endParse();
+ }
-// #included from: catch_text.hpp
-#define TWOBLUECUBES_CATCH_TEXT_HPP_INCLUDED
+ TagExtracter::TagExtracter( std::set<std::string>& tags )
+ : m_tags( tags )
+ {}
-#include <string>
-#include <vector>
+ TagExtracter::~TagExtracter() {}
+
+ void TagExtracter::parse( std::string& description ) {
+ TagParser::parse( description );
+ description = m_remainder;
+ }
+
+ void TagExtracter::acceptTag( std::string const& tag ) {
+ m_tags.insert( toLower( tag ) );
+ }
+ void TagExtracter::acceptChar( char c ) {
+ m_remainder += c;
+ }
+
+ Tag::Tag() : m_isNegated( false ) {}
+ Tag::Tag( std::string const& name, bool isNegated )
+ : m_name( name ),
+ m_isNegated( isNegated )
+ {}
+
+ std::string Tag::getName() const {
+ return m_name;
+ }
+ bool Tag::isNegated() const {
+ return m_isNegated;
+ }
+
+ bool Tag::operator ! () const {
+ return m_name.empty();
+ }
+
+ void TagSet::add( Tag const& tag ) {
+ m_tags.insert( std::make_pair( toLower( tag.getName() ), tag ) );
+ }
+
+ bool TagSet::empty() const {
+ return m_tags.empty();
+ }
+
+ bool TagSet::matches( std::set<std::string> const& tags ) const {
+ for( TagMap::const_iterator
+ it = m_tags.begin(), itEnd = m_tags.end();
+ it != itEnd;
+ ++it ) {
+ bool found = tags.find( it->first ) != tags.end();
+ if( found == it->second.isNegated() )
+ return false;
+ }
+ return true;
+ }
+
+ bool TagExpression::matches( std::set<std::string> const& tags ) const {
+ for( std::vector<TagSet>::const_iterator
+ it = m_tagSets.begin(), itEnd = m_tagSets.end();
+ it != itEnd;
+ ++it )
+ if( it->matches( tags ) )
+ return true;
+ return false;
+ }
+
+ TagExpressionParser::TagExpressionParser( TagExpression& exp )
+ : m_isNegated( false ),
+ m_exp( exp )
+ {}
+
+ TagExpressionParser::~TagExpressionParser() {}
+
+ void TagExpressionParser::acceptTag( std::string const& tag ) {
+ m_currentTagSet.add( Tag( tag, m_isNegated ) );
+ m_isNegated = false;
+ }
+
+ void TagExpressionParser::acceptChar( char c ) {
+ switch( c ) {
+ case '~':
+ m_isNegated = true;
+ break;
+ case ',':
+ m_exp.m_tagSets.push_back( m_currentTagSet );
+ m_currentTagSet = TagSet();
+ break;
+ }
+ }
+
+ void TagExpressionParser::endParse() {
+ if( !m_currentTagSet.empty() )
+ m_exp.m_tagSets.push_back( m_currentTagSet );
+ }
+
+} // end namespace Catch
+
+// #included from: catch_test_spec.hpp
+#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
namespace Catch {
- Text::Text( std::string const& _str, TextAttributes const& _attr )
- : attr( _attr )
+ TestCaseFilter::TestCaseFilter( std::string const& testSpec, IfFilterMatches::DoWhat matchBehaviour )
+ : m_stringToMatch( toLower( testSpec ) ),
+ m_filterType( matchBehaviour ),
+ m_wildcardPosition( NoWildcard )
{
- std::string wrappableChars = " [({.,/|\\-";
- std::size_t indent = _attr.initialIndent != std::string::npos
- ? _attr.initialIndent
- : _attr.indent;
- std::string remainder = _str;
-
- while( !remainder.empty() ) {
- if( lines.size() >= 1000 ) {
- lines.push_back( "... message truncated due to excessive size" );
- return;
+ if( m_filterType == IfFilterMatches::AutoDetectBehaviour ) {
+ if( startsWith( m_stringToMatch, "exclude:" ) ) {
+ m_stringToMatch = m_stringToMatch.substr( 8 );
+ m_filterType = IfFilterMatches::ExcludeTests;
}
- std::size_t tabPos = std::string::npos;
- std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
- std::size_t pos = remainder.find_first_of( '\n' );
- if( pos <= width ) {
- width = pos;
- }
- pos = remainder.find_last_of( _attr.tabChar, width );
- if( pos != std::string::npos ) {
- tabPos = pos;
- if( remainder[width] == '\n' )
- width--;
- remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
- }
-
- if( width == remainder.size() ) {
- spliceLine( indent, remainder, width );
- }
- else if( remainder[width] == '\n' ) {
- spliceLine( indent, remainder, width );
- if( width <= 1 || remainder.size() != 1 )
- remainder = remainder.substr( 1 );
- indent = _attr.indent;
+ else if( startsWith( m_stringToMatch, "~" ) ) {
+ m_stringToMatch = m_stringToMatch.substr( 1 );
+ m_filterType = IfFilterMatches::ExcludeTests;
}
else {
- pos = remainder.find_last_of( wrappableChars, width );
- if( pos != std::string::npos && pos > 0 ) {
- spliceLine( indent, remainder, pos );
- if( remainder[0] == ' ' )
- remainder = remainder.substr( 1 );
- }
- else {
- spliceLine( indent, remainder, width-1 );
- lines.back() += "-";
- }
- if( lines.size() == 1 )
- indent = _attr.indent;
- if( tabPos != std::string::npos )
- indent += tabPos;
+ m_filterType = IfFilterMatches::IncludeTests;
}
}
+
+ if( startsWith( m_stringToMatch, "*" ) ) {
+ m_stringToMatch = m_stringToMatch.substr( 1 );
+ m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtStart );
+ }
+ if( endsWith( m_stringToMatch, "*" ) ) {
+ m_stringToMatch = m_stringToMatch.substr( 0, m_stringToMatch.size()-1 );
+ m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtEnd );
+ }
}
- void Text::spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
- lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
- _remainder = _remainder.substr( _pos );
+ IfFilterMatches::DoWhat TestCaseFilter::getFilterType() const {
+ return m_filterType;
}
- std::string Text::toString() const {
- std::ostringstream oss;
- oss << *this;
- return oss.str();
+ bool TestCaseFilter::shouldInclude( TestCase const& testCase ) const {
+ return isMatch( testCase ) == (m_filterType == IfFilterMatches::IncludeTests);
}
- std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
- for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
- it != itEnd; ++it ) {
- if( it != _text.begin() )
- _stream << "\n";
- _stream << *it;
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunreachable-code"
+#endif
+
+ bool TestCaseFilter::isMatch( TestCase const& testCase ) const {
+ std::string name = testCase.getTestCaseInfo().name;
+ toLowerInPlace( name );
+
+ switch( m_wildcardPosition ) {
+ case NoWildcard:
+ return m_stringToMatch == name;
+ case WildcardAtStart:
+ return endsWith( name, m_stringToMatch );
+ case WildcardAtEnd:
+ return startsWith( name, m_stringToMatch );
+ case WildcardAtBothEnds:
+ return contains( name, m_stringToMatch );
}
- return _stream;
+ throw std::logic_error( "Unhandled wildcard type" );
}
-} // end namespace Catch
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+ TestCaseFilters::TestCaseFilters( std::string const& name ) : m_name( name ) {}
+
+ std::string TestCaseFilters::getName() const {
+ return m_name;
+ }
+
+ void TestCaseFilters::addFilter( TestCaseFilter const& filter ) {
+ if( filter.getFilterType() == IfFilterMatches::ExcludeTests )
+ m_exclusionFilters.push_back( filter );
+ else
+ m_inclusionFilters.push_back( filter );
+ }
+
+ void TestCaseFilters::addTags( std::string const& tagPattern ) {
+ TagExpression exp;
+ TagExpressionParser( exp ).parse( tagPattern );
+
+ m_tagExpressions.push_back( exp );
+ }
+
+ bool TestCaseFilters::shouldInclude( TestCase const& testCase ) const {
+ if( !m_tagExpressions.empty() ) {
+ std::vector<TagExpression>::const_iterator it = m_tagExpressions.begin();
+ std::vector<TagExpression>::const_iterator itEnd = m_tagExpressions.end();
+ for(; it != itEnd; ++it )
+ if( it->matches( testCase.getTags() ) )
+ break;
+ if( it == itEnd )
+ return false;
+ }
+
+ if( !m_inclusionFilters.empty() ) {
+ std::vector<TestCaseFilter>::const_iterator it = m_inclusionFilters.begin();
+ std::vector<TestCaseFilter>::const_iterator itEnd = m_inclusionFilters.end();
+ for(; it != itEnd; ++it )
+ if( it->shouldInclude( testCase ) )
+ break;
+ if( it == itEnd )
+ return false;
+ }
+ else if( m_exclusionFilters.empty() && m_tagExpressions.empty() ) {
+ return !testCase.isHidden();
+ }
+
+ std::vector<TestCaseFilter>::const_iterator it = m_exclusionFilters.begin();
+ std::vector<TestCaseFilter>::const_iterator itEnd = m_exclusionFilters.end();
+ for(; it != itEnd; ++it )
+ if( !it->shouldInclude( testCase ) )
+ return false;
+ return true;
+ }
+}
+
+// #included from: catch_version.hpp
+#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
+
+namespace Catch {
+
+ // These numbers are maintained by a script
+ Version libraryVersion( 1, 0, 43, "master" );
+}
// #included from: catch_message.hpp
#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
@@ -6446,6 +6698,26 @@ namespace Catch {
namespace Catch
{
+ // Deprecated
+ struct IReporter : IShared {
+ virtual ~IReporter();
+
+ virtual bool shouldRedirectStdout() const = 0;
+
+ virtual void StartTesting() = 0;
+ virtual void EndTesting( Totals const& totals ) = 0;
+ virtual void StartGroup( std::string const& groupName ) = 0;
+ virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
+ virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
+ virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
+ virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
+ virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
+ virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
+ virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
+ virtual void Aborted() = 0;
+ virtual void Result( AssertionResult const& result ) = 0;
+ };
+
class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
{
public:
@@ -6593,9 +6865,507 @@ namespace Catch {
#ifdef __clang__
#pragma clang diagnostic pop
#endif
+// #included from: catch_common.hpp
+#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
+
+namespace Catch {
+
+ bool startsWith( std::string const& s, std::string const& prefix ) {
+ return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
+ }
+ bool endsWith( std::string const& s, std::string const& suffix ) {
+ return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
+ }
+ bool contains( std::string const& s, std::string const& infix ) {
+ return s.find( infix ) != std::string::npos;
+ }
+ void toLowerInPlace( std::string& s ) {
+ std::transform( s.begin(), s.end(), s.begin(), ::tolower );
+ }
+ std::string toLower( std::string const& s ) {
+ std::string lc = s;
+ toLowerInPlace( lc );
+ return lc;
+ }
+ std::string trim( std::string const& str ) {
+ static char const* whitespaceChars = "\n\r\t ";
+ std::string::size_type start = str.find_first_not_of( whitespaceChars );
+ std::string::size_type end = str.find_last_not_of( whitespaceChars );
+
+ return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
+ }
+
+ pluralise::pluralise( std::size_t count, std::string const& label )
+ : m_count( count ),
+ m_label( label )
+ {}
+
+ std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
+ os << pluraliser.m_count << " " << pluraliser.m_label;
+ if( pluraliser.m_count != 1 )
+ os << "s";
+ return os;
+ }
+
+ SourceLineInfo::SourceLineInfo() : line( 0 ){}
+ SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line )
+ : file( _file ),
+ line( _line )
+ {}
+ SourceLineInfo::SourceLineInfo( SourceLineInfo const& other )
+ : file( other.file ),
+ line( other.line )
+ {}
+ bool SourceLineInfo::empty() const {
+ return file.empty();
+ }
+ bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const {
+ return line == other.line && file == other.file;
+ }
+
+ std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
+#ifndef __GNUG__
+ os << info.file << "(" << info.line << ")";
+#else
+ os << info.file << ":" << info.line;
+#endif
+ return os;
+ }
+
+ void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
+ std::ostringstream oss;
+ oss << locationInfo << ": Internal Catch error: '" << message << "'";
+ if( isTrue( true ))
+ throw std::logic_error( oss.str() );
+ }
+}
+
+// #included from: catch_section.hpp
+#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
+
+namespace Catch {
+
+ Section::Section( SourceLineInfo const& lineInfo,
+ std::string const& name,
+ std::string const& description )
+ : m_info( name, description, lineInfo ),
+ m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( m_info, m_assertions ) )
+ {
+ m_timer.start();
+ }
+
+ Section::~Section() {
+ if( m_sectionIncluded )
+ getCurrentContext().getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() );
+ }
+
+ // This indicates whether the section should be executed or not
+ Section::operator bool() {
+ return m_sectionIncluded;
+ }
+
+} // end namespace Catch
+
+// #included from: catch_debugger.hpp
+#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
+
+#include <iostream>
+
+#ifdef CATCH_PLATFORM_MAC
+
+ #include <assert.h>
+ #include <stdbool.h>
+ #include <sys/types.h>
+ #include <unistd.h>
+ #include <sys/sysctl.h>
+
+ namespace Catch{
+
+ // The following function is taken directly from the following technical note:
+ // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
+
+ // Returns true if the current process is being debugged (either
+ // running under the debugger or has a debugger attached post facto).
+ bool isDebuggerActive(){
+
+ int mib[4];
+ struct kinfo_proc info;
+ size_t size;
+
+ // Initialize the flags so that, if sysctl fails for some bizarre
+ // reason, we get a predictable result.
+
+ info.kp_proc.p_flag = 0;
+
+ // Initialize mib, which tells sysctl the info we want, in this case
+ // we're looking for information about a specific process ID.
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = getpid();
+
+ // Call sysctl.
+
+ size = sizeof(info);
+ if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) {
+ std::cerr << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
+ return false;
+ }
+
+ // We're being debugged if the P_TRACED flag is set.
+
+ return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
+ }
+ } // namespace Catch
+
+#elif defined(_MSC_VER)
+ extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
+ namespace Catch {
+ bool isDebuggerActive() {
+ return IsDebuggerPresent() != 0;
+ }
+ }
+#elif defined(__MINGW32__)
+ extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
+ namespace Catch {
+ bool isDebuggerActive() {
+ return IsDebuggerPresent() != 0;
+ }
+ }
+#else
+ namespace Catch {
+ inline bool isDebuggerActive() { return false; }
+ }
+#endif // Platform
+
+#ifdef CATCH_PLATFORM_WINDOWS
+ extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
+ namespace Catch {
+ void writeToDebugConsole( std::string const& text ) {
+ ::OutputDebugStringA( text.c_str() );
+ }
+ }
+#else
+ namespace Catch {
+ void writeToDebugConsole( std::string const& text ) {
+ // !TBD: Need a version for Mac/ XCode and other IDEs
+ std::cout << text;
+ }
+ }
+#endif // Platform
+
+// #included from: catch_tostring.hpp
+#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
+
+namespace Catch {
+
+std::string toString( std::string const& value ) {
+ std::string s = value;
+ if( getCurrentContext().getConfig()->showInvisibles() ) {
+ for(size_t i = 0; i < s.size(); ++i ) {
+ std::string subs;
+ switch( s[i] ) {
+ case '\n': subs = "\\n"; break;
+ case '\t': subs = "\\t"; break;
+ default: break;
+ }
+ if( !subs.empty() ) {
+ s = s.substr( 0, i ) + subs + s.substr( i+1 );
+ ++i;
+ }
+ }
+ }
+ return "\"" + s + "\"";
+}
+std::string toString( std::wstring const& value ) {
+
+ std::string s;
+ s.reserve( value.size() );
+ for(size_t i = 0; i < value.size(); ++i )
+ s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
+ return toString( s );
+}
+
+std::string toString( const char* const value ) {
+ return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
+}
+
+std::string toString( char* const value ) {
+ return Catch::toString( static_cast<const char*>( value ) );
+}
+
+std::string toString( int value ) {
+ std::ostringstream oss;
+ oss << value;
+ return oss.str();
+}
+
+std::string toString( unsigned long value ) {
+ std::ostringstream oss;
+ if( value > 8192 )
+ oss << "0x" << std::hex << value;
+ else
+ oss << value;
+ return oss.str();
+}
+
+std::string toString( unsigned int value ) {
+ return toString( static_cast<unsigned long>( value ) );
+}
+
+std::string toString( const double value ) {
+ std::ostringstream oss;
+ oss << std::setprecision( 10 )
+ << std::fixed
+ << value;
+ std::string d = oss.str();
+ std::size_t i = d.find_last_not_of( '0' );
+ if( i != std::string::npos && i != d.size()-1 ) {
+ if( d[i] == '.' )
+ i++;
+ d = d.substr( 0, i+1 );
+ }
+ return d;
+}
+
+std::string toString( bool value ) {
+ return value ? "true" : "false";
+}
+
+std::string toString( char value ) {
+ return value < ' '
+ ? toString( static_cast<unsigned int>( value ) )
+ : Detail::makeString( value );
+}
+
+std::string toString( signed char value ) {
+ return toString( static_cast<char>( value ) );
+}
+
+std::string toString( unsigned char value ) {
+ return toString( static_cast<char>( value ) );
+}
+
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+std::string toString( std::nullptr_t ) {
+ return "nullptr";
+}
+#endif
+
+#ifdef __OBJC__
+ std::string toString( NSString const * const& nsstring ) {
+ if( !nsstring )
+ return "nil";
+ return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
+ }
+ std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
+ if( !nsstring )
+ return "nil";
+ return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
+ }
+ std::string toString( NSObject* const& nsObject ) {
+ return toString( [nsObject description] );
+ }
+#endif
+
+} // end namespace Catch
+
// #included from: ../reporters/catch_reporter_xml.hpp
#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
+// #included from: catch_reporter_bases.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
+
+namespace Catch {
+
+ struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
+
+ StreamingReporterBase( ReporterConfig const& _config )
+ : m_config( _config.fullConfig() ),
+ stream( _config.stream() )
+ {}
+
+ virtual ~StreamingReporterBase();
+
+ virtual void noMatchingTestCases( std::string const& ) {}
+
+ virtual void testRunStarting( TestRunInfo const& _testRunInfo ) {
+ currentTestRunInfo = _testRunInfo;
+ }
+ virtual void testGroupStarting( GroupInfo const& _groupInfo ) {
+ currentGroupInfo = _groupInfo;
+ }
+
+ virtual void testCaseStarting( TestCaseInfo const& _testInfo ) {
+ currentTestCaseInfo = _testInfo;
+ }
+ virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
+ m_sectionStack.push_back( _sectionInfo );
+ }
+
+ virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) {
+ m_sectionStack.pop_back();
+ }
+ virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) {
+ currentTestCaseInfo.reset();
+ assert( m_sectionStack.empty() );
+ }
+ virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) {
+ currentGroupInfo.reset();
+ }
+ virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) {
+ currentTestCaseInfo.reset();
+ currentGroupInfo.reset();
+ currentTestRunInfo.reset();
+ }
+
+ Ptr<IConfig> m_config;
+ std::ostream& stream;
+
+ LazyStat<TestRunInfo> currentTestRunInfo;
+ LazyStat<GroupInfo> currentGroupInfo;
+ LazyStat<TestCaseInfo> currentTestCaseInfo;
+
+ std::vector<SectionInfo> m_sectionStack;
+ };
+
+ struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
+ template<typename T, typename ChildNodeT>
+ struct Node : SharedImpl<> {
+ explicit Node( T const& _value ) : value( _value ) {}
+ virtual ~Node() {}
+
+ typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
+ T value;
+ ChildNodes children;
+ };
+ struct SectionNode : SharedImpl<> {
+ explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {}
+ virtual ~SectionNode();
+
+ bool operator == ( SectionNode const& other ) const {
+ return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
+ }
+ bool operator == ( Ptr<SectionNode> const& other ) const {
+ return operator==( *other );
+ }
+
+ SectionStats stats;
+ typedef std::vector<Ptr<SectionNode> > ChildSections;
+ typedef std::vector<AssertionStats> Assertions;
+ ChildSections childSections;
+ Assertions assertions;
+ std::string stdOut;
+ std::string stdErr;
+ };
+
+ struct BySectionInfo {
+ BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
+ bool operator() ( Ptr<SectionNode> const& node ) const {
+ return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
+ }
+ private:
+ BySectionInfo& operator=( BySectionInfo const& other ); // = delete;
+
+ SectionInfo const& m_other;
+ };
+
+ typedef Node<TestCaseStats, SectionNode> TestCaseNode;
+ typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
+ typedef Node<TestRunStats, TestGroupNode> TestRunNode;
+
+ CumulativeReporterBase( ReporterConfig const& _config )
+ : m_config( _config.fullConfig() ),
+ stream( _config.stream() )
+ {}
+ ~CumulativeReporterBase();
+
+ virtual void testRunStarting( TestRunInfo const& ) {}
+ virtual void testGroupStarting( GroupInfo const& ) {}
+
+ virtual void testCaseStarting( TestCaseInfo const& ) {}
+
+ virtual void sectionStarting( SectionInfo const& sectionInfo ) {
+ SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
+ Ptr<SectionNode> node;
+ if( m_sectionStack.empty() ) {
+ if( !m_rootSection )
+ m_rootSection = new SectionNode( incompleteStats );
+ node = m_rootSection;
+ }
+ else {
+ SectionNode& parentNode = *m_sectionStack.back();
+ SectionNode::ChildSections::const_iterator it =
+ std::find_if( parentNode.childSections.begin(),
+ parentNode.childSections.end(),
+ BySectionInfo( sectionInfo ) );
+ if( it == parentNode.childSections.end() ) {
+ node = new SectionNode( incompleteStats );
+ parentNode.childSections.push_back( node );
+ }
+ else
+ node = *it;
+ }
+ m_sectionStack.push_back( node );
+ m_deepestSection = node;
+ }
+
+ virtual void assertionStarting( AssertionInfo const& ) {}
+
+ virtual bool assertionEnded( AssertionStats const& assertionStats ) {
+ assert( !m_sectionStack.empty() );
+ SectionNode& sectionNode = *m_sectionStack.back();
+ sectionNode.assertions.push_back( assertionStats );
+ return true;
+ }
+ virtual void sectionEnded( SectionStats const& sectionStats ) {
+ assert( !m_sectionStack.empty() );
+ SectionNode& node = *m_sectionStack.back();
+ node.stats = sectionStats;
+ m_sectionStack.pop_back();
+ }
+ virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
+ Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
+ assert( m_sectionStack.size() == 0 );
+ node->children.push_back( m_rootSection );
+ m_testCases.push_back( node );
+ m_rootSection.reset();
+
+ assert( m_deepestSection );
+ m_deepestSection->stdOut = testCaseStats.stdOut;
+ m_deepestSection->stdErr = testCaseStats.stdErr;
+ }
+ virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
+ Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
+ node->children.swap( m_testCases );
+ m_testGroups.push_back( node );
+ }
+ virtual void testRunEnded( TestRunStats const& testRunStats ) {
+ Ptr<TestRunNode> node = new TestRunNode( testRunStats );
+ node->children.swap( m_testGroups );
+ m_testRuns.push_back( node );
+ testRunEndedCumulative();
+ }
+ virtual void testRunEndedCumulative() = 0;
+
+ Ptr<IConfig> m_config;
+ std::ostream& stream;
+ std::vector<AssertionStats> m_assertions;
+ std::vector<std::vector<Ptr<SectionNode> > > m_sections;
+ std::vector<Ptr<TestCaseNode> > m_testCases;
+ std::vector<Ptr<TestGroupNode> > m_testGroups;
+
+ std::vector<Ptr<TestRunNode> > m_testRuns;
+
+ Ptr<SectionNode> m_rootSection;
+ Ptr<SectionNode> m_deepestSection;
+ std::vector<Ptr<SectionNode> > m_sectionStack;
+
+ };
+
+} // end namespace Catch
+
// #included from: ../internal/catch_reporter_registrars.hpp
#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
@@ -6720,11 +7490,18 @@ namespace Catch {
endElement();
}
+# ifndef CATCH_CPP11_OR_GREATER
XmlWriter& operator = ( XmlWriter const& other ) {
XmlWriter temp( other );
swap( temp );
return *this;
}
+# else
+ XmlWriter( XmlWriter const& ) = default;
+ XmlWriter( XmlWriter && ) = default;
+ XmlWriter& operator = ( XmlWriter const& ) = default;
+ XmlWriter& operator = ( XmlWriter && ) = default;
+# endif
void swap( XmlWriter& other ) {
std::swap( m_tagIsOpen, other.m_tagIsOpen );
@@ -6907,7 +7684,7 @@ namespace Catch {
virtual void StartSection( const std::string& sectionName, const std::string& description ) {
if( m_sectionDepth++ > 0 ) {
m_xml.startElement( "Section" )
- .writeAttribute( "name", sectionName )
+ .writeAttribute( "name", trim( sectionName ) )
.writeAttribute( "description", description );
}
}
@@ -6924,7 +7701,7 @@ namespace Catch {
}
virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) {
- m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.name );
+ m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
m_currentTestSuccess = true;
}
@@ -7055,7 +7832,7 @@ namespace Catch {
writeGroup( *m_testGroups.back(), suiteTime );
}
- virtual void testRunEnded() {
+ virtual void testRunEndedCumulative() {
xml.endElement();
}
@@ -7211,6 +7988,8 @@ namespace Catch {
// #included from: ../reporters/catch_reporter_console.hpp
#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
+#include <cstring>
+
namespace Catch {
struct ConsoleReporter : StreamingReporterBase {
@@ -7454,13 +8233,13 @@ namespace Catch {
m_atLeastOneTestCasePrinted = true;
}
void lazyPrintRunInfo() {
- stream << "\n" << getTildes() << "\n";
+ stream << "\n" << getLineOfChars<'~'>() << "\n";
Colour colour( Colour::SecondaryText );
stream << currentTestRunInfo->name
<< " is a Catch v" << libraryVersion.majorVersion << "."
<< libraryVersion.minorVersion << " b"
<< libraryVersion.buildNumber;
- if( libraryVersion.branchName != "master" )
+ if( libraryVersion.branchName != std::string( "master" ) )
stream << " (" << libraryVersion.branchName << ")";
stream << " host application.\n"
<< "Run with -? for options\n\n";
@@ -7490,19 +8269,19 @@ namespace Catch {
SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
if( !lineInfo.empty() ){
- stream << getDashes() << "\n";
+ stream << getLineOfChars<'-'>() << "\n";
Colour colourGuard( Colour::FileName );
stream << lineInfo << "\n";
}
- stream << getDots() << "\n" << std::endl;
+ stream << getLineOfChars<'.'>() << "\n" << std::endl;
}
void printClosedHeader( std::string const& _name ) {
printOpenHeader( _name );
- stream << getDots() << "\n";
+ stream << getLineOfChars<'.'>() << "\n";
}
void printOpenHeader( std::string const& _name ) {
- stream << getDashes() << "\n";
+ stream << getLineOfChars<'-'>() << "\n";
{
Colour colourGuard( Colour::Headers );
printHeaderString( _name );
@@ -7575,26 +8354,19 @@ namespace Catch {
}
void printTotalsDivider() {
- stream << getDoubleDashes() << "\n";
+ stream << getLineOfChars<'='>() << "\n";
}
void printSummaryDivider() {
- stream << getDashes() << "\n";
- }
- static std::string const& getDashes() {
- static const std::string dashes( CATCH_CONFIG_CONSOLE_WIDTH-1, '-' );
- return dashes;
- }
- static std::string const& getDots() {
- static const std::string dots( CATCH_CONFIG_CONSOLE_WIDTH-1, '.' );
- return dots;
+ stream << getLineOfChars<'-'>() << "\n";
}
- static std::string const& getDoubleDashes() {
- static const std::string doubleDashes( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' );
- return doubleDashes;
- }
- static std::string const& getTildes() {
- static const std::string dots( CATCH_CONFIG_CONSOLE_WIDTH-1, '~' );
- return dots;
+ template<char C>
+ static char const* getLineOfChars() {
+ static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
+ if( !*line ) {
+ memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
+ line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
+ }
+ return line;
}
private:
@@ -7606,10 +8378,291 @@ namespace Catch {
} // end namespace Catch
+// #included from: ../reporters/catch_reporter_compact.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED
+
+namespace Catch {
+
+ struct CompactReporter : StreamingReporterBase {
+
+ CompactReporter( ReporterConfig const& _config )
+ : StreamingReporterBase( _config )
+ {}
+
+ virtual ~CompactReporter();
+
+ static std::string getDescription() {
+ return "Reports test results on a single line, suitable for IDEs";
+ }
+
+ virtual ReporterPreferences getPreferences() const {
+ ReporterPreferences prefs;
+ prefs.shouldRedirectStdOut = false;
+ return prefs;
+ }
+
+ virtual void noMatchingTestCases( std::string const& spec ) {
+ stream << "No test cases matched '" << spec << "'" << std::endl;
+ }
+
+ virtual void assertionStarting( AssertionInfo const& ) {
+ }
+
+ virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
+ AssertionResult const& result = _assertionStats.assertionResult;
+
+ bool printInfoMessages = true;
+
+ // Drop out if result was successful and we're not printing those
+ if( !m_config->includeSuccessfulResults() && result.isOk() ) {
+ if( result.getResultType() != ResultWas::Warning )
+ return false;
+ printInfoMessages = false;
+ }
+
+ AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
+ printer.print();
+
+ stream << std::endl;
+ return true;
+ }
+
+ virtual void testRunEnded( TestRunStats const& _testRunStats ) {
+ printTotals( _testRunStats.totals );
+ stream << "\n" << std::endl;
+ StreamingReporterBase::testRunEnded( _testRunStats );
+ }
+
+ private:
+ class AssertionPrinter {
+ void operator= ( AssertionPrinter const& );
+ public:
+ AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
+ : stream( _stream )
+ , stats( _stats )
+ , result( _stats.assertionResult )
+ , messages( _stats.infoMessages )
+ , itMessage( _stats.infoMessages.begin() )
+ , printInfoMessages( _printInfoMessages )
+ {}
+
+ void print() {
+ printSourceInfo();
+
+ itMessage = messages.begin();
+
+ switch( result.getResultType() ) {
+ case ResultWas::Ok:
+ printResultType( Colour::ResultSuccess, passedString() );
+ printOriginalExpression();
+ printReconstructedExpression();
+ if ( ! result.hasExpression() )
+ printRemainingMessages( Colour::None );
+ else
+ printRemainingMessages();
+ break;
+ case ResultWas::ExpressionFailed:
+ if( result.isOk() )
+ printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) );
+ else
+ printResultType( Colour::Error, failedString() );
+ printOriginalExpression();
+ printReconstructedExpression();
+ printRemainingMessages();
+ break;
+ case ResultWas::ThrewException:
+ printResultType( Colour::Error, failedString() );
+ printIssue( "unexpected exception with message:" );
+ printMessage();
+ printExpressionWas();
+ printRemainingMessages();
+ break;
+ case ResultWas::DidntThrowException:
+ printResultType( Colour::Error, failedString() );
+ printIssue( "expected exception, got none" );
+ printExpressionWas();
+ printRemainingMessages();
+ break;
+ case ResultWas::Info:
+ printResultType( Colour::None, "info" );
+ printMessage();
+ printRemainingMessages();
+ break;
+ case ResultWas::Warning:
+ printResultType( Colour::None, "warning" );
+ printMessage();
+ printRemainingMessages();
+ break;
+ case ResultWas::ExplicitFailure:
+ printResultType( Colour::Error, failedString() );
+ printIssue( "explicitly" );
+ printRemainingMessages( Colour::None );
+ break;
+ // These cases are here to prevent compiler warnings
+ case ResultWas::Unknown:
+ case ResultWas::FailureBit:
+ case ResultWas::Exception:
+ printResultType( Colour::Error, "** internal error **" );
+ break;
+ }
+ }
+
+ private:
+ // Colour::LightGrey
+
+ static Colour dimColour() { return Colour::FileName; }
+
+#ifdef CATCH_PLATFORM_MAC
+ static const char* failedString() { return "FAILED"; }
+ static const char* passedString() { return "PASSED"; }
+#else
+ static const char* failedString() { return "failed"; }
+ static const char* passedString() { return "passed"; }
+#endif
+
+ void printSourceInfo() const {
+ Colour colourGuard( Colour::FileName );
+ stream << result.getSourceInfo() << ":";
+ }
+
+ void printResultType( Colour colour, std::string passOrFail ) const {
+ if( !passOrFail.empty() ) {
+ {
+ Colour colourGuard( colour );
+ stream << " " << passOrFail;
+ }
+ stream << ":";
+ }
+ }
+
+ void printIssue( std::string issue ) const {
+ stream << " " << issue;
+ }
+
+ void printExpressionWas() {
+ if( result.hasExpression() ) {
+ stream << ";";
+ {
+ Colour colour( dimColour() );
+ stream << " expression was:";
+ }
+ printOriginalExpression();
+ }
+ }
+
+ void printOriginalExpression() const {
+ if( result.hasExpression() ) {
+ stream << " " << result.getExpression();
+ }
+ }
+
+ void printReconstructedExpression() const {
+ if( result.hasExpandedExpression() ) {
+ {
+ Colour colour( dimColour() );
+ stream << " for: ";
+ }
+ stream << result.getExpandedExpression();
+ }
+ }
+
+ void printMessage() {
+ if ( itMessage != messages.end() ) {
+ stream << " '" << itMessage->message << "'";
+ ++itMessage;
+ }
+ }
+
+ void printRemainingMessages( Colour colour = dimColour() ) {
+ if ( itMessage == messages.end() )
+ return;
+
+ // using messages.end() directly yields compilation error:
+ std::vector<MessageInfo>::const_iterator itEnd = messages.end();
+ const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
+
+ {
+ Colour colourGuard( colour );
+ stream << " with " << pluralise( N, "message" ) << ":";
+ }
+
+ for(; itMessage != itEnd; ) {
+ // If this assertion is a warning ignore any INFO messages
+ if( printInfoMessages || itMessage->type != ResultWas::Info ) {
+ stream << " '" << itMessage->message << "'";
+ if ( ++itMessage != itEnd ) {
+ Colour colourGuard( dimColour() );
+ stream << " and";
+ }
+ }
+ }
+ }
+
+ private:
+ std::ostream& stream;
+ AssertionStats const& stats;
+ AssertionResult const& result;
+ std::vector<MessageInfo> messages;
+ std::vector<MessageInfo>::const_iterator itMessage;
+ bool printInfoMessages;
+ };
+
+ // Colour, message variants:
+ // - white: No tests ran.
+ // - red: Failed [both/all] N test cases, failed [both/all] M assertions.
+ // - white: Passed [both/all] N test cases (no assertions).
+ // - red: Failed N tests cases, failed M assertions.
+ // - green: Passed [both/all] N tests cases with M assertions.
+
+ std::string bothOrAll( std::size_t count ) const {
+ return count == 1 ? "" : count == 2 ? "both " : "all " ;
+ }
+
+ void printTotals( const Totals& totals ) const {
+ if( totals.testCases.total() == 0 ) {
+ stream << "No tests ran.";
+ }
+ else if( totals.testCases.failed == totals.testCases.total() ) {
+ Colour colour( Colour::ResultError );
+ const std::string qualify_assertions_failed =
+ totals.assertions.failed == totals.assertions.total() ?
+ bothOrAll( totals.assertions.failed ) : "";
+ stream <<
+ "Failed " << bothOrAll( totals.testCases.failed )
+ << pluralise( totals.testCases.failed, "test case" ) << ", "
+ "failed " << qualify_assertions_failed <<
+ pluralise( totals.assertions.failed, "assertion" ) << ".";
+ }
+ else if( totals.assertions.total() == 0 ) {
+ stream <<
+ "Passed " << bothOrAll( totals.testCases.total() )
+ << pluralise( totals.testCases.total(), "test case" )
+ << " (no assertions).";
+ }
+ else if( totals.assertions.failed ) {
+ Colour colour( Colour::ResultError );
+ stream <<
+ "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", "
+ "failed " << pluralise( totals.assertions.failed, "assertion" ) << ".";
+ }
+ else {
+ Colour colour( Colour::ResultSuccess );
+ stream <<
+ "Passed " << bothOrAll( totals.testCases.passed )
+ << pluralise( totals.testCases.passed, "test case" ) <<
+ " with " << pluralise( totals.assertions.passed, "assertion" ) << ".";
+ }
+ }
+ };
+
+ INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter )
+
+} // end namespace Catch
+
namespace Catch {
NonCopyable::~NonCopyable() {}
IShared::~IShared() {}
- StreamBufBase::~StreamBufBase() throw() {}
+ StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
IContext::~IContext() {}
IResultCapture::~IResultCapture() {}
ITestCase::~ITestCase() {}
@@ -7632,6 +8685,7 @@ namespace Catch {
StreamingReporterBase::~StreamingReporterBase() {}
ConsoleReporter::~ConsoleReporter() {}
+ CompactReporter::~CompactReporter() {}
IRunner::~IRunner() {}
IMutableContext::~IMutableContext() {}
IConfig::~IConfig() {}
@@ -7641,9 +8695,6 @@ namespace Catch {
FreeFunctionTestCase::~FreeFunctionTestCase() {}
IGeneratorInfo::~IGeneratorInfo() {}
IGeneratorsForTest::~IGeneratorsForTest() {}
- TagParser::~TagParser() {}
- TagExtracter::~TagExtracter() {}
- TagExpressionParser::~TagExpressionParser() {}
Matchers::Impl::StdString::Equals::~Equals() {}
Matchers::Impl::StdString::Contains::~Contains() {}
@@ -7694,6 +8745,10 @@ int main (int argc, char * const argv[]) {
#endif
+#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
+# undef CLARA_CONFIG_MAIN
+#endif
+
//////
// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
@@ -7720,9 +8775,7 @@ int main (int argc, char * const argv[]) {
#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
-#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN" )
-#define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL" )
-#define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED" )
+#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
@@ -7732,11 +8785,15 @@ int main (int argc, char * const argv[]) {
#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
+ #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
+ #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
#else
#define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
#define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
#define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
#define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
+ #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
+ #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
#endif
#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
@@ -7781,9 +8838,7 @@ int main (int argc, char * const argv[]) {
#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
-#define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN" )
-#define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL" )
-#define SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED" )
+#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
@@ -7793,11 +8848,15 @@ int main (int argc, char * const argv[]) {
#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
+ #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
+ #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
#else
#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
#define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
#define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
#define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
+ #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
+ #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
#endif
#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )