From c4a089c12b905843819bf0d3f17b45c9a51af3a2 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 3 Dec 2013 18:52:41 +0000 Subject: [PATCH] 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 --- include/catch.hpp | 6 +- include/internal/catch_capture.hpp | 5 +- include/internal/catch_common.h | 72 +---- include/internal/catch_common.hpp | 86 ++++++ include/internal/catch_config.hpp | 2 +- include/internal/catch_debugger.h | 49 ++++ include/internal/catch_debugger.hpp | 67 ++--- include/internal/catch_impl.hpp | 7 +- include/internal/catch_interfaces_capture.h | 2 +- .../internal/catch_interfaces_registry_hub.h | 7 +- include/internal/catch_interfaces_reporter.h | 217 +------------- include/internal/catch_interfaces_runner.h | 4 - .../internal/catch_legacy_reporter_adapter.h | 20 ++ include/internal/catch_list.hpp | 1 + include/internal/catch_objc.hpp | 5 +- include/internal/catch_section.h | 49 ++++ include/internal/catch_section.hpp | 54 ++-- include/internal/catch_section_info.h | 31 ++ include/internal/catch_stream.h | 33 +++ include/internal/catch_stream.hpp | 35 +-- include/internal/catch_tags.h | 109 +++++++ include/internal/catch_tags.hpp | 277 +++++++----------- include/internal/catch_test_case_info.hpp | 2 +- include/internal/catch_test_spec.h | 125 +------- include/internal/catch_test_spec.hpp | 133 +++++++++ include/reporters/catch_reporter_bases.hpp | 192 ++++++++++++ include/reporters/catch_reporter_console.hpp | 3 +- include/reporters/catch_reporter_junit.hpp | 3 +- include/reporters/catch_reporter_xml.hpp | 3 +- .../SelfTest/SurrogateCpps/catch_debugger.cpp | 2 +- .../SelfTest/SurrogateCpps/catch_stream.cpp | 2 +- .../SelfTest/SurrogateCpps/catch_tags.cpp | 2 +- .../CatchSelfTest.xcodeproj/project.pbxproj | 16 + scripts/generateSingleHeader.py | 39 ++- 34 files changed, 978 insertions(+), 682 deletions(-) create mode 100644 include/internal/catch_common.hpp create mode 100644 include/internal/catch_debugger.h create mode 100644 include/internal/catch_section.h create mode 100644 include/internal/catch_section_info.h create mode 100644 include/internal/catch_stream.h create mode 100644 include/internal/catch_tags.h create mode 100644 include/internal/catch_test_spec.hpp create mode 100644 include/reporters/catch_reporter_bases.hpp diff --git a/include/catch.hpp b/include/catch.hpp index 600815f7..28e7f9bc 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -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 ////// diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 849dee97..a352a622 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -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 @@ -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 ); \ diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index 7759987d..650e1fbe 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -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( __LINE__ ) ) diff --git a/include/internal/catch_common.hpp b/include/internal/catch_common.hpp new file mode 100644 index 00000000..4fbf1ffc --- /dev/null +++ b/include/internal/catch_common.hpp @@ -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 + diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 51b5913a..30cd34b9 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -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 #include diff --git a/include/internal/catch_debugger.h b/include/internal/catch_debugger.h new file mode 100644 index 00000000..0fb6621b --- /dev/null +++ b/include/internal/catch_debugger.h @@ -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 + +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 diff --git a/include/internal/catch_debugger.hpp b/include/internal/catch_debugger.hpp index 9979dff8..f3ad100f 100644 --- a/include/internal/catch_debugger.hpp +++ b/include/internal/catch_debugger.hpp @@ -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 +#include "catch_debugger.h" -#include "catch_platform.h" +#include #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 diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 30ac219d..01522355 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -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() {} diff --git a/include/internal/catch_interfaces_capture.h b/include/internal/catch_interfaces_capture.h index 2601ab46..de779e07 100644 --- a/include/internal/catch_interfaces_capture.h +++ b/include/internal/catch_interfaces_capture.h @@ -10,7 +10,6 @@ #include #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 { diff --git a/include/internal/catch_interfaces_registry_hub.h b/include/internal/catch_interfaces_registry_hub.h index 7fae3abd..b657183b 100644 --- a/include/internal/catch_interfaces_registry_hub.h +++ b/include/internal/catch_interfaces_registry_hub.h @@ -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 +#include namespace Catch { @@ -19,6 +16,8 @@ namespace Catch { struct ITestCaseRegistry; struct IExceptionTranslatorRegistry; struct IExceptionTranslator; + struct IReporterRegistry; + struct IReporterFactory; struct IRegistryHub { virtual ~IRegistryHub(); diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index 1de4778e..eafaaa3a 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -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 const& _infoMessages, @@ -223,201 +210,6 @@ namespace Catch virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; }; - struct StreamingReporterBase : SharedImpl { - - 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 m_config; - std::ostream& stream; - - LazyStat currentTestRunInfo; - LazyStat currentGroupInfo; - LazyStat currentTestCaseInfo; - - std::vector m_sectionStack; - }; - - struct CumulativeReporterBase : SharedImpl { - template - struct Node : SharedImpl<> { - explicit Node( T const& _value ) : value( _value ) {} - virtual ~Node() {} - - typedef std::vector > 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 const& other ) const { - return operator==( *other ); - } - - SectionStats stats; - typedef std::vector > ChildSections; - typedef std::vector Assertions; - ChildSections childSections; - Assertions assertions; - std::string stdOut; - std::string stdErr; - }; - friend bool operator == ( Ptr const& node, SectionInfo const& other ) { - return node->stats.sectionInfo.lineInfo == other.lineInfo; - } - - typedef Node TestCaseNode; - typedef Node TestGroupNode; - typedef Node 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 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 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 node = new TestGroupNode( testGroupStats ); - node->children.swap( m_testCases ); - m_testGroups.push_back( node ); - } - virtual void testRunEnded( TestRunStats const& testRunStats ) { - Ptr node = new TestRunNode( testRunStats ); - node->children.swap( m_testGroups ); - m_testRuns.push_back( node ); - testRunEnded(); - } - virtual void testRunEnded() = 0; - - Ptr m_config; - std::ostream& stream; - std::vector m_assertions; - std::vector > > m_sections; - std::vector > m_testCases; - std::vector > m_testGroups; - - std::vector > m_testRuns; - - Ptr m_rootSection; - Ptr m_deepestSection; - std::vector > 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 diff --git a/include/internal/catch_interfaces_runner.h b/include/internal/catch_interfaces_runner.h index ab127b9f..6438f205 100644 --- a/include/internal/catch_interfaces_runner.h +++ b/include/internal/catch_interfaces_runner.h @@ -8,10 +8,6 @@ #ifndef TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED #define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED -#include "catch_totals.hpp" - -#include - namespace Catch { class TestCase; diff --git a/include/internal/catch_legacy_reporter_adapter.h b/include/internal/catch_legacy_reporter_adapter.h index 32d03f15..fb579c7c 100644 --- a/include/internal/catch_legacy_reporter_adapter.h +++ b/include/internal/catch_legacy_reporter_adapter.h @@ -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 { public: diff --git a/include/internal/catch_list.hpp b/include/internal/catch_list.hpp index 70d7668c..1ee3d1f5 100644 --- a/include/internal/catch_list.hpp +++ b/include/internal/catch_list.hpp @@ -11,6 +11,7 @@ #include "catch_commandline.hpp" #include "catch_text.h" #include "catch_console_colour.hpp" +#include "catch_interfaces_reporter.h" #include #include diff --git a/include/internal/catch_objc.hpp b/include/internal/catch_objc.hpp index 45d64ba9..85181f44 100644 --- a/include/internal/catch_objc.hpp +++ b/include/internal/catch_objc.hpp @@ -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 ); diff --git a/include/internal/catch_section.h b/include/internal/catch_section.h new file mode 100644 index 00000000..c1a81f6f --- /dev/null +++ b/include/internal/catch_section.h @@ -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 + +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 diff --git a/include/internal/catch_section.hpp b/include/internal/catch_section.hpp index e58e72a8..96fc8320 100644 --- a/include/internal/catch_section.hpp +++ b/include/internal/catch_section.hpp @@ -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 - 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 diff --git a/include/internal/catch_section_info.h b/include/internal/catch_section_info.h new file mode 100644 index 00000000..6bcc72a9 --- /dev/null +++ b/include/internal/catch_section_info.h @@ -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 diff --git a/include/internal/catch_stream.h b/include/internal/catch_stream.h new file mode 100644 index 00000000..70ddb58c --- /dev/null +++ b/include/internal/catch_stream.h @@ -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 + +#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 diff --git a/include/internal/catch_stream.hpp b/include/internal/catch_stream.hpp index eea576ef..784ef86b 100644 --- a/include/internal/catch_stream.hpp +++ b/include/internal/catch_stream.hpp @@ -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 #include @@ -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 diff --git a/include/internal/catch_tags.h b/include/internal/catch_tags.h new file mode 100644 index 00000000..8fd20b7e --- /dev/null +++ b/include/internal/catch_tags.h @@ -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 +#include +#include +#include + +#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& 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& 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 TagMap; + public: + void add( Tag const& tag ); + bool empty() const; + bool matches( std::set const& tags ) const; + + private: + TagMap m_tags; + }; + + + class TagExpression { + public: + bool matches( std::set const& tags ) const; + + private: + friend class TagExpressionParser; + + std::vector 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 diff --git a/include/internal/catch_tags.hpp b/include/internal/catch_tags.hpp index 36ecd1d6..d02ed8dd 100644 --- a/include/internal/catch_tags.hpp +++ b/include/internal/catch_tags.hpp @@ -8,188 +8,129 @@ #ifndef TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED #define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED -#include "catch_common.h" - -#include -#include -#include -#include - -#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& 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& 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 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 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 const& tags ) const { - for( std::vector::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 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& 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 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 const& tags ) const { + for( std::vector::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 diff --git a/include/internal/catch_test_case_info.hpp b/include/internal/catch_test_case_info.hpp index 59fc39f4..3d46320f 100644 --- a/include/internal/catch_test_case_info.hpp +++ b/include/internal/catch_test_case_info.hpp @@ -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" diff --git a/include/internal/catch_test_spec.h b/include/internal/catch_test_spec.h index 05f877cf..758f49e2 100644 --- a/include/internal/catch_test_spec.h +++ b/include/internal/catch_test_spec.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 #include 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::const_iterator it = m_tagExpressions.begin(); - std::vector::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::const_iterator it = m_inclusionFilters.begin(); - std::vector::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::const_iterator it = m_exclusionFilters.begin(); - std::vector::const_iterator itEnd = m_exclusionFilters.end(); - for(; it != itEnd; ++it ) - if( !it->shouldInclude( testCase ) ) - return false; - return true; - } private: std::vector m_tagExpressions; std::vector m_inclusionFilters; diff --git a/include/internal/catch_test_spec.hpp b/include/internal/catch_test_spec.hpp new file mode 100644 index 00000000..6df01bc7 --- /dev/null +++ b/include/internal/catch_test_spec.hpp @@ -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::const_iterator it = m_tagExpressions.begin(); + std::vector::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::const_iterator it = m_inclusionFilters.begin(); + std::vector::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::const_iterator it = m_exclusionFilters.begin(); + std::vector::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 diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp new file mode 100644 index 00000000..a109d860 --- /dev/null +++ b/include/reporters/catch_reporter_bases.hpp @@ -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 { + + 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 m_config; + std::ostream& stream; + + LazyStat currentTestRunInfo; + LazyStat currentGroupInfo; + LazyStat currentTestCaseInfo; + + std::vector m_sectionStack; + }; + + struct CumulativeReporterBase : SharedImpl { + template + struct Node : SharedImpl<> { + explicit Node( T const& _value ) : value( _value ) {} + virtual ~Node() {} + + typedef std::vector > 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 const& other ) const { + return operator==( *other ); + } + + SectionStats stats; + typedef std::vector > ChildSections; + typedef std::vector Assertions; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; + }; + friend bool operator == ( Ptr const& node, SectionInfo const& other ) { + return node->stats.sectionInfo.lineInfo == other.lineInfo; + } + + typedef Node TestCaseNode; + typedef Node TestGroupNode; + typedef Node 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 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 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 node = new TestGroupNode( testGroupStats ); + node->children.swap( m_testCases ); + m_testGroups.push_back( node ); + } + virtual void testRunEnded( TestRunStats const& testRunStats ) { + Ptr node = new TestRunNode( testRunStats ); + node->children.swap( m_testGroups ); + m_testRuns.push_back( node ); + testRunEnded(); + } + virtual void testRunEnded() = 0; + + Ptr m_config; + std::ostream& stream; + std::vector m_assertions; + std::vector > > m_sections; + std::vector > m_testCases; + std::vector > m_testGroups; + + std::vector > m_testRuns; + + Ptr m_rootSection; + Ptr m_deepestSection; + std::vector > m_sectionStack; + + }; + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED diff --git a/include/reporters/catch_reporter_console.hpp b/include/reporters/catch_reporter_console.hpp index 17b07a7f..60ada648 100644 --- a/include/reporters/catch_reporter_console.hpp +++ b/include/reporters/catch_reporter_console.hpp @@ -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" diff --git a/include/reporters/catch_reporter_junit.hpp b/include/reporters/catch_reporter_junit.hpp index c9cf9293..db12635b 100644 --- a/include/reporters/catch_reporter_junit.hpp +++ b/include/reporters/catch_reporter_junit.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" diff --git a/include/reporters/catch_reporter_xml.hpp b/include/reporters/catch_reporter_xml.hpp index 4c8095e0..11ecd910 100644 --- a/include/reporters/catch_reporter_xml.hpp +++ b/include/reporters/catch_reporter_xml.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" diff --git a/projects/SelfTest/SurrogateCpps/catch_debugger.cpp b/projects/SelfTest/SurrogateCpps/catch_debugger.cpp index f6b39f5e..33f76ae6 100644 --- a/projects/SelfTest/SurrogateCpps/catch_debugger.cpp +++ b/projects/SelfTest/SurrogateCpps/catch_debugger.cpp @@ -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" diff --git a/projects/SelfTest/SurrogateCpps/catch_stream.cpp b/projects/SelfTest/SurrogateCpps/catch_stream.cpp index 43458dec..9911aec6 100644 --- a/projects/SelfTest/SurrogateCpps/catch_stream.cpp +++ b/projects/SelfTest/SurrogateCpps/catch_stream.cpp @@ -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" diff --git a/projects/SelfTest/SurrogateCpps/catch_tags.cpp b/projects/SelfTest/SurrogateCpps/catch_tags.cpp index 63d15406..36e8789b 100644 --- a/projects/SelfTest/SurrogateCpps/catch_tags.cpp +++ b/projects/SelfTest/SurrogateCpps/catch_tags.cpp @@ -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" diff --git a/projects/XCode4/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj b/projects/XCode4/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj index 30b0b29e..c6a13fb8 100644 --- a/projects/XCode4/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj +++ b/projects/XCode4/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj @@ -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 = ""; }; + 261488FB184C83EA0041FBEB /* catch_tags.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_tags.h; sourceTree = ""; }; + 261488FC184D1DC10041FBEB /* catch_stream.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_stream.h; sourceTree = ""; }; + 261488FD184D21290041FBEB /* catch_section_info.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_section_info.h; sourceTree = ""; }; + 261488FE184DC32F0041FBEB /* catch_section.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_section.h; sourceTree = ""; }; + 261488FF184DC4A20041FBEB /* catch_debugger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_debugger.h; sourceTree = ""; }; + 262E7399184673A800CAC268 /* catch_reporter_bases.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_bases.hpp; sourceTree = ""; }; + 262E739A1846759000CAC268 /* catch_common.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_common.hpp; sourceTree = ""; }; 263FD06017AF8DF200988A20 /* catch_timer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_timer.hpp; sourceTree = ""; }; 263FD06117AF8DF200988A20 /* catch_timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_timer.h; sourceTree = ""; }; 266B06B616F3A60A004ED264 /* VariadicMacrosTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VariadicMacrosTests.cpp; path = ../../../SelfTest/VariadicMacrosTests.cpp; sourceTree = ""; }; @@ -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 = ""; @@ -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 = ""; @@ -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 = ""; diff --git a/scripts/generateSingleHeader.py b/scripts/generateSingleHeader.py index ba4c5cde..0f7aa9ed 100644 --- a/scripts/generateSingleHeader.py +++ b/scripts/generateSingleHeader.py @@ -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):