gtest-matchers.h (googletest-release-1.10.0) | : | gtest-matchers.h (googletest-release-1.11.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 "testing/base/public/gunit.h" | #ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ | |||
// IWYU pragma: friend third_party/googletest/googlemock/.* | #define GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ | |||
// IWYU pragma: friend third_party/googletest/googletest/.* | ||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ | ||||
#define GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ | ||||
#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" | |||
#include "gtest/internal/gtest-internal.h" | #include "gtest/internal/gtest-internal.h" | |||
#include "gtest/internal/gtest-port.h" | #include "gtest/internal/gtest-port.h" | |||
// MSVC warning C5046 is new as of VS2017 version 15.8. | // MSVC warning C5046 is new as of VS2017 version 15.8. | |||
skipping to change at line 66 | skipping to change at line 63 | |||
#endif | #endif | |||
GTEST_DISABLE_MSC_WARNINGS_PUSH_( | GTEST_DISABLE_MSC_WARNINGS_PUSH_( | |||
4251 GTEST_MAYBE_5046_ /* class A needs to have dll-interface to be used by | 4251 GTEST_MAYBE_5046_ /* class A needs to have dll-interface to be used by | |||
clients of class B */ | clients of class B */ | |||
/* Symbol involving type with internal linkage not defined */) | /* Symbol involving type with internal linkage not defined */) | |||
namespace testing { | namespace testing { | |||
// To implement a matcher Foo for type T, define: | // To implement a matcher Foo for type T, define: | |||
// 1. a class FooMatcherImpl that implements the | // 1. a class FooMatcherMatcher that implements the matcher interface: | |||
// MatcherInterface<T> interface, and | // using is_gtest_matcher = void; | |||
// 2. a factory function that creates a Matcher<T> object from a | // bool MatchAndExplain(const T&, std::ostream*); | |||
// FooMatcherImpl*. | // (MatchResultListener* can also be used instead of std::ostream*) | |||
// void DescribeTo(std::ostream*); | ||||
// void DescribeNegationTo(std::ostream*); | ||||
// | // | |||
// The two-level delegation design makes it possible to allow a user | // 2. a factory function that creates a Matcher<T> object from a | |||
// to write "v" instead of "Eq(v)" where a Matcher is expected, which | // FooMatcherMatcher. | |||
// is impossible if we pass matchers by pointers. It also eases | ||||
// ownership management as Matcher objects can now be copied like | ||||
// plain values. | ||||
// MatchResultListener is an abstract class. Its << operator can be | ||||
// used by a matcher to explain why a value matches or doesn't match. | ||||
// | ||||
class MatchResultListener { | class MatchResultListener { | |||
public: | public: | |||
// Creates a listener object with the given underlying ostream. The | // Creates a listener object with the given underlying ostream. The | |||
// listener does not own the ostream, and does not dereference it | // listener does not own the ostream, and does not dereference it | |||
// in the constructor or destructor. | // in the constructor or destructor. | |||
explicit MatchResultListener(::std::ostream* os) : stream_(os) {} | explicit MatchResultListener(::std::ostream* os) : stream_(os) {} | |||
virtual ~MatchResultListener() = 0; // Makes this class abstract. | virtual ~MatchResultListener() = 0; // Makes this class abstract. | |||
// Streams x to the underlying ostream; does nothing if the ostream | // Streams x to the underlying ostream; does nothing if the ostream | |||
// is NULL. | // is NULL. | |||
skipping to change at line 116 | skipping to change at line 109 | |||
::std::ostream* const stream_; | ::std::ostream* const stream_; | |||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MatchResultListener); | GTEST_DISALLOW_COPY_AND_ASSIGN_(MatchResultListener); | |||
}; | }; | |||
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 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 | |||
// being matched. For example, the DescribeTo() method of the Gt(7) | // being matched. For example, the DescribeTo() method of the Gt(7) | |||
// matcher prints "is greater than 7". | // matcher prints "is greater than 7". | |||
virtual void DescribeTo(::std::ostream* os) const = 0; | virtual void DescribeTo(::std::ostream* os) const = 0; | |||
skipping to change at line 184 | skipping to change at line 177 | |||
// listener->stream() may be NULL. | // listener->stream() may be NULL. | |||
virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0; | virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0; | |||
// 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 { | |||
// Converts a MatcherInterface<T> to a MatcherInterface<const T&>. | ||||
template <typename T> | ||||
class MatcherInterfaceAdapter : public MatcherInterface<const T&> { | ||||
public: | ||||
explicit MatcherInterfaceAdapter(const MatcherInterface<T>* impl) | ||||
: impl_(impl) {} | ||||
~MatcherInterfaceAdapter() override { delete impl_; } | ||||
void DescribeTo(::std::ostream* os) const override { impl_->DescribeTo(os); } | ||||
void DescribeNegationTo(::std::ostream* os) const override { | ||||
impl_->DescribeNegationTo(os); | ||||
} | ||||
bool MatchAndExplain(const T& x, | ||||
MatchResultListener* listener) const override { | ||||
return impl_->MatchAndExplain(x, listener); | ||||
} | ||||
private: | ||||
const MatcherInterface<T>* const impl_; | ||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MatcherInterfaceAdapter); | ||||
}; | ||||
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> | |||
skipping to change at line 255 | skipping to change at line 223 | |||
// 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); | GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamMatchResultListener); | |||
}; | }; | |||
struct SharedPayloadBase { | ||||
std::atomic<int> ref{1}; | ||||
void Ref() { ref.fetch_add(1, std::memory_order_relaxed); } | ||||
bool Unref() { return ref.fetch_sub(1, std::memory_order_acq_rel) == 1; } | ||||
}; | ||||
template <typename T> | ||||
struct SharedPayload : SharedPayloadBase { | ||||
explicit SharedPayload(const T& v) : value(v) {} | ||||
explicit SharedPayload(T&& v) : value(std::move(v)) {} | ||||
static void Destroy(SharedPayloadBase* shared) { | ||||
delete static_cast<SharedPayload*>(shared); | ||||
} | ||||
T value; | ||||
}; | ||||
// An internal class for implementing Matcher<T>, which will derive | // An internal class for implementing Matcher<T>, which will derive | |||
// from it. We put functionalities common to all Matcher<T> | // from it. We put functionalities common to all Matcher<T> | |||
// specializations here to avoid code duplication. | // specializations here to avoid code duplication. | |||
template <typename T> | template <typename T> | |||
class MatcherBase { | class MatcherBase : private MatcherDescriberInterface { | |||
public: | public: | |||
// Returns true if and only if the matcher matches x; also explains the | // Returns true if and only if the matcher matches x; also explains the | |||
// match result to 'listener'. | // match result to 'listener'. | |||
bool MatchAndExplain(const T& x, MatchResultListener* listener) const { | bool MatchAndExplain(const T& x, MatchResultListener* listener) const { | |||
return impl_->MatchAndExplain(x, listener); | GTEST_CHECK_(vtable_ != nullptr); | |||
return vtable_->match_and_explain(*this, x, listener); | ||||
} | } | |||
// Returns true if and only if this matcher matches x. | // Returns true if and only if this matcher matches x. | |||
bool Matches(const T& x) const { | bool Matches(const T& x) const { | |||
DummyMatchResultListener dummy; | DummyMatchResultListener dummy; | |||
return MatchAndExplain(x, &dummy); | return MatchAndExplain(x, &dummy); | |||
} | } | |||
// Describes this matcher to an ostream. | // Describes this matcher to an ostream. | |||
void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); } | void DescribeTo(::std::ostream* os) const final { | |||
GTEST_CHECK_(vtable_ != nullptr); | ||||
vtable_->describe(*this, os, false); | ||||
} | ||||
// Describes the negation of this matcher to an ostream. | // Describes the negation of this matcher to an ostream. | |||
void DescribeNegationTo(::std::ostream* os) const { | void DescribeNegationTo(::std::ostream* os) const final { | |||
impl_->DescribeNegationTo(os); | GTEST_CHECK_(vtable_ != nullptr); | |||
vtable_->describe(*this, os, true); | ||||
} | } | |||
// Explains why x matches, or doesn't match, the matcher. | // Explains why x matches, or doesn't match, the matcher. | |||
void ExplainMatchResultTo(const T& x, ::std::ostream* os) const { | void ExplainMatchResultTo(const T& x, ::std::ostream* os) const { | |||
StreamMatchResultListener listener(os); | StreamMatchResultListener listener(os); | |||
MatchAndExplain(x, &listener); | MatchAndExplain(x, &listener); | |||
} | } | |||
// 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 { | |||
return impl_.get(); | if (vtable_ == nullptr) return nullptr; | |||
return vtable_->get_describer(*this); | ||||
} | } | |||
protected: | protected: | |||
MatcherBase() {} | MatcherBase() : vtable_(nullptr) {} | |||
// Constructs a matcher from its implementation. | // Constructs a matcher from its implementation. | |||
explicit MatcherBase(const MatcherInterface<const T&>* impl) : impl_(impl) {} | ||||
template <typename U> | template <typename U> | |||
explicit MatcherBase( | explicit MatcherBase(const MatcherInterface<U>* impl) { | |||
const MatcherInterface<U>* impl, | Init(impl); | |||
typename std::enable_if<!std::is_same<U, const U&>::value>::type* = | } | |||
nullptr) | ||||
: impl_(new internal::MatcherInterfaceAdapter<U>(impl)) {} | template <typename M, typename = typename std::remove_reference< | |||
M>::type::is_gtest_matcher> | ||||
MatcherBase(M&& m) { // NOLINT | ||||
Init(std::forward<M>(m)); | ||||
} | ||||
MatcherBase(const MatcherBase&) = default; | MatcherBase(const MatcherBase& other) | |||
MatcherBase& operator=(const MatcherBase&) = default; | : vtable_(other.vtable_), buffer_(other.buffer_) { | |||
MatcherBase(MatcherBase&&) = default; | if (IsShared()) buffer_.shared->Ref(); | |||
MatcherBase& operator=(MatcherBase&&) = default; | } | |||
virtual ~MatcherBase() {} | MatcherBase& operator=(const MatcherBase& other) { | |||
if (this == &other) return *this; | ||||
Destroy(); | ||||
vtable_ = other.vtable_; | ||||
buffer_ = other.buffer_; | ||||
if (IsShared()) buffer_.shared->Ref(); | ||||
return *this; | ||||
} | ||||
MatcherBase(MatcherBase&& other) | ||||
: vtable_(other.vtable_), buffer_(other.buffer_) { | ||||
other.vtable_ = nullptr; | ||||
} | ||||
MatcherBase& operator=(MatcherBase&& other) { | ||||
if (this == &other) return *this; | ||||
Destroy(); | ||||
vtable_ = other.vtable_; | ||||
buffer_ = other.buffer_; | ||||
other.vtable_ = nullptr; | ||||
return *this; | ||||
} | ||||
~MatcherBase() override { Destroy(); } | ||||
private: | private: | |||
std::shared_ptr<const MatcherInterface<const T&>> impl_; | struct VTable { | |||
bool (*match_and_explain)(const MatcherBase&, const T&, | ||||
MatchResultListener*); | ||||
void (*describe)(const MatcherBase&, std::ostream*, bool negation); | ||||
// Returns the captured object if it implements the interface, otherwise | ||||
// returns the MatcherBase itself. | ||||
const MatcherDescriberInterface* (*get_describer)(const MatcherBase&); | ||||
// Called on shared instances when the reference count reaches 0. | ||||
void (*shared_destroy)(SharedPayloadBase*); | ||||
}; | ||||
bool IsShared() const { | ||||
return vtable_ != nullptr && vtable_->shared_destroy != nullptr; | ||||
} | ||||
// If the implementation uses a listener, call that. | ||||
template <typename P> | ||||
static auto MatchAndExplainImpl(const MatcherBase& m, const T& value, | ||||
MatchResultListener* listener) | ||||
-> decltype(P::Get(m).MatchAndExplain(value, listener->stream())) { | ||||
return P::Get(m).MatchAndExplain(value, listener->stream()); | ||||
} | ||||
template <typename P> | ||||
static auto MatchAndExplainImpl(const MatcherBase& m, const T& value, | ||||
MatchResultListener* listener) | ||||
-> decltype(P::Get(m).MatchAndExplain(value, listener)) { | ||||
return P::Get(m).MatchAndExplain(value, listener); | ||||
} | ||||
template <typename P> | ||||
static void DescribeImpl(const MatcherBase& m, std::ostream* os, | ||||
bool negation) { | ||||
if (negation) { | ||||
P::Get(m).DescribeNegationTo(os); | ||||
} else { | ||||
P::Get(m).DescribeTo(os); | ||||
} | ||||
} | ||||
template <typename P> | ||||
static const MatcherDescriberInterface* GetDescriberImpl( | ||||
const MatcherBase& m) { | ||||
// If the impl is a MatcherDescriberInterface, then return it. | ||||
// Otherwise use MatcherBase itself. | ||||
// This allows us to implement the GetDescriber() function without support | ||||
// from the impl, but some users really want to get their impl back when | ||||
// they call GetDescriber(). | ||||
// We use std::get on a tuple as a workaround of not having `if constexpr`. | ||||
return std::get<( | ||||
std::is_convertible<decltype(&P::Get(m)), | ||||
const MatcherDescriberInterface*>::value | ||||
? 1 | ||||
: 0)>(std::make_tuple(&m, &P::Get(m))); | ||||
} | ||||
template <typename P> | ||||
const VTable* GetVTable() { | ||||
static constexpr VTable kVTable = {&MatchAndExplainImpl<P>, | ||||
&DescribeImpl<P>, &GetDescriberImpl<P>, | ||||
P::shared_destroy}; | ||||
return &kVTable; | ||||
} | ||||
union Buffer { | ||||
// Add some types to give Buffer some common alignment/size use cases. | ||||
void* ptr; | ||||
double d; | ||||
int64_t i; | ||||
// And add one for the out-of-line cases. | ||||
SharedPayloadBase* shared; | ||||
}; | ||||
void Destroy() { | ||||
if (IsShared() && buffer_.shared->Unref()) { | ||||
vtable_->shared_destroy(buffer_.shared); | ||||
} | ||||
} | ||||
template <typename M> | ||||
static constexpr bool IsInlined() { | ||||
return sizeof(M) <= sizeof(Buffer) && alignof(M) <= alignof(Buffer) && | ||||
std::is_trivially_copy_constructible<M>::value && | ||||
std::is_trivially_destructible<M>::value; | ||||
} | ||||
template <typename M, bool = MatcherBase::IsInlined<M>()> | ||||
struct ValuePolicy { | ||||
static const M& Get(const MatcherBase& m) { | ||||
// When inlined along with Init, need to be explicit to avoid violating | ||||
// strict aliasing rules. | ||||
const M *ptr = static_cast<const M*>( | ||||
static_cast<const void*>(&m.buffer_)); | ||||
return *ptr; | ||||
} | ||||
static void Init(MatcherBase& m, M impl) { | ||||
::new (static_cast<void*>(&m.buffer_)) M(impl); | ||||
} | ||||
static constexpr auto shared_destroy = nullptr; | ||||
}; | ||||
template <typename M> | ||||
struct ValuePolicy<M, false> { | ||||
using Shared = SharedPayload<M>; | ||||
static const M& Get(const MatcherBase& m) { | ||||
return static_cast<Shared*>(m.buffer_.shared)->value; | ||||
} | ||||
template <typename Arg> | ||||
static void Init(MatcherBase& m, Arg&& arg) { | ||||
m.buffer_.shared = new Shared(std::forward<Arg>(arg)); | ||||
} | ||||
static constexpr auto shared_destroy = &Shared::Destroy; | ||||
}; | ||||
template <typename U, bool B> | ||||
struct ValuePolicy<const MatcherInterface<U>*, B> { | ||||
using M = const MatcherInterface<U>; | ||||
using Shared = SharedPayload<std::unique_ptr<M>>; | ||||
static const M& Get(const MatcherBase& m) { | ||||
return *static_cast<Shared*>(m.buffer_.shared)->value; | ||||
} | ||||
static void Init(MatcherBase& m, M* impl) { | ||||
m.buffer_.shared = new Shared(std::unique_ptr<M>(impl)); | ||||
} | ||||
static constexpr auto shared_destroy = &Shared::Destroy; | ||||
}; | ||||
template <typename M> | ||||
void Init(M&& m) { | ||||
using MM = typename std::decay<M>::type; | ||||
using Policy = ValuePolicy<MM>; | ||||
vtable_ = GetVTable<Policy>(); | ||||
Policy::Init(*this, std::forward<M>(m)); | ||||
} | ||||
const VTable* vtable_; | ||||
Buffer buffer_; | ||||
}; | }; | |||
} // namespace internal | } // namespace internal | |||
// A Matcher<T> is a copyable and IMMUTABLE (except by assignment) | // A Matcher<T> is a copyable and IMMUTABLE (except by assignment) | |||
// object that can check whether a value of type T matches. The | // object that can check whether a value of type T matches. The | |||
// implementation of Matcher<T> is just a std::shared_ptr to const | // implementation of Matcher<T> is just a std::shared_ptr to const | |||
// MatcherInterface<T>. Don't inherit from Matcher! | // MatcherInterface<T>. Don't inherit from Matcher! | |||
template <typename T> | template <typename T> | |||
class Matcher : public internal::MatcherBase<T> { | class Matcher : public internal::MatcherBase<T> { | |||
skipping to change at line 343 | skipping to change at line 497 | |||
explicit Matcher(const MatcherInterface<const T&>* impl) | explicit Matcher(const MatcherInterface<const T&>* impl) | |||
: internal::MatcherBase<T>(impl) {} | : internal::MatcherBase<T>(impl) {} | |||
template <typename U> | template <typename U> | |||
explicit Matcher( | explicit Matcher( | |||
const MatcherInterface<U>* impl, | const MatcherInterface<U>* impl, | |||
typename std::enable_if<!std::is_same<U, const U&>::value>::type* = | typename std::enable_if<!std::is_same<U, const U&>::value>::type* = | |||
nullptr) | nullptr) | |||
: internal::MatcherBase<T>(impl) {} | : internal::MatcherBase<T>(impl) {} | |||
template <typename M, typename = typename std::remove_reference< | ||||
M>::type::is_gtest_matcher> | ||||
Matcher(M&& m) : internal::MatcherBase<T>(std::forward<M>(m)) {} // NOLINT | ||||
// Implicit constructor here allows people to write | // Implicit constructor here allows people to write | |||
// EXPECT_CALL(foo, Bar(5)) instead of EXPECT_CALL(foo, Bar(Eq(5))) sometimes | // EXPECT_CALL(foo, Bar(5)) instead of EXPECT_CALL(foo, Bar(Eq(5))) sometimes | |||
Matcher(T value); // NOLINT | Matcher(T value); // NOLINT | |||
}; | }; | |||
// The following two specializations allow the user to write str | // The following two specializations allow the user to write str | |||
// instead of Eq(str) and "foo" instead of Eq("foo") when a std::string | // instead of Eq(str) and "foo" instead of Eq("foo") when a std::string | |||
// matcher is expected. | // matcher is expected. | |||
template <> | template <> | |||
class GTEST_API_ Matcher<const std::string&> | class GTEST_API_ Matcher<const std::string&> | |||
: public internal::MatcherBase<const std::string&> { | : public internal::MatcherBase<const std::string&> { | |||
public: | public: | |||
Matcher() {} | Matcher() {} | |||
explicit Matcher(const MatcherInterface<const std::string&>* impl) | explicit Matcher(const MatcherInterface<const std::string&>* impl) | |||
: internal::MatcherBase<const std::string&>(impl) {} | : internal::MatcherBase<const std::string&>(impl) {} | |||
template <typename M, typename = typename std::remove_reference< | ||||
M>::type::is_gtest_matcher> | ||||
Matcher(M&& m) // NOLINT | ||||
: internal::MatcherBase<const std::string&>(std::forward<M>(m)) {} | ||||
// Allows the user to write str instead of Eq(str) sometimes, where | // Allows the user to write str instead of Eq(str) sometimes, where | |||
// str is a std::string object. | // str is a std::string object. | |||
Matcher(const std::string& s); // NOLINT | Matcher(const std::string& s); // NOLINT | |||
// Allows the user to write "foo" instead of Eq("foo") sometimes. | // Allows the user to write "foo" instead of Eq("foo") sometimes. | |||
Matcher(const char* s); // NOLINT | Matcher(const char* s); // NOLINT | |||
}; | }; | |||
template <> | template <> | |||
class GTEST_API_ Matcher<std::string> | class GTEST_API_ Matcher<std::string> | |||
: public internal::MatcherBase<std::string> { | : public internal::MatcherBase<std::string> { | |||
public: | public: | |||
Matcher() {} | Matcher() {} | |||
explicit Matcher(const MatcherInterface<const std::string&>* impl) | explicit Matcher(const MatcherInterface<const std::string&>* impl) | |||
: internal::MatcherBase<std::string>(impl) {} | : internal::MatcherBase<std::string>(impl) {} | |||
explicit Matcher(const MatcherInterface<std::string>* impl) | explicit Matcher(const MatcherInterface<std::string>* impl) | |||
: internal::MatcherBase<std::string>(impl) {} | : internal::MatcherBase<std::string>(impl) {} | |||
template <typename M, typename = typename std::remove_reference< | ||||
M>::type::is_gtest_matcher> | ||||
Matcher(M&& m) // NOLINT | ||||
: internal::MatcherBase<std::string>(std::forward<M>(m)) {} | ||||
// Allows the user to write str instead of Eq(str) sometimes, where | // Allows the user to write str instead of Eq(str) sometimes, where | |||
// str is a string object. | // str is a string object. | |||
Matcher(const std::string& s); // NOLINT | Matcher(const std::string& s); // NOLINT | |||
// Allows the user to write "foo" instead of Eq("foo") sometimes. | // Allows the user to write "foo" instead of Eq("foo") sometimes. | |||
Matcher(const char* s); // NOLINT | Matcher(const char* s); // NOLINT | |||
}; | }; | |||
#if GTEST_HAS_ABSL | #if GTEST_INTERNAL_HAS_STRING_VIEW | |||
// The following two specializations allow the user to write str | // The following two specializations allow the user to write str | |||
// instead of Eq(str) and "foo" instead of Eq("foo") when a absl::string_view | // instead of Eq(str) and "foo" instead of Eq("foo") when a absl::string_view | |||
// matcher is expected. | // matcher is expected. | |||
template <> | template <> | |||
class GTEST_API_ Matcher<const absl::string_view&> | class GTEST_API_ Matcher<const internal::StringView&> | |||
: public internal::MatcherBase<const absl::string_view&> { | : public internal::MatcherBase<const internal::StringView&> { | |||
public: | public: | |||
Matcher() {} | Matcher() {} | |||
explicit Matcher(const MatcherInterface<const absl::string_view&>* impl) | explicit Matcher(const MatcherInterface<const internal::StringView&>* impl) | |||
: internal::MatcherBase<const absl::string_view&>(impl) {} | : internal::MatcherBase<const internal::StringView&>(impl) {} | |||
template <typename M, typename = typename std::remove_reference< | ||||
M>::type::is_gtest_matcher> | ||||
Matcher(M&& m) // NOLINT | ||||
: internal::MatcherBase<const internal::StringView&>(std::forward<M>(m)) { | ||||
} | ||||
// Allows the user to write str instead of Eq(str) sometimes, where | // Allows the user to write str instead of Eq(str) sometimes, where | |||
// str is a std::string object. | // str is a std::string object. | |||
Matcher(const std::string& s); // NOLINT | Matcher(const std::string& s); // NOLINT | |||
// Allows the user to write "foo" instead of Eq("foo") sometimes. | // Allows the user to write "foo" instead of Eq("foo") sometimes. | |||
Matcher(const char* s); // NOLINT | Matcher(const char* s); // NOLINT | |||
// Allows the user to pass absl::string_views directly. | // Allows the user to pass absl::string_views or std::string_views directly. | |||
Matcher(absl::string_view s); // NOLINT | Matcher(internal::StringView s); // NOLINT | |||
}; | }; | |||
template <> | template <> | |||
class GTEST_API_ Matcher<absl::string_view> | class GTEST_API_ Matcher<internal::StringView> | |||
: public internal::MatcherBase<absl::string_view> { | : public internal::MatcherBase<internal::StringView> { | |||
public: | public: | |||
Matcher() {} | Matcher() {} | |||
explicit Matcher(const MatcherInterface<const absl::string_view&>* impl) | explicit Matcher(const MatcherInterface<const internal::StringView&>* impl) | |||
: internal::MatcherBase<absl::string_view>(impl) {} | : internal::MatcherBase<internal::StringView>(impl) {} | |||
explicit Matcher(const MatcherInterface<absl::string_view>* impl) | explicit Matcher(const MatcherInterface<internal::StringView>* impl) | |||
: internal::MatcherBase<absl::string_view>(impl) {} | : internal::MatcherBase<internal::StringView>(impl) {} | |||
template <typename M, typename = typename std::remove_reference< | ||||
M>::type::is_gtest_matcher> | ||||
Matcher(M&& m) // NOLINT | ||||
: internal::MatcherBase<internal::StringView>(std::forward<M>(m)) {} | ||||
// Allows the user to write str instead of Eq(str) sometimes, where | // Allows the user to write str instead of Eq(str) sometimes, where | |||
// str is a std::string object. | // str is a std::string object. | |||
Matcher(const std::string& s); // NOLINT | Matcher(const std::string& s); // NOLINT | |||
// Allows the user to write "foo" instead of Eq("foo") sometimes. | // Allows the user to write "foo" instead of Eq("foo") sometimes. | |||
Matcher(const char* s); // NOLINT | Matcher(const char* s); // NOLINT | |||
// Allows the user to pass absl::string_views directly. | // Allows the user to pass absl::string_views or std::string_views directly. | |||
Matcher(absl::string_view s); // NOLINT | Matcher(internal::StringView s); // NOLINT | |||
}; | }; | |||
#endif // GTEST_HAS_ABSL | #endif // GTEST_INTERNAL_HAS_STRING_VIEW | |||
// Prints a matcher in a human-readable format. | // Prints a matcher in a human-readable format. | |||
template <typename T> | template <typename T> | |||
std::ostream& operator<<(std::ostream& os, const Matcher<T>& matcher) { | std::ostream& operator<<(std::ostream& os, const Matcher<T>& matcher) { | |||
matcher.DescribeTo(&os); | matcher.DescribeTo(&os); | |||
return os; | return os; | |||
} | } | |||
// The PolymorphicMatcher class template makes it easy to implement a | // The PolymorphicMatcher class template makes it easy to implement a | |||
// polymorphic matcher (i.e. a matcher that can match values of more | // polymorphic matcher (i.e. a matcher that can match values of more | |||
skipping to change at line 477 | skipping to change at line 656 | |||
operator Matcher<T>() const { | operator Matcher<T>() const { | |||
return Matcher<T>(new MonomorphicImpl<const T&>(impl_)); | return Matcher<T>(new MonomorphicImpl<const T&>(impl_)); | |||
} | } | |||
private: | private: | |||
template <typename T> | template <typename T> | |||
class MonomorphicImpl : public MatcherInterface<T> { | class MonomorphicImpl : public MatcherInterface<T> { | |||
public: | public: | |||
explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {} | explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {} | |||
virtual void DescribeTo(::std::ostream* os) const { impl_.DescribeTo(os); } | void DescribeTo(::std::ostream* os) const override { impl_.DescribeTo(os); } | |||
virtual void DescribeNegationTo(::std::ostream* os) const { | void DescribeNegationTo(::std::ostream* os) const override { | |||
impl_.DescribeNegationTo(os); | impl_.DescribeNegationTo(os); | |||
} | } | |||
virtual bool MatchAndExplain(T x, MatchResultListener* listener) const { | bool MatchAndExplain(T x, MatchResultListener* listener) const override { | |||
return impl_.MatchAndExplain(x, listener); | return impl_.MatchAndExplain(x, listener); | |||
} | } | |||
private: | private: | |||
const Impl impl_; | const Impl impl_; | |||
}; | }; | |||
Impl impl_; | Impl impl_; | |||
}; | }; | |||
skipping to change at line 532 | skipping to change at line 711 | |||
// The matcher defined here is polymorphic (for example, Eq(5) can be | // The matcher defined here is polymorphic (for example, Eq(5) can be | |||
// used to match an int, a short, a double, etc). Therefore we use | // used to match an int, a short, a double, etc). Therefore we use | |||
// a template type conversion operator in the implementation. | // a template type conversion operator in the implementation. | |||
// | // | |||
// The following template definition assumes that the Rhs parameter is | // The following template definition assumes that the Rhs parameter is | |||
// a "bare" type (i.e. neither 'const T' nor 'T&'). | // a "bare" type (i.e. neither 'const T' nor 'T&'). | |||
template <typename D, typename Rhs, typename Op> | template <typename D, typename Rhs, typename Op> | |||
class ComparisonBase { | class ComparisonBase { | |||
public: | public: | |||
explicit ComparisonBase(const Rhs& rhs) : rhs_(rhs) {} | explicit ComparisonBase(const Rhs& rhs) : rhs_(rhs) {} | |||
using is_gtest_matcher = void; | ||||
template <typename Lhs> | template <typename Lhs> | |||
operator Matcher<Lhs>() const { | bool MatchAndExplain(const Lhs& lhs, std::ostream*) const { | |||
return Matcher<Lhs>(new Impl<const Lhs&>(rhs_)); | return Op()(lhs, Unwrap(rhs_)); | |||
} | ||||
void DescribeTo(std::ostream* os) const { | ||||
*os << D::Desc() << " "; | ||||
UniversalPrint(Unwrap(rhs_), os); | ||||
} | ||||
void DescribeNegationTo(std::ostream* os) const { | ||||
*os << D::NegatedDesc() << " "; | ||||
UniversalPrint(Unwrap(rhs_), os); | ||||
} | } | |||
private: | private: | |||
template <typename T> | template <typename T> | |||
static const T& Unwrap(const T& v) { return v; } | static const T& Unwrap(const T& v) { | |||
return v; | ||||
} | ||||
template <typename T> | template <typename T> | |||
static const T& Unwrap(std::reference_wrapper<T> v) { return v; } | static const T& Unwrap(std::reference_wrapper<T> v) { | |||
return v; | ||||
template <typename Lhs, typename = Rhs> | } | |||
class Impl : public MatcherInterface<Lhs> { | ||||
public: | ||||
explicit Impl(const Rhs& rhs) : rhs_(rhs) {} | ||||
bool MatchAndExplain(Lhs lhs, | ||||
MatchResultListener* /* listener */) const override { | ||||
return Op()(lhs, Unwrap(rhs_)); | ||||
} | ||||
void DescribeTo(::std::ostream* os) const override { | ||||
*os << D::Desc() << " "; | ||||
UniversalPrint(Unwrap(rhs_), os); | ||||
} | ||||
void DescribeNegationTo(::std::ostream* os) const override { | ||||
*os << D::NegatedDesc() << " "; | ||||
UniversalPrint(Unwrap(rhs_), os); | ||||
} | ||||
private: | ||||
Rhs rhs_; | ||||
}; | ||||
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"; } | |||
skipping to change at line 615 | skipping to change at line 789 | |||
}; | }; | |||
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< | ||||
std::is_constructible<std::string, T>::value>::type> | ||||
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 | |||
// T can be converted to a string. | // T can be converted to a string. | |||
class MatchesRegexMatcher { | class MatchesRegexMatcher { | |||
public: | public: | |||
MatchesRegexMatcher(const RE* regex, bool full_match) | MatchesRegexMatcher(const RE* regex, bool full_match) | |||
: regex_(regex), full_match_(full_match) {} | : regex_(regex), full_match_(full_match) {} | |||
#if GTEST_HAS_ABSL | #if GTEST_INTERNAL_HAS_STRING_VIEW | |||
bool MatchAndExplain(const absl::string_view& s, | bool MatchAndExplain(const internal::StringView& s, | |||
MatchResultListener* listener) const { | MatchResultListener* listener) const { | |||
return MatchAndExplain(std::string(s), listener); | return MatchAndExplain(std::string(s), listener); | |||
} | } | |||
#endif // GTEST_HAS_ABSL | #endif // GTEST_INTERNAL_HAS_STRING_VIEW | |||
// Accepts pointer types, particularly: | // Accepts pointer types, particularly: | |||
// const char* | // const char* | |||
// char* | // char* | |||
// const wchar_t* | // const wchar_t* | |||
// wchar_t* | // wchar_t* | |||
template <typename CharType> | template <typename CharType> | |||
bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { | bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { | |||
return s != nullptr && MatchAndExplain(std::string(s), listener); | return s != nullptr && MatchAndExplain(std::string(s), listener); | |||
} | } | |||
skipping to change at line 675 | skipping to change at line 853 | |||
const bool full_match_; | const bool full_match_; | |||
}; | }; | |||
} // namespace internal | } // namespace internal | |||
// Matches a string that fully matches regular expression 'regex'. | // Matches a string that fully matches regular expression 'regex'. | |||
// The matcher takes ownership of 'regex'. | // The matcher takes ownership of 'regex'. | |||
inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex( | inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex( | |||
const internal::RE* regex) { | const internal::RE* regex) { | |||
return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true)); | return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true)); | |||
} | } | |||
inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex( | template <typename T = std::string> | |||
const std::string& regex) { | PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex( | |||
return MatchesRegex(new internal::RE(regex)); | const internal::StringLike<T>& regex) { | |||
return MatchesRegex(new internal::RE(std::string(regex))); | ||||
} | } | |||
// Matches a string that contains regular expression 'regex'. | // Matches a string that contains regular expression 'regex'. | |||
// The matcher takes ownership of 'regex'. | // The matcher takes ownership of 'regex'. | |||
inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex( | inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex( | |||
const internal::RE* regex) { | const internal::RE* regex) { | |||
return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false)); | return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false)); | |||
} | } | |||
inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex( | template <typename T = std::string> | |||
const std::string& regex) { | PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex( | |||
return ContainsRegex(new internal::RE(regex)); | const internal::StringLike<T>& 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'. | |||
skipping to change at line 750 | skipping to change at line 930 | |||
// Creates a polymorphic matcher that matches anything != x. | // Creates a polymorphic matcher that matches anything != x. | |||
template <typename Rhs> | template <typename Rhs> | |||
inline internal::NeMatcher<Rhs> Ne(Rhs x) { | inline internal::NeMatcher<Rhs> Ne(Rhs x) { | |||
return internal::NeMatcher<Rhs>(x); | return internal::NeMatcher<Rhs>(x); | |||
} | } | |||
} // namespace testing | } // namespace testing | |||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 5046 | GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 5046 | |||
#endif // GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ | #endif // GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ | |||
End of changes. 44 change blocks. | ||||
116 lines changed or deleted | 296 lines changed or added |