Fix bug in test spec parser handling of escaping in ORed patterns

It did not clear out all of its internal state when switching from
one pattern to another, so when it should've escaped `,`, it took
its position from its position in the original user-provided string,
rather than its position in the current pattern.

Fixes #1905
This commit is contained in:
Martin Hořeňovský 2020-04-12 18:44:42 +02:00
parent 035a062596
commit 5d32ce26f4
No known key found for this signature in database
GPG Key ID: DE48307B8B0D381A
9 changed files with 96 additions and 9 deletions

View File

@ -168,6 +168,7 @@ namespace Catch {
m_pos = m_arg.size(); m_pos = m_arg.size();
m_substring.clear(); m_substring.clear();
m_patternName.clear(); m_patternName.clear();
m_realPatternPos = 0;
return false; return false;
} }
endMode(); endMode();
@ -186,6 +187,7 @@ namespace Catch {
} }
m_patternName.clear(); m_patternName.clear();
m_realPatternPos = 0;
return token; return token;
} }

View File

@ -23,6 +23,9 @@ This would not be caught previously
Nor would this Nor would this
Tricky.tests.cpp:<line number>: failed: explicitly with 1 message: '1514' Tricky.tests.cpp:<line number>: failed: explicitly with 1 message: '1514'
Compilation.tests.cpp:<line number>: passed: std::is_same<TypeList<int>, TypeList<int>>::value for: true Compilation.tests.cpp:<line number>: passed: std::is_same<TypeList<int>, TypeList<int>>::value for: true
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase("spec . char")) for: true
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase("spec , char")) for: true
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(fakeTestCase(R"(spec \, char)"))) for: !false
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42' with 1 message: 'expected exception' Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42' with 1 message: 'expected exception'
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42'; expression was: thisThrows() with 1 message: 'expected exception' Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42'; expression was: thisThrows() with 1 message: 'expected exception'
Exception.tests.cpp:<line number>: passed: thisThrows() with 1 message: 'answer := 42' Exception.tests.cpp:<line number>: passed: thisThrows() with 1 message: 'answer := 42'

View File

@ -1380,6 +1380,6 @@ due to unexpected exception with message:
Why would you throw a std::string? Why would you throw a std::string?
=============================================================================== ===============================================================================
test cases: 307 | 233 passed | 70 failed | 4 failed as expected test cases: 308 | 234 passed | 70 failed | 4 failed as expected
assertions: 1677 | 1525 passed | 131 failed | 21 failed as expected assertions: 1680 | 1528 passed | 131 failed | 21 failed as expected

View File

@ -188,6 +188,27 @@ Compilation.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
true true
-------------------------------------------------------------------------------
#1905 -- test spec parser properly clears internal state between compound tests
-------------------------------------------------------------------------------
CmdLine.tests.cpp:<line number>
...............................................................................
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase("spec . char")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase("spec , char")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( spec.matches(fakeTestCase(R"(spec \, char)")) )
with expansion:
!false
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
#748 - captures with unexpected exceptions #748 - captures with unexpected exceptions
outside assertions outside assertions
@ -13427,6 +13448,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED: Misc.tests.cpp:<line number>: PASSED:
=============================================================================== ===============================================================================
test cases: 307 | 217 passed | 86 failed | 4 failed as expected test cases: 308 | 218 passed | 86 failed | 4 failed as expected
assertions: 1694 | 1525 passed | 148 failed | 21 failed as expected assertions: 1697 | 1528 passed | 148 failed | 21 failed as expected

View File

