Support bitand and bitor in REQUIRE/CHECK

This means that bit-flag-like types with conversion to bool can be
asserted on, like so `REQUIRE(var & Flags::AddNewline)`.
This commit is contained in:
Martin Hořeňovský 2020-04-21 11:00:08 +02:00
parent 2a93a65bc2
commit 53434a2f32
No known key found for this signature in database
GPG Key ID: DE48307B8B0D381A
11 changed files with 106 additions and 8 deletions

View File

@ -208,6 +208,14 @@ namespace Catch {
auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs }; return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
} }
template <typename RhsT>
auto operator | (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
return { static_cast<bool>(m_lhs | rhs), m_lhs, "|", rhs };
}
template <typename RhsT>
auto operator & (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
return { static_cast<bool>(m_lhs & rhs), m_lhs, "&", rhs };
}
template<typename RhsT> template<typename RhsT>
auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const { auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {

View File

@ -81,6 +81,7 @@ Nor would this
:test-result: PASS Approximate comparisons with ints :test-result: PASS Approximate comparisons with ints
:test-result: PASS Approximate comparisons with mixed numeric types :test-result: PASS Approximate comparisons with mixed numeric types
:test-result: PASS Arbitrary predicate matcher :test-result: PASS Arbitrary predicate matcher
:test-result: PASS Assertion macros support bit operators and bool conversions
:test-result: PASS Assertions then sections :test-result: PASS Assertions then sections
:test-result: PASS Basic use of the Contains range matcher :test-result: PASS Basic use of the Contains range matcher
:test-result: PASS Basic use of the Empty range matcher :test-result: PASS Basic use of the Empty range matcher

View File

@ -245,6 +245,9 @@ Matchers.tests.cpp:<line number>: passed: 1, Predicate<int>(alwaysTrue, "always
Matchers.tests.cpp:<line number>: passed: 1, !Predicate<int>(alwaysFalse, "always false") for: 1 not matches predicate: "always false" Matchers.tests.cpp:<line number>: passed: 1, !Predicate<int>(alwaysFalse, "always false") for: 1 not matches predicate: "always false"
Matchers.tests.cpp:<line number>: passed: "Hello olleH", Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") for: "Hello olleH" matches predicate: "First and last character should be equal" Matchers.tests.cpp:<line number>: passed: "Hello olleH", Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") for: "Hello olleH" matches predicate: "First and last character should be equal"
Matchers.tests.cpp:<line number>: passed: "This wouldn't pass", !Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) for: "This wouldn't pass" not matches undescribed predicate Matchers.tests.cpp:<line number>: passed: "This wouldn't pass", !Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) for: "This wouldn't pass" not matches undescribed predicate
Compilation.tests.cpp:<line number>: passed: lhs | rhs for: Val: 1 | Val: 2
Compilation.tests.cpp:<line number>: passed: !(lhs & rhs) for: !(Val: 1 & Val: 2)
Compilation.tests.cpp:<line number>: passed: HasBitOperators{ 1 } & HasBitOperators{ 1 } for: Val: 1 & Val: 1
Tricky.tests.cpp:<line number>: passed: true Tricky.tests.cpp:<line number>: passed: true
Tricky.tests.cpp:<line number>: passed: true Tricky.tests.cpp:<line number>: passed: true
Tricky.tests.cpp:<line number>: passed: true Tricky.tests.cpp:<line number>: passed: true

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: 334 | 260 passed | 70 failed | 4 failed as expected test cases: 335 | 261 passed | 70 failed | 4 failed as expected
assertions: 1892 | 1740 passed | 131 failed | 21 failed as expected assertions: 1895 | 1743 passed | 131 failed | 21 failed as expected

View File

