Skip to content

Commit

Permalink
Provide overloads for {Unordered}RangeEquals taking a std::initialize…
Browse files Browse the repository at this point in the history
…r_list

This allows writing something like

  const auto v = calculateSomeVectorOfInts();
  CHECK_THAT(v, RangeEquals({1, 2, 3}));

Fixes #2915.
  • Loading branch information
Stefan Haller authored and horenmar committed Oct 14, 2024
1 parent 1e0ccb1 commit 69d62ab
Show file tree
Hide file tree
Showing 15 changed files with 238 additions and 11 deletions.
32 changes: 32 additions & 0 deletions src/catch2/matchers/catch_matchers_range_equals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,22 @@ namespace Catch {
return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) };
}

/**
* Creates a matcher that checks if all elements in a range are equal
* to all elements in an initializer list.
*
* Uses the provided predicate `predicate` to do the comparisons
* (defaulting to `std::equal_to`)
*/
template <typename T,
typename Equality = decltype( std::equal_to<>{} )>
constexpr
RangeEqualsMatcher<std::initializer_list<T>, Equality>
RangeEquals( std::initializer_list<T> range,
Equality&& predicate = std::equal_to<>{} ) {
return { range, CATCH_FORWARD( predicate ) };
}

/**
* Creates a matcher that checks if all elements in a range are equal
* to all elements in another range, in some permutation.
Expand All @@ -123,6 +139,22 @@ namespace Catch {
Equality&& predicate = std::equal_to<>{} ) {
return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) };
}

/**
* Creates a matcher that checks if all elements in a range are equal
* to all elements in an initializer list, in some permutation.
*
* Uses the provided predicate `predicate` to do the comparisons
* (defaulting to `std::equal_to`)
*/
template <typename T,
typename Equality = decltype( std::equal_to<>{} )>
constexpr
UnorderedRangeEqualsMatcher<std::initializer_list<T>, Equality>
UnorderedRangeEquals( std::initializer_list<T> range,
Equality&& predicate = std::equal_to<>{} ) {
return { range, CATCH_FORWARD( predicate ) };
}
} // namespace Matchers
} // namespace Catch