@ -188,6 +188,27 @@ Compilation.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
true true
-------------------------------------------------------------------------------
#1905 -- test spec parser properly clears internal state between compound tests
-------------------------------------------------------------------------------
CmdLine.tests.cpp:<line number>
...............................................................................
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase("spec . char")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase("spec , char")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( spec.matches(fakeTestCase(R"(spec \, char)")) )
with expansion:
!false
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
#748 - captures with unexpected exceptions #748 - captures with unexpected exceptions
outside assertions outside assertions
@ -368,6 +389,6 @@ Condition.tests.cpp:<line number>: FAILED:
CHECK( true != true ) CHECK( true != true )
=============================================================================== ===============================================================================
test cases: 19 | 14 passed | 3 failed | 2 failed as expected test cases: 20 | 15 passed | 3 failed | 2 failed as expected
assertions: 42 | 35 passed | 4 failed | 3 failed as expected assertions: 45 | 38 passed | 4 failed | 3 failed as expected

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<testsuitesloose text artifact <testsuitesloose text artifact
> >
<testsuite name="<exe-name>" errors="17" failures="132" tests="1695" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> <testsuite name="<exe-name>" errors="17" failures="132" tests="1698" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<properties> <properties>
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals]"/> <property name="filters" value="~[!nonportable]~[!benchmark]~[approvals]"/>
<property name="random-seed" value="1"/> <property name="random-seed" value="1"/>
@ -30,6 +30,7 @@ Nor would this
</system-err> </system-err>
</testcase> </testcase>
<testcase classname="<exe-name>.global" name="#1548" time="{duration}"/> <testcase classname="<exe-name>.global" name="#1548" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1905 -- test spec parser properly clears internal state between compound tests" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}"> <testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}">
<error type="TEST_CASE"> <error type="TEST_CASE">
FAILED: FAILED:

View File

@ -2,6 +2,7 @@
<testExecutions version="1"loose text artifact <testExecutions version="1"loose text artifact
> >
<file path="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp"> <file path="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp">
<testCase name="#1905 -- test spec parser properly clears internal state between compound tests" duration="{duration}"/>
<testCase name="Parse test names and tags/Empty test spec should have no filters" duration="{duration}"/> <testCase name="Parse test names and tags/Empty test spec should have no filters" duration="{duration}"/>
<testCase name="Parse test names and tags/Test spec from empty string should have no filters" duration="{duration}"/> <testCase name="Parse test names and tags/Test spec from empty string should have no filters" duration="{duration}"/>
<testCase name="Parse test names and tags/Test spec from just a comma should have no filters" duration="{duration}"/> <testCase name="Parse test names and tags/Test spec from just a comma should have no filters" duration="{duration}"/>

View File

@ -196,6 +196,33 @@ Nor would this
</Expression> </Expression>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<TestCase name="#1905 -- test spec parser properly clears internal state between compound tests" tags="[command-line][test-spec]" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
spec.matches(fakeTestCase("spec . char"))
</Original>
<Expanded>
true
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
spec.matches(fakeTestCase("spec , char"))
</Original>
<Expanded>
true
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
<Original>
!(spec.matches(fakeTestCase(R"(spec \, char)")))
</Original>
<Expanded>
!false
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="#748 - captures with unexpected exceptions" tags="[!hide][!shouldfail][!throws][.][failing]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" > <TestCase name="#748 - captures with unexpected exceptions" tags="[!hide][!shouldfail][!throws][.][failing]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
<Section name="outside assertions" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" > <Section name="outside assertions" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
<Info> <Info>
@ -16048,7 +16075,7 @@ loose text artifact
</Section> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<OverallResults successes="1525" failures="149" expectedFailures="21"/> <OverallResults successes="1528" failures="149" expectedFailures="21"/>
</Group> </Group>
<OverallResults successes="1525" failures="148" expectedFailures="21"/> <OverallResults successes="1528" failures="148" expectedFailures="21"/>
</Catch> </Catch>

View File

@ -292,6 +292,17 @@ TEST_CASE( "Parse test names and tags", "[command-line][test-spec]" ) {
} }
} }
TEST_CASE("#1905 -- test spec parser properly clears internal state between compound tests", "[command-line][test-spec]") {
using Catch::parseTestSpec;
using Catch::TestSpec;
// We ask for one of 2 different tests and the latter one of them has a , in name that needs escaping
TestSpec spec = parseTestSpec(R"("spec . char","spec \, char")");
REQUIRE(spec.matches(fakeTestCase("spec . char")));
REQUIRE(spec.matches(fakeTestCase("spec , char")));
REQUIRE_FALSE(spec.matches(fakeTestCase(R"(spec \, char)")));
}
TEST_CASE( "Process can be configured on command line", "[config][command-line]" ) { TEST_CASE( "Process can be configured on command line", "[config][command-line]" ) {
#ifndef CATCH_CONFIG_DISABLE_MATCHERS #ifndef CATCH_CONFIG_DISABLE_MATCHERS