diff options
Diffstat (limited to 'test/unit/catch.hpp')
-rw-r--r-- | test/unit/catch.hpp | 953 |
1 files changed, 398 insertions, 555 deletions
diff --git a/test/unit/catch.hpp b/test/unit/catch.hpp index 03665c43f..a8aec02d6 100644 --- a/test/unit/catch.hpp +++ b/test/unit/catch.hpp @@ -1,6 +1,6 @@ /* - * CATCH v1.0 build 43 (master branch) - * Generated: 2014-05-04 09:22:51.466832 + * CATCH v1.0 build 47 (master branch) + * Generated: 2014-05-20 19:02:15.946806 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -13,6 +13,10 @@ #define TWOBLUECUBES_CATCH_HPP_INCLUDED +// #included from: internal/catch_suppress_warnings.h + +#define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED + #ifdef __clang__ #pragma clang diagnostic ignored "-Wglobal-constructors" #pragma clang diagnostic ignored "-Wvariadic-macros" @@ -265,6 +269,7 @@ namespace Catch { { public: NotImplementedException( SourceLineInfo const& lineInfo ); + NotImplementedException( NotImplementedException const& ) {} virtual ~NotImplementedException() CATCH_NOEXCEPT {} @@ -408,8 +413,8 @@ namespace Catch { { virtual ~IContext(); - virtual IResultCapture& getResultCapture() = 0; - virtual IRunner& getRunner() = 0; + virtual IResultCapture* getResultCapture() = 0; + virtual IRunner* getRunner() = 0; virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; virtual bool advanceGeneratorsForCurrentTest() = 0; virtual Ptr<IConfig const> getConfig() const = 0; @@ -440,7 +445,7 @@ namespace Catch { namespace Catch { - class TestCaseFilters; + class TestSpec; struct ITestCase : IShared { virtual void invoke () const = 0; @@ -454,8 +459,7 @@ namespace Catch { struct ITestCaseRegistry { virtual ~ITestCaseRegistry(); virtual std::vector<TestCase> const& getAllTests() const = 0; - virtual void getFilteredTests( TestCaseFilters const& filters, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const = 0; - virtual void getFilteredTests( IConfig const& config, std::vector<TestCase>& matchingTestCases ) const = 0; + virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const = 0; }; } @@ -729,25 +733,25 @@ namespace Detail { enum Arch { Big, Little }; static Arch which() { - union { + union _{ int asInt; char asChar[sizeof (int)]; - }; + } u; - asInt = 1; - return ( asChar[sizeof(int)-1] == 1 ) ? Big : Little; + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; } }; // Writes the raw memory into a string, considering endianness template<typename T> std::string rawMemoryToString( T value ) { - union { + union _ { T typedValue; unsigned char bytes[sizeof(T)]; - }; + } u; - typedValue = value; + u.typedValue = value; std::ostringstream oss; oss << "0x"; @@ -758,7 +762,7 @@ namespace Detail { end = inc = -1; } for( ; i != end; i += inc ) - oss << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)bytes[i]; + oss << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)u.bytes[i]; return oss.str(); } @@ -1359,6 +1363,7 @@ namespace Catch { class ScopedMessage { public: ScopedMessage( MessageBuilder const& builder ); + ScopedMessage( ScopedMessage const& other ); ~ScopedMessage(); MessageInfo m_info; @@ -1513,7 +1518,7 @@ namespace Catch { Never }; }; - class TestCaseFilters; + class TestSpec; struct IConfig : IShared { @@ -1528,7 +1533,7 @@ namespace Catch { virtual int abortAfter() const = 0; virtual bool showInvisibles() const = 0; virtual ShowDurations::OrNot showDurations() const = 0; - virtual std::vector<TestCaseFilters> const& filters() const = 0; + virtual TestSpec const& testSpec() const = 0; }; } @@ -1537,7 +1542,10 @@ namespace Catch { namespace Catch { inline IResultCapture& getResultCapture() { - return getCurrentContext().getResultCapture(); + if( IResultCapture* capture = getCurrentContext().getResultCapture() ) + return *capture; + else + throw std::logic_error( "No result capture instance" ); } template<typename MatcherT> @@ -2407,13 +2415,14 @@ namespace Catch { std::string className; std::string description; std::set<std::string> tags; + std::set<std::string> lcaseTags; std::string tagsAsString; SourceLineInfo lineInfo; bool isHidden; bool throws; }; - class TestCase : protected TestCaseInfo { + class TestCase : public TestCaseInfo { public: TestCase( ITestCase* testCase, TestCaseInfo const& info ); @@ -2427,9 +2436,6 @@ namespace Catch { bool isHidden() const; bool throws() const; - bool hasTag( std::string const& tag ) const; - bool matchesTags( std::string const& tagPattern ) const; - std::set<std::string> const& getTags() const; void swap( TestCase& other ); bool operator == ( TestCase const& other ) const; @@ -2678,158 +2684,224 @@ return @ desc; \ // #included from: catch_config.hpp #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED -// #included from: catch_test_spec.h -#define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED - -// #included from: catch_tags.h -#define TWOBLUECUBES_CATCH_TAGS_H_INCLUDED - -#include <string> -#include <set> -#include <map> -#include <vector> +// #included from: catch_test_spec_parser.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED #ifdef __clang__ +#pragma clang diagnostic push #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&); +// #included from: catch_test_spec.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED - std::set<std::string>& m_tags; - std::string m_remainder; - }; +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif - class Tag { - public: - Tag(); - Tag( std::string const& name, bool isNegated ); - std::string getName() const; - bool isNegated() const; - bool operator ! () const; +#include <string> +#include <vector> - private: - std::string m_name; - bool m_isNegated; - }; +namespace Catch { - 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; + class TestSpec { + struct Pattern : SharedImpl<> { + virtual ~Pattern(); + virtual bool matches( TestCaseInfo const& testCase ) const = 0; + }; + class NamePattern : public Pattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; - private: - TagMap m_tags; - }; + public: + NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) { + if( startsWith( m_name, "*" ) ) { + m_name = m_name.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_name, "*" ) ) { + m_name = m_name.substr( 0, m_name.size()-1 ); + m_wildcard = (WildcardPosition)( m_wildcard | WildcardAtEnd ); + } + } + virtual ~NamePattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_name == toLower( testCase.name ); + case WildcardAtStart: + return endsWith( toLower( testCase.name ), m_name ); + case WildcardAtEnd: + return startsWith( toLower( testCase.name ), m_name ); + case WildcardAtBothEnds: + return contains( toLower( testCase.name ), m_name ); + } - class TagExpression { - public: - bool matches( std::set<std::string> const& tags ) const; +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string m_name; + WildcardPosition m_wildcard; + }; + class TagPattern : public Pattern { + public: + TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + virtual ~TagPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); + } + private: + std::string m_tag; + }; + class ExcludedPattern : public Pattern { + public: + ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + virtual ~ExcludedPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + private: + Ptr<Pattern> m_underlyingPattern; + }; - private: - friend class TagExpressionParser; + struct Filter { + std::vector<Ptr<Pattern> > m_patterns; - std::vector<TagSet> m_tagSets; - }; + bool matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) + if( !(*it)->matches( testCase ) ) + return false; + return true; + } + }; - class TagExpressionParser : public TagParser { public: - TagExpressionParser( TagExpression& exp ); - ~TagExpressionParser(); + bool hasFilters() const { + return !m_filters.empty(); + } + bool matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) + if( it->matches( testCase ) ) + return true; + return false; + } private: - virtual void acceptTag( std::string const& tag ); - virtual void acceptChar( char c ); - virtual void endParse(); - - TagExpressionParser& operator=(TagExpressionParser const&); + std::vector<Filter> m_filters; - bool m_isNegated; - TagSet m_currentTagSet; - TagExpression& m_exp; + friend class TestSpecParser; }; +} -} // end namespace Catch - -#include <string> -#include <vector> +#ifdef __clang__ +#pragma clang diagnostic pop +#endif namespace Catch { - class TestCase; - - struct IfFilterMatches{ enum DoWhat { - AutoDetectBehaviour, - IncludeTests, - ExcludeTests - }; }; - - class TestCaseFilter { - enum WildcardPosition { - NoWildcard = 0, - WildcardAtStart = 1, - WildcardAtEnd = 2, - WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd - }; + class TestSpecParser { + enum Mode{ None, Name, QuotedName, Tag }; + Mode m_mode; + bool m_exclusion; + std::size_t m_start, m_pos; + std::string m_arg; + TestSpec::Filter m_currentFilter; + TestSpec m_testSpec; public: - TestCaseFilter( std::string const& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::AutoDetectBehaviour ); - - IfFilterMatches::DoWhat getFilterType() const; - bool shouldInclude( TestCase const& testCase ) const; - + TestSpecParser parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = arg; + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) + visitChar( m_arg[m_pos] ); + if( m_mode == Name ) + addPattern<TestSpec::NamePattern>(); + return *this; + } + TestSpec testSpec() { + addFilter(); + return m_testSpec; + } private: - bool isMatch( TestCase const& testCase ) const; - - std::string m_stringToMatch; - IfFilterMatches::DoWhat m_filterType; - WildcardPosition m_wildcardPosition; + void visitChar( char c ) { + if( m_mode == None ) { + switch( c ) { + case ' ': return; + case '~': m_exclusion = true; return; + case '[': return startNewMode( Tag, ++m_pos ); + case '"': return startNewMode( QuotedName, ++m_pos ); + default: startNewMode( Name, m_pos ); break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern<TestSpec::NamePattern>(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern<TestSpec::NamePattern>(); + startNewMode( Tag, ++m_pos ); + } + } + else if( m_mode == QuotedName && c == '"' ) + addPattern<TestSpec::NamePattern>(); + else if( m_mode == Tag && c == ']' ) + addPattern<TestSpec::TagPattern>(); + } + void startNewMode( Mode mode, std::size_t start ) { + m_mode = mode; + m_start = start; + } + std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + template<typename T> + void addPattern() { + std::string token = subString(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + Ptr<TestSpec::Pattern> pattern = new T( token ); + if( m_exclusion ) + pattern = new TestSpec::ExcludedPattern( pattern ); + m_currentFilter.m_patterns.push_back( pattern ); + } + m_exclusion = false; + m_mode = None; + } + void addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } }; + inline TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser().parse( arg ).testSpec(); + } - class TestCaseFilters { - public: - TestCaseFilters( std::string const& name ); - std::string getName() const; - void addFilter( TestCaseFilter const& filter ); - void addTags( std::string const& tagPattern ); - bool shouldInclude( TestCase const& testCase ) const; - - private: - std::vector<TagExpression> m_tagExpressions; - std::vector<TestCaseFilter> m_inclusionFilters; - std::vector<TestCaseFilter> m_exclusionFilters; - std::string m_name; - }; +} // namespace Catch -} +#ifdef __clang__ +#pragma clang diagnostic pop +#endif // #included from: catch_stream.h #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED @@ -2925,21 +2997,10 @@ namespace Catch { m_os( std::cout.rdbuf() ) { if( !data.testsOrTags.empty() ) { - std::string groupName; - for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) { - if( i != 0 ) - groupName += " "; - groupName += data.testsOrTags[i]; - } - TestCaseFilters filters( groupName ); - for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) { - std::string filter = data.testsOrTags[i]; - if( startsWith( filter, "[" ) || startsWith( filter, "~[" ) ) - filters.addTags( filter ); - else - filters.addFilter( TestCaseFilter( filter ) ); - } - m_filterSets.push_back( filters ); + TestSpecParser parser; + for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) + parser.parse( data.testsOrTags[i] ); + m_testSpec = parser.testSpec(); } } @@ -2961,13 +3022,9 @@ namespace Catch { bool listTags() const { return m_data.listTags; } bool listReporters() const { return m_data.listReporters; } - std::string getProcessName() const { - return m_data.processName; - } + std::string getProcessName() const { return m_data.processName; } - bool shouldDebugBreak() const { - return m_data.shouldDebugBreak; - } + bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } void setStreamBuf( std::streambuf* buf ) { m_os.rdbuf( buf ? buf : std::cout.rdbuf() ); @@ -2982,19 +3039,9 @@ namespace Catch { std::string getReporterName() const { return m_data.reporterName; } - void addTestSpec( std::string const& testSpec ) { - TestCaseFilters filters( testSpec ); - filters.addFilter( TestCaseFilter( testSpec ) ); - m_filterSets.push_back( filters ); - } + int abortAfter() const { return m_data.abortAfter; } - int abortAfter() const { - return m_data.abortAfter; - } - - std::vector<TestCaseFilters> const& filters() const { - return m_filterSets; - } + TestSpec const& testSpec() const { return m_testSpec; } bool showHelp() const { return m_data.showHelp; } bool showInvisibles() const { return m_data.showInvisibles; } @@ -3012,7 +3059,7 @@ namespace Catch { Stream m_stream; mutable std::ostream m_os; - std::vector<TestCaseFilters> m_filterSets; + TestSpec m_testSpec; }; } // end namespace Catch @@ -3922,7 +3969,7 @@ namespace Catch { while( std::getline( f, line ) ) { line = trim(line); if( !line.empty() && !startsWith( line, "#" ) ) - addTestOrTags( config, line ); + addTestOrTags( config, "\"" + line + "\"," ); } } @@ -4233,6 +4280,7 @@ namespace Catch { static void use( Code _colourCode ); private: + Colour( Colour const& other ); static Detail::IColourImpl* impl(); }; @@ -4554,10 +4602,14 @@ namespace Catch namespace Catch { inline std::size_t listTests( Config const& config ) { - if( config.filters().empty() ) - std::cout << "All available test cases:\n"; - else + + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) std::cout << "Matching test cases:\n"; + else { + std::cout << "All available test cases:\n"; + testSpec = TestSpecParser().parse( "*" ).testSpec(); + } std::size_t matchedTests = 0; TextAttributes nameAttr, tagsAttr; @@ -4565,7 +4617,7 @@ namespace Catch { tagsAttr.setIndent( 6 ); std::vector<TestCase> matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( config, matchedTestCases ); + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { @@ -4581,7 +4633,7 @@ namespace Catch { std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; } - if( config.filters().empty() ) + if( !config.testSpec().hasFilters() ) std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl; else std::cout << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; @@ -4589,9 +4641,12 @@ namespace Catch { } inline std::size_t listTestsNamesOnly( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( !config.testSpec().hasFilters() ) + testSpec = TestSpecParser().parse( "*" ).testSpec(); std::size_t matchedTests = 0; std::vector<TestCase> matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( config, matchedTestCases ); + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { @@ -4602,16 +4657,37 @@ namespace Catch { return matchedTests; } + struct TagInfo { + TagInfo() : count ( 0 ) {} + void add( std::string const& spelling ) { + ++count; + spellings.insert( spelling ); + } + std::string all() const { + std::string out; + for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end(); + it != itEnd; + ++it ) + out += "[" + *it + "]"; + return out; + } + std::set<std::string> spellings; + std::size_t count; + }; + inline std::size_t listTags( Config const& config ) { - if( config.filters().empty() ) + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + std::cout << "Tags for matching test cases:\n"; + else { std::cout << "All available tags:\n"; - else - std::cout << "Matching tags:\n"; + testSpec = TestSpecParser().parse( "*" ).testSpec(); + } - std::map<std::string, int> tagCounts; + std::map<std::string, TagInfo> tagCounts; std::vector<TestCase> matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( config, matchedTestCases ); + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { @@ -4620,24 +4696,24 @@ namespace Catch { tagIt != tagItEnd; ++tagIt ) { std::string tagName = *tagIt; - std::map<std::string, int>::iterator countIt = tagCounts.find( tagName ); + std::string lcaseTagName = toLower( tagName ); + std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName ); if( countIt == tagCounts.end() ) - tagCounts.insert( std::make_pair( tagName, 1 ) ); - else - countIt->second++; + countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; + countIt->second.add( tagName ); } } - for( std::map<std::string, int>::const_iterator countIt = tagCounts.begin(), - countItEnd = tagCounts.end(); + for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(), + countItEnd = tagCounts.end(); countIt != countItEnd; ++countIt ) { std::ostringstream oss; - oss << " " << countIt->second << " "; - Text wrapper( "[" + countIt->first + "]", TextAttributes() - .setInitialIndent( 0 ) - .setIndent( oss.str().size() ) - .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); + oss << " " << std::setw(2) << countIt->second.count << " "; + Text wrapper( countIt->second.all(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( oss.str().size() ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); std::cout << oss.str() << wrapper << "\n"; } std::cout << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; @@ -4863,8 +4939,8 @@ namespace Catch { m_activeTestCase( NULL ), m_config( config ), m_reporter( reporter ), - m_prevRunner( &m_context.getRunner() ), - m_prevResultCapture( &m_context.getResultCapture() ), + m_prevRunner( m_context.getRunner() ), + m_prevResultCapture( m_context.getResultCapture() ), m_prevConfig( m_context.getConfig() ) { m_context.setRunner( this ); @@ -5163,28 +5239,18 @@ namespace Catch { Totals runTests() { - std::vector<TestCaseFilters> filterGroups = m_config->filters(); - if( filterGroups.empty() ) { - TestCaseFilters filterGroup( "" ); - filterGroups.push_back( filterGroup ); - } - RunContext context( m_config.get(), m_reporter ); Totals totals; - for( std::size_t i=0; i < filterGroups.size() && !context.aborting(); ++i ) { - context.testGroupStarting( filterGroups[i].getName(), i, filterGroups.size() ); - totals += runTestsForGroup( context, filterGroups[i] ); - context.testGroupEnded( filterGroups[i].getName(), totals, i, filterGroups.size() ); - } - return totals; - } - Totals runTestsForGroup( RunContext& context, TestCaseFilters const& filterGroup ) { - Totals totals; + context.testGroupStarting( "", 1, 1 ); // deprecated? + + TestSpec testSpec = m_config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser().parse( "~[.]" ).testSpec(); // All not hidden tests std::vector<TestCase> testCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( filterGroup, *m_config, testCases ); + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases ); int testsRunForGroup = 0; for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end(); @@ -5200,8 +5266,7 @@ namespace Catch { m_testsAlreadyRun.insert( *it ); } } - if( testsRunForGroup == 0 && !filterGroup.getName().empty() ) - m_reporter->noMatchingTestCases( filterGroup.getName() ); + context.testGroupEnded( "", totals, 1, 1 ); return totals; } @@ -5403,25 +5468,15 @@ namespace Catch { return m_nonHiddenFunctions; } - virtual void getFilteredTests( TestCaseFilters const& filters, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const { + virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const { for( std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin(), itEnd = m_functionsInOrder.end(); it != itEnd; ++it ) { - if( filters.shouldInclude( *it ) && ( config.allowThrows() || !it->throws() ) ) + if( testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() ) ) matchingTestCases.push_back( *it ); } } - virtual void getFilteredTests( IConfig const& config, std::vector<TestCase>& matchingTestCases ) const { - if( config.filters().empty() ) - return getFilteredTests( TestCaseFilters( "empty" ), config, matchingTestCases ); - - for( std::vector<TestCaseFilters>::const_iterator it = config.filters().begin(), - itEnd = config.filters().end(); - it != itEnd; - ++it ) - getFilteredTests( *it, config, matchingTestCases ); - } private: @@ -5766,11 +5821,11 @@ namespace Catch { void operator=( Context const& ); public: // IContext - virtual IResultCapture& getResultCapture() { - return *m_resultCapture; + virtual IResultCapture* getResultCapture() { + return m_resultCapture; } - virtual IRunner& getRunner() { - return *m_runner; + virtual IRunner* getRunner() { + return m_runner; } virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { return getGeneratorsForCurrentTest() @@ -5801,7 +5856,7 @@ namespace Catch { private: IGeneratorsForTest* findGeneratorsForCurrentTest() { - std::string testName = getResultCapture().getCurrentTestName(); + std::string testName = getResultCapture()->getCurrentTestName(); std::map<std::string, IGeneratorsForTest*>::const_iterator it = m_generatorsByTestName.find( testName ); @@ -5813,7 +5868,7 @@ namespace Catch { IGeneratorsForTest& getGeneratorsForCurrentTest() { IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); if( !generators ) { - std::string testName = getResultCapture().getCurrentTestName(); + std::string testName = getResultCapture()->getCurrentTestName(); generators = createGeneratorsForTest(); m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); } @@ -6265,6 +6320,21 @@ namespace Catch { inline bool isReservedTag( std::string const& tag ) { return !isSpecialTag( tag ) && tag.size() > 0 && !isalnum( tag[0] ); } + inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + if( isReservedTag( tag ) ) { + { + Colour colourGuard( Colour::Red ); + std::cerr + << "Tag name [" << tag << "] not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n"; + } + { + Colour colourGuard( Colour::FileName ); + std::cerr << _lineInfo << std::endl; + } + exit(1); + } + } TestCase makeTestCase( ITestCase* _testCase, std::string const& _className, @@ -6272,34 +6342,40 @@ namespace Catch { std::string const& _descOrTags, SourceLineInfo const& _lineInfo ) { - std::string desc = _descOrTags; bool isHidden( startsWith( _name, "./" ) ); // Legacy support + + // Parse out tags std::set<std::string> tags; - TagExtracter( tags ).parse( desc ); - for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); - it != itEnd; - ++it ) - if( isReservedTag( *it ) ) { - { - Colour colourGuard( Colour::Red ); - std::cerr - << "Tag name [" << *it << "] not allowed.\n" - << "Tag names starting with non alpha-numeric characters are reserved\n"; - } - { - Colour colourGuard( Colour::FileName ); - std::cerr << _lineInfo << std::endl; - } - exit(1); + std::string desc, tag; + bool inTag = false; + for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { + char c = _descOrTags[i]; + if( !inTag ) { + if( c == '[' ) + inTag = true; + else + desc += c; } + else { + if( c == ']' ) { + enforceNotReservedTag( tag, _lineInfo ); - if( tags.find( "hide" ) != tags.end() || tags.find( "." ) != tags.end() ) - isHidden = true; - + inTag = false; + if( tag == "hide" || tag == "." ) + isHidden = true; + else + tags.insert( tag ); + tag.clear(); + } + else + tag += c; + } + } if( isHidden ) { tags.insert( "hide" ); tags.insert( "." ); } + TestCaseInfo info( _name, _className, desc, tags, isHidden, _lineInfo ); return TestCase( _testCase, info ); } @@ -6323,6 +6399,7 @@ namespace Catch { oss << "[" << *it << "]"; if( *it == "!throws" ) throws = true; + lcaseTags.insert( toLower( *it ) ); } tagsAsString = oss.str(); } @@ -6332,6 +6409,7 @@ namespace Catch { className( other.className ), description( other.description ), tags( other.tags ), + lcaseTags( other.lcaseTags ), tagsAsString( other.tagsAsString ), lineInfo( other.lineInfo ), isHidden( other.isHidden ), @@ -6351,6 +6429,19 @@ namespace Catch { return other; } + void TestCase::swap( TestCase& other ) { + test.swap( other.test ); + name.swap( other.name ); + className.swap( other.className ); + description.swap( other.description ); + tags.swap( other.tags ); + lcaseTags.swap( other.lcaseTags ); + tagsAsString.swap( other.tagsAsString ); + std::swap( TestCaseInfo::isHidden, static_cast<TestCaseInfo&>( other ).isHidden ); + std::swap( TestCaseInfo::throws, static_cast<TestCaseInfo&>( other ).throws ); + std::swap( lineInfo, other.lineInfo ); + } + void TestCase::invoke() const { test->invoke(); } @@ -6362,26 +6453,6 @@ namespace Catch { return TestCaseInfo::throws; } - bool TestCase::hasTag( std::string const& tag ) const { - return tags.find( toLower( tag ) ) != tags.end(); - } - bool TestCase::matchesTags( std::string const& tagPattern ) const { - TagExpression exp; - TagExpressionParser( exp ).parse( tagPattern ); - return exp.matches( tags ); - } - std::set<std::string> const& TestCase::getTags() const { - return tags; - } - - void TestCase::swap( TestCase& other ) { - test.swap( other.test ); - className.swap( other.className ); - name.swap( other.name ); - description.swap( other.description ); - std::swap( lineInfo, other.lineInfo ); - } - bool TestCase::operator == ( TestCase const& other ) const { return test.get() == other.test.get() && name == other.name && @@ -6404,259 +6475,13 @@ namespace Catch { } // end namespace Catch -// #included from: catch_tags.hpp -#define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED - -namespace Catch { - TagParser::~TagParser() {} - - void TagParser::parse( std::string const& str ) { - std::size_t pos = 0; - while( pos < str.size() ) { - char c = str[pos]; - if( c == '[' ) { - std::size_t end = str.find_first_of( ']', pos ); - if( end != std::string::npos ) { - acceptTag( str.substr( pos+1, end-pos-1 ) ); - pos = end+1; - } - else { - acceptChar( c ); - pos++; - } - } - else { - acceptChar( c ); - pos++; - } - } - endParse(); - } - - 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; - } - } - - void TagExpressionParser::endParse() { - if( !m_currentTagSet.empty() ) - m_exp.m_tagSets.push_back( m_currentTagSet ); - } - -} // end namespace Catch - -// #included from: catch_test_spec.hpp -#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED - -namespace Catch { - - 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; - } -} - // #included from: catch_version.hpp #define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED namespace Catch { // These numbers are maintained by a script - Version libraryVersion( 1, 0, 43, "master" ); + Version libraryVersion( 1, 0, 47, "master" ); } // #included from: catch_message.hpp @@ -6684,6 +6509,10 @@ namespace Catch { m_info.message = builder.m_stream.str(); getResultCapture().pushScopedMessage( m_info ); } + ScopedMessage::ScopedMessage( ScopedMessage const& other ) + : m_info( other.m_info ) + {} + ScopedMessage::~ScopedMessage() { getResultCapture().popScopedMessage( m_info ); } @@ -6949,14 +6778,14 @@ namespace Catch { std::string const& name, std::string const& description ) : m_info( name, description, lineInfo ), - m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( m_info, m_assertions ) ) + m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) { m_timer.start(); } Section::~Section() { if( m_sectionIncluded ) - getCurrentContext().getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() ); + getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() ); } // This indicates whether the section should be executed or not @@ -7262,12 +7091,12 @@ namespace Catch { struct BySectionInfo { BySectionInfo( SectionInfo const& other ) : m_other( other ) {} + BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} bool operator() ( Ptr<SectionNode> const& node ) const { return node->stats.sectionInfo.lineInfo == m_other.lineInfo; } private: - BySectionInfo& operator=( BySectionInfo const& other ); // = delete; - + void operator=( BySectionInfo const& ); SectionInfo const& m_other; }; @@ -7490,26 +7319,26 @@ namespace Catch { endElement(); } -# ifndef CATCH_CPP11_OR_GREATER - XmlWriter& operator = ( XmlWriter const& other ) { - XmlWriter temp( other ); - swap( temp ); - return *this; - } -# else - XmlWriter( XmlWriter const& ) = default; - XmlWriter( XmlWriter && ) = default; - XmlWriter& operator = ( XmlWriter const& ) = default; - XmlWriter& operator = ( XmlWriter && ) = default; -# endif - - void swap( XmlWriter& other ) { - std::swap( m_tagIsOpen, other.m_tagIsOpen ); - std::swap( m_needsNewline, other.m_needsNewline ); - std::swap( m_tags, other.m_tags ); - std::swap( m_indent, other.m_indent ); - std::swap( m_os, other.m_os ); - } +//# ifndef CATCH_CPP11_OR_GREATER +// XmlWriter& operator = ( XmlWriter const& other ) { +// XmlWriter temp( other ); +// swap( temp ); +// return *this; +// } +//# else +// XmlWriter( XmlWriter const& ) = default; +// XmlWriter( XmlWriter && ) = default; +// XmlWriter& operator = ( XmlWriter const& ) = default; +// XmlWriter& operator = ( XmlWriter && ) = default; +//# endif +// +// void swap( XmlWriter& other ) { +// std::swap( m_tagIsOpen, other.m_tagIsOpen ); +// std::swap( m_needsNewline, other.m_needsNewline ); +// std::swap( m_tags, other.m_tags ); +// std::swap( m_indent, other.m_indent ); +// std::swap( m_os, other.m_os ); +// } XmlWriter& startElement( std::string const& name ) { ensureTagClosed(); @@ -7587,7 +7416,13 @@ namespace Catch { return *this; } + void setStream( std::ostream& os ) { + m_os = &os; + } + private: + XmlWriter( XmlWriter const& ); + void operator=( XmlWriter const& ); std::ostream& stream() { return *m_os; @@ -7656,7 +7491,7 @@ namespace Catch { } virtual void StartTesting() { - m_xml = XmlWriter( m_config.stream() ); + m_xml.setStream( m_config.stream() ); m_xml.startElement( "Catch" ); if( !m_config.fullConfig()->name().empty() ) m_xml.writeAttribute( "name", m_config.fullConfig()->name() ); @@ -8510,7 +8345,7 @@ namespace Catch { private: // Colour::LightGrey - static Colour dimColour() { return Colour::FileName; } + static Colour::Code dimColour() { return Colour::FileName; } #ifdef CATCH_PLATFORM_MAC static const char* failedString() { return "FAILED"; } @@ -8525,7 +8360,7 @@ namespace Catch { stream << result.getSourceInfo() << ":"; } - void printResultType( Colour colour, std::string passOrFail ) const { + void printResultType( Colour::Code colour, std::string passOrFail ) const { if( !passOrFail.empty() ) { { Colour colourGuard( colour ); @@ -8573,7 +8408,7 @@ namespace Catch { } } - void printRemainingMessages( Colour colour = dimColour() ) { + void printRemainingMessages( Colour::Code colour = dimColour() ) { if ( itMessage == messages.end() ) return; @@ -8695,6 +8530,10 @@ namespace Catch { FreeFunctionTestCase::~FreeFunctionTestCase() {} IGeneratorInfo::~IGeneratorInfo() {} IGeneratorsForTest::~IGeneratorsForTest() {} + TestSpec::Pattern::~Pattern() {} + TestSpec::NamePattern::~NamePattern() {} + TestSpec::TagPattern::~TagPattern() {} + TestSpec::ExcludedPattern::~ExcludedPattern() {} Matchers::Impl::StdString::Equals::~Equals() {} Matchers::Impl::StdString::Contains::~Contains() {} @@ -8883,6 +8722,10 @@ int main (int argc, char * const argv[]) { using Catch::Detail::Approx; +// #included from: internal/catch_reenable_warnings.h + +#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED + #ifdef __clang__ #pragma clang diagnostic pop #endif |