"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "googletest/include/gtest/gtest-matchers.h" between
googletest-release-1.10.0.tar.gz and googletest-release-1.11.0.tar.gz

About: GoogleTest is Google's (unit) testing and mocking framework for C++ tests.

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

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)