mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-11-04 05:59:32 +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:
		
							
								
								
									
										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)));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user