@ -1943,6 +1943,27 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
"This wouldn't pass" not matches undescribed predicate "This wouldn't pass" not matches undescribed predicate
-------------------------------------------------------------------------------
Assertion macros support bit operators and bool conversions
-------------------------------------------------------------------------------
Compilation.tests.cpp:<line number>
...............................................................................
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE( lhs | rhs )
with expansion:
Val: 1 | Val: 2
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( lhs & rhs )
with expansion:
!(Val: 1 & Val: 2)
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE( HasBitOperators{ 1 } & HasBitOperators{ 1 } )
with expansion:
Val: 1 & Val: 1
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Assertions then sections Assertions then sections
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -14773,6 +14794,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED: Misc.tests.cpp:<line number>: PASSED:
=============================================================================== ===============================================================================
test cases: 334 | 244 passed | 86 failed | 4 failed as expected test cases: 335 | 245 passed | 86 failed | 4 failed as expected
assertions: 1909 | 1740 passed | 148 failed | 21 failed as expected assertions: 1912 | 1743 passed | 148 failed | 21 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="1910" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> <testsuite name="<exe-name>" errors="17" failures="132" tests="1913" 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"/>
@ -341,6 +341,7 @@ Exception.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Approximate comparisons with mixed numeric types" time="{duration}"/> <testcase classname="<exe-name>.global" name="Approximate comparisons with mixed numeric types" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Arbitrary predicate matcher/Function pointer" time="{duration}"/> <testcase classname="<exe-name>.global" name="Arbitrary predicate matcher/Function pointer" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Arbitrary predicate matcher/Lambdas + different type" time="{duration}"/> <testcase classname="<exe-name>.global" name="Arbitrary predicate matcher/Lambdas + different type" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Assertion macros support bit operators and bool conversions" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Assertions then sections" time="{duration}"/> <testcase classname="<exe-name>.global" name="Assertions then sections" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Assertions then sections/A section" time="{duration}"/> <testcase classname="<exe-name>.global" name="Assertions then sections/A section" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Assertions then sections/A section/Another section" time="{duration}"/> <testcase classname="<exe-name>.global" name="Assertions then sections/A section/Another section" time="{duration}"/>

View File

@ -396,6 +396,7 @@ Class.tests.cpp:<line number>
<testCase name="#809" duration="{duration}"/> <testCase name="#809" duration="{duration}"/>
<testCase name="#833" duration="{duration}"/> <testCase name="#833" duration="{duration}"/>
<testCase name="#872" duration="{duration}"/> <testCase name="#872" duration="{duration}"/>
<testCase name="Assertion macros support bit operators and bool conversions" duration="{duration}"/>
<testCase name="Lambdas in assertions" duration="{duration}"/> <testCase name="Lambdas in assertions" duration="{duration}"/>
<testCase name="Optionally static assertions" duration="{duration}"/> <testCase name="Optionally static assertions" duration="{duration}"/>
</file> </file>

View File

@ -488,6 +488,12 @@ ok {test-number} - 1, !Predicate<int>(alwaysFalse, "always false") for: 1 not ma
ok {test-number} - "Hello olleH", Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") for: "Hello olleH" matches predicate: "First and last character should be equal" ok {test-number} - "Hello olleH", Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") for: "Hello olleH" matches predicate: "First and last character should be equal"
# Arbitrary predicate matcher # Arbitrary predicate matcher
ok {test-number} - "This wouldn't pass", !Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) for: "This wouldn't pass" not matches undescribed predicate ok {test-number} - "This wouldn't pass", !Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) for: "This wouldn't pass" not matches undescribed predicate
# Assertion macros support bit operators and bool conversions
ok {test-number} - lhs | rhs for: Val: 1 | Val: 2
# Assertion macros support bit operators and bool conversions
ok {test-number} - !(lhs & rhs) for: !(Val: 1 & Val: 2)
# Assertion macros support bit operators and bool conversions
ok {test-number} - HasBitOperators{ 1 } & HasBitOperators{ 1 } for: Val: 1 & Val: 1
# Assertions then sections # Assertions then sections
ok {test-number} - true ok {test-number} - true
# Assertions then sections # Assertions then sections
@ -3810,5 +3816,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
ok {test-number} - ok {test-number} -
# xmlentitycheck # xmlentitycheck
ok {test-number} - ok {test-number} -
1..1901 1..1904

