diff --git a/single_include/catch.hpp b/single_include/catch.hpp index ba9a0797..656b3d89 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,5 +1,5 @@ /* - * Generated: 2012-09-15 17:50:31.695760 + * Generated: 2012-09-24 08:29:47.663979 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -1311,8 +1311,8 @@ public: return *this; } - std::string getInfo () const { - return m_oss.str(); + ResultInfo getInfo () const { + return ResultInfo( "", ResultWas::Info, false, SourceLineInfo(), "SCOPED_INFO", m_oss.str().c_str() ); } private: @@ -1668,6 +1668,7 @@ namespace Catch { const SourceLineInfo& getLineInfo() const; bool isHidden() const; bool hasTag( const std::string& tag ) const; + bool matchesTags( const std::string& tagPattern ) const; const std::set& tags() const; void swap( TestCaseInfo& other ); @@ -2007,10 +2008,20 @@ namespace Catch fullConfig( _fullConfig ) {} + ReporterConfig( const ReporterConfig& other ) + : name( other.name ), + stream( other.stream ), + includeSuccessfulResults( other.includeSuccessfulResults ), + fullConfig( other.fullConfig ) + {} + std::string name; std::ostream& stream; bool includeSuccessfulResults; ConfigData fullConfig; + + private: + void operator=(const ReporterConfig&); }; class TestCaseInfo; @@ -2754,7 +2765,7 @@ namespace Catch { "\n" "If spec is prefixed with exclude: or the ~ character then the pattern matches an exclusion. " "This means that tests matching the pattern are excluded from the set - even if a prior " - "inclusion spec included them. Subsequent inclusion specs will take precendence, however. " + "inclusion spec included them. Subsequent inclusion specs will take precedence, however. " "Inclusions and exclusions are evaluated in left-to-right order.\n" "\n" "Examples:\n" @@ -2783,6 +2794,41 @@ namespace Catch { } }; + class TagOptionParser : public OptionParser { + public: + TagOptionParser() : OptionParser( 1, -1 ) { + m_optionNames.push_back( "-g" ); + m_optionNames.push_back( "--tag" ); + } + virtual std::string argsSynopsis() const { + return " [,...]"; + } + virtual std::string optionSummary() const { + return "Matches test cases against tags or tag patterns"; + } + + // Lines are split at the nearest prior space char to the 80 char column. + // Tab chars are removed from the output but their positions are used to align + // subsequently wrapped lines + virtual std::string optionDescription() const { + return + "!TBD"; + } + + virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) { +// std::string groupName; +// for( std::size_t i = 0; i < cmd.argsCount(); ++i ) { +// if( i != 0 ) +// groupName += " "; +// groupName += cmd[i]; +// } +// TestCaseFilters filters( groupName ); +// for( std::size_t i = 0; i < cmd.argsCount(); ++i ) +// filters.addFilter( TestCaseFilter( cmd[i] ) ); +// config.filters.push_back( filters ); + } + }; + class ListOptionParser : public OptionParser { public: ListOptionParser() : OptionParser( 0, 2 ) { @@ -2888,9 +2934,9 @@ namespace Catch { virtual std::string optionDescription() const { return "Use this option to send all output to a file or a stream. By default output is " - "sent to stdout (note that uses ofstdout and stderr from within test cases are " + "sent to stdout (note that uses of stdout and stderr from within test cases are " "redirected and included in the report - so even stderr will effectively end up " - "on stdout). If the name begins with % it is interpretted as a stream. " + "on stdout). If the name begins with % it is interpreted as a stream. " "Otherwise it is treated as a filename.\n" "\n" "Examples are:\n" @@ -2926,7 +2972,7 @@ namespace Catch { return "Usually you only want to see reporting for failed tests. Sometimes it's useful " "to see all the output (especially when you don't trust that that test you just " - "added worked first time!). To see successul, as well as failing, test results " + "added worked first time!). To see successful, as well as failing, test results " "just pass this option."; } virtual void parseIntoConfig( const Command&, ConfigData& config ) { @@ -3540,10 +3586,18 @@ namespace Catch { else if( !result.ok() ) { m_totals.assertions.failed++; - std::vector::const_iterator it = m_info.begin(); - std::vector::const_iterator itEnd = m_info.end(); - for(; it != itEnd; ++it ) - m_reporter->Result( *it ); + { + std::vector::const_iterator it = m_scopedInfos.begin(); + std::vector::const_iterator itEnd = m_scopedInfos.end(); + for(; it != itEnd; ++it ) + m_reporter->Result( (*it)->getInfo() ); + } + { + std::vector::const_iterator it = m_info.begin(); + std::vector::const_iterator itEnd = m_info.end(); + for(; it != itEnd; ++it ) + m_reporter->Result( *it ); + } m_info.clear(); } @@ -3801,6 +3855,7 @@ namespace Catch { // Handle list request if( config.listSpec != List::None ) { List( config ); + Catch::cleanUp(); return 0; } @@ -4744,38 +4799,197 @@ namespace Catch { // #included from: catch_test_case_info.hpp #define TWOBLUECUBES_CATCH_TESTCASEINFO_HPP_INCLUDED -namespace Catch { +// #included from: catch_tags.hpp +#define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED - namespace { - void extractTags( std::string& str, std::set& tags ) { - std::string remainder; - std::size_t last = 0; - std::size_t begin = str.find_first_of( '[' ); - while( begin != std::string::npos ) { - std::size_t end = str.find_first_of( ']', begin ); - if( end != std::string::npos ) { - std::string tag = str.substr( begin+1, end-begin-1 ); - tags.insert( tag ); - if( begin - last > 0 ) - remainder += str.substr( last, begin-last ); - last = end+1; - } - else if( begin != str.size()-1 ) { - end = begin+1; +#include +#include +#include +#include + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + class TagParser { + public: + virtual ~TagParser(); + + void parse( const std::string& 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 { - break; + acceptChar( c ); + pos++; } - begin = str.find_first_of( '[', end ); } - if( !tags.empty() ) { - if( last < str.size() ) - str = remainder + str.substr( last ); - else - str = remainder; + endParse(); + } + + protected: + virtual void acceptTag( const std::string& 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( const std::string& tag ) { + m_tags.insert( tag ); + } + virtual void acceptChar( char c ) { + m_remainder += c; + } + + std::set& m_tags; + std::string m_remainder; + }; + + class Tag + { + public: + Tag() + : m_isNegated( false ) + {} + + Tag( const std::string& 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( const Tag& tag ) { + m_tags.insert( std::make_pair( tag.getName(), tag ) ); + } + + // needed? + Tag find( const std::string& name ) const { + TagMap::const_iterator it = m_tags.find( name ); + if( it == m_tags.end() ) + return Tag(); + else + return it->second; + } + bool empty() const { + return m_tags.empty(); + } + + bool matches( const std::set& tags ) const { + TagMap::const_iterator it = m_tags.begin(); + TagMap::const_iterator itEnd = m_tags.end(); + for(; 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( const std::set& tags ) const { + std::vector::const_iterator it = m_tagSets.begin(); + std::vector::const_iterator itEnd = m_tagSets.end(); + for(; 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( const std::string& 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 ); + break; } } - } + virtual void endParse() { + if( !m_currentTagSet.empty() ) + m_exp.m_tagSets.push_back( m_currentTagSet ); + } + + bool m_isNegated; + TagSet m_currentTagSet; + TagExpression& m_exp; + }; + +} // end namespace Catch + +namespace Catch { + TestCaseInfo::TestCaseInfo( ITestCase* testCase, const char* name, const char* description, @@ -4786,7 +5000,7 @@ namespace Catch { m_lineInfo( lineInfo ), m_isHidden( startsWith( name, "./" ) ) { - extractTags( m_description, m_tags ); + TagExtracter( m_tags ).parse( m_description ); if( hasTag( "hide" ) ) m_isHidden = true; } @@ -4839,6 +5053,11 @@ namespace Catch { bool TestCaseInfo::hasTag( const std::string& tag ) const { return m_tags.find( tag ) != m_tags.end(); } + bool TestCaseInfo::matchesTags( const std::string& tagPattern ) const { + TagExpression exp; + TagExpressionParser( exp ).parse( tagPattern ); + return exp.matches( m_tags ); + } const std::set& TestCaseInfo::tags() const { return m_tags; } @@ -4862,7 +5081,8 @@ namespace Catch { swap( temp ); return *this; } -} + +} // end namespace Catch // #included from: ../reporters/catch_reporter_basic.hpp #define TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED @@ -5784,6 +6004,9 @@ namespace Catch { FreeFunctionTestCase::~FreeFunctionTestCase() {} IGeneratorInfo::~IGeneratorInfo() {} IGeneratorsForTest::~IGeneratorsForTest() {} + TagParser::~TagParser() {} + TagExtracter::~TagExtracter() {} + TagExpressionParser::~TagExpressionParser() {} void Config::dummy() {}