Expand Down
6 changes: 5 additions & 1 deletion tests/SelfTest/Baselines/compact.sw.approved.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2284,6 +2284,8 @@ MatchersRanges.tests.cpp:<line number>: passed: vector_a, RangeEquals( vector_a_
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !RangeEquals( vector_b, close_enough ) for: { 1, 2, 3 } not elements are { 3, 3, 4 }
MatchersRanges.tests.cpp:<line number>: passed: needs_adl1, RangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } elements are { 1, 2, 3, 4, 5 }
MatchersRanges.tests.cpp:<line number>: passed: needs_adl1, RangeEquals( needs_adl3, []( int l, int r ) { return l + 1 == r; } ) for: { 1, 2, 3, 4, 5 } elements are { 2, 3, 4, 5, 6 }
MatchersRanges.tests.cpp:<line number>: passed: array_a, RangeEquals( { 1, 2, 3 } ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: array_a, RangeEquals( { 2, 4, 6 }, []( int l, int r ) { return l * 2 == r; } ) for: { 1, 2, 3 } elements are { 2, 4, 6 }
MatchersRanges.tests.cpp:<line number>: passed: mocked1, !RangeEquals( arr ) for: { 1, 2, 3, 4 } not elements are { 1, 2, 4, 4 }
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[0] for: true
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[1] for: true
Expand All @@ -2304,6 +2306,8 @@ MatchersRanges.tests.cpp:<line number>: passed: vector_a, !UnorderedRangeEquals(
MatchersRanges.tests.cpp:<line number>: passed: vector_a, UnorderedRangeEquals( vector_a_plus_1, close_enough ) for: { 1, 10, 20 } unordered elements are { 11, 21, 2 }
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !UnorderedRangeEquals( vector_b, close_enough ) for: { 1, 10, 21 } not unordered elements are { 11, 21, 3 }
MatchersRanges.tests.cpp:<line number>: passed: needs_adl1, UnorderedRangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } unordered elements are { 1, 2, 3, 4, 5 }
MatchersRanges.tests.cpp:<line number>: passed: array_a, UnorderedRangeEquals( { 10, 20, 1 } ) for: { 1, 10, 20 } unordered elements are { 10, 20, 1 }
MatchersRanges.tests.cpp:<line number>: passed: array_a, UnorderedRangeEquals( { 11, 21, 2 }, []( int l, int r ) { return std::abs( l - r ) <= 1; } ) for: { 1, 10, 20 } unordered elements are { 11, 21, 2 }
MatchersRanges.tests.cpp:<line number>: passed: empty_vec, SizeIs(0) for: { } has size == 0
MatchersRanges.tests.cpp:<line number>: passed: empty_vec, !SizeIs(2) for: { } not has size == 2
MatchersRanges.tests.cpp:<line number>: passed: empty_vec, SizeIs(Lt(2)) for: { } size matches is less than 2
Expand Down Expand Up @@ -2851,6 +2855,6 @@ InternalBenchmark.tests.cpp:<line number>: passed: q3 == 23. for: 23.0 == 23.0
Misc.tests.cpp:<line number>: passed:
Misc.tests.cpp:<line number>: passed:
test cases: 419 | 313 passed | 86 failed | 6 skipped | 14 failed as expected
assertions: 2265 | 2083 passed | 147 failed | 35 failed as expected
assertions: 2269 | 2087 passed | 147 failed | 35 failed as expected


6 changes: 5 additions & 1 deletion tests/SelfTest/Baselines/compact.sw.multi.approved.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2277,6 +2277,8 @@ MatchersRanges.tests.cpp:<line number>: passed: vector_a, RangeEquals( vector_a_
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !RangeEquals( vector_b, close_enough ) for: { 1, 2, 3 } not elements are { 3, 3, 4 }
MatchersRanges.tests.cpp:<line number>: passed: needs_adl1, RangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } elements are { 1, 2, 3, 4, 5 }
MatchersRanges.tests.cpp:<line number>: passed: needs_adl1, RangeEquals( needs_adl3, []( int l, int r ) { return l + 1 == r; } ) for: { 1, 2, 3, 4, 5 } elements are { 2, 3, 4, 5, 6 }
MatchersRanges.tests.cpp:<line number>: passed: array_a, RangeEquals( { 1, 2, 3 } ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: array_a, RangeEquals( { 2, 4, 6 }, []( int l, int r ) { return l * 2 == r; } ) for: { 1, 2, 3 } elements are { 2, 4, 6 }
MatchersRanges.tests.cpp:<line number>: passed: mocked1, !RangeEquals( arr ) for: { 1, 2, 3, 4 } not elements are { 1, 2, 4, 4 }
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[0] for: true
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[1] for: true
Expand All @@ -2297,6 +2299,8 @@ MatchersRanges.tests.cpp:<line number>: passed: vector_a, !UnorderedRangeEquals(
MatchersRanges.tests.cpp:<line number>: passed: vector_a, UnorderedRangeEquals( vector_a_plus_1, close_enough ) for: { 1, 10, 20 } unordered elements are { 11, 21, 2 }
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !UnorderedRangeEquals( vector_b, close_enough ) for: { 1, 10, 21 } not unordered elements are { 11, 21, 3 }
MatchersRanges.tests.cpp:<line number>: passed: needs_adl1, UnorderedRangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } unordered elements are { 1, 2, 3, 4, 5 }
MatchersRanges.tests.cpp:<line number>: passed: array_a, UnorderedRangeEquals( { 10, 20, 1 } ) for: { 1, 10, 20 } unordered elements are { 10, 20, 1 }
MatchersRanges.tests.cpp:<line number>: passed: array_a, UnorderedRangeEquals( { 11, 21, 2 }, []( int l, int r ) { return std::abs( l - r ) <= 1; } ) for: { 1, 10, 20 } unordered elements are { 11, 21, 2 }
MatchersRanges.tests.cpp:<line number>: passed: empty_vec, SizeIs(0) for: { } has size == 0
MatchersRanges.tests.cpp:<line number>: passed: empty_vec, !SizeIs(2) for: { } not has size == 2
MatchersRanges.tests.cpp:<line number>: passed: empty_vec, SizeIs(Lt(2)) for: { } size matches is less than 2
Expand Down Expand Up @@ -2840,6 +2844,6 @@ InternalBenchmark.tests.cpp:<line number>: passed: q3 == 23. for: 23.0 == 23.0
Misc.tests.cpp:<line number>: passed:
Misc.tests.cpp:<line number>: passed:
test cases: 419 | 313 passed | 86 failed | 6 skipped | 14 failed as expected
assertions: 2265 | 2083 passed | 147 failed | 35 failed as expected
assertions: 2269 | 2087 passed | 147 failed | 35 failed as expected


2 changes: 1 addition & 1 deletion tests/SelfTest/Baselines/console.std.approved.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1611,5 +1611,5 @@ due to unexpected exception with message:

===============================================================================
test cases: 419 | 327 passed | 71 failed | 7 skipped | 14 failed as expected
assertions: 2248 | 2083 passed | 130 failed | 35 failed as expected
assertions: 2252 | 2087 passed | 130 failed | 35 failed as expected

36 changes: 35 additions & 1 deletion tests/SelfTest/Baselines/console.sw.approved.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14981,6 +14981,23 @@ MatchersRanges.tests.cpp:<line number>: PASSED:
with expansion:
{ 1, 2, 3, 4, 5 } elements are { 2, 3, 4, 5, 6 }

-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Compare against std::initializer_list
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................

MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( array_a, RangeEquals( { 1, 2, 3 } ) )
with expansion:
{ 1, 2, 3 } elements are { 1, 2, 3 }

MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( array_a, RangeEquals( { 2, 4, 6 }, []( int l, int r ) { return l * 2 == r; } ) )
with expansion:
{ 1, 2, 3 } elements are { 2, 4, 6 }

-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Check short-circuiting behaviour
Expand Down Expand Up @@ -15168,6 +15185,23 @@ MatchersRanges.tests.cpp:<line number>: PASSED:
with expansion:
{ 1, 2, 3, 4, 5 } unordered elements are { 1, 2, 3, 4, 5 }

-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Compare against std::initializer_list
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................

MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( array_a, UnorderedRangeEquals( { 10, 20, 1 } ) )
with expansion:
{ 1, 10, 20 } unordered elements are { 10, 20, 1 }

MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( array_a, UnorderedRangeEquals( { 11, 21, 2 }, []( int l, int r ) { return std::abs( l - r ) <= 1; } ) )
with expansion:
{ 1, 10, 20 } unordered elements are { 11, 21, 2 }

-------------------------------------------------------------------------------
Usage of the SizeIs range matcher
Some with stdlib containers
Expand Down Expand Up @@ -18979,5 +19013,5 @@ Misc.tests.cpp:<line number>: PASSED:

===============================================================================
test cases: 419 | 313 passed | 86 failed | 6 skipped | 14 failed as expected
assertions: 2265 | 2083 passed | 147 failed | 35 failed as expected
assertions: 2269 | 2087 passed | 147 failed | 35 failed as expected

36 changes: 35 additions & 1 deletion tests/SelfTest/Baselines/console.sw.multi.approved.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14974,6 +14974,23 @@ MatchersRanges.tests.cpp:<line number>: PASSED:
with expansion:
{ 1, 2, 3, 4, 5 } elements are { 2, 3, 4, 5, 6 }

-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Compare against std::initializer_list
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................

MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( array_a, RangeEquals( { 1, 2, 3 } ) )
with expansion:
{ 1, 2, 3 } elements are { 1, 2, 3 }

MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( array_a, RangeEquals( { 2, 4, 6 }, []( int l, int r ) { return l * 2 == r; } ) )
with expansion:
{ 1, 2, 3 } elements are { 2, 4, 6 }

-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Check short-circuiting behaviour
Expand Down Expand Up @@ -15161,6 +15178,23 @@ MatchersRanges.tests.cpp:<line number>: PASSED:
with expansion:
{ 1, 2, 3, 4, 5 } unordered elements are { 1, 2, 3, 4, 5 }

-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Compare against std::initializer_list
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................

MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( array_a, UnorderedRangeEquals( { 10, 20, 1 } ) )
with expansion:
{ 1, 10, 20 } unordered elements are { 10, 20, 1 }

MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( array_a, UnorderedRangeEquals( { 11, 21, 2 }, []( int l, int r ) { return std::abs( l - r ) <= 1; } ) )
with expansion:
{ 1, 10, 20 } unordered elements are { 11, 21, 2 }

-------------------------------------------------------------------------------
Usage of the SizeIs range matcher
Some with stdlib containers
Expand Down Expand Up @@ -18968,5 +19002,5 @@ Misc.tests.cpp:<line number>: PASSED:

===============================================================================
test cases: 419 | 313 passed | 86 failed | 6 skipped | 14 failed as expected
assertions: 2265 | 2083 passed | 147 failed | 35 failed as expected
assertions: 2269 | 2087 passed | 147 failed | 35 failed as expected

4 changes: 3 additions & 1 deletion tests/SelfTest/Baselines/junit.sw.approved.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuitesloose text artifact
>
<testsuite name="<exe-name>" errors="17" failures="130" skipped="12" tests="2277" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testsuite name="<exe-name>" errors="17" failures="130" skipped="12" tests="2281" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<properties>
<property name="random-seed" value="1"/>
<property name="filters" value="&quot;*&quot; ~[!nonportable] ~[!benchmark] ~[approvals]"/>
Expand Down Expand Up @@ -1652,6 +1652,7 @@ at Exception.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Custom predicate/Two equal non-empty containers (close enough)" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Custom predicate/Two non-equal non-empty containers (close enough)" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Ranges that need ADL begin/end" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Compare against std::initializer_list" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Check short-circuiting behaviour" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Check short-circuiting behaviour/Check short-circuits on failure" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Check short-circuiting behaviour/All elements are checked on success" time="{duration}" status="run"/>
Expand All @@ -1667,6 +1668,7 @@ at Exception.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Custom predicate/Two equal non-empty containers (close enough)" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Custom predicate/Two non-equal non-empty containers (close enough)" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Ranges that need ADL begin/end" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Compare against std::initializer_list" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of the SizeIs range matcher" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of the SizeIs range matcher/Some with stdlib containers" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of the SizeIs range matcher/Type requires ADL found size free function" time="{duration}" status="run"/>
Expand Down
4 changes: 3 additions & 1 deletion tests/SelfTest/Baselines/junit.sw.multi.approved.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite name="<exe-name>" errors="17" failures="130" skipped="12" tests="2277" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testsuite name="<exe-name>" errors="17" failures="130" skipped="12" tests="2281" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<properties>
<property name="random-seed" value="1"/>
<property name="filters" value="&quot;*&quot; ~[!nonportable] ~[!benchmark] ~[approvals]"/>
Expand Down Expand Up @@ -1651,6 +1651,7 @@ at Exception.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Custom predicate/Two equal non-empty containers (close enough)" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Custom predicate/Two non-equal non-empty containers (close enough)" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Ranges that need ADL begin/end" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Compare against std::initializer_list" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Check short-circuiting behaviour" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Check short-circuiting behaviour/Check short-circuits on failure" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of RangeEquals range matcher/Check short-circuiting behaviour/All elements are checked on success" time="{duration}" status="run"/>
Expand All @@ -1666,6 +1667,7 @@ at Exception.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Custom predicate/Two equal non-empty containers (close enough)" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Custom predicate/Two non-equal non-empty containers (close enough)" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Ranges that need ADL begin/end" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of UnorderedRangeEquals range matcher/Compare against std::initializer_list" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of the SizeIs range matcher" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of the SizeIs range matcher/Some with stdlib containers" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Usage of the SizeIs range matcher/Type requires ADL found size free function" time="{duration}" status="run"/>
Expand Down
Loading

0 comments on commit 69d62ab

Please sign in to comment.