mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-25 23:06:10 +01:00
Refactored a lot of code from headers into impl headers only compiled into one TU
- also added noimpl option to single header script - which only generates the non impl code
This commit is contained in:
parent
8ba6555acd
commit
c4a089c12b
@ -21,7 +21,7 @@
|
||||
#include "internal/catch_context.h"
|
||||
#include "internal/catch_test_registry.hpp"
|
||||
#include "internal/catch_capture.hpp"
|
||||
#include "internal/catch_section.hpp"
|
||||
#include "internal/catch_section.h"
|
||||
#include "internal/catch_generators.hpp"
|
||||
#include "internal/catch_interfaces_exception.h"
|
||||
#include "internal/catch_approx.hpp"
|
||||
@ -39,11 +39,11 @@
|
||||
|
||||
#if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER )
|
||||
#include "internal/catch_impl.hpp"
|
||||
#endif
|
||||
#endif // CATCH_CONFIG_MAIN || CATCH_CONFIG_RUNNER
|
||||
|
||||
#ifdef CATCH_CONFIG_MAIN
|
||||
#include "internal/catch_default_main.hpp"
|
||||
#endif
|
||||
#endif // CATCH_CONFIG_MAIN
|
||||
|
||||
//////
|
||||
|
||||
|
@ -12,11 +12,12 @@
|
||||
#include "catch_expressionresult_builder.h"
|
||||
#include "catch_message.h"
|
||||
#include "catch_interfaces_capture.h"
|
||||
#include "catch_debugger.hpp"
|
||||
#include "catch_debugger.h"
|
||||
#include "catch_context.h"
|
||||
#include "catch_common.h"
|
||||
#include "catch_tostring.hpp"
|
||||
#include "catch_interfaces_registry_hub.h"
|
||||
#include "catch_interfaces_config.h"
|
||||
#include "internal/catch_compiler_capabilities.h"
|
||||
|
||||
#include <ostream>
|
||||
@ -66,7 +67,7 @@ struct TestFailureException{};
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#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( 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 ); \
|
||||
|
@ -67,36 +67,17 @@ namespace Catch {
|
||||
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;
|
||||
@ -104,43 +85,22 @@ 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( std::string const& _file, std::size_t _line );
|
||||
SourceLineInfo( SourceLineInfo const& other );
|
||||
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 );
|
||||
}
|
||||
|
||||
#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
|
||||
|
86
include/internal/catch_common.hpp
Normal file
86
include/internal/catch_common.hpp
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Created by Phil on 27/11/2013.
|
||||
* Copyright 2013 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
|
||||
|
||||
#include "catch_common.h"
|
||||
|
||||
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( std::string 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() );
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "catch_test_spec.h"
|
||||
#include "catch_context.h"
|
||||
#include "catch_interfaces_config.h"
|
||||
#include "catch_stream.hpp"
|
||||
#include "catch_stream.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
49
include/internal/catch_debugger.h
Normal file
49
include/internal/catch_debugger.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Created by Phil on 3/12/2013.
|
||||
* Copyright 2013 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
*/
|
||||
#ifndef TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
|
||||
|
||||
#include "catch_platform.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Catch{
|
||||
|
||||
bool isDebuggerActive();
|
||||
void writeToDebugConsole( std::string const& text );
|
||||
}
|
||||
|
||||
#ifdef CATCH_PLATFORM_MAC
|
||||
|
||||
// The following code snippet based on:
|
||||
// http://cocoawithlove.com/2008/03/break-into-debugger.html
|
||||
#ifdef DEBUG
|
||||
#if defined(__ppc64__) || defined(__ppc__)
|
||||
#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 CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
|
||||
#elif defined(__MINGW32__)
|
||||
extern "C" __declspec(dllimport) void __stdcall DebugBreak();
|
||||
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
|
||||
#endif
|
||||
|
||||
#ifndef CATCH_BREAK_INTO_DEBUGGER
|
||||
#define CATCH_BREAK_INTO_DEBUGGER()
|
||||
#endif
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
|
@ -5,14 +5,13 @@
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* Provides a BreakIntoDebugger() macro for Windows and Mac (so far)
|
||||
*/
|
||||
#ifndef TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
|
||||
|
||||
#include <iostream>
|
||||
#include "catch_debugger.h"
|
||||
|
||||
#include "catch_platform.h"
|
||||
#include <iostream>
|
||||
|
||||
#ifdef CATCH_PLATFORM_MAC
|
||||
|
||||
@ -29,7 +28,7 @@
|
||||
|
||||
// Returns true if the current process is being debugged (either
|
||||
// running under the debugger or has a debugger attached post facto).
|
||||
inline bool isDebuggerActive(){
|
||||
bool isDebuggerActive(){
|
||||
|
||||
int junk;
|
||||
int mib[4];
|
||||
@ -59,52 +58,42 @@
|
||||
|
||||
return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
|
||||
}
|
||||
}
|
||||
|
||||
// The following code snippet taken from:
|
||||
// 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" ); \
|
||||
}
|
||||
#else
|
||||
#define BreakIntoDebugger() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
|
||||
#endif
|
||||
#else
|
||||
inline void BreakIntoDebugger(){}
|
||||
#endif
|
||||
} // namespace Catch
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
|
||||
#define BreakIntoDebugger() if (IsDebuggerPresent() ) { __debugbreak(); }
|
||||
inline bool isDebuggerActive() {
|
||||
return IsDebuggerPresent() != 0;
|
||||
namespace Catch {
|
||||
bool isDebuggerActive() {
|
||||
return IsDebuggerPresent() != 0;
|
||||
}
|
||||
}
|
||||
#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;
|
||||
namespace Catch {
|
||||
bool isDebuggerActive() {
|
||||
return IsDebuggerPresent() != 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
inline void BreakIntoDebugger(){}
|
||||
namespace Catch {
|
||||
inline bool isDebuggerActive() { return false; }
|
||||
#endif
|
||||
}
|
||||
#endif // Platform
|
||||
|
||||
#ifdef CATCH_PLATFORM_WINDOWS
|
||||
extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
|
||||
inline void writeToDebugConsole( std::string const& text ) {
|
||||
::OutputDebugStringA( text.c_str() );
|
||||
}
|
||||
extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
|
||||
namespace Catch {
|
||||
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
|
||||
namespace Catch {
|
||||
void writeToDebugConsole( std::string const& text ) {
|
||||
// !TBD: Need a version for Mac/ XCode and other IDEs
|
||||
std::cout << text;
|
||||
}
|
||||
}
|
||||
#endif // Platform
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
|
||||
|
@ -26,11 +26,15 @@
|
||||
#include "catch_expressionresult_builder.hpp"
|
||||
#include "catch_test_case_info.hpp"
|
||||
#include "catch_tags.hpp"
|
||||
#include "catch_test_spec.hpp"
|
||||
#include "catch_version.hpp"
|
||||
#include "catch_text.hpp"
|
||||
#include "catch_message.hpp"
|
||||
#include "catch_legacy_reporter_adapter.hpp"
|
||||
#include "catch_timer.hpp"
|
||||
#include "catch_common.hpp"
|
||||
#include "catch_section.hpp"
|
||||
#include "catch_debugger.hpp"
|
||||
|
||||
#include "../reporters/catch_reporter_xml.hpp"
|
||||
#include "../reporters/catch_reporter_junit.hpp"
|
||||
@ -71,9 +75,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() {}
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
#include <string>
|
||||
#include "catch_result_type.h"
|
||||
#include "catch_totals.hpp"
|
||||
#include "catch_common.h"
|
||||
|
||||
namespace Catch {
|
||||
@ -22,6 +21,7 @@ namespace Catch {
|
||||
struct SectionInfo;
|
||||
struct MessageInfo;
|
||||
class ScopedMessageBuilder;
|
||||
struct Counts;
|
||||
|
||||
struct IResultCapture {
|
||||
|
||||
|
@ -8,10 +8,7 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
|
||||
|
||||
#include "catch_interfaces_reporter.h"
|
||||
#include "catch_interfaces_config.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
@ -19,6 +16,8 @@ namespace Catch {
|
||||
struct ITestCaseRegistry;
|
||||
struct IExceptionTranslatorRegistry;
|
||||
struct IExceptionTranslator;
|
||||
struct IReporterRegistry;
|
||||
struct IReporterFactory;
|
||||
|
||||
struct IRegistryHub {
|
||||
virtual ~IRegistryHub();
|
||||
|
@ -8,6 +8,7 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
|
||||
|
||||
#include "catch_section_info.h"
|
||||
#include "catch_common.h"
|
||||
#include "catch_totals.hpp"
|
||||
#include "catch_ptr.hpp"
|
||||
@ -80,20 +81,6 @@ namespace Catch
|
||||
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,
|
||||
@ -223,201 +210,6 @@ namespace Catch
|
||||
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();
|
||||
@ -433,13 +225,6 @@ namespace Catch
|
||||
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 ) : "";
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
|
||||
|
@ -8,10 +8,6 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
|
||||
|
||||
#include "catch_totals.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Catch {
|
||||
class TestCase;
|
||||
|
||||
|
@ -12,6 +12,26 @@
|
||||
|
||||
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:
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "catch_commandline.hpp"
|
||||
#include "catch_text.h"
|
||||
#include "catch_console_colour.hpp"
|
||||
#include "catch_interfaces_reporter.h"
|
||||
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
|
@ -56,9 +56,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,
|
||||
@ -88,7 +85,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 );
|
||||
|
49
include/internal/catch_section.h
Normal file
49
include/internal/catch_section.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Created by Phil on 03/12/2013.
|
||||
* Copyright 2013 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
|
||||
|
||||
#include "catch_section_info.h"
|
||||
#include "catch_totals.hpp"
|
||||
#include "catch_timer.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
class Section {
|
||||
public:
|
||||
Section( SourceLineInfo const& lineInfo,
|
||||
std::string const& name,
|
||||
std::string const& description = "" );
|
||||
~Section();
|
||||
|
||||
// This indicates whether the section should be executed or not
|
||||
operator bool();
|
||||
|
||||
private:
|
||||
|
||||
SectionInfo m_info;
|
||||
|
||||
std::string m_name;
|
||||
Counts m_assertions;
|
||||
bool m_sectionIncluded;
|
||||
Timer m_timer;
|
||||
};
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#ifdef CATCH_CONFIG_VARIADIC_MACROS
|
||||
#define INTERNAL_CATCH_SECTION( ... ) \
|
||||
if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
|
||||
#else
|
||||
#define INTERNAL_CATCH_SECTION( name, desc ) \
|
||||
if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, name, desc ) )
|
||||
#endif
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
|
@ -8,53 +8,33 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
|
||||
|
||||
#include "catch_section.h"
|
||||
#include "catch_capture.hpp"
|
||||
#include "catch_totals.hpp"
|
||||
#include "catch_compiler_capabilities.h"
|
||||
#include "catch_timer.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
class Section {
|
||||
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::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() );
|
||||
}
|
||||
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
|
||||
operator bool() {
|
||||
return m_sectionIncluded;
|
||||
}
|
||||
// This indicates whether the section should be executed or not
|
||||
Section::operator bool() {
|
||||
return m_sectionIncluded;
|
||||
}
|
||||
|
||||
private:
|
||||
SectionInfo m_info;
|
||||
|
||||
std::string m_name;
|
||||
Counts m_assertions;
|
||||
bool m_sectionIncluded;
|
||||
Timer m_timer;
|
||||
};
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#ifdef CATCH_CONFIG_VARIADIC_MACROS
|
||||
#define INTERNAL_CATCH_SECTION( ... ) \
|
||||
if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
|
||||
#else
|
||||
#define INTERNAL_CATCH_SECTION( name, desc ) \
|
||||
if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, name, desc ) )
|
||||
#endif
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
|
||||
|
31
include/internal/catch_section_info.h
Normal file
31
include/internal/catch_section_info.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Created by Phil on 03/11/2010.
|
||||
* Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
|
||||
|
||||
#include "catch_common.h"
|
||||
|
||||
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
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
|
33
include/internal/catch_stream.h
Normal file
33
include/internal/catch_stream.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Created by Phil on 2/12/2013.
|
||||
* Copyright 2013 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
*/
|
||||
#ifndef TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
|
||||
#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;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
|
@ -9,8 +9,9 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
|
||||
|
||||
#include "catch_stream.h"
|
||||
#include "catch_streambuf.h"
|
||||
#include "catch_debugger.hpp"
|
||||
#include "catch_debugger.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cstdio>
|
||||
@ -62,29 +63,21 @@ namespace Catch {
|
||||
}
|
||||
};
|
||||
|
||||
class Stream {
|
||||
public:
|
||||
Stream()
|
||||
: streamBuf( NULL ), isOwned( false )
|
||||
{}
|
||||
Stream::Stream()
|
||||
: streamBuf( NULL ), isOwned( false )
|
||||
{}
|
||||
|
||||
Stream( std::streambuf* _streamBuf, bool _isOwned )
|
||||
: streamBuf( _streamBuf ), isOwned( _isOwned )
|
||||
{}
|
||||
Stream::Stream( std::streambuf* _streamBuf, bool _isOwned )
|
||||
: streamBuf( _streamBuf ), isOwned( _isOwned )
|
||||
{}
|
||||
|
||||
void release() {
|
||||
if( isOwned ) {
|
||||
delete streamBuf;
|
||||
streamBuf = NULL;
|
||||
isOwned = false;
|
||||
}
|
||||
void Stream::release() {
|
||||
if( isOwned ) {
|
||||
delete streamBuf;
|
||||
streamBuf = NULL;
|
||||
isOwned = false;
|
||||
}
|
||||
|
||||
std::streambuf* streamBuf;
|
||||
|
||||
private:
|
||||
bool isOwned;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
|
||||
|
109
include/internal/catch_tags.h
Normal file
109
include/internal/catch_tags.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Created by Phil on 2/12/2013.
|
||||
* Copyright 2013 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef TWOBLUECUBES_CATCH_TAGS_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_TAGS_H_INCLUDED
|
||||
|
||||
#include "catch_common.h"
|
||||
|
||||
#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
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED
|
@ -8,188 +8,129 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED
|
||||
|
||||
#include "catch_common.h"
|
||||
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic ignored "-Wpadded"
|
||||
#endif
|
||||
#include "catch_tags.h"
|
||||
|
||||
namespace Catch {
|
||||
class TagParser {
|
||||
public:
|
||||
virtual ~TagParser();
|
||||
TagParser::~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++;
|
||||
}
|
||||
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++;
|
||||
}
|
||||
}
|
||||
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;
|
||||
else {
|
||||
acceptChar( c );
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
virtual void endParse() {
|
||||
if( !m_currentTagSet.empty() )
|
||||
endParse();
|
||||
}
|
||||
|
||||
TagExtracter::TagExtracter( std::set<std::string>& tags )
|
||||
: m_tags( tags )
|
||||
{}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
TagExpressionParser& operator=(TagExpressionParser const&);
|
||||
|
||||
bool m_isNegated;
|
||||
TagSet m_currentTagSet;
|
||||
TagExpression& m_exp;
|
||||
};
|
||||
void TagExpressionParser::endParse() {
|
||||
if( !m_currentTagSet.empty() )
|
||||
m_exp.m_tagSets.push_back( m_currentTagSet );
|
||||
}
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
|
||||
|
||||
#include "catch_tags.hpp"
|
||||
#include "catch_tags.h"
|
||||
#include "catch_test_case_info.h"
|
||||
#include "catch_interfaces_testcase.h"
|
||||
#include "catch_common.h"
|
||||
|
@ -8,15 +8,15 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED
|
||||
|
||||
#include "catch_test_case_info.h"
|
||||
#include "catch_tags.hpp"
|
||||
#include "catch_common.h"
|
||||
#include "catch_tags.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
class TestCase;
|
||||
|
||||
struct IfFilterMatches{ enum DoWhat {
|
||||
AutoDetectBehaviour,
|
||||
IncludeTests,
|
||||
@ -32,69 +32,13 @@ namespace Catch {
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
TestCaseFilter( std::string const& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::AutoDetectBehaviour );
|
||||
|
||||
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;
|
||||
bool shouldInclude( TestCase const& testCase ) const;
|
||||
|
||||
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
|
||||
bool isMatch( TestCase const& testCase ) const;
|
||||
|
||||
std::string m_stringToMatch;
|
||||
IfFilterMatches::DoWhat m_filterType;
|
||||
@ -103,57 +47,12 @@ namespace Catch {
|
||||
|
||||
class TestCaseFilters {
|
||||
public:
|
||||
TestCaseFilters( std::string const& name ) : m_name( name ) {}
|
||||
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;
|
||||
|
||||
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;
|
||||
|
133
include/internal/catch_test_spec.hpp
Normal file
133
include/internal/catch_test_spec.hpp
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Created by Phil on 2/12/2013.
|
||||
* Copyright 2013 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
|
||||
|
||||
#include "catch_test_spec.hpp"
|
||||
#include "catch_test_case_info.h"
|
||||
#include "catch_common.h"
|
||||
|
||||
namespace Catch {
|
||||
|
||||
TestCaseFilter::TestCaseFilter( std::string const& testSpec, IfFilterMatches::DoWhat matchBehaviour )
|
||||
: 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 TestCaseFilter::getFilterType() const {
|
||||
return m_filterType;
|
||||
}
|
||||
|
||||
bool TestCaseFilter::shouldInclude( TestCase const& testCase ) const {
|
||||
return isMatch( testCase ) == (m_filterType == IfFilterMatches::IncludeTests);
|
||||
}
|
||||
|
||||
#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 );
|
||||
}
|
||||
throw std::logic_error( "Unhandled wildcard type" );
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
|
192
include/reporters/catch_reporter_bases.hpp
Normal file
192
include/reporters/catch_reporter_bases.hpp
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Created by Phil on 27/11/2013.
|
||||
* Copyright 2013 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
|
||||
|
||||
#include "../internal/catch_interfaces_reporter.h"
|
||||
|
||||
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;
|
||||
};
|
||||
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;
|
||||
|
||||
};
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
|
@ -8,7 +8,8 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
|
||||
|
||||
#include "../internal/catch_interfaces_reporter.h"
|
||||
#include "catch_reporter_bases.hpp"
|
||||
|
||||
#include "../internal/catch_reporter_registrars.hpp"
|
||||
#include "../internal/catch_console_colour.hpp"
|
||||
|
||||
|
@ -8,8 +8,9 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
|
||||
|
||||
#include "catch_reporter_bases.hpp"
|
||||
|
||||
#include "../internal/catch_tostring.hpp"
|
||||
#include "../internal/catch_interfaces_reporter.h"
|
||||
#include "../internal/catch_reporter_registrars.hpp"
|
||||
#include "../internal/catch_xmlwriter.hpp"
|
||||
|
||||
|
@ -8,8 +8,9 @@
|
||||
#ifndef TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
|
||||
|
||||
#include "catch_reporter_bases.hpp"
|
||||
|
||||
#include "../internal/catch_capture.hpp"
|
||||
#include "../internal/catch_interfaces_reporter.h"
|
||||
#include "../internal/catch_reporter_registrars.hpp"
|
||||
#include "../internal/catch_xmlwriter.hpp"
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
// This file is only here to verify (to the extent possible) the self sufficiency of the header
|
||||
#include "catch_debugger.hpp"
|
||||
#include "catch_debugger.h"
|
||||
|
@ -1,2 +1,2 @@
|
||||
// This file is only here to verify (to the extent possible) the self sufficiency of the header
|
||||
#include "catch_stream.hpp"
|
||||
#include "catch_stream.h"
|
||||
|
@ -1,2 +1,2 @@
|
||||
// This file is only here to verify (to the extent possible) the self sufficiency of the header
|
||||
#include "catch_tags.hpp"
|
||||
#include "catch_tags.h"
|
||||
|
@ -56,6 +56,14 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
261488FA184C81130041FBEB /* catch_test_spec.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_spec.hpp; sourceTree = "<group>"; };
|
||||
261488FB184C83EA0041FBEB /* catch_tags.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_tags.h; sourceTree = "<group>"; };
|
||||
261488FC184D1DC10041FBEB /* catch_stream.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_stream.h; sourceTree = "<group>"; };
|
||||
261488FD184D21290041FBEB /* catch_section_info.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_section_info.h; sourceTree = "<group>"; };
|
||||
261488FE184DC32F0041FBEB /* catch_section.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_section.h; sourceTree = "<group>"; };
|
||||
261488FF184DC4A20041FBEB /* catch_debugger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_debugger.h; sourceTree = "<group>"; };
|
||||
262E7399184673A800CAC268 /* catch_reporter_bases.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_bases.hpp; sourceTree = "<group>"; };
|
||||
262E739A1846759000CAC268 /* catch_common.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_common.hpp; sourceTree = "<group>"; };
|
||||
263FD06017AF8DF200988A20 /* catch_timer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_timer.hpp; sourceTree = "<group>"; };
|
||||
263FD06117AF8DF200988A20 /* catch_timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_timer.h; sourceTree = "<group>"; };
|
||||
266B06B616F3A60A004ED264 /* VariadicMacrosTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VariadicMacrosTests.cpp; path = ../../../SelfTest/VariadicMacrosTests.cpp; sourceTree = "<group>"; };
|
||||
@ -277,6 +285,7 @@
|
||||
4A6D0C65149B3E3D00DB3EAA /* reporters */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
262E7399184673A800CAC268 /* catch_reporter_bases.hpp */,
|
||||
4A6D0C67149B3E3D00DB3EAA /* catch_reporter_junit.hpp */,
|
||||
4A6D0C68149B3E3D00DB3EAA /* catch_reporter_xml.hpp */,
|
||||
4AB42F84166F3E1A0099F2C8 /* catch_reporter_console.hpp */,
|
||||
@ -314,6 +323,7 @@
|
||||
4AC91CB4155B9EBF00DC5117 /* impl */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
261488FA184C81130041FBEB /* catch_test_spec.hpp */,
|
||||
263FD06017AF8DF200988A20 /* catch_timer.hpp */,
|
||||
266E9AD117230ACF0061DAB2 /* catch_text.hpp */,
|
||||
4A4B0F9C15CEFA8300AE2392 /* catch_impl.hpp */,
|
||||
@ -341,6 +351,7 @@
|
||||
4A6D0C5D149B3E3D00DB3EAA /* catch_assertionresult.h */,
|
||||
4A9D84B315599AC900FBB209 /* catch_expressionresult_builder.h */,
|
||||
4A6D0C5F149B3E3D00DB3EAA /* catch_section.hpp */,
|
||||
261488FE184DC32F0041FBEB /* catch_section.h */,
|
||||
4A3D7DD01503869D005F9203 /* catch_matchers.hpp */,
|
||||
4A9D84B11558FC0400FBB209 /* catch_tostring.hpp */,
|
||||
4A6D0C46149B3E3D00DB3EAA /* catch_approx.hpp */,
|
||||
@ -349,6 +360,7 @@
|
||||
4AC91CD0155D8DA600DC5117 /* catch_expression_decomposer.hpp */,
|
||||
4A4B0F9A15CEF84800AE2392 /* catch_notimplemented_exception.h */,
|
||||
26847E5B16BBAB790043B9C1 /* catch_message.h */,
|
||||
261488FD184D21290041FBEB /* catch_section_info.h */,
|
||||
);
|
||||
name = Assertions;
|
||||
sourceTree = "<group>";
|
||||
@ -375,6 +387,7 @@
|
||||
4A084F1D15DAD15F0027E631 /* catch_test_spec.h */,
|
||||
4A8E4DCC160A344100194CBD /* catch_tags.hpp */,
|
||||
26948287179EF7F900ED166E /* catch_test_case_tracker.hpp */,
|
||||
261488FB184C83EA0041FBEB /* catch_tags.h */,
|
||||
);
|
||||
name = "Test execution";
|
||||
sourceTree = "<group>";
|
||||
@ -411,6 +424,7 @@
|
||||
266ECD8D1713614B0030D735 /* catch_legacy_reporter_adapter.h */,
|
||||
4A6D0C49149B3E3D00DB3EAA /* catch_common.h */,
|
||||
4A6D0C4B149B3E3D00DB3EAA /* catch_debugger.hpp */,
|
||||
261488FF184DC4A20041FBEB /* catch_debugger.h */,
|
||||
4A6D0C60149B3E3D00DB3EAA /* catch_stream.hpp */,
|
||||
4A6D0C64149B3E3D00DB3EAA /* catch_xmlwriter.hpp */,
|
||||
4AB1C73714F97C1300F31DF7 /* catch_console_colour.hpp */,
|
||||
@ -422,6 +436,8 @@
|
||||
26DACF2F17206D3400A21326 /* catch_text.h */,
|
||||
263FD06117AF8DF200988A20 /* catch_timer.h */,
|
||||
26AEAF1617BEA18E009E32C9 /* catch_platform.h */,
|
||||
262E739A1846759000CAC268 /* catch_common.hpp */,
|
||||
261488FC184D1DC10041FBEB /* catch_stream.h */,
|
||||
);
|
||||
name = Infrastructure;
|
||||
sourceTree = "<group>";
|
||||
|
@ -2,6 +2,7 @@ import os
|
||||
import sys
|
||||
import re
|
||||
import datetime
|
||||
import string
|
||||
|
||||
from scriptCommon import catchPath
|
||||
|
||||
@ -9,6 +10,9 @@ versionParser = re.compile( r'(\s*Version\slibraryVersion)\s*\(\s*(.*)\s*,\s*(.*
|
||||
includesParser = re.compile( r'\s*#include\s*"(.*)"' )
|
||||
guardParser = re.compile( r'\s*#.*_INCLUDED')
|
||||
defineParser = re.compile( r'\s*#define')
|
||||
ifParser = re.compile( r'\s*#if')
|
||||
endIfParser = re.compile( r'\s*#endif')
|
||||
ifImplParser = re.compile( r'\s*#if.*(CATCH_CONFIG_MAIN|CATCH_CONFIG_RUNNER)')
|
||||
commentParser1 = re.compile( r'^\s*/\*')
|
||||
commentParser2 = re.compile( r'^\s*\*')
|
||||
blankParser = re.compile( r'^\s*$')
|
||||
@ -18,21 +22,48 @@ versionPath = os.path.join( rootPath, "internal/catch_version.hpp" )
|
||||
readmePath = os.path.join( catchPath, "README.md" )
|
||||
outputPath = os.path.join( catchPath, 'single_include/catch.hpp' )
|
||||
|
||||
bumpVersion = len(sys.argv) < 2 or sys.argv[1] <> "nobump"
|
||||
bumpVersion = True
|
||||
includeImpl = True
|
||||
|
||||
for arg in sys.argv[1:]:
|
||||
arg = string.lower(arg)
|
||||
if arg == "nobump":
|
||||
bumpVersion = False
|
||||
print "Not bumping version number"
|
||||
elif arg == "noimpl":
|
||||
includeImpl = False
|
||||
bumpVersion = False
|
||||
print "Not including impl code (and not bumping version)"
|
||||
else:
|
||||
print "\n** Unrecognised argument: " + arg + " **\n"
|
||||
exit(1)
|
||||
|
||||
out = open( outputPath, 'w' )
|
||||
ifdefs = 0
|
||||
implIfDefs = -1
|
||||
|
||||
def write( line ):
|
||||
if includeImpl or implIfDefs == -1:
|
||||
out.write( line )
|
||||
|
||||
def parseFile( path, filename ):
|
||||
global ifdefs
|
||||
global implIfDefs
|
||||
|
||||
f = open( path + filename, 'r' )
|
||||
blanks = 0
|
||||
for line in f:
|
||||
if ifParser.match( line ):
|
||||
ifdefs = ifdefs + 1
|
||||
elif endIfParser.match( line ):
|
||||
ifdefs = ifdefs - 1
|
||||
m = includesParser.match( line )
|
||||
if m:
|
||||
header = m.group(1)
|
||||
headerPath, sep, headerFile = header.rpartition( "/" )
|
||||
if not headerFile in seenHeaders:
|
||||
seenHeaders.add( headerFile )
|
||||
out.write( "// #included from: {0}\n".format( header ) )
|
||||
write( "// #included from: {0}\n".format( header ) )
|
||||
if( headerPath == "internal" and path.endswith( "internal/" ) ):
|
||||
headerPath = ""
|
||||
sep = ""
|
||||
@ -40,13 +71,15 @@ def parseFile( path, filename ):
|
||||
parseFile( path + headerPath + sep, headerFile )
|
||||
else:
|
||||
parseFile( rootPath + headerPath + sep, headerFile )
|
||||
elif ifImplParser.match(line):
|
||||
implIfDefs = ifdefs
|
||||
elif (not guardParser.match( line ) or defineParser.match( line ) ) and not commentParser1.match( line )and not commentParser2.match( line ):
|
||||
if blankParser.match( line ):
|
||||
blanks = blanks + 1
|
||||
else:
|
||||
blanks = 0
|
||||
if blanks < 2:
|
||||
out.write( line.rstrip() + "\n" )
|
||||
write( line.rstrip() + "\n" )
|
||||
|
||||
class Version:
|
||||
def __init__(self):
|
||||
|
Loading…
Reference in New Issue
Block a user