View File

@ -195,6 +195,8 @@ Exception.tests.cpp:<line number>|nunexpected exception with message:|n "unexpe
##teamcity[testFinished name='Approximate comparisons with mixed numeric types' duration="{duration}"] ##teamcity[testFinished name='Approximate comparisons with mixed numeric types' duration="{duration}"]
##teamcity[testStarted name='Arbitrary predicate matcher'] ##teamcity[testStarted name='Arbitrary predicate matcher']
##teamcity[testFinished name='Arbitrary predicate matcher' duration="{duration}"] ##teamcity[testFinished name='Arbitrary predicate matcher' duration="{duration}"]
##teamcity[testStarted name='Assertion macros support bit operators and bool conversions']
##teamcity[testFinished name='Assertion macros support bit operators and bool conversions' duration="{duration}"]
##teamcity[testStarted name='Assertions then sections'] ##teamcity[testStarted name='Assertions then sections']
##teamcity[testFinished name='Assertions then sections' duration="{duration}"] ##teamcity[testFinished name='Assertions then sections' duration="{duration}"]
##teamcity[testStarted name='Basic use of the Contains range matcher'] ##teamcity[testStarted name='Basic use of the Contains range matcher']

View File

@ -2183,6 +2183,33 @@ Nor would this
</Section> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<TestCase name="Assertion macros support bit operators and bool conversions" tags="[bitops][compilation]" filename="tests/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Original>
lhs | rhs
</Original>
<Expanded>
Val: 1 | Val: 2
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="tests/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Original>
!(lhs &amp; rhs)
</Original>
<Expanded>
!(Val: 1 &amp; Val: 2)
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Original>
HasBitOperators{ 1 } &amp; HasBitOperators{ 1 }
</Original>
<Expanded>
Val: 1 &amp; Val: 1
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Assertions then sections" tags="[Tricky]" filename="tests/<exe-name>/UsageTests/Tricky.tests.cpp" > <TestCase name="Assertions then sections" tags="[Tricky]" filename="tests/<exe-name>/UsageTests/Tricky.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Tricky.tests.cpp" > <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Tricky.tests.cpp" >
<Original> <Original>
@ -17732,7 +17759,7 @@ loose text artifact
</Section> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<OverallResults successes="1740" failures="149" expectedFailures="21"/> <OverallResults successes="1743" failures="149" expectedFailures="21"/>
</Group> </Group>
<OverallResults successes="1740" failures="148" expectedFailures="21"/> <OverallResults successes="1743" failures="148" expectedFailures="21"/>
</Catch> </Catch>

View File

@ -237,3 +237,31 @@ namespace { namespace CompilationTests {
}} // namespace CompilationTests }} // namespace CompilationTests
namespace {
struct HasBitOperators {
int value;
friend HasBitOperators operator| (HasBitOperators lhs, HasBitOperators rhs) {
return { lhs.value | rhs.value };
}
friend HasBitOperators operator& (HasBitOperators lhs, HasBitOperators rhs) {
return { lhs.value & rhs.value };
}
explicit operator bool() const {
return !!value;
}
friend std::ostream& operator<<(std::ostream& out, HasBitOperators val) {
out << "Val: " << val.value;
return out;
}
};
}
TEST_CASE("Assertion macros support bit operators and bool conversions", "[compilation][bitops]") {
HasBitOperators lhs{ 1 }, rhs{ 2 };
REQUIRE(lhs | rhs);
REQUIRE_FALSE(lhs & rhs);
REQUIRE(HasBitOperators{ 1 } & HasBitOperators{ 1 });
}