Split [.foo] into [.][foo] when parsing test specs

b77cec05c0 fixed this problem for tagging tests, so that a test
case tagged with `[.foo]` would be parsed as tagged with `[.][foo]`.
This does the same for the test spec parsing.

Fixes #1798
This commit is contained in:
Martin Hořeňovský
2019-11-05 23:28:47 +01:00
parent c409dccee5
commit 930f49a641
9 changed files with 201 additions and 42 deletions

View File

@@ -20,10 +20,10 @@ 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 )
//if visitChar fails
if( !visitChar( m_arg[m_pos] ) ){
if( !visitChar( m_arg[m_pos] ) ){
m_testSpec.m_invalidArgs.push_back(arg);
break;
}
@@ -113,9 +113,9 @@ namespace Catch {
switch( m_mode ) {
case Name:
case QuotedName:
return addPattern<TestSpec::NamePattern>();
return addNamePattern();
case Tag:
return addPattern<TestSpec::TagPattern>();
return addTagPattern();
case EscapedName:
revertBackToLastMode();
return;
@@ -156,12 +156,12 @@ namespace Catch {
void TestSpecParser::saveLastMode() {
lastMode = m_mode;
}
void TestSpecParser::revertBackToLastMode() {
m_mode = lastMode;
}
bool TestSpecParser::separate() {
bool TestSpecParser::separate() {
if( (m_mode==QuotedName) || (m_mode==Tag) ){
//invalid argument, signal failure to previous scope.
m_mode = None;
@@ -174,7 +174,63 @@ namespace Catch {
addFilter();
return true; //success
}
std::string TestSpecParser::preprocessPattern() {
std::string token = m_patternName;
for (std::size_t i = 0; i < m_escapeChars.size(); ++i)
token = token.substr(0, m_escapeChars[i] - i) + token.substr(m_escapeChars[i] - i + 1);
m_escapeChars.clear();
if (startsWith(token, "exclude:")) {
m_exclusion = true;
token = token.substr(8);
}
m_patternName.clear();
return token;
}
void TestSpecParser::addNamePattern() {
auto token = preprocessPattern();
if (!token.empty()) {
TestSpec::PatternPtr pattern = std::make_shared<TestSpec::NamePattern>(token, m_substring);
if (m_exclusion)
pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);
m_currentFilter.m_patterns.push_back(pattern);
}
m_substring.clear();
m_exclusion = false;
m_mode = None;
}
void TestSpecParser::addTagPattern() {
auto token = preprocessPattern();
if (!token.empty()) {
// If the tag pattern is the "hide and tag" shorthand (e.g. [.foo])
// we have to create a separate hide tag and shorten the real one
if (token.size() > 1 && token[0] == '.') {
token.erase(token.begin());
TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(".", m_substring);
if (m_exclusion) {
pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);
}
m_currentFilter.m_patterns.push_back(pattern);
}
TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(token, m_substring);
if (m_exclusion) {
pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);
}
m_currentFilter.m_patterns.push_back(pattern);
}
m_substring.clear();
m_exclusion = false;
m_mode = None;
}
TestSpec parseTestSpec( std::string const& arg ) {
return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
}

View File

@@ -53,35 +53,20 @@ namespace Catch {
void revertBackToLastMode();
void addFilter();
bool separate();
template<typename T>
void addPattern() {
std::string token = m_patternName;
for( std::size_t i = 0; i < m_escapeChars.size(); ++i )
token = token.substr( 0, m_escapeChars[i] - i ) + token.substr( m_escapeChars[i] -i +1 );
m_escapeChars.clear();
if( startsWith( token, "exclude:" ) ) {
m_exclusion = true;
token = token.substr( 8 );
}
if( !token.empty() ) {
TestSpec::PatternPtr pattern = std::make_shared<T>( token, m_substring );
if( m_exclusion )
pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern );
m_currentFilter.m_patterns.push_back( pattern );
}
m_substring.clear();
m_patternName.clear();
m_exclusion = false;
m_mode = None;
}
// Handles common preprocessing of the pattern for name/tag patterns
std::string preprocessPattern();
// Adds the current pattern as a test name
void addNamePattern();
// Adds the current pattern as a tag
void addTagPattern();
inline void addCharToPattern(char c) {
m_substring += c;
m_patternName += c;
m_realPatternPos++;
}
};
TestSpec parseTestSpec( std::string const& arg );