diff --git a/include/internal/catch_commandline.cpp b/include/internal/catch_commandline.cpp index 0359272c..365a3c9d 100644 --- a/include/internal/catch_commandline.cpp +++ b/include/internal/catch_commandline.cpp @@ -49,9 +49,15 @@ namespace Catch { if( !line.empty() && !startsWith( line, '#' ) ) { if( !startsWith( line, '"' ) ) line = '"' + line + '"'; - config.testsOrTags.push_back( line + ',' ); + config.testsOrTags.push_back( line ); + config.testsOrTags.push_back( "," ); + } } + //Remove comma in the end + if(!config.testsOrTags.empty()) + config.testsOrTags.erase( config.testsOrTags.end()-1 ); + return ParserResult::ok( ParseResultType::Matched ); }; auto const setTestOrder = [&]( std::string const& order ) { diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index e54a24a8..751ef2c2 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -214,6 +214,8 @@ namespace Catch { virtual void noMatchingTestCases( std::string const& spec ) = 0; + virtual void reportInvalidArguments(std::string const&) {} + virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; diff --git a/include/internal/catch_session.cpp b/include/internal/catch_session.cpp index 94db4597..b1d7a404 100644 --- a/include/internal/catch_session.cpp +++ b/include/internal/catch_session.cpp @@ -68,8 +68,9 @@ namespace Catch { { auto const& allTestCases = getAllTestCasesSorted(*m_config); m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config); - - if (m_matches.empty()) { + auto const& invalidArgs = m_config->testSpec().getInvalidArgs(); + + if (m_matches.empty() && invalidArgs.empty()) { for (auto const& test : allTestCases) if (!test.isHidden()) m_tests.emplace(&test); @@ -80,6 +81,7 @@ namespace Catch { } Totals execute() { + auto const& invalidArgs = m_config->testSpec().getInvalidArgs(); Totals totals; m_context.testGroupStarting(m_config->name(), 1, 1); for (auto const& testCase : m_tests) { @@ -95,6 +97,12 @@ namespace Catch { totals.error = -1; } } + + if (!invalidArgs.empty()) { + for (auto const& invalidArg: invalidArgs) + m_context.reporter().reportInvalidArguments(invalidArg); + } + m_context.testGroupEnded(m_config->name(), totals, 1, 1); return totals; } diff --git a/include/internal/catch_test_spec.cpp b/include/internal/catch_test_spec.cpp index 4c80c56e..65d34d0e 100644 --- a/include/internal/catch_test_spec.cpp +++ b/include/internal/catch_test_spec.cpp @@ -91,5 +91,9 @@ namespace Catch { } ); return matches; } + + const TestSpec::vectorStrings& TestSpec::getInvalidArgs() const{ + return (m_invalidArgs); + } } diff --git a/include/internal/catch_test_spec.h b/include/internal/catch_test_spec.h index d0e7ea9f..2e546463 100644 --- a/include/internal/catch_test_spec.h +++ b/include/internal/catch_test_spec.h @@ -73,14 +73,16 @@ namespace Catch { std::vector tests; }; using Matches = std::vector; + using vectorStrings = std::vector; bool hasFilters() const; bool matches( TestCaseInfo const& testCase ) const; Matches matchesByFilter( std::vector const& testCases, IConfig const& config ) const; + const vectorStrings & getInvalidArgs() const; private: std::vector m_filters; - + std::vector m_invalidArgs; friend class TestSpecParser; }; } diff --git a/include/internal/catch_test_spec_parser.cpp b/include/internal/catch_test_spec_parser.cpp index 718185fa..b872b191 100644 --- a/include/internal/catch_test_spec_parser.cpp +++ b/include/internal/catch_test_spec_parser.cpp @@ -20,8 +20,13 @@ namespace Catch { m_substring.reserve(m_arg.size()); m_patternName.reserve(m_arg.size()); m_realPatternPos = 0; + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) - visitChar( m_arg[m_pos] ); + //if visitChar fails + if( !visitChar( m_arg[m_pos] ) ){ + m_testSpec.m_invalidArgs.push_back(arg); + break; + } endMode(); return *this; } @@ -29,38 +34,32 @@ namespace Catch { addFilter(); return m_testSpec; } - void TestSpecParser::visitChar( char c ) { + bool TestSpecParser::visitChar( char c ) { if( (m_mode != EscapedName) && (c == '\\') ) { escape(); - m_substring += c; - m_patternName += c; - m_realPatternPos++; - return; + addCharToPattern(c); + return true; }else if((m_mode != EscapedName) && (c == ',') ) { - endMode(); - addFilter(); - return; + return separate(); } switch( m_mode ) { case None: if( processNoneChar( c ) ) - return; + return true; break; case Name: processNameChar( c ); break; case EscapedName: endMode(); - m_substring += c; - m_patternName += c; - m_realPatternPos++; - return; + addCharToPattern(c); + return true; default: case Tag: case QuotedName: if( processOtherChar( c ) ) - return; + return true; break; } @@ -69,6 +68,7 @@ namespace Catch { m_patternName += c; m_realPatternPos++; } + return true; } // Two of the processing methods return true to signal the caller to return // without adding the given character to the current pattern strings @@ -161,6 +161,20 @@ namespace Catch { m_mode = lastMode; } + bool TestSpecParser::separate() { + if( (m_mode==QuotedName) || (m_mode==Tag) ){ + //invalid argument, signal failure to previous scope. + m_mode = None; + m_pos = m_arg.size(); + m_substring.clear(); + m_patternName.clear(); + return false; + } + endMode(); + addFilter(); + return true; //success + } + TestSpec parseTestSpec( std::string const& arg ) { return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); } diff --git a/include/internal/catch_test_spec_parser.h b/include/internal/catch_test_spec_parser.h index c80787c8..179d3532 100644 --- a/include/internal/catch_test_spec_parser.h +++ b/include/internal/catch_test_spec_parser.h @@ -41,7 +41,7 @@ namespace Catch { TestSpec testSpec(); private: - void visitChar( char c ); + bool visitChar( char c ); void startNewMode( Mode mode ); bool processNoneChar( char c ); void processNameChar( char c ); @@ -51,6 +51,8 @@ namespace Catch { bool isControlChar( char c ) const; void saveLastMode(); void revertBackToLastMode(); + void addFilter(); + bool separate(); template void addPattern() { @@ -73,8 +75,13 @@ namespace Catch { m_exclusion = false; m_mode = None; } - - void addFilter(); + + inline void addCharToPattern(char c) { + m_substring += c; + m_patternName += c; + m_realPatternPos++; + } + }; TestSpec parseTestSpec( std::string const& arg ); diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index a9b0640c..66a891ff 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -51,6 +51,8 @@ namespace Catch { void noMatchingTestCases(std::string const&) override {} + void reportInvalidArguments(std::string const&) override {} + void testRunStarting(TestRunInfo const& _testRunInfo) override { currentTestRunInfo = _testRunInfo; } @@ -277,4 +279,4 @@ namespace Catch { } // end namespace Catch -#endif // TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED +#endif // TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED \ No newline at end of file diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp index ad663ca4..be00d0bd 100644 --- a/include/reporters/catch_reporter_console.cpp +++ b/include/reporters/catch_reporter_console.cpp @@ -383,6 +383,10 @@ void ConsoleReporter::noMatchingTestCases(std::string const& spec) { stream << "No test cases matched '" << spec << '\'' << std::endl; } +void ConsoleReporter::reportInvalidArguments(std::string const&arg){ + stream << "Invalid Filter: " << arg << std::endl; +} + void ConsoleReporter::assertionStarting(AssertionInfo const&) {} bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) { @@ -694,4 +698,4 @@ CATCH_REGISTER_REPORTER("console", ConsoleReporter) #if defined(__clang__) # pragma clang diagnostic pop -#endif +#endif \ No newline at end of file diff --git a/include/reporters/catch_reporter_console.h b/include/reporters/catch_reporter_console.h index 5d21ffb6..43024daf 100644 --- a/include/reporters/catch_reporter_console.h +++ b/include/reporters/catch_reporter_console.h @@ -32,6 +32,8 @@ namespace Catch { void noMatchingTestCases(std::string const& spec) override; + void reportInvalidArguments(std::string const&arg) override; + void assertionStarting(AssertionInfo const&) override; bool assertionEnded(AssertionStats const& _assertionStats) override; @@ -84,4 +86,4 @@ namespace Catch { #pragma warning(pop) #endif -#endif // TWOBLUECUBES_CATCH_REPORTER_CONSOLE_H_INCLUDED +#endif // TWOBLUECUBES_CATCH_REPORTER_CONSOLE_H_INCLUDED \ No newline at end of file diff --git a/include/reporters/catch_reporter_listening.cpp b/include/reporters/catch_reporter_listening.cpp index 6864e90b..91e6b39a 100644 --- a/include/reporters/catch_reporter_listening.cpp +++ b/include/reporters/catch_reporter_listening.cpp @@ -41,6 +41,13 @@ namespace Catch { } m_reporter->noMatchingTestCases( spec ); } + + void ListeningReporter::reportInvalidArguments(std::string const&arg){ + for ( auto const& listener : m_listeners ) { + listener->reportInvalidArguments( arg ); + } + m_reporter->reportInvalidArguments( arg ); + } #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) void ListeningReporter::benchmarkPreparing( std::string const& name ) { @@ -154,4 +161,4 @@ namespace Catch { return true; } -} // end namespace Catch +} // end namespace Catch \ No newline at end of file diff --git a/include/reporters/catch_reporter_listening.h b/include/reporters/catch_reporter_listening.h index 802db446..bfaa3085 100644 --- a/include/reporters/catch_reporter_listening.h +++ b/include/reporters/catch_reporter_listening.h @@ -28,7 +28,9 @@ namespace Catch { ReporterPreferences getPreferences() const override; void noMatchingTestCases( std::string const& spec ) override; - + + void reportInvalidArguments(std::string const&arg) override; + static std::set getSupportedVerbosities(); #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) @@ -58,4 +60,4 @@ namespace Catch { } // end namespace Catch -#endif // TWOBLUECUBES_CATCH_MULTI_REPORTER_H_INCLUDED +#endif // TWOBLUECUBES_CATCH_MULTI_REPORTER_H_INCLUDED \ No newline at end of file