From 4c97fc5619d6fcef7b068a9ed428c54bce196b18 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 24 Aug 2012 08:23:50 +0100 Subject: [PATCH] WIldcards at both ends --- include/internal/catch_common.h | 25 +++++- include/internal/catch_list.hpp | 11 ++- include/internal/catch_test_spec.h | 41 +++++++--- include/reporters/catch_reporter_basic.hpp | 17 ---- projects/SelfTest/TestMain.cpp | 19 ++++- single_include/catch.hpp | 94 ++++++++++++++-------- 6 files changed, 141 insertions(+), 66 deletions(-) diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index 4a3567e5..49c5918e 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -78,7 +78,30 @@ namespace Catch { inline bool startsWith( const std::string& s, const std::string& prefix ) { return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; } - + inline bool endsWith( const std::string& s, const std::string& suffix ) { + return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; + } + inline bool contains( const std::string& s, const std::string& infix ) { + return s.find( infix ) != std::string::npos; + } + + struct pluralise { + pluralise( std::size_t count, const std::string& label ) + : m_count( count ), + m_label( label ) + {} + + friend std::ostream& operator << ( std::ostream& os, const pluralise& pluraliser ) { + os << pluraliser.m_count << " " << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << "s"; + return os; + } + + std::size_t m_count; + std::string m_label; + }; + struct SourceLineInfo { SourceLineInfo() : line( 0 ){} diff --git a/include/internal/catch_list.hpp b/include/internal/catch_list.hpp index d9c1200a..82586a1b 100644 --- a/include/internal/catch_list.hpp +++ b/include/internal/catch_list.hpp @@ -35,20 +35,25 @@ namespace Catch { if( config.listSpec & List::Tests ) { if( config.filters.empty() ) - std::cout << "All available tests:\n"; + std::cout << "All available test cases:\n"; else - std::cout << "Matching tests:\n"; + std::cout << "Matching test cases:\n"; std::vector::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin(); std::vector::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end(); + std::size_t matchedTests = 0; for(; it != itEnd; ++it ) { if( matchesFilters( config.filters, *it ) ) { + matchedTests++; // !TBD: consider listAs() std::cout << "\t" << it->getName() << "\n"; if( ( config.listSpec & List::TestNames ) != List::TestNames ) std::cout << "\t\t '" << it->getDescription() << "'\n"; } } - std::cout << std::endl; + if( config.filters.empty() ) + std::cout << pluralise( matchedTests, "test case" ) << std::endl; + else + std::cout << pluralise( matchedTests, "matching test case" ) << std::endl; } if( ( config.listSpec & List::All ) == 0 ) { diff --git a/include/internal/catch_test_spec.h b/include/internal/catch_test_spec.h index 909db165..1effad6f 100644 --- a/include/internal/catch_test_spec.h +++ b/include/internal/catch_test_spec.h @@ -18,15 +18,26 @@ namespace Catch { }; }; class TestCaseFilter { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + public: TestCaseFilter( const std::string& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::IncludeTests ) - : m_testSpec( testSpec ), + : m_stringToMatch( testSpec ), m_filterType( matchBehaviour ), - m_isWildcarded( false ) + m_wildcardPosition( NoWildcard ) { - if( m_testSpec[m_testSpec.size()-1] == '*' ) { - m_testSpec = m_testSpec.substr( 0, m_testSpec.size()-1 ); - m_isWildcarded = true; + if( m_stringToMatch[0] == '*' ) { + m_stringToMatch = m_stringToMatch.substr( 1 ); + m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtStart ); + } + if( m_stringToMatch[m_stringToMatch.size()-1] == '*' ) { + m_stringToMatch = m_stringToMatch.substr( 0, m_stringToMatch.size()-1 ); + m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtEnd ); } } @@ -41,15 +52,23 @@ namespace Catch { bool isMatch( const TestCaseInfo& testCase ) const { const std::string& name = testCase.getName(); - if( !m_isWildcarded ) - return m_testSpec == name; - else - return name.size() >= m_testSpec.size() && name.substr( 0, m_testSpec.size() ) == m_testSpec; + + 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 ); + } + } - std::string m_testSpec; + std::string m_stringToMatch; IfFilterMatches::DoWhat m_filterType; - bool m_isWildcarded; + WildcardPosition m_wildcardPosition; }; class TestCaseFilters { diff --git a/include/reporters/catch_reporter_basic.hpp b/include/reporters/catch_reporter_basic.hpp index 0e1edc1e..4cff4729 100644 --- a/include/reporters/catch_reporter_basic.hpp +++ b/include/reporters/catch_reporter_basic.hpp @@ -15,23 +15,6 @@ namespace Catch { - struct pluralise { - pluralise( std::size_t count, const std::string& label ) - : m_count( count ), - m_label( label ) - {} - - friend std::ostream& operator << ( std::ostream& os, const pluralise& pluraliser ) { - os << pluraliser.m_count << " " << pluraliser.m_label; - if( pluraliser.m_count != 1 ) - os << "s"; - return os; - } - - std::size_t m_count; - std::string m_label; - }; - class BasicReporter : public SharedImpl { struct SpanInfo { diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index 42185757..8760646a 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -251,7 +251,7 @@ TEST_CASE( "selftest/parser/2", "ConfigData" ) { } } -TEST_CASE( "selftest/test filter", "Groups of tests can be selected" ) { +TEST_CASE( "selftest/test filter", "Individual filters" ) { Catch::TestCaseFilter matchAny( "*" ); Catch::TestCaseFilter matchNone( "*", Catch::IfFilterMatches::ExcludeTests ); @@ -268,7 +268,7 @@ TEST_CASE( "selftest/test filter", "Groups of tests can be selected" ) { CHECK( matchNonHidden.shouldInclude( makeTestCase( "./any" ) ) == false ); } -TEST_CASE( "selftest/test filters", "Groups of tests can be selected" ) { +TEST_CASE( "selftest/test filters", "Sets of filters" ) { Catch::TestCaseFilter matchHidden( "./*" ); Catch::TestCaseFilter dontMatchA( "./a*", Catch::IfFilterMatches::ExcludeTests ); @@ -282,3 +282,18 @@ TEST_CASE( "selftest/test filters", "Groups of tests can be selected" ) { CHECK( filters.shouldInclude( makeTestCase( "./something" ) ) ); CHECK( filters.shouldInclude( makeTestCase( "./anything" ) ) == false ); } + +TEST_CASE( "selftest/filter/prefix wildcard", "Individual filters with wildcards at the start" ) { + Catch::TestCaseFilter matchBadgers( "*badger" ); + + CHECK( matchBadgers.shouldInclude( makeTestCase( "big badger" ) )); + CHECK( matchBadgers.shouldInclude( makeTestCase( "little badgers" ) ) == false ); +} +TEST_CASE( "selftest/filter/wildcard at both ends", "Individual filters with wildcards at both ends" ) { + Catch::TestCaseFilter matchBadgers( "*badger*" ); + + CHECK( matchBadgers.shouldInclude( makeTestCase( "big badger" ) )); + CHECK( matchBadgers.shouldInclude( makeTestCase( "little badgers" ) ) ); + CHECK( matchBadgers.shouldInclude( makeTestCase( "badgers are big" ) ) ); + CHECK( matchBadgers.shouldInclude( makeTestCase( "hedgehogs" ) ) == false ); +} diff --git a/single_include/catch.hpp b/single_include/catch.hpp index b4933e93..05ff852a 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,5 +1,5 @@ /* - * Generated: 2012-08-23 20:06:52.538506 + * Generated: 2012-08-24 08:23:10.017875 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -95,6 +95,29 @@ namespace Catch { inline bool startsWith( const std::string& s, const std::string& prefix ) { return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; } + inline bool endsWith( const std::string& s, const std::string& suffix ) { + return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; + } + inline bool contains( const std::string& s, const std::string& infix ) { + return s.find( infix ) != std::string::npos; + } + + struct pluralise { + pluralise( std::size_t count, const std::string& label ) + : m_count( count ), + m_label( label ) + {} + + friend std::ostream& operator << ( std::ostream& os, const pluralise& pluraliser ) { + os << pluraliser.m_count << " " << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << "s"; + return os; + } + + std::size_t m_count; + std::string m_label; + }; struct SourceLineInfo { @@ -2216,15 +2239,26 @@ namespace Catch { }; }; class TestCaseFilter { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + public: TestCaseFilter( const std::string& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::IncludeTests ) - : m_testSpec( testSpec ), + : m_stringToMatch( testSpec ), m_filterType( matchBehaviour ), - m_isWildcarded( false ) + m_wildcardPosition( NoWildcard ) { - if( m_testSpec[m_testSpec.size()-1] == '*' ) { - m_testSpec = m_testSpec.substr( 0, m_testSpec.size()-1 ); - m_isWildcarded = true; + if( m_stringToMatch[0] == '*' ) { + m_stringToMatch = m_stringToMatch.substr( 1 ); + m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtStart ); + } + if( m_stringToMatch[m_stringToMatch.size()-1] == '*' ) { + m_stringToMatch = m_stringToMatch.substr( 0, m_stringToMatch.size()-1 ); + m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtEnd ); } } @@ -2239,15 +2273,23 @@ namespace Catch { bool isMatch( const TestCaseInfo& testCase ) const { const std::string& name = testCase.getName(); - if( !m_isWildcarded ) - return m_testSpec == name; - else - return name.size() >= m_testSpec.size() && name.substr( 0, m_testSpec.size() ) == m_testSpec; + + 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 ); + } + } - std::string m_testSpec; + std::string m_stringToMatch; IfFilterMatches::DoWhat m_filterType; - bool m_isWildcarded; + WildcardPosition m_wildcardPosition; }; class TestCaseFilters { @@ -2643,20 +2685,25 @@ namespace Catch { if( config.listSpec & List::Tests ) { if( config.filters.empty() ) - std::cout << "All available tests:\n"; + std::cout << "All available test cases:\n"; else - std::cout << "Matching tests:\n"; + std::cout << "Matching test cases:\n"; std::vector::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin(); std::vector::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end(); + std::size_t matchedTests = 0; for(; it != itEnd; ++it ) { if( matchesFilters( config.filters, *it ) ) { + matchedTests++; // !TBD: consider listAs() std::cout << "\t" << it->getName() << "\n"; if( ( config.listSpec & List::TestNames ) != List::TestNames ) std::cout << "\t\t '" << it->getDescription() << "'\n"; } } - std::cout << std::endl; + if( config.filters.empty() ) + std::cout << pluralise( matchedTests, "test case" ) << std::endl; + else + std::cout << pluralise( matchedTests, "matching test case" ) << std::endl; } if( ( config.listSpec & List::All ) == 0 ) { @@ -4230,23 +4277,6 @@ namespace Catch { namespace Catch { - struct pluralise { - pluralise( std::size_t count, const std::string& label ) - : m_count( count ), - m_label( label ) - {} - - friend std::ostream& operator << ( std::ostream& os, const pluralise& pluraliser ) { - os << pluraliser.m_count << " " << pluraliser.m_label; - if( pluraliser.m_count != 1 ) - os << "s"; - return os; - } - - std::size_t m_count; - std::string m_label; - }; - class BasicReporter : public SharedImpl { struct SpanInfo {