mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-25 23:06:10 +01:00
Add generic Contains matcher
It matches a range iff the range contains a specific element, or an element in the range matches the provided matcher.
This commit is contained in:
parent
89e857349b
commit
007efc173a
@ -73,6 +73,7 @@ set(INTERNAL_HEADERS
|
|||||||
${SOURCES_DIR}/catch_leak_detector.h
|
${SOURCES_DIR}/catch_leak_detector.h
|
||||||
${SOURCES_DIR}/catch_list.h
|
${SOURCES_DIR}/catch_list.h
|
||||||
${SOURCES_DIR}/matchers/catch_matchers.hpp
|
${SOURCES_DIR}/matchers/catch_matchers.hpp
|
||||||
|
${SOURCES_DIR}/matchers/catch_matchers_contains.hpp
|
||||||
${SOURCES_DIR}/matchers/catch_matchers_exception.hpp
|
${SOURCES_DIR}/matchers/catch_matchers_exception.hpp
|
||||||
${SOURCES_DIR}/matchers/catch_matchers_floating.hpp
|
${SOURCES_DIR}/matchers/catch_matchers_floating.hpp
|
||||||
${SOURCES_DIR}/matchers/catch_matchers_generic.hpp
|
${SOURCES_DIR}/matchers/catch_matchers_generic.hpp
|
||||||
|
102
src/catch2/matchers/catch_matchers_contains.hpp
Normal file
102
src/catch2/matchers/catch_matchers_contains.hpp
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
#ifndef TWOBLUECUBES_CATCH_MATCHERS_CONTAINS_HPP_INCLUDED
|
||||||
|
#define TWOBLUECUBES_CATCH_MATCHERS_CONTAINS_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <catch2/matchers/catch_matchers_templates.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
namespace Matchers {
|
||||||
|
//! Matcher for checking that an element in range is equal to specific element
|
||||||
|
template <typename T, typename Equality>
|
||||||
|
class ContainsElementMatcher final : public MatcherGenericBase {
|
||||||
|
T m_desired;
|
||||||
|
Equality m_eq;
|
||||||
|
public:
|
||||||
|
template <typename T2, typename Equality2>
|
||||||
|
ContainsElementMatcher(T2&& target, Equality2&& predicate):
|
||||||
|
m_desired(std::forward<T2>(target)),
|
||||||
|
m_eq(std::forward<Equality2>(predicate))
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::string describe() const override {
|
||||||
|
return "contains element " + Catch::Detail::stringify(m_desired);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename RangeLike>
|
||||||
|
bool match(RangeLike&& rng) const {
|
||||||
|
using std::begin; using std::end;
|
||||||
|
|
||||||
|
return end(rng) != std::find_if(begin(rng), end(rng),
|
||||||
|
[&](auto const& elem) {
|
||||||
|
return m_eq(elem, m_desired);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Meta-matcher for checking that an element in a range matches a specific matcher
|
||||||
|
template <typename Matcher>
|
||||||
|
class ContainsMatcherMatcher final : public MatcherGenericBase {
|
||||||
|
Matcher m_matcher;
|
||||||
|
public:
|
||||||
|
// Note that we do a copy+move to avoid having to SFINAE this
|
||||||
|
// constructor (and also avoid some perfect forwarding failure
|
||||||
|
// cases)
|
||||||
|
ContainsMatcherMatcher(Matcher matcher):
|
||||||
|
m_matcher(std::move(matcher))
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <typename RangeLike>
|
||||||
|
bool match(RangeLike&& rng) const {
|
||||||
|
using std::begin; using std::endl;
|
||||||
|
for (auto&& elem : rng) {
|
||||||
|
if (m_matcher.match(elem)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string describe() const override {
|
||||||
|
return "contains element matching " + m_matcher.describe();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a matcher that checks whether a range contains a specific element.
|
||||||
|
*
|
||||||
|
* Uses `std::equal_to` to do the comparison
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
std::enable_if_t<!Detail::is_matcher<T>::value,
|
||||||
|
ContainsElementMatcher<T, std::equal_to<>>> Contains(T&& elem) {
|
||||||
|
return { std::forward<T>(elem), std::equal_to<>{} };
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Creates a matcher that checks whether a range contains element matching a matcher
|
||||||
|
template <typename Matcher>
|
||||||
|
std::enable_if_t<Detail::is_matcher<Matcher>::value,
|
||||||
|
ContainsMatcherMatcher<Matcher>> Contains(Matcher&& matcher) {
|
||||||
|
return { std::forward<Matcher>(matcher) };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a matcher that checks whether a range contains a specific element.
|
||||||
|
*
|
||||||
|
* Uses `eq` to do the comparisons
|
||||||
|
*/
|
||||||
|
template <typename T, typename Equality>
|
||||||
|
ContainsElementMatcher<T, Equality> Contains(T&& elem, Equality&& eq) {
|
||||||
|
return { std::forward<T>(elem), std::forward<Equality>(eq) };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TWOBLUECUBES_CATCH_MATCHERS_CONTAINS_HPP_INCLUDED
|
@ -50,6 +50,7 @@ set(TEST_SOURCES
|
|||||||
${SELF_TEST_DIR}/UsageTests/ToStringWhich.tests.cpp
|
${SELF_TEST_DIR}/UsageTests/ToStringWhich.tests.cpp
|
||||||
${SELF_TEST_DIR}/UsageTests/Tricky.tests.cpp
|
${SELF_TEST_DIR}/UsageTests/Tricky.tests.cpp
|
||||||
${SELF_TEST_DIR}/UsageTests/VariadicMacros.tests.cpp
|
${SELF_TEST_DIR}/UsageTests/VariadicMacros.tests.cpp
|
||||||
|
${SELF_TEST_DIR}/UsageTests/MatchersRanges.tests.cpp
|
||||||
${SELF_TEST_DIR}/UsageTests/Matchers.tests.cpp
|
${SELF_TEST_DIR}/UsageTests/Matchers.tests.cpp
|
||||||
)
|
)
|
||||||
CheckFileList(TEST_SOURCES ${SELF_TEST_DIR})
|
CheckFileList(TEST_SOURCES ${SELF_TEST_DIR})
|
||||||
|
@ -80,6 +80,7 @@ Nor would this
|
|||||||
: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 Assertions then sections
|
:test-result: PASS Assertions then sections
|
||||||
|
:test-result: PASS Basic use of the Contains range matcher
|
||||||
:test-result: PASS CAPTURE can deal with complex expressions
|
:test-result: PASS CAPTURE can deal with complex expressions
|
||||||
:test-result: PASS CAPTURE can deal with complex expressions involving commas
|
:test-result: PASS CAPTURE can deal with complex expressions involving commas
|
||||||
:test-result: PASS CAPTURE parses string and character constants
|
:test-result: PASS CAPTURE parses string and character constants
|
||||||
|
@ -244,6 +244,18 @@ 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
|
Tricky.tests.cpp:<line number>: passed: true
|
||||||
|
MatchersRanges.tests.cpp:<line number>: passed: a, Contains(1) for: { 1, 2, 3 } contains element 1
|
||||||
|
MatchersRanges.tests.cpp:<line number>: passed: b, Contains(1) for: { 0, 1, 2 } contains element 1
|
||||||
|
MatchersRanges.tests.cpp:<line number>: passed: c, !Contains(1) for: { 4, 5, 6 } not contains element 1
|
||||||
|
MatchersRanges.tests.cpp:<line number>: passed: a, Contains(0, close_enough) for: { 1, 2, 3 } contains element 0
|
||||||
|
MatchersRanges.tests.cpp:<line number>: passed: b, Contains(0, close_enough) for: { 0, 1, 2 } contains element 0
|
||||||
|
MatchersRanges.tests.cpp:<line number>: passed: c, !Contains(0, close_enough) for: { 4, 5, 6 } not contains element 0
|
||||||
|
MatchersRanges.tests.cpp:<line number>: passed: a, Contains(4, [](auto&& lhs, size_t sz) { return lhs.size() == sz; }) for: { "abc", "abcd", "abcde" } contains element 4
|
||||||
|
MatchersRanges.tests.cpp:<line number>: passed: in, Contains(1) for: { 1, 2, 3, 4, 5 } contains element 1
|
||||||
|
MatchersRanges.tests.cpp:<line number>: passed: in, !Contains(8) for: { 1, 2, 3, 4, 5 } not contains element 8
|
||||||
|
MatchersRanges.tests.cpp:<line number>: passed: in, Contains(MoveOnlyTestElement{ 2 }) for: { 1, 2, 3 } contains element 2
|
||||||
|
MatchersRanges.tests.cpp:<line number>: passed: in, !Contains(MoveOnlyTestElement{ 9 }) for: { 1, 2, 3 } not contains element 9
|
||||||
|
MatchersRanges.tests.cpp:<line number>: passed: in, Contains(Catch::Matchers::WithinAbs(0.5, 0.5)) for: { 1.0, 2.0, 3.0, 0.0 } contains element matching is within 0.5 of 0.5
|
||||||
Message.tests.cpp:<line number>: passed: with 7 messages: 'a := 1' and 'b := 2' and 'c := 3' and 'a + b := 3' and 'a+b := 3' and 'c > b := true' and 'a == 1 := true'
|
Message.tests.cpp:<line number>: passed: with 7 messages: 'a := 1' and 'b := 2' and 'c := 3' and 'a + b := 3' and 'a+b := 3' and 'c > b := true' and 'a == 1 := true'
|
||||||
Message.tests.cpp:<line number>: passed: with 7 messages: 'std::vector<int>{1, 2, 3}[0, 1, 2] := 3' and 'std::vector<int>{1, 2, 3}[(0, 1)] := 2' and 'std::vector<int>{1, 2, 3}[0] := 1' and '(helper_1436<int, int>{12, -12}) := { 12, -12 }' and '(helper_1436<int, int>(-12, 12)) := { -12, 12 }' and '(1, 2) := 2' and '(2, 3) := 3'
|
Message.tests.cpp:<line number>: passed: with 7 messages: 'std::vector<int>{1, 2, 3}[0, 1, 2] := 3' and 'std::vector<int>{1, 2, 3}[(0, 1)] := 2' and 'std::vector<int>{1, 2, 3}[0] := 1' and '(helper_1436<int, int>{12, -12}) := { 12, -12 }' and '(helper_1436<int, int>(-12, 12)) := { -12, 12 }' and '(1, 2) := 2' and '(2, 3) := 3'
|
||||||
Message.tests.cpp:<line number>: passed: with 11 messages: '("comma, in string", "escaped, \", ") := "escaped, ", "' and '"single quote in string,'," := "single quote in string,',"' and '"some escapes, \\,\\\\" := "some escapes, \,\\"' and '"some, ), unmatched, } prenheses {[<" := "some, ), unmatched, } prenheses {[<"' and ''"' := '"'' and ''\'' := '''' and '',' := ','' and ''}' := '}'' and '')' := ')'' and ''(' := '('' and ''{' := '{''
|
Message.tests.cpp:<line number>: passed: with 11 messages: '("comma, in string", "escaped, \", ") := "escaped, ", "' and '"single quote in string,'," := "single quote in string,',"' and '"some escapes, \\,\\\\" := "some escapes, \,\\"' and '"some, ), unmatched, } prenheses {[<" := "some, ), unmatched, } prenheses {[<"' and ''"' := '"'' and ''\'' := '''' and '',' := ','' and ''}' := '}'' and '')' := ')'' and ''(' := '('' and ''{' := '{''
|
||||||
|
@ -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: 328 | 254 passed | 70 failed | 4 failed as expected
|
test cases: 329 | 255 passed | 70 failed | 4 failed as expected
|
||||||
assertions: 1839 | 1687 passed | 131 failed | 21 failed as expected
|
assertions: 1851 | 1699 passed | 131 failed | 21 failed as expected
|
||||||
|
|
||||||
|
@ -1948,6 +1948,108 @@ Tricky.tests.cpp:<line number>
|
|||||||
Tricky.tests.cpp:<line number>: PASSED:
|
Tricky.tests.cpp:<line number>: PASSED:
|
||||||
REQUIRE( true )
|
REQUIRE( true )
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Basic use of the Contains range matcher
|
||||||
|
Different argument ranges, same element type, default comparison
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
MatchersRanges.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( a, Contains(1) )
|
||||||
|
with expansion:
|
||||||
|
{ 1, 2, 3 } contains element 1
|
||||||
|
|
||||||
|
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( b, Contains(1) )
|
||||||
|
with expansion:
|
||||||
|
{ 0, 1, 2 } contains element 1
|
||||||
|
|
||||||
|
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( c, !Contains(1) )
|
||||||
|
with expansion:
|
||||||
|
{ 4, 5, 6 } not contains element 1
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Basic use of the Contains range matcher
|
||||||
|
Different argument ranges, same element type, custom comparison
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
MatchersRanges.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( a, Contains(0, close_enough) )
|
||||||
|
with expansion:
|
||||||
|
{ 1, 2, 3 } contains element 0
|
||||||
|
|
||||||
|
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( b, Contains(0, close_enough) )
|
||||||
|
with expansion:
|
||||||
|
{ 0, 1, 2 } contains element 0
|
||||||
|
|
||||||
|
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( c, !Contains(0, close_enough) )
|
||||||
|
with expansion:
|
||||||
|
{ 4, 5, 6 } not contains element 0
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Basic use of the Contains range matcher
|
||||||
|
Different element type, custom comparisons
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
MatchersRanges.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( a, Contains(4, [](auto&& lhs, size_t sz) { return lhs.size() == sz; }) )
|
||||||
|
with expansion:
|
||||||
|
{ "abc", "abcd", "abcde" } contains element 4
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Basic use of the Contains range matcher
|
||||||
|
Can handle type that requires ADL-found free function begin and end
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
MatchersRanges.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( in, Contains(1) )
|
||||||
|
with expansion:
|
||||||
|
{ 1, 2, 3, 4, 5 } contains element 1
|
||||||
|
|
||||||
|
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( in, !Contains(8) )
|
||||||
|
with expansion:
|
||||||
|
{ 1, 2, 3, 4, 5 } not contains element 8
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Basic use of the Contains range matcher
|
||||||
|
Initialization with move only types
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
MatchersRanges.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( in, Contains(MoveOnlyTestElement{ 2 }) )
|
||||||
|
with expansion:
|
||||||
|
{ 1, 2, 3 } contains element 2
|
||||||
|
|
||||||
|
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( in, !Contains(MoveOnlyTestElement{ 9 }) )
|
||||||
|
with expansion:
|
||||||
|
{ 1, 2, 3 } not contains element 9
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Basic use of the Contains range matcher
|
||||||
|
Matching using matcher
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
MatchersRanges.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
MatchersRanges.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( in, Contains(Catch::Matchers::WithinAbs(0.5, 0.5)) )
|
||||||
|
with expansion:
|
||||||
|
{ 1.0, 2.0, 3.0, 0.0 } contains element matching is within 0.5 of 0.5
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
CAPTURE can deal with complex expressions
|
CAPTURE can deal with complex expressions
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -14396,6 +14498,6 @@ Misc.tests.cpp:<line number>
|
|||||||
Misc.tests.cpp:<line number>: PASSED:
|
Misc.tests.cpp:<line number>: PASSED:
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
test cases: 328 | 238 passed | 86 failed | 4 failed as expected
|
test cases: 329 | 239 passed | 86 failed | 4 failed as expected
|
||||||
assertions: 1856 | 1687 passed | 148 failed | 21 failed as expected
|
assertions: 1868 | 1699 passed | 148 failed | 21 failed as expected
|
||||||
|
|
||||||
|
@ -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="1857" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
<testsuite name="<exe-name>" errors="17" failures="132" tests="1869" 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"/>
|
||||||
@ -342,6 +342,12 @@ Exception.tests.cpp:<line number>
|
|||||||
<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}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Assertions then sections/A section/Another other section" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Assertions then sections/A section/Another other section" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Basic use of the Contains range matcher/Different argument ranges, same element type, default comparison" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Basic use of the Contains range matcher/Different argument ranges, same element type, custom comparison" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Basic use of the Contains range matcher/Different element type, custom comparisons" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Basic use of the Contains range matcher/Can handle type that requires ADL-found free function begin and end" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Basic use of the Contains range matcher/Initialization with move only types" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Basic use of the Contains range matcher/Matching using matcher" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="CAPTURE can deal with complex expressions" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="CAPTURE can deal with complex expressions" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="CAPTURE can deal with complex expressions involving commas" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="CAPTURE can deal with complex expressions involving commas" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="CAPTURE parses string and character constants" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="CAPTURE parses string and character constants" time="{duration}"/>
|
||||||
|
@ -1215,6 +1215,14 @@ Matchers.tests.cpp:<line number>
|
|||||||
</failure>
|
</failure>
|
||||||
</testCase>
|
</testCase>
|
||||||
</file>
|
</file>
|
||||||
|
<file path="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp">
|
||||||
|
<testCase name="Basic use of the Contains range matcher/Different argument ranges, same element type, default comparison" duration="{duration}"/>
|
||||||
|
<testCase name="Basic use of the Contains range matcher/Different argument ranges, same element type, custom comparison" duration="{duration}"/>
|
||||||
|
<testCase name="Basic use of the Contains range matcher/Different element type, custom comparisons" duration="{duration}"/>
|
||||||
|
<testCase name="Basic use of the Contains range matcher/Can handle type that requires ADL-found free function begin and end" duration="{duration}"/>
|
||||||
|
<testCase name="Basic use of the Contains range matcher/Initialization with move only types" duration="{duration}"/>
|
||||||
|
<testCase name="Basic use of the Contains range matcher/Matching using matcher" duration="{duration}"/>
|
||||||
|
</file>
|
||||||
<file path="tests/<exe-name>/UsageTests/Message.tests.cpp">
|
<file path="tests/<exe-name>/UsageTests/Message.tests.cpp">
|
||||||
<testCase name="#1455 - INFO and WARN can start with a linebreak" duration="{duration}"/>
|
<testCase name="#1455 - INFO and WARN can start with a linebreak" duration="{duration}"/>
|
||||||
<testCase name="CAPTURE can deal with complex expressions" duration="{duration}"/>
|
<testCase name="CAPTURE can deal with complex expressions" duration="{duration}"/>
|
||||||
|
@ -486,6 +486,30 @@ ok {test-number} - true
|
|||||||
ok {test-number} - true
|
ok {test-number} - true
|
||||||
# Assertions then sections
|
# Assertions then sections
|
||||||
ok {test-number} - true
|
ok {test-number} - true
|
||||||
|
# Basic use of the Contains range matcher
|
||||||
|
ok {test-number} - a, Contains(1) for: { 1, 2, 3 } contains element 1
|
||||||
|
# Basic use of the Contains range matcher
|
||||||
|
ok {test-number} - b, Contains(1) for: { 0, 1, 2 } contains element 1
|
||||||
|
# Basic use of the Contains range matcher
|
||||||
|
ok {test-number} - c, !Contains(1) for: { 4, 5, 6 } not contains element 1
|
||||||
|
# Basic use of the Contains range matcher
|
||||||
|
ok {test-number} - a, Contains(0, close_enough) for: { 1, 2, 3 } contains element 0
|
||||||
|
# Basic use of the Contains range matcher
|
||||||
|
ok {test-number} - b, Contains(0, close_enough) for: { 0, 1, 2 } contains element 0
|
||||||
|
# Basic use of the Contains range matcher
|
||||||
|
ok {test-number} - c, !Contains(0, close_enough) for: { 4, 5, 6 } not contains element 0
|
||||||
|
# Basic use of the Contains range matcher
|
||||||
|
ok {test-number} - a, Contains(4, [](auto&& lhs, size_t sz) { return lhs.size() == sz; }) for: { "abc", "abcd", "abcde" } contains element 4
|
||||||
|
# Basic use of the Contains range matcher
|
||||||
|
ok {test-number} - in, Contains(1) for: { 1, 2, 3, 4, 5 } contains element 1
|
||||||
|
# Basic use of the Contains range matcher
|
||||||
|
ok {test-number} - in, !Contains(8) for: { 1, 2, 3, 4, 5 } not contains element 8
|
||||||
|
# Basic use of the Contains range matcher
|
||||||
|
ok {test-number} - in, Contains(MoveOnlyTestElement{ 2 }) for: { 1, 2, 3 } contains element 2
|
||||||
|
# Basic use of the Contains range matcher
|
||||||
|
ok {test-number} - in, !Contains(MoveOnlyTestElement{ 9 }) for: { 1, 2, 3 } not contains element 9
|
||||||
|
# Basic use of the Contains range matcher
|
||||||
|
ok {test-number} - in, Contains(Catch::Matchers::WithinAbs(0.5, 0.5)) for: { 1.0, 2.0, 3.0, 0.0 } contains element matching is within 0.5 of 0.5
|
||||||
# CAPTURE can deal with complex expressions
|
# CAPTURE can deal with complex expressions
|
||||||
ok {test-number} - with 7 messages: 'a := 1' and 'b := 2' and 'c := 3' and 'a + b := 3' and 'a+b := 3' and 'c > b := true' and 'a == 1 := true'
|
ok {test-number} - with 7 messages: 'a := 1' and 'b := 2' and 'c := 3' and 'a + b := 3' and 'a+b := 3' and 'c > b := true' and 'a == 1 := true'
|
||||||
# CAPTURE can deal with complex expressions involving commas
|
# CAPTURE can deal with complex expressions involving commas
|
||||||
@ -3704,5 +3728,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..1848
|
1..1860
|
||||||
|
|
||||||
|
@ -193,6 +193,8 @@ Exception.tests.cpp:<line number>|nunexpected exception with message:|n "unexpe
|
|||||||
##teamcity[testFinished name='Arbitrary predicate matcher' duration="{duration}"]
|
##teamcity[testFinished name='Arbitrary predicate matcher' 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[testFinished name='Basic use of the Contains range matcher' duration="{duration}"]
|
||||||
##teamcity[testStarted name='CAPTURE can deal with complex expressions']
|
##teamcity[testStarted name='CAPTURE can deal with complex expressions']
|
||||||
##teamcity[testFinished name='CAPTURE can deal with complex expressions' duration="{duration}"]
|
##teamcity[testFinished name='CAPTURE can deal with complex expressions' duration="{duration}"]
|
||||||
##teamcity[testStarted name='CAPTURE can deal with complex expressions involving commas']
|
##teamcity[testStarted name='CAPTURE can deal with complex expressions involving commas']
|
||||||
|
@ -2178,6 +2178,123 @@ Nor would this
|
|||||||
</Section>
|
</Section>
|
||||||
<OverallResult success="true"/>
|
<OverallResult success="true"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
|
<TestCase name="Basic use of the Contains range matcher" tags="[contains][matchers][templated]" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||||
|
<Section name="Different argument ranges, same element type, default comparison" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
a, Contains(1)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ 1, 2, 3 } contains element 1
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
b, Contains(1)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ 0, 1, 2 } contains element 1
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
c, !Contains(1)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ 4, 5, 6 } not contains element 1
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResults successes="3" failures="0" expectedFailures="0"/>
|
||||||
|
</Section>
|
||||||
|
<Section name="Different argument ranges, same element type, custom comparison" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
a, Contains(0, close_enough)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ 1, 2, 3 } contains element 0
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
b, Contains(0, close_enough)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ 0, 1, 2 } contains element 0
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
c, !Contains(0, close_enough)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ 4, 5, 6 } not contains element 0
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResults successes="3" failures="0" expectedFailures="0"/>
|
||||||
|
</Section>
|
||||||
|
<Section name="Different element type, custom comparisons" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
a, Contains(4, [](auto&& lhs, size_t sz) { return lhs.size() == sz; })
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ "abc", "abcd", "abcde" } contains element 4
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResults successes="1" failures="0" expectedFailures="0"/>
|
||||||
|
</Section>
|
||||||
|
<Section name="Can handle type that requires ADL-found free function begin and end" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
in, Contains(1)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ 1, 2, 3, 4, 5 } contains element 1
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
in, !Contains(8)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ 1, 2, 3, 4, 5 } not contains element 8
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResults successes="2" failures="0" expectedFailures="0"/>
|
||||||
|
</Section>
|
||||||
|
<Section name="Initialization with move only types" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
in, Contains(MoveOnlyTestElement{ 2 })
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ 1, 2, 3 } contains element 2
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
in, !Contains(MoveOnlyTestElement{ 9 })
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ 1, 2, 3 } not contains element 9
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResults successes="2" failures="0" expectedFailures="0"/>
|
||||||
|
</Section>
|
||||||
|
<Section name="Matching using matcher" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
in, Contains(Catch::Matchers::WithinAbs(0.5, 0.5))
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ 1.0, 2.0, 3.0, 0.0 } contains element matching is within 0.5 of 0.5
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResults successes="1" failures="0" expectedFailures="0"/>
|
||||||
|
</Section>
|
||||||
|
<OverallResult success="true"/>
|
||||||
|
</TestCase>
|
||||||
<TestCase name="CAPTURE can deal with complex expressions" tags="[capture][messages]" filename="tests/<exe-name>/UsageTests/Message.tests.cpp" >
|
<TestCase name="CAPTURE can deal with complex expressions" tags="[capture][messages]" filename="tests/<exe-name>/UsageTests/Message.tests.cpp" >
|
||||||
<Info>
|
<Info>
|
||||||
a := 1
|
a := 1
|
||||||
@ -17264,7 +17381,7 @@ loose text artifact
|
|||||||
</Section>
|
</Section>
|
||||||
<OverallResult success="true"/>
|
<OverallResult success="true"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
<OverallResults successes="1687" failures="149" expectedFailures="21"/>
|
<OverallResults successes="1699" failures="149" expectedFailures="21"/>
|
||||||
</Group>
|
</Group>
|
||||||
<OverallResults successes="1687" failures="148" expectedFailures="21"/>
|
<OverallResults successes="1699" failures="148" expectedFailures="21"/>
|
||||||
</Catch>
|
</Catch>
|
||||||
|
107
tests/SelfTest/UsageTests/MatchersRanges.tests.cpp
Normal file
107
tests/SelfTest/UsageTests/MatchersRanges.tests.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
#include <catch2/matchers/catch_matchers_contains.hpp>
|
||||||
|
#include <catch2/matchers/catch_matchers_floating.hpp>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cmath>
|
||||||
|
#include <list>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace unrelated {
|
||||||
|
class needs_ADL_begin {
|
||||||
|
std::array<int, 5> elements{ {1, 2, 3, 4, 5} };
|
||||||
|
public:
|
||||||
|
using iterator = std::array<int, 5>::iterator;
|
||||||
|
using const_iterator = std::array<int, 5>::const_iterator;
|
||||||
|
|
||||||
|
const_iterator Begin() const { return elements.begin(); }
|
||||||
|
const_iterator End() const { return elements.end(); }
|
||||||
|
|
||||||
|
friend const_iterator begin(needs_ADL_begin const& lhs) {
|
||||||
|
return lhs.Begin();
|
||||||
|
}
|
||||||
|
friend const_iterator end(needs_ADL_begin const& rhs) {
|
||||||
|
return rhs.End();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // end anon namespace
|
||||||
|
|
||||||
|
struct MoveOnlyTestElement {
|
||||||
|
int num = 0;
|
||||||
|
MoveOnlyTestElement(int n) :num(n) {}
|
||||||
|
|
||||||
|
MoveOnlyTestElement(MoveOnlyTestElement&& rhs) = default;
|
||||||
|
MoveOnlyTestElement& operator=(MoveOnlyTestElement&& rhs) = default;
|
||||||
|
|
||||||
|
friend bool operator==(MoveOnlyTestElement const& lhs, MoveOnlyTestElement const& rhs) {
|
||||||
|
return lhs.num == rhs.num;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend std::ostream& operator<<(std::ostream& out, MoveOnlyTestElement const& elem) {
|
||||||
|
out << elem.num;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CASE("Basic use of the Contains range matcher", "[matchers][templated][contains]") {
|
||||||
|
using Catch::Matchers::Contains;
|
||||||
|
|
||||||
|
SECTION("Different argument ranges, same element type, default comparison") {
|
||||||
|
std::array<int, 3> a{ { 1,2,3 } };
|
||||||
|
std::vector<int> b{ 0,1,2 };
|
||||||
|
std::list<int> c{ 4,5,6 };
|
||||||
|
|
||||||
|
// A contains 1
|
||||||
|
REQUIRE_THAT(a, Contains(1));
|
||||||
|
// B contains 1
|
||||||
|
REQUIRE_THAT(b, Contains(1));
|
||||||
|
// C does not contain 1
|
||||||
|
REQUIRE_THAT(c, !Contains(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Different argument ranges, same element type, custom comparison") {
|
||||||
|
std::array<int, 3> a{ { 1,2,3 } };
|
||||||
|
std::vector<int> b{ 0,1,2 };
|
||||||
|
std::list<int> c{ 4,5,6 };
|
||||||
|
|
||||||
|
auto close_enough = [](int lhs, int rhs) { return std::abs(lhs - rhs) <= 1; };
|
||||||
|
|
||||||
|
// A contains 1, which is "close enough" to 0
|
||||||
|
REQUIRE_THAT(a, Contains(0, close_enough));
|
||||||
|
// B contains 0 directly
|
||||||
|
REQUIRE_THAT(b, Contains(0, close_enough));
|
||||||
|
// C does not contain anything "close enough" to 0
|
||||||
|
REQUIRE_THAT(c, !Contains(0, close_enough));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Different element type, custom comparisons") {
|
||||||
|
std::array<std::string, 3> a{ { "abc", "abcd" , "abcde" } };
|
||||||
|
|
||||||
|
REQUIRE_THAT(a, Contains(4, [](auto&& lhs, size_t sz) {
|
||||||
|
return lhs.size() == sz;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Can handle type that requires ADL-found free function begin and end") {
|
||||||
|
unrelated::needs_ADL_begin in;
|
||||||
|
|
||||||
|
REQUIRE_THAT(in, Contains(1));
|
||||||
|
REQUIRE_THAT(in, !Contains(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Initialization with move only types") {
|
||||||
|
std::array<MoveOnlyTestElement, 3> in{ { MoveOnlyTestElement{ 1 }, MoveOnlyTestElement{ 2 }, MoveOnlyTestElement{ 3 } } };
|
||||||
|
|
||||||
|
REQUIRE_THAT(in, Contains(MoveOnlyTestElement{ 2 }));
|
||||||
|
REQUIRE_THAT(in, !Contains(MoveOnlyTestElement{ 9 }));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Matching using matcher") {
|
||||||
|
std::array<double, 4> in{ {1, 2, 3} };
|
||||||
|
|
||||||
|
REQUIRE_THAT(in, Contains(Catch::Matchers::WithinAbs(0.5, 0.5)));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user