catch_matchers_vector.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * Created by Phil Nash on 21/02/2017.
  3. * Copyright (c) 2017 Two Blue Cubes Ltd. All rights reserved.
  4. *
  5. * Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. */
  8. #ifndef TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
  9. #define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
  10. #include "catch_matchers.h"
  11. #include "catch_approx.h"
  12. #include <algorithm>
  13. namespace Catch {
  14. namespace Matchers {
  15. namespace Vector {
  16. template<typename T, typename Alloc>
  17. struct ContainsElementMatcher : MatcherBase<std::vector<T, Alloc>> {
  18. ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
  19. bool match(std::vector<T, Alloc> const &v) const override {
  20. for (auto const& el : v) {
  21. if (el == m_comparator) {
  22. return true;
  23. }
  24. }
  25. return false;
  26. }
  27. std::string describe() const override {
  28. return "Contains: " + ::Catch::Detail::stringify( m_comparator );
  29. }
  30. T const& m_comparator;
  31. };
  32. template<typename T, typename AllocComp, typename AllocMatch>
  33. struct ContainsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
  34. ContainsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {}
  35. bool match(std::vector<T, AllocMatch> const &v) const override {
  36. // !TBD: see note in EqualsMatcher
  37. if (m_comparator.size() > v.size())
  38. return false;
  39. for (auto const& comparator : m_comparator) {
  40. auto present = false;
  41. for (const auto& el : v) {
  42. if (el == comparator) {
  43. present = true;
  44. break;
  45. }
  46. }
  47. if (!present) {
  48. return false;
  49. }
  50. }
  51. return true;
  52. }
  53. std::string describe() const override {
  54. return "Contains: " + ::Catch::Detail::stringify( m_comparator );
  55. }
  56. std::vector<T, AllocComp> const& m_comparator;
  57. };
  58. template<typename T, typename AllocComp, typename AllocMatch>
  59. struct EqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
  60. EqualsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {}
  61. bool match(std::vector<T, AllocMatch> const &v) const override {
  62. // !TBD: This currently works if all elements can be compared using !=
  63. // - a more general approach would be via a compare template that defaults
  64. // to using !=. but could be specialised for, e.g. std::vector<T, Alloc> etc
  65. // - then just call that directly
  66. if (m_comparator.size() != v.size())
  67. return false;
  68. for (std::size_t i = 0; i < v.size(); ++i)
  69. if (m_comparator[i] != v[i])
  70. return false;
  71. return true;
  72. }
  73. std::string describe() const override {
  74. return "Equals: " + ::Catch::Detail::stringify( m_comparator );
  75. }
  76. std::vector<T, AllocComp> const& m_comparator;
  77. };
  78. template<typename T, typename AllocComp, typename AllocMatch>
  79. struct ApproxMatcher : MatcherBase<std::vector<T, AllocMatch>> {
  80. ApproxMatcher(std::vector<T, AllocComp> const& comparator) : m_comparator( comparator ) {}
  81. bool match(std::vector<T, AllocMatch> const &v) const override {
  82. if (m_comparator.size() != v.size())
  83. return false;
  84. for (std::size_t i = 0; i < v.size(); ++i)
  85. if (m_comparator[i] != approx(v[i]))
  86. return false;
  87. return true;
  88. }
  89. std::string describe() const override {
  90. return "is approx: " + ::Catch::Detail::stringify( m_comparator );
  91. }
  92. template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
  93. ApproxMatcher& epsilon( T const& newEpsilon ) {
  94. approx.epsilon(newEpsilon);
  95. return *this;
  96. }
  97. template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
  98. ApproxMatcher& margin( T const& newMargin ) {
  99. approx.margin(newMargin);
  100. return *this;
  101. }
  102. template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
  103. ApproxMatcher& scale( T const& newScale ) {
  104. approx.scale(newScale);
  105. return *this;
  106. }
  107. std::vector<T, AllocComp> const& m_comparator;
  108. mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom();
  109. };
  110. template<typename T, typename AllocComp, typename AllocMatch>
  111. struct UnorderedEqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
  112. UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target) : m_target(target) {}
  113. bool match(std::vector<T, AllocMatch> const& vec) const override {
  114. if (m_target.size() != vec.size()) {
  115. return false;
  116. }
  117. return std::is_permutation(m_target.begin(), m_target.end(), vec.begin());
  118. }
  119. std::string describe() const override {
  120. return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
  121. }
  122. private:
  123. std::vector<T, AllocComp> const& m_target;
  124. };
  125. } // namespace Vector
  126. // The following functions create the actual matcher objects.
  127. // This allows the types to be inferred
  128. template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
  129. Vector::ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) {
  130. return Vector::ContainsMatcher<T, AllocComp, AllocMatch>( comparator );
  131. }
  132. template<typename T, typename Alloc = std::allocator<T>>
  133. Vector::ContainsElementMatcher<T, Alloc> VectorContains( T const& comparator ) {
  134. return Vector::ContainsElementMatcher<T, Alloc>( comparator );
  135. }
  136. template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
  137. Vector::EqualsMatcher<T, AllocComp, AllocMatch> Equals( std::vector<T, AllocComp> const& comparator ) {
  138. return Vector::EqualsMatcher<T, AllocComp, AllocMatch>( comparator );
  139. }
  140. template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
  141. Vector::ApproxMatcher<T, AllocComp, AllocMatch> Approx( std::vector<T, AllocComp> const& comparator ) {
  142. return Vector::ApproxMatcher<T, AllocComp, AllocMatch>( comparator );
  143. }
  144. template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
  145. Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch> UnorderedEquals(std::vector<T, AllocComp> const& target) {
  146. return Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch>( target );
  147. }
  148. } // namespace Matchers
  149. } // namespace Catch
  150. #endif // TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED