diff options
| author | Lexi Winter <lexi@le-fay.org> | 2025-06-29 19:25:29 +0100 |
|---|---|---|
| committer | Lexi Winter <lexi@le-fay.org> | 2025-06-29 19:25:29 +0100 |
| commit | bc524d70253a4ab2fe40c3ca3e5666e267c0a4d1 (patch) | |
| tree | 1e629e7b46b1d9972a973bc93fd100bcebd395be /src/catch2/matchers/catch_matchers_vector.hpp | |
| download | nihil-bc524d70253a4ab2fe40c3ca3e5666e267c0a4d1.tar.gz nihil-bc524d70253a4ab2fe40c3ca3e5666e267c0a4d1.tar.bz2 | |
import catch2 3.8.1vendor/catch2/3.8.1vendor/catch2
Diffstat (limited to 'src/catch2/matchers/catch_matchers_vector.hpp')
| -rw-r--r-- | src/catch2/matchers/catch_matchers_vector.hpp | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/src/catch2/matchers/catch_matchers_vector.hpp b/src/catch2/matchers/catch_matchers_vector.hpp new file mode 100644 index 0000000..fffbfdf --- /dev/null +++ b/src/catch2/matchers/catch_matchers_vector.hpp @@ -0,0 +1,194 @@ + +// 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_VECTOR_HPP_INCLUDED +#define CATCH_MATCHERS_VECTOR_HPP_INCLUDED + +#include <catch2/matchers/catch_matchers.hpp> +#include <catch2/catch_approx.hpp> + +#include <algorithm> + +namespace Catch { +namespace Matchers { + + template<typename T, typename Alloc> + class VectorContainsElementMatcher final : public MatcherBase<std::vector<T, Alloc>> { + T const& m_comparator; + + public: + VectorContainsElementMatcher(T const& comparator): + m_comparator(comparator) + {} + + bool match(std::vector<T, Alloc> 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 ); + } + }; + + template<typename T, typename AllocComp, typename AllocMatch> + class ContainsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> { + std::vector<T, AllocComp> const& m_comparator; + + public: + ContainsMatcher(std::vector<T, AllocComp> const& comparator): + m_comparator( comparator ) + {} + + bool match(std::vector<T, AllocMatch> 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 ); + } + }; + + template<typename T, typename AllocComp, typename AllocMatch> + class EqualsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> { + std::vector<T, AllocComp> const& m_comparator; + + public: + EqualsMatcher(std::vector<T, AllocComp> const& comparator): + m_comparator( comparator ) + {} + + bool match(std::vector<T, AllocMatch> 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 ); + } + }; + + template<typename T, typename AllocComp, typename AllocMatch> + class ApproxMatcher final : public MatcherBase<std::vector<T, AllocMatch>> { + std::vector<T, AllocComp> const& m_comparator; + mutable Catch::Approx approx = Catch::Approx::custom(); + + public: + ApproxMatcher(std::vector<T, AllocComp> const& comparator): + m_comparator( comparator ) + {} + + bool match(std::vector<T, AllocMatch> 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 = std::enable_if_t<std::is_constructible<double, T>::value>> + ApproxMatcher& epsilon( T const& newEpsilon ) { + approx.epsilon(static_cast<double>(newEpsilon)); + return *this; + } + template <typename = std::enable_if_t<std::is_constructible<double, T>::value>> + ApproxMatcher& margin( T const& newMargin ) { + approx.margin(static_cast<double>(newMargin)); + return *this; + } + template <typename = std::enable_if_t<std::is_constructible<double, T>::value>> + ApproxMatcher& scale( T const& newScale ) { + approx.scale(static_cast<double>(newScale)); + return *this; + } + }; + + template<typename T, typename AllocComp, typename AllocMatch> + class UnorderedEqualsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> { + std::vector<T, AllocComp> const& m_target; + + public: + UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target): + m_target(target) + {} + bool match(std::vector<T, AllocMatch> const& vec) const override { + 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); + } + }; + + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + + //! Creates a matcher that matches vectors that contain all elements in `comparator` + template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> + ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) { + return ContainsMatcher<T, AllocComp, AllocMatch>(comparator); + } + + //! Creates a matcher that matches vectors that contain `comparator` as an element + template<typename T, typename Alloc = std::allocator<T>> + VectorContainsElementMatcher<T, Alloc> VectorContains( T const& comparator ) { + return VectorContainsElementMatcher<T, Alloc>(comparator); + } + + //! Creates a matcher that matches vectors that are exactly equal to `comparator` + template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> + EqualsMatcher<T, AllocComp, AllocMatch> Equals( std::vector<T, AllocComp> const& comparator ) { + return EqualsMatcher<T, AllocComp, AllocMatch>(comparator); + } + + //! Creates a matcher that matches vectors that `comparator` as an element + template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> + ApproxMatcher<T, AllocComp, AllocMatch> Approx( std::vector<T, AllocComp> const& comparator ) { + return ApproxMatcher<T, AllocComp, AllocMatch>(comparator); + } + + //! Creates a matcher that matches vectors that is equal to `target` modulo permutation + template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> + UnorderedEqualsMatcher<T, AllocComp, AllocMatch> UnorderedEquals(std::vector<T, AllocComp> const& target) { + return UnorderedEqualsMatcher<T, AllocComp, AllocMatch>(target); + } + +} // namespace Matchers +} // namespace Catch + +#endif // CATCH_MATCHERS_VECTOR_HPP_INCLUDED |
