gtest-matchers.h (googletest-release-1.11.0) | : | gtest-matchers.h (googletest-release-1.12.0) | ||
---|---|---|---|---|
skipping to change at line 35 | skipping to change at line 35 | |||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
// The Google C++ Testing and Mocking Framework (Google Test) | // The Google C++ Testing and Mocking Framework (Google Test) | |||
// | // | |||
// This file implements just enough of the matcher interface to allow | // This file implements just enough of the matcher interface to allow | |||
// EXPECT_DEATH and friends to accept a matcher argument. | // EXPECT_DEATH and friends to accept a matcher argument. | |||
// IWYU pragma: private, include "gtest/gtest.h" | ||||
// IWYU pragma: friend gtest/.* | ||||
// IWYU pragma: friend gmock/.* | ||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ | #ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ | |||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ | #define GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ | |||
#include <atomic> | #include <atomic> | |||
#include <memory> | #include <memory> | |||
#include <ostream> | #include <ostream> | |||
#include <string> | #include <string> | |||
#include <type_traits> | #include <type_traits> | |||
#include "gtest/gtest-printers.h" | #include "gtest/gtest-printers.h" | |||
skipping to change at line 101 | skipping to change at line 105 | |||
// Returns true if and only if the listener is interested in an explanation | // Returns true if and only if the listener is interested in an explanation | |||
// of the match result. A matcher's MatchAndExplain() method can use | // of the match result. A matcher's MatchAndExplain() method can use | |||
// this information to avoid generating the explanation when no one | // this information to avoid generating the explanation when no one | |||
// intends to hear it. | // intends to hear it. | |||
bool IsInterested() const { return stream_ != nullptr; } | bool IsInterested() const { return stream_ != nullptr; } | |||
private: | private: | |||
::std::ostream* const stream_; | ::std::ostream* const stream_; | |||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MatchResultListener); | MatchResultListener(const MatchResultListener&) = delete; | |||
MatchResultListener& operator=(const MatchResultListener&) = delete; | ||||
}; | }; | |||
inline MatchResultListener::~MatchResultListener() { | inline MatchResultListener::~MatchResultListener() {} | |||
} | ||||
// An instance of a subclass of this knows how to describe itself as a | // An instance of a subclass of this knows how to describe itself as a | |||
// matcher. | // matcher. | |||
class GTEST_API_ MatcherDescriberInterface { | class GTEST_API_ MatcherDescriberInterface { | |||
public: | public: | |||
virtual ~MatcherDescriberInterface() {} | virtual ~MatcherDescriberInterface() {} | |||
// Describes this matcher to an ostream. The function should print | // Describes this matcher to an ostream. The function should print | |||
// a verb phrase that describes the property a value matching this | // a verb phrase that describes the property a value matching this | |||
// matcher should have. The subject of the verb phrase is the value | // matcher should have. The subject of the verb phrase is the value | |||
skipping to change at line 179 | skipping to change at line 183 | |||
// Inherits these methods from MatcherDescriberInterface: | // Inherits these methods from MatcherDescriberInterface: | |||
// virtual void DescribeTo(::std::ostream* os) const = 0; | // virtual void DescribeTo(::std::ostream* os) const = 0; | |||
// virtual void DescribeNegationTo(::std::ostream* os) const; | // virtual void DescribeNegationTo(::std::ostream* os) const; | |||
}; | }; | |||
namespace internal { | namespace internal { | |||
struct AnyEq { | struct AnyEq { | |||
template <typename A, typename B> | template <typename A, typename B> | |||
bool operator()(const A& a, const B& b) const { return a == b; } | bool operator()(const A& a, const B& b) const { | |||
return a == b; | ||||
} | ||||
}; | }; | |||
struct AnyNe { | struct AnyNe { | |||
template <typename A, typename B> | template <typename A, typename B> | |||
bool operator()(const A& a, const B& b) const { return a != b; } | bool operator()(const A& a, const B& b) const { | |||
return a != b; | ||||
} | ||||
}; | }; | |||
struct AnyLt { | struct AnyLt { | |||
template <typename A, typename B> | template <typename A, typename B> | |||
bool operator()(const A& a, const B& b) const { return a < b; } | bool operator()(const A& a, const B& b) const { | |||
return a < b; | ||||
} | ||||
}; | }; | |||
struct AnyGt { | struct AnyGt { | |||
template <typename A, typename B> | template <typename A, typename B> | |||
bool operator()(const A& a, const B& b) const { return a > b; } | bool operator()(const A& a, const B& b) const { | |||
return a > b; | ||||
} | ||||
}; | }; | |||
struct AnyLe { | struct AnyLe { | |||
template <typename A, typename B> | template <typename A, typename B> | |||
bool operator()(const A& a, const B& b) const { return a <= b; } | bool operator()(const A& a, const B& b) const { | |||
return a <= b; | ||||
} | ||||
}; | }; | |||
struct AnyGe { | struct AnyGe { | |||
template <typename A, typename B> | template <typename A, typename B> | |||
bool operator()(const A& a, const B& b) const { return a >= b; } | bool operator()(const A& a, const B& b) const { | |||
return a >= b; | ||||
} | ||||
}; | }; | |||
// A match result listener that ignores the explanation. | // A match result listener that ignores the explanation. | |||
class DummyMatchResultListener : public MatchResultListener { | class DummyMatchResultListener : public MatchResultListener { | |||
public: | public: | |||
DummyMatchResultListener() : MatchResultListener(nullptr) {} | DummyMatchResultListener() : MatchResultListener(nullptr) {} | |||
private: | private: | |||
GTEST_DISALLOW_COPY_AND_ASSIGN_(DummyMatchResultListener); | DummyMatchResultListener(const DummyMatchResultListener&) = delete; | |||
DummyMatchResultListener& operator=(const DummyMatchResultListener&) = delete; | ||||
}; | }; | |||
// A match result listener that forwards the explanation to a given | // A match result listener that forwards the explanation to a given | |||
// ostream. The difference between this and MatchResultListener is | // ostream. The difference between this and MatchResultListener is | |||
// that the former is concrete. | // that the former is concrete. | |||
class StreamMatchResultListener : public MatchResultListener { | class StreamMatchResultListener : public MatchResultListener { | |||
public: | public: | |||
explicit StreamMatchResultListener(::std::ostream* os) | explicit StreamMatchResultListener(::std::ostream* os) | |||
: MatchResultListener(os) {} | : MatchResultListener(os) {} | |||
private: | private: | |||
GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamMatchResultListener); | StreamMatchResultListener(const StreamMatchResultListener&) = delete; | |||
StreamMatchResultListener& operator=(const StreamMatchResultListener&) = | ||||
delete; | ||||
}; | }; | |||
struct SharedPayloadBase { | struct SharedPayloadBase { | |||
std::atomic<int> ref{1}; | std::atomic<int> ref{1}; | |||
void Ref() { ref.fetch_add(1, std::memory_order_relaxed); } | void Ref() { ref.fetch_add(1, std::memory_order_relaxed); } | |||
bool Unref() { return ref.fetch_sub(1, std::memory_order_acq_rel) == 1; } | bool Unref() { return ref.fetch_sub(1, std::memory_order_acq_rel) == 1; } | |||
}; | }; | |||
template <typename T> | template <typename T> | |||
struct SharedPayload : SharedPayloadBase { | struct SharedPayload : SharedPayloadBase { | |||
skipping to change at line 287 | skipping to change at line 306 | |||
// Returns the describer for this matcher object; retains ownership | // Returns the describer for this matcher object; retains ownership | |||
// of the describer, which is only guaranteed to be alive when | // of the describer, which is only guaranteed to be alive when | |||
// this matcher object is alive. | // this matcher object is alive. | |||
const MatcherDescriberInterface* GetDescriber() const { | const MatcherDescriberInterface* GetDescriber() const { | |||
if (vtable_ == nullptr) return nullptr; | if (vtable_ == nullptr) return nullptr; | |||
return vtable_->get_describer(*this); | return vtable_->get_describer(*this); | |||
} | } | |||
protected: | protected: | |||
MatcherBase() : vtable_(nullptr) {} | MatcherBase() : vtable_(nullptr), buffer_() {} | |||
// Constructs a matcher from its implementation. | // Constructs a matcher from its implementation. | |||
template <typename U> | template <typename U> | |||
explicit MatcherBase(const MatcherInterface<U>* impl) { | explicit MatcherBase(const MatcherInterface<U>* impl) | |||
: vtable_(nullptr), buffer_() { | ||||
Init(impl); | Init(impl); | |||
} | } | |||
template <typename M, typename = typename std::remove_reference< | template <typename M, typename = typename std::remove_reference< | |||
M>::type::is_gtest_matcher> | M>::type::is_gtest_matcher> | |||
MatcherBase(M&& m) { // NOLINT | MatcherBase(M&& m) : vtable_(nullptr), buffer_() { // NOLINT | |||
Init(std::forward<M>(m)); | Init(std::forward<M>(m)); | |||
} | } | |||
MatcherBase(const MatcherBase& other) | MatcherBase(const MatcherBase& other) | |||
: vtable_(other.vtable_), buffer_(other.buffer_) { | : vtable_(other.vtable_), buffer_(other.buffer_) { | |||
if (IsShared()) buffer_.shared->Ref(); | if (IsShared()) buffer_.shared->Ref(); | |||
} | } | |||
MatcherBase& operator=(const MatcherBase& other) { | MatcherBase& operator=(const MatcherBase& other) { | |||
if (this == &other) return *this; | if (this == &other) return *this; | |||
skipping to change at line 423 | skipping to change at line 443 | |||
return sizeof(M) <= sizeof(Buffer) && alignof(M) <= alignof(Buffer) && | return sizeof(M) <= sizeof(Buffer) && alignof(M) <= alignof(Buffer) && | |||
std::is_trivially_copy_constructible<M>::value && | std::is_trivially_copy_constructible<M>::value && | |||
std::is_trivially_destructible<M>::value; | std::is_trivially_destructible<M>::value; | |||
} | } | |||
template <typename M, bool = MatcherBase::IsInlined<M>()> | template <typename M, bool = MatcherBase::IsInlined<M>()> | |||
struct ValuePolicy { | struct ValuePolicy { | |||
static const M& Get(const MatcherBase& m) { | static const M& Get(const MatcherBase& m) { | |||
// When inlined along with Init, need to be explicit to avoid violating | // When inlined along with Init, need to be explicit to avoid violating | |||
// strict aliasing rules. | // strict aliasing rules. | |||
const M *ptr = static_cast<const M*>( | const M* ptr = | |||
static_cast<const void*>(&m.buffer_)); | static_cast<const M*>(static_cast<const void*>(&m.buffer_)); | |||
return *ptr; | return *ptr; | |||
} | } | |||
static void Init(MatcherBase& m, M impl) { | static void Init(MatcherBase& m, M impl) { | |||
::new (static_cast<void*>(&m.buffer_)) M(impl); | ::new (static_cast<void*>(&m.buffer_)) M(impl); | |||
} | } | |||
static constexpr auto shared_destroy = nullptr; | static constexpr auto shared_destroy = nullptr; | |||
}; | }; | |||
template <typename M> | template <typename M> | |||
struct ValuePolicy<M, false> { | struct ValuePolicy<M, false> { | |||
skipping to change at line 744 | skipping to change at line 764 | |||
return v; | return v; | |||
} | } | |||
Rhs rhs_; | Rhs rhs_; | |||
}; | }; | |||
template <typename Rhs> | template <typename Rhs> | |||
class EqMatcher : public ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq> { | class EqMatcher : public ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq> { | |||
public: | public: | |||
explicit EqMatcher(const Rhs& rhs) | explicit EqMatcher(const Rhs& rhs) | |||
: ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq>(rhs) { } | : ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq>(rhs) {} | |||
static const char* Desc() { return "is equal to"; } | static const char* Desc() { return "is equal to"; } | |||
static const char* NegatedDesc() { return "isn't equal to"; } | static const char* NegatedDesc() { return "isn't equal to"; } | |||
}; | }; | |||
template <typename Rhs> | template <typename Rhs> | |||
class NeMatcher : public ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe> { | class NeMatcher : public ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe> { | |||
public: | public: | |||
explicit NeMatcher(const Rhs& rhs) | explicit NeMatcher(const Rhs& rhs) | |||
: ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe>(rhs) { } | : ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe>(rhs) {} | |||
static const char* Desc() { return "isn't equal to"; } | static const char* Desc() { return "isn't equal to"; } | |||
static const char* NegatedDesc() { return "is equal to"; } | static const char* NegatedDesc() { return "is equal to"; } | |||
}; | }; | |||
template <typename Rhs> | template <typename Rhs> | |||
class LtMatcher : public ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt> { | class LtMatcher : public ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt> { | |||
public: | public: | |||
explicit LtMatcher(const Rhs& rhs) | explicit LtMatcher(const Rhs& rhs) | |||
: ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt>(rhs) { } | : ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt>(rhs) {} | |||
static const char* Desc() { return "is <"; } | static const char* Desc() { return "is <"; } | |||
static const char* NegatedDesc() { return "isn't <"; } | static const char* NegatedDesc() { return "isn't <"; } | |||
}; | }; | |||
template <typename Rhs> | template <typename Rhs> | |||
class GtMatcher : public ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt> { | class GtMatcher : public ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt> { | |||
public: | public: | |||
explicit GtMatcher(const Rhs& rhs) | explicit GtMatcher(const Rhs& rhs) | |||
: ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt>(rhs) { } | : ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt>(rhs) {} | |||
static const char* Desc() { return "is >"; } | static const char* Desc() { return "is >"; } | |||
static const char* NegatedDesc() { return "isn't >"; } | static const char* NegatedDesc() { return "isn't >"; } | |||
}; | }; | |||
template <typename Rhs> | template <typename Rhs> | |||
class LeMatcher : public ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe> { | class LeMatcher : public ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe> { | |||
public: | public: | |||
explicit LeMatcher(const Rhs& rhs) | explicit LeMatcher(const Rhs& rhs) | |||
: ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe>(rhs) { } | : ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe>(rhs) {} | |||
static const char* Desc() { return "is <="; } | static const char* Desc() { return "is <="; } | |||
static const char* NegatedDesc() { return "isn't <="; } | static const char* NegatedDesc() { return "isn't <="; } | |||
}; | }; | |||
template <typename Rhs> | template <typename Rhs> | |||
class GeMatcher : public ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe> { | class GeMatcher : public ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe> { | |||
public: | public: | |||
explicit GeMatcher(const Rhs& rhs) | explicit GeMatcher(const Rhs& rhs) | |||
: ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe>(rhs) { } | : ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe>(rhs) {} | |||
static const char* Desc() { return "is >="; } | static const char* Desc() { return "is >="; } | |||
static const char* NegatedDesc() { return "isn't >="; } | static const char* NegatedDesc() { return "isn't >="; } | |||
}; | }; | |||
template <typename T, typename = typename std::enable_if< | template <typename T, typename = typename std::enable_if< | |||
std::is_constructible<std::string, T>::value>::type> | std::is_constructible<std::string, T>::value>::type> | |||
using StringLike = T; | using StringLike = T; | |||
// Implements polymorphic matchers MatchesRegex(regex) and | // Implements polymorphic matchers MatchesRegex(regex) and | |||
// ContainsRegex(regex), which can be used as a Matcher<T> as long as | // ContainsRegex(regex), which can be used as a Matcher<T> as long as | |||
skipping to change at line 875 | skipping to change at line 895 | |||
template <typename T = std::string> | template <typename T = std::string> | |||
PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex( | PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex( | |||
const internal::StringLike<T>& regex) { | const internal::StringLike<T>& regex) { | |||
return ContainsRegex(new internal::RE(std::string(regex))); | return ContainsRegex(new internal::RE(std::string(regex))); | |||
} | } | |||
// Creates a polymorphic matcher that matches anything equal to x. | // Creates a polymorphic matcher that matches anything equal to x. | |||
// Note: if the parameter of Eq() were declared as const T&, Eq("foo") | // Note: if the parameter of Eq() were declared as const T&, Eq("foo") | |||
// wouldn't compile. | // wouldn't compile. | |||
template <typename T> | template <typename T> | |||
inline internal::EqMatcher<T> Eq(T x) { return internal::EqMatcher<T>(x); } | inline internal::EqMatcher<T> Eq(T x) { | |||
return internal::EqMatcher<T>(x); | ||||
} | ||||
// Constructs a Matcher<T> from a 'value' of type T. The constructed | // Constructs a Matcher<T> from a 'value' of type T. The constructed | |||
// matcher matches any value that's equal to 'value'. | // matcher matches any value that's equal to 'value'. | |||
template <typename T> | template <typename T> | |||
Matcher<T>::Matcher(T value) { *this = Eq(value); } | Matcher<T>::Matcher(T value) { | |||
*this = Eq(value); | ||||
} | ||||
// Creates a monomorphic matcher that matches anything with type Lhs | // Creates a monomorphic matcher that matches anything with type Lhs | |||
// and equal to rhs. A user may need to use this instead of Eq(...) | // and equal to rhs. A user may need to use this instead of Eq(...) | |||
// in order to resolve an overloading ambiguity. | // in order to resolve an overloading ambiguity. | |||
// | // | |||
// TypedEq<T>(x) is just a convenient short-hand for Matcher<T>(Eq(x)) | // TypedEq<T>(x) is just a convenient short-hand for Matcher<T>(Eq(x)) | |||
// or Matcher<T>(x), but more readable than the latter. | // or Matcher<T>(x), but more readable than the latter. | |||
// | // | |||
// We could define similar monomorphic matchers for other comparison | // We could define similar monomorphic matchers for other comparison | |||
// operations (e.g. TypedLt, TypedGe, and etc), but decided not to do | // operations (e.g. TypedLt, TypedGe, and etc), but decided not to do | |||
// it yet as those are used much less than Eq() in practice. A user | // it yet as those are used much less than Eq() in practice. A user | |||
// can always write Matcher<T>(Lt(5)) to be explicit about the type, | // can always write Matcher<T>(Lt(5)) to be explicit about the type, | |||
// for example. | // for example. | |||
template <typename Lhs, typename Rhs> | template <typename Lhs, typename Rhs> | |||
inline Matcher<Lhs> TypedEq(const Rhs& rhs) { return Eq(rhs); } | inline Matcher<Lhs> TypedEq(const Rhs& rhs) { | |||
return Eq(rhs); | ||||
} | ||||
// Creates a polymorphic matcher that matches anything >= x. | // Creates a polymorphic matcher that matches anything >= x. | |||
template <typename Rhs> | template <typename Rhs> | |||
inline internal::GeMatcher<Rhs> Ge(Rhs x) { | inline internal::GeMatcher<Rhs> Ge(Rhs x) { | |||
return internal::GeMatcher<Rhs>(x); | return internal::GeMatcher<Rhs>(x); | |||
} | } | |||
// Creates a polymorphic matcher that matches anything > x. | // Creates a polymorphic matcher that matches anything > x. | |||
template <typename Rhs> | template <typename Rhs> | |||
inline internal::GtMatcher<Rhs> Gt(Rhs x) { | inline internal::GtMatcher<Rhs> Gt(Rhs x) { | |||
End of changes. 24 change blocks. | ||||
25 lines changed or deleted | 51 lines changed or added |