catch_matchers.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /*
  2. * Created by Phil Nash on 04/03/2012.
  3. * Copyright (c) 2012 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_HPP_INCLUDED
  9. #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
  10. #include "catch_common.h"
  11. #include <string>
  12. #include <vector>
  13. namespace Catch {
  14. namespace Matchers {
  15. namespace Impl {
  16. template<typename ArgT> struct MatchAllOf;
  17. template<typename ArgT> struct MatchAnyOf;
  18. template<typename ArgT> struct MatchNotOf;
  19. class MatcherUntypedBase {
  20. public:
  21. MatcherUntypedBase() = default;
  22. MatcherUntypedBase ( MatcherUntypedBase const& ) = default;
  23. MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete;
  24. std::string toString() const;
  25. protected:
  26. virtual ~MatcherUntypedBase();
  27. virtual std::string describe() const = 0;
  28. mutable std::string m_cachedToString;
  29. };
  30. #ifdef __clang__
  31. # pragma clang diagnostic push
  32. # pragma clang diagnostic ignored "-Wnon-virtual-dtor"
  33. #endif
  34. template<typename ObjectT>
  35. struct MatcherMethod {
  36. virtual bool match( ObjectT const& arg ) const = 0;
  37. };
  38. #if defined(__OBJC__)
  39. // Hack to fix Catch GH issue #1661. Could use id for generic Object support.
  40. // use of const for Object pointers is very uncommon and under ARC it causes some kind of signature mismatch that breaks compilation
  41. template<>
  42. struct MatcherMethod<NSString*> {
  43. virtual bool match( NSString* arg ) const = 0;
  44. };
  45. #endif
  46. #ifdef __clang__
  47. # pragma clang diagnostic pop
  48. #endif
  49. template<typename T>
  50. struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> {
  51. MatchAllOf<T> operator && ( MatcherBase const& other ) const;
  52. MatchAnyOf<T> operator || ( MatcherBase const& other ) const;
  53. MatchNotOf<T> operator ! () const;
  54. };
  55. template<typename ArgT>
  56. struct MatchAllOf : MatcherBase<ArgT> {
  57. bool match( ArgT const& arg ) const override {
  58. for( auto matcher : m_matchers ) {
  59. if (!matcher->match(arg))
  60. return false;
  61. }
  62. return true;
  63. }
  64. std::string describe() const override {
  65. std::string description;
  66. description.reserve( 4 + m_matchers.size()*32 );
  67. description += "( ";
  68. bool first = true;
  69. for( auto matcher : m_matchers ) {
  70. if( first )
  71. first = false;
  72. else
  73. description += " and ";
  74. description += matcher->toString();
  75. }
  76. description += " )";
  77. return description;
  78. }
  79. MatchAllOf<ArgT> operator && ( MatcherBase<ArgT> const& other ) {
  80. auto copy(*this);
  81. copy.m_matchers.push_back( &other );
  82. return copy;
  83. }
  84. std::vector<MatcherBase<ArgT> const*> m_matchers;
  85. };
  86. template<typename ArgT>
  87. struct MatchAnyOf : MatcherBase<ArgT> {
  88. bool match( ArgT const& arg ) const override {
  89. for( auto matcher : m_matchers ) {
  90. if (matcher->match(arg))
  91. return true;
  92. }
  93. return false;
  94. }
  95. std::string describe() const override {
  96. std::string description;
  97. description.reserve( 4 + m_matchers.size()*32 );
  98. description += "( ";
  99. bool first = true;
  100. for( auto matcher : m_matchers ) {
  101. if( first )
  102. first = false;
  103. else
  104. description += " or ";
  105. description += matcher->toString();
  106. }
  107. description += " )";
  108. return description;
  109. }
  110. MatchAnyOf<ArgT> operator || ( MatcherBase<ArgT> const& other ) {
  111. auto copy(*this);
  112. copy.m_matchers.push_back( &other );
  113. return copy;
  114. }
  115. std::vector<MatcherBase<ArgT> const*> m_matchers;
  116. };
  117. template<typename ArgT>
  118. struct MatchNotOf : MatcherBase<ArgT> {
  119. MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {}
  120. bool match( ArgT const& arg ) const override {
  121. return !m_underlyingMatcher.match( arg );
  122. }
  123. std::string describe() const override {
  124. return "not " + m_underlyingMatcher.toString();
  125. }
  126. MatcherBase<ArgT> const& m_underlyingMatcher;
  127. };
  128. template<typename T>
  129. MatchAllOf<T> MatcherBase<T>::operator && ( MatcherBase const& other ) const {
  130. return MatchAllOf<T>() && *this && other;
  131. }
  132. template<typename T>
  133. MatchAnyOf<T> MatcherBase<T>::operator || ( MatcherBase const& other ) const {
  134. return MatchAnyOf<T>() || *this || other;
  135. }
  136. template<typename T>
  137. MatchNotOf<T> MatcherBase<T>::operator ! () const {
  138. return MatchNotOf<T>( *this );
  139. }
  140. } // namespace Impl
  141. } // namespace Matchers
  142. using namespace Matchers;
  143. using Matchers::Impl::MatcherBase;
  144. } // namespace Catch
  145. #endif // TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED