From 0e77adee059f2d43ef6278f872f4c5a6198fc957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sun, 14 Jun 2020 21:48:08 +0200 Subject: [PATCH] Add explicit test for shortcircuiting behaviour of combined matchers --- .../Baselines/automake.sw.approved.txt | 1 + .../Baselines/compact.sw.approved.txt | 6 ++ .../Baselines/console.std.approved.txt | 4 +- .../Baselines/console.sw.approved.txt | 50 ++++++++++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 4 +- .../Baselines/sonarqube.sw.approved.txt | 2 + tests/SelfTest/Baselines/tap.sw.approved.txt | 14 ++++- .../Baselines/teamcity.sw.approved.txt | 2 + tests/SelfTest/Baselines/xml.sw.approved.txt | 61 ++++++++++++++++++- tests/SelfTest/UsageTests/Matchers.tests.cpp | 41 +++++++++++++ 10 files changed, 177 insertions(+), 8 deletions(-) diff --git a/tests/SelfTest/Baselines/automake.sw.approved.txt b/tests/SelfTest/Baselines/automake.sw.approved.txt index cc531e1d..d6cf5cc6 100644 --- a/tests/SelfTest/Baselines/automake.sw.approved.txt +++ b/tests/SelfTest/Baselines/automake.sw.approved.txt @@ -108,6 +108,7 @@ Nor would this :test-result: PASS Comparisons between ints where one side is computed :test-result: PASS Comparisons between unsigned ints and negative signed ints match c++ standard behaviour :test-result: PASS Comparisons with int literals don't warn when mixing signed/ unsigned +:test-result: PASS Composed matchers shortcircuit :test-result: FAIL Contains string matcher :test-result: PASS Copy and then generate a range :test-result: FAIL Custom exceptions can be translated when testing for nothrow diff --git a/tests/SelfTest/Baselines/compact.sw.approved.txt b/tests/SelfTest/Baselines/compact.sw.approved.txt index aed08153..fc8ce18b 100644 --- a/tests/SelfTest/Baselines/compact.sw.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.approved.txt @@ -387,6 +387,12 @@ Condition.tests.cpp:: passed: 4 == ul for: 4 == 4 Condition.tests.cpp:: passed: 5 == c for: 5 == 5 Condition.tests.cpp:: passed: 6 == uc for: 6 == 6 Condition.tests.cpp:: passed: (std::numeric_limits::max)() > ul for: 4294967295 (0x) > 4 +Matchers.tests.cpp:: passed: 1, !(first && second) for: 1 not ( CheckedTestingMatcher set to fail and CheckedTestingMatcher set to fail ) +Matchers.tests.cpp:: passed: first.matchCalled for: true +Matchers.tests.cpp:: passed: !second.matchCalled for: true +Matchers.tests.cpp:: passed: 1, first || second for: 1 ( CheckedTestingMatcher set to succeed or CheckedTestingMatcher set to fail ) +Matchers.tests.cpp:: passed: first.matchCalled for: true +Matchers.tests.cpp:: passed: !second.matchCalled for: true Matchers.tests.cpp:: failed: testStringForMatching(), Contains("not there", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" contains: "not there" (case insensitive) Matchers.tests.cpp:: failed: testStringForMatching(), Contains("STRING") for: "this string contains 'abc' as a substring" contains: "STRING" Generators.tests.cpp:: passed: elem % 2 == 1 for: 1 == 1 diff --git a/tests/SelfTest/Baselines/console.std.approved.txt b/tests/SelfTest/Baselines/console.std.approved.txt index 1b423428..75813901 100644 --- a/tests/SelfTest/Baselines/console.std.approved.txt +++ b/tests/SelfTest/Baselines/console.std.approved.txt @@ -1380,6 +1380,6 @@ due to unexpected exception with message: Why would you throw a std::string? =============================================================================== -test cases: 342 | 268 passed | 70 failed | 4 failed as expected -assertions: 1935 | 1783 passed | 131 failed | 21 failed as expected +test cases: 343 | 269 passed | 70 failed | 4 failed as expected +assertions: 1941 | 1789 passed | 131 failed | 21 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.approved.txt b/tests/SelfTest/Baselines/console.sw.approved.txt index 4b8d12f6..be013f5c 100644 --- a/tests/SelfTest/Baselines/console.sw.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.approved.txt @@ -2955,6 +2955,52 @@ Condition.tests.cpp:: PASSED: with expansion: 4294967295 (0x) > 4 +------------------------------------------------------------------------------- +Composed matchers shortcircuit + && +------------------------------------------------------------------------------- +Matchers.tests.cpp: +............................................................................... + +Matchers.tests.cpp:: PASSED: + CHECK_THAT( 1, !(first && second) ) +with expansion: + 1 not ( CheckedTestingMatcher set to fail and CheckedTestingMatcher set to + fail ) + +Matchers.tests.cpp:: PASSED: + REQUIRE( first.matchCalled ) +with expansion: + true + +Matchers.tests.cpp:: PASSED: + REQUIRE( !second.matchCalled ) +with expansion: + true + +------------------------------------------------------------------------------- +Composed matchers shortcircuit + || +------------------------------------------------------------------------------- +Matchers.tests.cpp: +............................................................................... + +Matchers.tests.cpp:: PASSED: + CHECK_THAT( 1, first || second ) +with expansion: + 1 ( CheckedTestingMatcher set to succeed or CheckedTestingMatcher set to fail + ) + +Matchers.tests.cpp:: PASSED: + REQUIRE( first.matchCalled ) +with expansion: + true + +Matchers.tests.cpp:: PASSED: + REQUIRE( !second.matchCalled ) +with expansion: + true + ------------------------------------------------------------------------------- Contains string matcher ------------------------------------------------------------------------------- @@ -15148,6 +15194,6 @@ Misc.tests.cpp: Misc.tests.cpp:: PASSED: =============================================================================== -test cases: 342 | 252 passed | 86 failed | 4 failed as expected -assertions: 1952 | 1783 passed | 148 failed | 21 failed as expected +test cases: 343 | 253 passed | 86 failed | 4 failed as expected +assertions: 1958 | 1789 passed | 148 failed | 21 failed as expected diff --git a/tests/SelfTest/Baselines/junit.sw.approved.txt b/tests/SelfTest/Baselines/junit.sw.approved.txt index 162fb04b..9b42e725 100644 --- a/tests/SelfTest/Baselines/junit.sw.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -381,6 +381,8 @@ Exception.tests.cpp: + + FAILED: diff --git a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt index cdbed24a..7c9b5f18 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt @@ -948,6 +948,8 @@ Exception.tests.cpp: + + FAILED: diff --git a/tests/SelfTest/Baselines/tap.sw.approved.txt b/tests/SelfTest/Baselines/tap.sw.approved.txt index 63d56bce..7d9b2ac8 100644 --- a/tests/SelfTest/Baselines/tap.sw.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.approved.txt @@ -772,6 +772,18 @@ ok {test-number} - 5 == c for: 5 == 5 ok {test-number} - 6 == uc for: 6 == 6 # Comparisons with int literals don't warn when mixing signed/ unsigned ok {test-number} - (std::numeric_limits::max)() > ul for: 4294967295 (0x) > 4 +# Composed matchers shortcircuit +ok {test-number} - 1, !(first && second) for: 1 not ( CheckedTestingMatcher set to fail and CheckedTestingMatcher set to fail ) +# Composed matchers shortcircuit +ok {test-number} - first.matchCalled for: true +# Composed matchers shortcircuit +ok {test-number} - !second.matchCalled for: true +# Composed matchers shortcircuit +ok {test-number} - 1, first || second for: 1 ( CheckedTestingMatcher set to succeed or CheckedTestingMatcher set to fail ) +# Composed matchers shortcircuit +ok {test-number} - first.matchCalled for: true +# Composed matchers shortcircuit +ok {test-number} - !second.matchCalled for: true # Contains string matcher not ok {test-number} - testStringForMatching(), Contains("not there", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" contains: "not there" (case insensitive) # Contains string matcher @@ -3896,5 +3908,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..1944 +1..1950 diff --git a/tests/SelfTest/Baselines/teamcity.sw.approved.txt b/tests/SelfTest/Baselines/teamcity.sw.approved.txt index 40264a41..703935f8 100644 --- a/tests/SelfTest/Baselines/teamcity.sw.approved.txt +++ b/tests/SelfTest/Baselines/teamcity.sw.approved.txt @@ -249,6 +249,8 @@ Exception.tests.cpp:|nunexpected exception with message:|n "unexpe ##teamcity[testFinished name='Comparisons between unsigned ints and negative signed ints match c++ standard behaviour' duration="{duration}"] ##teamcity[testStarted name='Comparisons with int literals don|'t warn when mixing signed/ unsigned'] ##teamcity[testFinished name='Comparisons with int literals don|'t warn when mixing signed/ unsigned' duration="{duration}"] +##teamcity[testStarted name='Composed matchers shortcircuit'] +##teamcity[testFinished name='Composed matchers shortcircuit' duration="{duration}"] ##teamcity[testStarted name='Contains string matcher'] Matchers.tests.cpp:|nexpression failed|n CHECK_THAT( testStringForMatching(), Contains("not there", Catch::CaseSensitive::No) )|nwith expansion:|n "this string contains |'abc|' as a substring" contains: "not there" (case insensitive)|n'] Matchers.tests.cpp:|nexpression failed|n CHECK_THAT( testStringForMatching(), Contains("STRING") )|nwith expansion:|n "this string contains |'abc|' as a substring" contains: "STRING"|n'] diff --git a/tests/SelfTest/Baselines/xml.sw.approved.txt b/tests/SelfTest/Baselines/xml.sw.approved.txt index a90439f7..b5ac74ab 100644 --- a/tests/SelfTest/Baselines/xml.sw.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.approved.txt @@ -3375,6 +3375,63 @@ Nor would this + +
+ + + 1, !(first && second) + + + 1 not ( CheckedTestingMatcher set to fail and CheckedTestingMatcher set to fail ) + + + + + first.matchCalled + + + true + + + + + !second.matchCalled + + + true + + + +
+
+ + + 1, first || second + + + 1 ( CheckedTestingMatcher set to succeed or CheckedTestingMatcher set to fail ) + + + + + first.matchCalled + + + true + + + + + !second.matchCalled + + + true + + + +
+ +
@@ -18118,7 +18175,7 @@ loose text artifact - + - + diff --git a/tests/SelfTest/UsageTests/Matchers.tests.cpp b/tests/SelfTest/UsageTests/Matchers.tests.cpp index f8c9ed1d..c9c61285 100644 --- a/tests/SelfTest/UsageTests/Matchers.tests.cpp +++ b/tests/SelfTest/UsageTests/Matchers.tests.cpp @@ -622,6 +622,47 @@ namespace { namespace MatchersTests { REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, Message("SpecialException::what")); } + struct CheckedTestingMatcher : Catch::Matchers::MatcherBase { + mutable bool matchCalled = false; + bool matchSucceeds = false; + + bool match(int const&) const override { + matchCalled = true; + return matchSucceeds; + } + std::string describe() const override { + return "CheckedTestingMatcher set to " + (matchSucceeds ? std::string("succeed") : std::string("fail")); + } + }; + + TEST_CASE("Composed matchers shortcircuit", "[matchers][composed]") { + // Check that if first returns false, second is not touched + CheckedTestingMatcher first, second; + SECTION("&&") { + first.matchSucceeds = false; + // This assertion doesn't actually test anything, we just + // want the composed matcher's `match` being called. + CHECK_THAT(1, !(first && second)); + + // These two assertions are the important ones + REQUIRE(first.matchCalled); + REQUIRE(!second.matchCalled); + } + // Check that if first returns true, second is not touched + SECTION("||") { + first.matchSucceeds = true; + // This assertion doesn't actually test anything, we just + // want the composed matcher's `match` being called. + CHECK_THAT(1, first || second); + + // These two assertions are the important ones + REQUIRE(first.matchCalled); + REQUIRE(!second.matchCalled); + } + } + + + template struct EqualsRangeMatcher : Catch::Matchers::MatcherGenericBase {