mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-11-04 09:01:50 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			183 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			183 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
 *  Created by Phil Nash on 21/02/2017.
 | 
						|
 *  Copyright (c) 2017 Two Blue Cubes Ltd. All rights reserved.
 | 
						|
 *
 | 
						|
 * 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_VECTOR_H_INCLUDED
 | 
						|
#define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
 | 
						|
 | 
						|
#include "catch_matchers.h"
 | 
						|
#include "catch_approx.h"
 | 
						|
 | 
						|
#include <algorithm>
 | 
						|
 | 
						|
namespace Catch {
 | 
						|
namespace Matchers {
 | 
						|
 | 
						|
    namespace Vector {
 | 
						|
        template<typename T>
 | 
						|
        struct ContainsElementMatcher : MatcherBase<std::vector<T>> {
 | 
						|
 | 
						|
            ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
 | 
						|
 | 
						|
            bool match(std::vector<T> const &v) const override {
 | 
						|
                for (auto const& el : v) {
 | 
						|
                    if (el == m_comparator) {
 | 
						|
                        return true;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                return false;
 | 
						|
            }
 | 
						|
 | 
						|
            std::string describe() const override {
 | 
						|
                return "Contains: " + ::Catch::Detail::stringify( m_comparator );
 | 
						|
            }
 | 
						|
 | 
						|
            T const& m_comparator;
 | 
						|
        };
 | 
						|
 | 
						|
        template<typename T>
 | 
						|
        struct ContainsMatcher : MatcherBase<std::vector<T>> {
 | 
						|
 | 
						|
            ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
 | 
						|
 | 
						|
            bool match(std::vector<T> const &v) const override {
 | 
						|
                // !TBD: see note in EqualsMatcher
 | 
						|
                if (m_comparator.size() > v.size())
 | 
						|
                    return false;
 | 
						|
                for (auto const& comparator : m_comparator) {
 | 
						|
                    auto present = false;
 | 
						|
                    for (const auto& el : v) {
 | 
						|
                        if (el == comparator) {
 | 
						|
                            present = true;
 | 
						|
                            break;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    if (!present) {
 | 
						|
                        return false;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                return true;
 | 
						|
            }
 | 
						|
            std::string describe() const override {
 | 
						|
                return "Contains: " + ::Catch::Detail::stringify( m_comparator );
 | 
						|
            }
 | 
						|
 | 
						|
            std::vector<T> const& m_comparator;
 | 
						|
        };
 | 
						|
 | 
						|
        template<typename T>
 | 
						|
        struct EqualsMatcher : MatcherBase<std::vector<T>> {
 | 
						|
 | 
						|
            EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
 | 
						|
 | 
						|
            bool match(std::vector<T> const &v) const override {
 | 
						|
                // !TBD: This currently works if all elements can be compared using !=
 | 
						|
                // - a more general approach would be via a compare template that defaults
 | 
						|
                // to using !=. but could be specialised for, e.g. std::vector<T> etc
 | 
						|
                // - then just call that directly
 | 
						|
                if (m_comparator.size() != v.size())
 | 
						|
                    return false;
 | 
						|
                for (std::size_t i = 0; i < v.size(); ++i)
 | 
						|
                    if (m_comparator[i] != v[i])
 | 
						|
                        return false;
 | 
						|
                return true;
 | 
						|
            }
 | 
						|
            std::string describe() const override {
 | 
						|
                return "Equals: " + ::Catch::Detail::stringify( m_comparator );
 | 
						|
            }
 | 
						|
            std::vector<T> const& m_comparator;
 | 
						|
        };
 | 
						|
 | 
						|
        template<typename T>
 | 
						|
        struct ApproxMatcher : MatcherBase<std::vector<T>> {
 | 
						|
 | 
						|
            ApproxMatcher(std::vector<T> const& comparator) : m_comparator( comparator ) {}
 | 
						|
 | 
						|
            bool match(std::vector<T> const &v) const override {
 | 
						|
                if (m_comparator.size() != v.size())
 | 
						|
                    return false;
 | 
						|
                for (std::size_t i = 0; i < v.size(); ++i)
 | 
						|
                    if (m_comparator[i] != approx(v[i]))
 | 
						|
                        return false;
 | 
						|
                return true;
 | 
						|
            }
 | 
						|
            std::string describe() const override {
 | 
						|
                return "is approx: " + ::Catch::Detail::stringify( m_comparator );
 | 
						|
            }
 | 
						|
            template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
 | 
						|
            ApproxMatcher& epsilon( T const& newEpsilon ) {
 | 
						|
                approx.epsilon(newEpsilon);
 | 
						|
                return *this;
 | 
						|
            }
 | 
						|
            template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
 | 
						|
            ApproxMatcher& margin( T const& newMargin ) {
 | 
						|
                approx.margin(newMargin);
 | 
						|
                return *this;
 | 
						|
            }
 | 
						|
            template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
 | 
						|
            ApproxMatcher& scale( T const& newScale ) {
 | 
						|
                approx.scale(newScale);
 | 
						|
                return *this;
 | 
						|
            }
 | 
						|
 | 
						|
            std::vector<T> const& m_comparator;
 | 
						|
            mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom();
 | 
						|
        };
 | 
						|
 | 
						|
        template<typename T>
 | 
						|
        struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> {
 | 
						|
            UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {}
 | 
						|
            bool match(std::vector<T> const& vec) const override {
 | 
						|
                // Note: This is a reimplementation of std::is_permutation,
 | 
						|
                //       because I don't want to include <algorithm> inside the common path
 | 
						|
                if (m_target.size() != vec.size()) {
 | 
						|
                    return false;
 | 
						|
                }
 | 
						|
                return std::is_permutation(m_target.begin(), m_target.end(), vec.begin());
 | 
						|
            }
 | 
						|
 | 
						|
            std::string describe() const override {
 | 
						|
                return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
 | 
						|
            }
 | 
						|
        private:
 | 
						|
            std::vector<T> const& m_target;
 | 
						|
        };
 | 
						|
 | 
						|
    } // namespace Vector
 | 
						|
 | 
						|
    // The following functions create the actual matcher objects.
 | 
						|
    // This allows the types to be inferred
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {
 | 
						|
        return Vector::ContainsMatcher<T>( comparator );
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) {
 | 
						|
        return Vector::ContainsElementMatcher<T>( comparator );
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {
 | 
						|
        return Vector::EqualsMatcher<T>( comparator );
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    Vector::ApproxMatcher<T> Approx( std::vector<T> const& comparator ) {
 | 
						|
        return Vector::ApproxMatcher<T>( comparator );
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) {
 | 
						|
        return Vector::UnorderedEqualsMatcher<T>(target);
 | 
						|
    }
 | 
						|
 | 
						|
} // namespace Matchers
 | 
						|
} // namespace Catch
 | 
						|
 | 
						|
#endif // TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
 |