Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJohn Beard2023-01-21 23:33:04 +0000
committerGitHub2023-01-22 00:33:04 +0100
commitefca9a0f1826885c1574ed44fc37c8d82ded4546 (patch)
tree1b7284ecb35feae1e7134ccd7eb3503b4e91c991
parentdd36f83b88f3a3d7796469bb2d91f9af71bfa675 (diff)
downloadcatch3-efca9a0f1826885c1574ed44fc37c8d82ded4546.tar.gz
Added ElementsAre and UnorderedElementsAre (#2377)
Co-authored-by: Garz4 <fancygarz4@gmail.com> Co-authored-by: Martin Hořeňovský <martin.horenovsky@gmail.com>
-rw-r--r--docs/matchers.md23
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/catch2/matchers/catch_matchers_all.hpp1
-rw-r--r--src/catch2/matchers/catch_matchers_range_equals.hpp136
-rw-r--r--tests/SelfTest/Baselines/automake.sw.approved.txt3
-rw-r--r--tests/SelfTest/Baselines/automake.sw.multi.approved.txt3
-rw-r--r--tests/SelfTest/Baselines/compact.sw.approved.txt40
-rw-r--r--tests/SelfTest/Baselines/compact.sw.multi.approved.txt40
-rw-r--r--tests/SelfTest/Baselines/console.std.approved.txt4
-rw-r--r--tests/SelfTest/Baselines/console.sw.approved.txt375
-rw-r--r--tests/SelfTest/Baselines/console.sw.multi.approved.txt375
-rw-r--r--tests/SelfTest/Baselines/junit.sw.approved.txt26
-rw-r--r--tests/SelfTest/Baselines/junit.sw.multi.approved.txt26
-rw-r--r--tests/SelfTest/Baselines/sonarqube.sw.approved.txt24
-rw-r--r--tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt24
-rw-r--r--tests/SelfTest/Baselines/tap.sw.approved.txt74
-rw-r--r--tests/SelfTest/Baselines/tap.sw.multi.approved.txt74
-rw-r--r--tests/SelfTest/Baselines/teamcity.sw.approved.txt6
-rw-r--r--tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt6
-rw-r--r--tests/SelfTest/Baselines/xml.sw.approved.txt434
-rw-r--r--tests/SelfTest/Baselines/xml.sw.multi.approved.txt434
-rw-r--r--tests/SelfTest/UsageTests/MatchersRanges.tests.cpp223
22 files changed, 2334 insertions, 18 deletions
diff --git a/docs/matchers.md b/docs/matchers.md
index 8940b6ad..c702fec0 100644
--- a/docs/matchers.md
+++ b/docs/matchers.md
@@ -231,6 +231,10 @@ definitions to handle generic range-like types. These are:
* `AllTrue()`
* `NoneTrue()`
* `AnyTrue()`
+* `RangeEquals(TargetRangeLike&&, Comparator = std::equal_to<>{})`
+* `UnorderedRangeEquals(TargetRangeLike&&, Comparator = std::equal_to<>{})`
+
+> `RangeEquals` and `UnorderedRangeEquals` matchers were [introduced](https://github.com/catchorg/Catch2/pull/2377) in Catch2 X.Y.Z
`IsEmpty` should be self-explanatory. It successfully matches objects
that are empty according to either `std::empty`, or ADL-found `empty`
@@ -257,6 +261,25 @@ all, none, or any of the contained elements are `true`, respectively.
It works for ranges of `bool`s and ranges of elements (explicitly)
convertible to `bool`.
+`RangeEquals` compares the range that the matcher is constructed with
+(the "target range") against the range to be tested, element-wise. The
+match succeeds if all elements from the two ranges compare equal (using
+`operator==` by default). The ranges do not need to be the same type,
+and the element types do not need to be the same, as long as they are
+comparable. (e.g. you may compare `std::vector<int>` to `std::array<char>`).
+
+`UnorderedRangeEquals` is similar to `RangeEquals`, but the order
+does not matter. For example "1, 2, 3" would match "3, 2, 1", but not
+"1, 1, 2, 3" As with `RangeEquals`, `UnorderedRangeEquals` compares
+the individual elements using using `operator==` by default.
+
+Both `RangeEquals` and `UnorderedRangeEquals` optionally accept a
+predicate which can be used to compare the containers element-wise.
+
+To check a container elementwise against a given matcher, use
+`AllMatch`.
+
+
## Writing custom matchers (old style)
The old style of writing matchers has been introduced back in Catch
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2791fa30..1e1e31b7 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -252,6 +252,7 @@ set(MATCHER_HEADERS
${SOURCES_DIR}/matchers/catch_matchers_all.hpp
${SOURCES_DIR}/matchers/catch_matchers_container_properties.hpp
${SOURCES_DIR}/matchers/catch_matchers_contains.hpp
+ ${SOURCES_DIR}/matchers/catch_matchers_range_equals.hpp
${SOURCES_DIR}/matchers/catch_matchers_exception.hpp
${SOURCES_DIR}/matchers/catch_matchers_floating_point.hpp
${SOURCES_DIR}/matchers/catch_matchers_predicate.hpp
diff --git a/src/catch2/matchers/catch_matchers_all.hpp b/src/catch2/matchers/catch_matchers_all.hpp
index eadf7082..83fe5386 100644
--- a/src/catch2/matchers/catch_matchers_all.hpp
+++ b/src/catch2/matchers/catch_matchers_all.hpp
@@ -27,6 +27,7 @@
#include <catch2/matchers/catch_matchers_floating_point.hpp>
#include <catch2/matchers/catch_matchers_predicate.hpp>
#include <catch2/matchers/catch_matchers_quantifiers.hpp>
+#include <catch2/matchers/catch_matchers_range_equals.hpp>
#include <catch2/matchers/catch_matchers_string.hpp>
#include <catch2/matchers/catch_matchers_templated.hpp>
#include <catch2/matchers/catch_matchers_vector.hpp>
diff --git a/src/catch2/matchers/catch_matchers_range_equals.hpp b/src/catch2/matchers/catch_matchers_range_equals.hpp
new file mode 100644
index 00000000..bc94e696
--- /dev/null
+++ b/src/catch2/matchers/catch_matchers_range_equals.hpp
@@ -0,0 +1,136 @@
+
+// Copyright Catch2 Authors
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE.txt or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+
+// SPDX-License-Identifier: BSL-1.0
+#ifndef CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
+#define CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
+
+#include <algorithm>
+#include <catch2/matchers/catch_matchers_templated.hpp>
+#include <utility>
+
+namespace Catch {
+ namespace Matchers {
+
+ /**
+ * Matcher for checking that an element contains the same
+ * elements in the same order
+ */
+ template <typename TargetRangeLike, typename Equality>
+ class RangeEqualsMatcher final : public MatcherGenericBase {
+ TargetRangeLike m_desired;
+ Equality m_predicate;
+
+ public:
+ template <typename TargetRangeLike2, typename Equality2>
+ RangeEqualsMatcher( TargetRangeLike2&& range,
+ Equality2&& predicate ):
+ m_desired( CATCH_FORWARD( range ) ),
+ m_predicate( CATCH_FORWARD( predicate ) ) {}
+
+ template <typename RangeLike>
+ bool match( RangeLike&& rng ) const {
+ using std::begin;
+ using std::end;
+ return std::equal( begin(m_desired),
+ end(m_desired),
+ begin(rng),
+ end(rng),
+ m_predicate );
+ }
+
+ std::string describe() const override {
+ return "elements are " + Catch::Detail::stringify( m_desired );
+ }
+ };
+
+ /**
+ * Matcher for checking that an element contains the same
+ * elements (but not necessarily in the same order)
+ */
+ template <typename TargetRangeLike, typename Equality>
+ class UnorderedRangeEqualsMatcher final : public MatcherGenericBase {
+ TargetRangeLike m_desired;
+ Equality m_predicate;
+
+ public:
+ template <typename TargetRangeLike2, typename Equality2>
+ UnorderedRangeEqualsMatcher( TargetRangeLike2&& range,
+ Equality2&& predicate ):
+ m_desired( CATCH_FORWARD( range ) ),
+ m_predicate( CATCH_FORWARD( predicate ) ) {}
+
+ template <typename RangeLike>
+ bool match( RangeLike&& rng ) const {
+ using std::begin;
+ using std::end;
+ return std::is_permutation( begin( m_desired ),
+ end( m_desired ),
+ begin( rng ),
+ end( rng ),
+ m_predicate );
+ }
+
+ std::string describe() const override {
+ return "unordered elements are " +
+ ::Catch::Detail::stringify( m_desired );
+ }
+ };
+
+ /**
+ * Creates a matcher that checks if all elements in a range are equal
+ * to all elements in another range.
+ *
+ * Uses `std::equal_to` to do the comparison
+ */
+ template <typename RangeLike>
+ std::enable_if_t<!Detail::is_matcher<RangeLike>::value,
+ RangeEqualsMatcher<RangeLike, std::equal_to<>>>
+ RangeEquals( RangeLike&& range ) {
+ return { CATCH_FORWARD( range ), std::equal_to<>{} };
+ }
+
+ /**
+ * Creates a matcher that checks if all elements in a range are equal
+ * to all elements in another range.
+ *
+ * Uses to provided predicate `predicate` to do the comparisons
+ */
+ template <typename RangeLike, typename Equality>
+ RangeEqualsMatcher<RangeLike, Equality>
+ RangeEquals( RangeLike&& range, Equality&& predicate ) {
+ return { CATCH_FORWARD( 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
+ *
+ * Uses `std::equal_to` to do the comparison
+ */
+ template <typename RangeLike>
+ std::enable_if_t<
+ !Detail::is_matcher<RangeLike>::value,
+ UnorderedRangeEqualsMatcher<RangeLike, std::equal_to<>>>
+ UnorderedRangeEquals( RangeLike&& range ) {
+ return { CATCH_FORWARD( range ), std::equal_to<>{} };
+ }
+
+ /**
+ * Creates a matcher that checks if all elements in a range are equal
+ * to all elements in another range, in some permuation.
+ *
+ * Uses to provided predicate `predicate` to do the comparisons
+ */
+ template <typename RangeLike, typename Equality>
+ UnorderedRangeEqualsMatcher<RangeLike, Equality>
+ UnorderedRangeEquals( RangeLike&& range, Equality&& predicate ) {
+ return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) };
+ }
+ } // namespace Matchers
+} // namespace Catch
+
+#endif // CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
diff --git a/tests/SelfTest/Baselines/automake.sw.approved.txt b/tests/SelfTest/Baselines/automake.sw.approved.txt
index 64e92396..1262ba98 100644
--- a/tests/SelfTest/Baselines/automake.sw.approved.txt
+++ b/tests/SelfTest/Baselines/automake.sw.approved.txt
@@ -269,6 +269,7 @@ Message from section two
:test-result: FAIL Thrown string literals are translated
:test-result: PASS Tracker
:test-result: PASS Trim strings
+:test-result: PASS Type conversions of RangeEquals and similar
:test-result: FAIL Unexpected exceptions can be translated
:test-result: PASS Upcasting special member functions
:test-result: PASS Usage of AllMatch range matcher
@@ -277,6 +278,8 @@ Message from section two
:test-result: PASS Usage of AnyTrue range matcher
:test-result: PASS Usage of NoneMatch range matcher
:test-result: PASS Usage of NoneTrue range matcher
+:test-result: PASS Usage of RangeEquals range matcher
+:test-result: PASS Usage of UnorderedRangeEquals range matcher
:test-result: PASS Usage of the SizeIs range matcher
:test-result: PASS Use a custom approx
:test-result: PASS Variadic macros
diff --git a/tests/SelfTest/Baselines/automake.sw.multi.approved.txt b/tests/SelfTest/Baselines/automake.sw.multi.approved.txt
index d6f5ebe9..e8c6a77b 100644
--- a/tests/SelfTest/Baselines/automake.sw.multi.approved.txt
+++ b/tests/SelfTest/Baselines/automake.sw.multi.approved.txt
@@ -262,6 +262,7 @@
:test-result: FAIL Thrown string literals are translated
:test-result: PASS Tracker
:test-result: PASS Trim strings
+:test-result: PASS Type conversions of RangeEquals and similar
:test-result: FAIL Unexpected exceptions can be translated
:test-result: PASS Upcasting special member functions
:test-result: PASS Usage of AllMatch range matcher
@@ -270,6 +271,8 @@
:test-result: PASS Usage of AnyTrue range matcher
:test-result: PASS Usage of NoneMatch range matcher
:test-result: PASS Usage of NoneTrue range matcher
+:test-result: PASS Usage of RangeEquals range matcher
+:test-result: PASS Usage of UnorderedRangeEquals range matcher
:test-result: PASS Usage of the SizeIs range matcher
:test-result: PASS Use a custom approx
:test-result: PASS Variadic macros
diff --git a/tests/SelfTest/Baselines/compact.sw.approved.txt b/tests/SelfTest/Baselines/compact.sw.approved.txt
index 1d8ea9a8..4ef3912e 100644
--- a/tests/SelfTest/Baselines/compact.sw.approved.txt
+++ b/tests/SelfTest/Baselines/compact.sw.approved.txt
@@ -1859,6 +1859,23 @@ There is no extra whitespace here
StringManip.tests.cpp:<line number>: passed: trim(StringRef(whitespace_at_both_ends)) == StringRef(no_whitespace) for: There is no extra whitespace here
==
There is no extra whitespace here
+MatchersRanges.tests.cpp:<line number>: passed: array_int_a, RangeEquals( c_array ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: array_int_a, UnorderedRangeEquals( c_array ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: array_int_3, !RangeEquals( array_int_4 ) for: { 1, 2, 3 } not elements are { 1, 2, 3, 4 }
+MatchersRanges.tests.cpp:<line number>: passed: array_int_3, !UnorderedRangeEquals( array_int_4 ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }
+MatchersRanges.tests.cpp:<line number>: passed: array_int_a, RangeEquals( vector_char_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: array_int_a, UnorderedRangeEquals( vector_char_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: with 1 message: 'ContainerIsRandomAccess( array_int_a ) != ContainerIsRandomAccess( list_char_a )'
+MatchersRanges.tests.cpp:<line number>: passed: array_int_a, RangeEquals( list_char_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: array_int_a, UnorderedRangeEquals( list_char_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: vector_int_a, RangeEquals( vector_char_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: vector_int_a, UnorderedRangeEquals( vector_char_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: vector_int_a, !RangeEquals( vector_char_b ) for: { 1, 2, 3 } not elements are { 1, 2, 2 }
+MatchersRanges.tests.cpp:<line number>: passed: vector_int_a, !UnorderedRangeEquals( vector_char_b ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 2 }
+MatchersRanges.tests.cpp:<line number>: passed: a, !RangeEquals( b ) for: { 1, 2, 3 } not elements are { 3, 2, 1 }
+MatchersRanges.tests.cpp:<line number>: passed: a, UnorderedRangeEquals( b ) for: { 1, 2, 3 } unordered elements are { 3, 2, 1 }
+MatchersRanges.tests.cpp:<line number>: passed: vector_a, RangeEquals( array_a_plus_1, close_enough ) for: { 1, 2, 3 } elements are { 2, 3, 4 }
+MatchersRanges.tests.cpp:<line number>: passed: vector_a, UnorderedRangeEquals( array_a_plus_1, close_enough ) for: { 1, 2, 3 } unordered elements are { 2, 3, 4 }
Exception.tests.cpp:<line number>: failed: unexpected exception with message: '3.14'
UniquePtr.tests.cpp:<line number>: passed: bptr->i == 3 for: 3 == 3
UniquePtr.tests.cpp:<line number>: passed: bptr->i == 3 for: 3 == 3
@@ -1964,6 +1981,25 @@ MatchersRanges.tests.cpp:<line number>: passed: mocked.m_derefed[1] for: true
MatchersRanges.tests.cpp:<line number>: passed: mocked.m_derefed[2] for: true
MatchersRanges.tests.cpp:<line number>: passed: !(mocked.m_derefed[3]) for: !false
MatchersRanges.tests.cpp:<line number>: passed: !(mocked.m_derefed[4]) for: !false
+MatchersRanges.tests.cpp:<line number>: passed: empty_vector, RangeEquals( empty_vector ) for: { } elements are { }
+MatchersRanges.tests.cpp:<line number>: passed: empty_vector, !RangeEquals( non_empty_vector ) for: { } not elements are { 1 }
+MatchersRanges.tests.cpp:<line number>: passed: non_empty_vector, !RangeEquals( empty_vector ) for: { 1 } not elements are { }
+MatchersRanges.tests.cpp:<line number>: passed: non_empty_array, RangeEquals( non_empty_array ) for: { 1 } elements are { 1 }
+MatchersRanges.tests.cpp:<line number>: passed: array_a, RangeEquals( array_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: array_a, !RangeEquals( array_b ) for: { 1, 2, 3 } not elements are { 2, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: array_a, !RangeEquals( array_c ) for: { 1, 2, 3 } not elements are { 1, 2, 2 }
+MatchersRanges.tests.cpp:<line number>: passed: vector_a, !RangeEquals( vector_b ) for: { 1, 2, 3 } not elements are { 1, 2, 3, 4 }
+MatchersRanges.tests.cpp:<line number>: passed: vector_a, RangeEquals( vector_a_plus_1, close_enough ) for: { 1, 2, 3 } elements are { 2, 3, 4 }
+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: empty_vector, UnorderedRangeEquals( empty_vector ) for: { } unordered elements are { }
+MatchersRanges.tests.cpp:<line number>: passed: empty_vector, !UnorderedRangeEquals( non_empty_vector ) for: { } not unordered elements are { 1 }
+MatchersRanges.tests.cpp:<line number>: passed: non_empty_vector, !UnorderedRangeEquals( empty_vector ) for: { 1 } not unordered elements are { }
+MatchersRanges.tests.cpp:<line number>: passed: non_empty_array, UnorderedRangeEquals( non_empty_array ) for: { 1 } unordered elements are { 1 }
+MatchersRanges.tests.cpp:<line number>: passed: array_a, UnorderedRangeEquals( array_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: array_a, !UnorderedRangeEquals( array_b ) for: { 1, 2, 3 } not unordered elements are { 2, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: vector_a, !UnorderedRangeEquals( vector_b ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }
+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: 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
@@ -2485,7 +2521,7 @@ InternalBenchmark.tests.cpp:<line number>: passed: med == 18. for: 18.0 == 18.0
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: 404 | 305 passed | 84 failed | 5 skipped | 10 failed as expected
-assertions: 2173 | 1997 passed | 145 failed | 31 failed as expected
+test cases: 407 | 308 passed | 84 failed | 5 skipped | 10 failed as expected
+assertions: 2209 | 2033 passed | 145 failed | 31 failed as expected
diff --git a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt
index 1b450553..b74d1e04 100644
--- a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt
+++ b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt
@@ -1852,6 +1852,23 @@ There is no extra whitespace here
StringManip.tests.cpp:<line number>: passed: trim(StringRef(whitespace_at_both_ends)) == StringRef(no_whitespace) for: There is no extra whitespace here
==
There is no extra whitespace here
+MatchersRanges.tests.cpp:<line number>: passed: array_int_a, RangeEquals( c_array ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: array_int_a, UnorderedRangeEquals( c_array ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: array_int_3, !RangeEquals( array_int_4 ) for: { 1, 2, 3 } not elements are { 1, 2, 3, 4 }
+MatchersRanges.tests.cpp:<line number>: passed: array_int_3, !UnorderedRangeEquals( array_int_4 ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }
+MatchersRanges.tests.cpp:<line number>: passed: array_int_a, RangeEquals( vector_char_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: array_int_a, UnorderedRangeEquals( vector_char_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: with 1 message: 'ContainerIsRandomAccess( array_int_a ) != ContainerIsRandomAccess( list_char_a )'
+MatchersRanges.tests.cpp:<line number>: passed: array_int_a, RangeEquals( list_char_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: array_int_a, UnorderedRangeEquals( list_char_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: vector_int_a, RangeEquals( vector_char_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: vector_int_a, UnorderedRangeEquals( vector_char_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: vector_int_a, !RangeEquals( vector_char_b ) for: { 1, 2, 3 } not elements are { 1, 2, 2 }
+MatchersRanges.tests.cpp:<line number>: passed: vector_int_a, !UnorderedRangeEquals( vector_char_b ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 2 }
+MatchersRanges.tests.cpp:<line number>: passed: a, !RangeEquals( b ) for: { 1, 2, 3 } not elements are { 3, 2, 1 }
+MatchersRanges.tests.cpp:<line number>: passed: a, UnorderedRangeEquals( b ) for: { 1, 2, 3 } unordered elements are { 3, 2, 1 }
+MatchersRanges.tests.cpp:<line number>: passed: vector_a, RangeEquals( array_a_plus_1, close_enough ) for: { 1, 2, 3 } elements are { 2, 3, 4 }
+MatchersRanges.tests.cpp:<line number>: passed: vector_a, UnorderedRangeEquals( array_a_plus_1, close_enough ) for: { 1, 2, 3 } unordered elements are { 2, 3, 4 }
Exception.tests.cpp:<line number>: failed: unexpected exception with message: '3.14'
UniquePtr.tests.cpp:<line number>: passed: bptr->i == 3 for: 3 == 3
UniquePtr.tests.cpp:<line number>: passed: bptr->i == 3 for: 3 == 3
@@ -1957,6 +1974,25 @@ MatchersRanges.tests.cpp:<line number>: passed: mocked.m_derefed[1] for: true
MatchersRanges.tests.cpp:<line number>: passed: mocked.m_derefed[2] for: true
MatchersRanges.tests.cpp:<line number>: passed: !(mocked.m_derefed[3]) for: !false
MatchersRanges.tests.cpp:<line number>: passed: !(mocked.m_derefed[4]) for: !false
+MatchersRanges.tests.cpp:<line number>: passed: empty_vector, RangeEquals( empty_vector ) for: { } elements are { }
+MatchersRanges.tests.cpp:<line number>: passed: empty_vector, !RangeEquals( non_empty_vector ) for: { } not elements are { 1 }
+MatchersRanges.tests.cpp:<line number>: passed: non_empty_vector, !RangeEquals( empty_vector ) for: { 1 } not elements are { }
+MatchersRanges.tests.cpp:<line number>: passed: non_empty_array, RangeEquals( non_empty_array ) for: { 1 } elements are { 1 }
+MatchersRanges.tests.cpp:<line number>: passed: array_a, RangeEquals( array_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: array_a, !RangeEquals( array_b ) for: { 1, 2, 3 } not elements are { 2, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: array_a, !RangeEquals( array_c ) for: { 1, 2, 3 } not elements are { 1, 2, 2 }
+MatchersRanges.tests.cpp:<line number>: passed: vector_a, !RangeEquals( vector_b ) for: { 1, 2, 3 } not elements are { 1, 2, 3, 4 }
+MatchersRanges.tests.cpp:<line number>: passed: vector_a, RangeEquals( vector_a_plus_1, close_enough ) for: { 1, 2, 3 } elements are { 2, 3, 4 }
+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: empty_vector, UnorderedRangeEquals( empty_vector ) for: { } unordered elements are { }
+MatchersRanges.tests.cpp:<line number>: passed: empty_vector, !UnorderedRangeEquals( non_empty_vector ) for: { } not unordered elements are { 1 }
+MatchersRanges.tests.cpp:<line number>: passed: non_empty_vector, !UnorderedRangeEquals( empty_vector ) for: { 1 } not unordered elements are { }
+MatchersRanges.tests.cpp:<line number>: passed: non_empty_array, UnorderedRangeEquals( non_empty_array ) for: { 1 } unordered elements are { 1 }
+MatchersRanges.tests.cpp:<line number>: passed: array_a, UnorderedRangeEquals( array_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: array_a, !UnorderedRangeEquals( array_b ) for: { 1, 2, 3 } not unordered elements are { 2, 2, 3 }
+MatchersRanges.tests.cpp:<line number>: passed: vector_a, !UnorderedRangeEquals( vector_b ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }
+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: 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
@@ -2474,7 +2510,7 @@ InternalBenchmark.tests.cpp:<line number>: passed: med == 18. for: 18.0 == 18.0
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: 404 | 305 passed | 84 failed | 5 skipped | 10 failed as expected
-assertions: 2173 | 1997 passed | 145 failed | 31 failed as expected
+test cases: 407 | 308 passed | 84 failed | 5 skipped | 10 failed as expected
+assertions: 2209 | 2033 passed | 145 failed | 31 failed as expected
diff --git a/tests/SelfTest/Baselines/console.std.approved.txt b/tests/SelfTest/Baselines/console.std.approved.txt
index dd3199f0..fdbe43e2 100644
--- a/tests/SelfTest/Baselines/console.std.approved.txt
+++ b/tests/SelfTest/Baselines/console.std.approved.txt
@@ -1523,6 +1523,6 @@ due to unexpected exception with message:
Why would you throw a std::string?
===============================================================================
-test cases: 404 | 319 passed | 69 failed | 6 skipped | 10 failed as expected
-assertions: 2156 | 1997 passed | 128 failed | 31 failed as expected
+test cases: 407 | 322 passed | 69 failed | 6 skipped | 10 failed as expected
+assertions: 2192 | 2033 passed | 128 failed | 31 failed as expected
diff --git a/tests/SelfTest/Baselines/console.sw.approved.txt b/tests/SelfTest/Baselines/console.sw.approved.txt
index 48609d97..826a78ad 100644
--- a/tests/SelfTest/Baselines/console.sw.approved.txt
+++ b/tests/SelfTest/Baselines/console.sw.approved.txt
@@ -13099,6 +13099,154 @@ with expansion:
There is no extra whitespace here
-------------------------------------------------------------------------------
+Type conversions of RangeEquals and similar
+ Container conversions
+ Two equal containers of different container types
+-------------------------------------------------------------------------------
+MatchersRanges.tests.cpp:<line number>
+...............................................................................
+
+MatchersRanges.tests.cpp:<line number>: PASSED:
+ CHECK_THAT( array_int_a, RangeEquals( c_array ) )
+with expansion:
+ { 1, 2, 3 } elements are { 1, 2, 3 }
+
+MatchersRanges.tests.cpp:<line number>: PASSED:
+ CHECK_THAT( array_int_a, UnorderedRangeEquals( c_array ) )
+with expansion:
+ { 1, 2, 3 } unordered elements are { 1, 2, 3 }
+
+-------------------------------------------------------------------------------
+Type conversions of RangeEquals and similar
+ Container conversions
+ Two equal containers of different container types (differ in array N)
+-------------------------------------------------------------------------------
+MatchersRanges.tests.cpp:<line number>
+...............................................................................
+
+MatchersRanges.tests.cpp:<line number>: PASSED:
+ CHECK_THAT( array_int_3, !RangeEquals( array_int_4 ) )
+with expansion:
+ { 1, 2, 3 } not elements are { 1, 2, 3, 4 }
+
+MatchersRanges.tests.cpp:<line number>: PASSED:
+ CHECK_THAT( array_int_3, !UnorderedRangeEquals( array_int_4 ) )
+with expansion:
+ { 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }
+
+-------------------------------------------------------------------------------
+Type conversions of RangeEquals and similar
+ Container conversions
+ Two equal containers of different container types and value types
+-------------------------------------------------------------------------------
+MatchersRanges.tests.cpp:<line number>
+...............................................................................
+
+MatchersRanges.tests.cpp:<line number>: PASSED:
+ CHECK_THAT( array_int_a, RangeEquals( vector_char_a ) )
+with expansion:
+ { 1, 2, 3 } elements are { 1, 2, 3 }
+
+MatchersRanges.tests.cpp:<line number>: PASSED:
+ CHECK_THAT( array_int_a, UnorderedRangeEquals( vector_char_a ) )
+with expansion:
+ { 1, 2, 3 } unordered elements are { 1, 2, 3 }
+
+-------------------------------------------------------------------------------
+Type conversions of RangeEquals and similar
+ Container conversions
+ Two equal containers, one random access, one not
+-------------------------------------------------------------------------------
+MatchersRanges.tests.cpp:<line number>
+...............................................................................
+
+MatchersRanges.tests.cpp:<line number>: PASSED:
+with message:
+ ContainerIsRandomAccess( array_int_a ) != ContainerIsRandomAccess(
+ list_char_a )
+
+MatchersRanges.tests.cpp:<line number>: PASSED:
+ CHECK_THAT( array_int_a, RangeEquals( list_char_a ) )
+with expansion:
+ { 1, 2, 3 } elements are { 1, 2, 3 }
+
+MatchersRanges.tests.cpp:<line number>: PASSED:
+ CHECK_THAT( array_int_a, UnorderedRangeEquals( list_char_a ) )
+with expansion:
+ { 1, 2, 3 } unordered elements are { 1, 2, 3 }
+
+-------------------------------------------------------------------------------
+Type conversions of RangeEquals and similar
+ Value type
+ Two equal containers of different value types
+-------------------------------------------------------------------------------
+MatchersRanges.tests.cpp:<line number>
+...............................................................................
+
+MatchersRanges.tests.cpp:<line number>: PASSED:
+ CHECK_THAT( vector_int_a, RangeEquals( vector_char_a ) )
+with expansion:
+ { 1, 2, 3 } elements are { 1, 2, 3 }
+
+MatchersRanges.tests.cpp:<line number>: PASSED:
+ CHECK_THAT( vector_int_a, UnorderedRangeEquals( vector_char_a ) )
+with expansion:
+ { 1, 2, 3 } unordered elements are { 1, 2, 3 }
+
+-------------------------------------------------------------------------------
+Type conversions of RangeEquals and similar
+ Value type
+ Two non-equal containers of different value types
+-------------------------------------------------------------------------------
+MatchersRanges.tests.cpp:<line number>
+...............................................................................
+
+MatchersRanges.tests.cpp:<line number>: PASSED:
+ CHECK_THAT( vector_int_a, !RangeEquals( vector_char_b ) )
+with expansion:
+ { 1, 2, 3 } not elements are { 1, 2, 2 }
+
+MatchersRanges.tests.cpp:<line number>: PASSED:
+ CHECK_THAT( vector_int_a, !UnorderedRangeEquals( vector_char_b ) )
+with expansion:
+ { 1, 2, 3 } not unordered elements are { 1, 2, 2 }
+
+-------------------------------------------------------------------------------
+Type conversions of RangeEquals and similar
+ Ranges with begin that needs ADL
+-------------------------------------------------------------------------------
+MatchersRanges.tests.cpp:<line number>
+...............................................................................
+
+MatchersRanges.tests.cpp:<line n