Adds more tests for using SetArgumentPointee with protobufs; works around a compiler bug on Symbian that gmock-printers.h triggers; reduces template code bloat in gmock-matchers.h; avoids RTTI when it's disabled.

This commit is contained in:
zhanyong.wan
2009-05-13 23:38:40 +00:00
parent 18490653e8
commit c6a412397b
4 changed files with 248 additions and 179 deletions

View File

@@ -960,10 +960,35 @@ GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Ne, !=, "not equal to");
#undef GMOCK_IMPLEMENT_COMPARISON2_MATCHER_
// TODO(vladl@google.com): Move Impl outside of NotMatcher and rename it
// NotMatcherImpl to reduce compilation overhead and the size of the binary.
// This also applies to BothOfMatcher::Impl and EitherOfMatcher::Impl.
//
// Implements the Not(...) matcher for a particular argument type T.
// We do not nest it inside the NotMatcher class template, as that
// will prevent different instantiations of NotMatcher from sharing
// the same NotMatcherImpl<T> class.
template <typename T>
class NotMatcherImpl : public MatcherInterface<T> {
public:
explicit NotMatcherImpl(const Matcher<T>& matcher)
: matcher_(matcher) {}
virtual bool Matches(T x) const {
return !matcher_.Matches(x);
}
virtual void DescribeTo(::std::ostream* os) const {
matcher_.DescribeNegationTo(os);
}
virtual void DescribeNegationTo(::std::ostream* os) const {
matcher_.DescribeTo(os);
}
virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const {
matcher_.ExplainMatchResultTo(x, os);
}
private:
const Matcher<T> matcher_;
};
// Implements the Not(m) matcher, which matches a value that doesn't
// match matcher m.
template <typename InnerMatcher>
@@ -975,38 +1000,74 @@ class NotMatcher {
// to match any type m can match.
template <typename T>
operator Matcher<T>() const {
return Matcher<T>(new Impl<T>(matcher_));
return Matcher<T>(new NotMatcherImpl<T>(SafeMatcherCast<T>(matcher_)));
}
private:
// Implements the Not(...) matcher for a particular argument type T.
template <typename T>
class Impl : public MatcherInterface<T> {
public:
explicit Impl(InnerMatcher matcher)
: matcher_(SafeMatcherCast<T>(matcher)) {}
virtual bool Matches(T x) const {
return !matcher_.Matches(x);
}
virtual void DescribeTo(::std::ostream* os) const {
matcher_.DescribeNegationTo(os);
}
virtual void DescribeNegationTo(::std::ostream* os) const {
matcher_.DescribeTo(os);
}
virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const {
matcher_.ExplainMatchResultTo(x, os);
}
private:
const Matcher<T> matcher_;
};
InnerMatcher matcher_;
};
// Implements the AllOf(m1, m2) matcher for a particular argument type
// T. We do not nest it inside the BothOfMatcher class template, as
// that will prevent different instantiations of BothOfMatcher from
// sharing the same BothOfMatcherImpl<T> class.
template <typename T>
class BothOfMatcherImpl : public MatcherInterface<T> {
public:
BothOfMatcherImpl(const Matcher<T>& matcher1, const Matcher<T>& matcher2)
: matcher1_(matcher1), matcher2_(matcher2) {}
virtual bool Matches(T x) const {
return matcher1_.Matches(x) && matcher2_.Matches(x);
}
virtual void DescribeTo(::std::ostream* os) const {
*os << "(";
matcher1_.DescribeTo(os);
*os << ") and (";
matcher2_.DescribeTo(os);
*os << ")";
}
virtual void DescribeNegationTo(::std::ostream* os) const {
*os << "not ";
DescribeTo(os);
}
virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const {
if (Matches(x)) {
// When both matcher1_ and matcher2_ match x, we need to
// explain why *both* of them match.
::std::stringstream ss1;
matcher1_.ExplainMatchResultTo(x, &ss1);
const internal::string s1 = ss1.str();
::std::stringstream ss2;
matcher2_.ExplainMatchResultTo(x, &ss2);
const internal::string s2 = ss2.str();
if (s1 == "") {
*os << s2;
} else {
*os << s1;
if (s2 != "") {
*os << "; " << s2;
}
}
} else {
// Otherwise we only need to explain why *one* of them fails
// to match.
if (!matcher1_.Matches(x)) {
matcher1_.ExplainMatchResultTo(x, os);
} else {
matcher2_.ExplainMatchResultTo(x, os);
}
}
}
private:
const Matcher<T> matcher1_;
const Matcher<T> matcher2_;
};
// Used for implementing the AllOf(m_1, ..., m_n) matcher, which
// matches a value that matches all of the matchers m_1, ..., and m_n.
template <typename Matcher1, typename Matcher2>
@@ -1020,72 +1081,73 @@ class BothOfMatcher {
// both Matcher1 and Matcher2 can match.
template <typename T>
operator Matcher<T>() const {
return Matcher<T>(new Impl<T>(matcher1_, matcher2_));
return Matcher<T>(new BothOfMatcherImpl<T>(SafeMatcherCast<T>(matcher1_),
SafeMatcherCast<T>(matcher2_)));
}
private:
// Implements the AllOf(m1, m2) matcher for a particular argument
// type T.
template <typename T>
class Impl : public MatcherInterface<T> {
public:
Impl(Matcher1 matcher1, Matcher2 matcher2)
: matcher1_(SafeMatcherCast<T>(matcher1)),
matcher2_(SafeMatcherCast<T>(matcher2)) {}
Matcher1 matcher1_;
Matcher2 matcher2_;
};
virtual bool Matches(T x) const {
return matcher1_.Matches(x) && matcher2_.Matches(x);
}
// Implements the AnyOf(m1, m2) matcher for a particular argument type
// T. We do not nest it inside the AnyOfMatcher class template, as
// that will prevent different instantiations of AnyOfMatcher from
// sharing the same EitherOfMatcherImpl<T> class.
template <typename T>
class EitherOfMatcherImpl : public MatcherInterface<T> {
public:
EitherOfMatcherImpl(const Matcher<T>& matcher1, const Matcher<T>& matcher2)
: matcher1_(matcher1), matcher2_(matcher2) {}
virtual void DescribeTo(::std::ostream* os) const {
*os << "(";
matcher1_.DescribeTo(os);
*os << ") and (";
matcher2_.DescribeTo(os);
*os << ")";
}
virtual bool Matches(T x) const {
return matcher1_.Matches(x) || matcher2_.Matches(x);
}
virtual void DescribeNegationTo(::std::ostream* os) const {
*os << "not ";
DescribeTo(os);
}
virtual void DescribeTo(::std::ostream* os) const {
*os << "(";
matcher1_.DescribeTo(os);
*os << ") or (";
matcher2_.DescribeTo(os);
*os << ")";
}
virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const {
if (Matches(x)) {
// When both matcher1_ and matcher2_ match x, we need to
// explain why *both* of them match.
::std::stringstream ss1;
matcher1_.ExplainMatchResultTo(x, &ss1);
const internal::string s1 = ss1.str();
virtual void DescribeNegationTo(::std::ostream* os) const {
*os << "not ";
DescribeTo(os);
}
::std::stringstream ss2;
matcher2_.ExplainMatchResultTo(x, &ss2);
const internal::string s2 = ss2.str();
if (s1 == "") {
*os << s2;
} else {
*os << s1;
if (s2 != "") {
*os << "; " << s2;
}
}
virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const {
if (Matches(x)) {
// If either matcher1_ or matcher2_ matches x, we just need
// to explain why *one* of them matches.
if (matcher1_.Matches(x)) {
matcher1_.ExplainMatchResultTo(x, os);
} else {
// Otherwise we only need to explain why *one* of them fails
// to match.
if (!matcher1_.Matches(x)) {
matcher1_.ExplainMatchResultTo(x, os);
} else {
matcher2_.ExplainMatchResultTo(x, os);
matcher2_.ExplainMatchResultTo(x, os);
}
} else {
// Otherwise we need to explain why *neither* matches.
::std::stringstream ss1;
matcher1_.ExplainMatchResultTo(x, &ss1);
const internal::string s1 = ss1.str();
::std::stringstream ss2;
matcher2_.ExplainMatchResultTo(x, &ss2);
const internal::string s2 = ss2.str();
if (s1 == "") {
*os << s2;
} else {
*os << s1;
if (s2 != "") {
*os << "; " << s2;
}
}
}
private:
const Matcher<T> matcher1_;
const Matcher<T> matcher2_;
};
Matcher1 matcher1_;
Matcher2 matcher2_;
}
private:
const Matcher<T> matcher1_;
const Matcher<T> matcher2_;
};
// Used for implementing the AnyOf(m_1, ..., m_n) matcher, which
@@ -1102,69 +1164,10 @@ class EitherOfMatcher {
// both Matcher1 and Matcher2 can match.
template <typename T>
operator Matcher<T>() const {
return Matcher<T>(new Impl<T>(matcher1_, matcher2_));
return Matcher<T>(new EitherOfMatcherImpl<T>(SafeMatcherCast<T>(matcher1_),
SafeMatcherCast<T>(matcher2_)));
}
private:
// Implements the AnyOf(m1, m2) matcher for a particular argument
// type T.
template <typename T>
class Impl : public MatcherInterface<T> {
public:
Impl(Matcher1 matcher1, Matcher2 matcher2)
: matcher1_(SafeMatcherCast<T>(matcher1)),
matcher2_(SafeMatcherCast<T>(matcher2)) {}
virtual bool Matches(T x) const {
return matcher1_.Matches(x) || matcher2_.Matches(x);
}
virtual void DescribeTo(::std::ostream* os) const {
*os << "(";
matcher1_.DescribeTo(os);
*os << ") or (";
matcher2_.DescribeTo(os);
*os << ")";
}
virtual void DescribeNegationTo(::std::ostream* os) const {
*os << "not ";
DescribeTo(os);
}
virtual void ExplainMatchResultTo(T x, ::std::ostream* os) const {
if (Matches(x)) {
// If either matcher1_ or matcher2_ matches x, we just need
// to explain why *one* of them matches.
if (matcher1_.Matches(x)) {
matcher1_.ExplainMatchResultTo(x, os);
} else {
matcher2_.ExplainMatchResultTo(x, os);
}
} else {
// Otherwise we need to explain why *neither* matches.
::std::stringstream ss1;
matcher1_.ExplainMatchResultTo(x, &ss1);
const internal::string s1 = ss1.str();
::std::stringstream ss2;
matcher2_.ExplainMatchResultTo(x, &ss2);
const internal::string s2 = ss2.str();
if (s1 == "") {
*os << s2;
} else {
*os << s1;
if (s2 != "") {
*os << "; " << s2;
}
}
}
}
private:
const Matcher<T> matcher1_;
const Matcher<T> matcher2_;
};
Matcher1 matcher1_;
Matcher2 matcher2_;
};

View File

@@ -211,7 +211,9 @@ class UniversalPrinter;
// Used to print an STL-style container when the user doesn't define
// a PrintTo() for it.
template <typename C>
void DefaultPrintTo(IsContainer, const C& container, ::std::ostream* os) {
void DefaultPrintTo(IsContainer /* dummy */,
false_type /* is not a pointer */,
const C& container, ::std::ostream* os) {
const size_t kMaxCount = 32; // The maximum number of elements to print.
*os << '{';
size_t count = 0;
@@ -234,9 +236,31 @@ void DefaultPrintTo(IsContainer, const C& container, ::std::ostream* os) {
*os << '}';
}
// Used to print a value when the user doesn't define PrintTo() for it.
// Used to print a pointer that is neither a char pointer nor a member
// pointer, when the user doesn't define PrintTo() for it. (A member
// variable pointer or member function pointer doesn't really point to
// a location in the address space. Their representation is
// implementation-defined. Therefore they will be printed as raw
// bytes.)
template <typename T>
void DefaultPrintTo(IsNotContainer, const T& value, ::std::ostream* os) {
void DefaultPrintTo(IsNotContainer /* dummy */,
true_type /* is a pointer */,
T* p, ::std::ostream* os) {
if (p == NULL) {
*os << "NULL";
} else {
// We cannot use implicit_cast or static_cast here, as they don't
// work when p is a function pointer.
*os << reinterpret_cast<const void*>(p);
}
}
// Used to print a non-container, non-pointer value when the user
// doesn't define PrintTo() for it.
template <typename T>
void DefaultPrintTo(IsNotContainer /* dummy */,
false_type /* is not a pointer */,
const T& value, ::std::ostream* os) {
::testing_internal::DefaultPrintNonContainerTo(value, os);
}
@@ -253,10 +277,11 @@ void DefaultPrintTo(IsNotContainer, const T& value, ::std::ostream* os) {
// wants).
template <typename T>
void PrintTo(const T& value, ::std::ostream* os) {
// DefaultPrintTo() is overloaded. The type of its first argument
// determines which version will be picked. If T is an STL-style
// container, the version for container will be called. Otherwise
// the generic version will be called.
// DefaultPrintTo() is overloaded. The type of its first two
// arguments determine which version will be picked. If T is an
// STL-style container, the version for container will be called; if
// T is a pointer, the pointer version will be called; otherwise the
// generic version will be called.
//
// Note that we check for container types here, prior to we check
// for protocol message types in our operator<<. The rationale is:
@@ -267,7 +292,14 @@ void PrintTo(const T& value, ::std::ostream* os) {
// incompatible with Google Mock's format for the container
// elements; therefore we check for container types here to ensure
// that our format is used.
DefaultPrintTo(IsContainerTest<T>(0), value, os);
//
// The second argument of DefaultPrintTo() is needed to bypass a bug
// in Symbian's C++ compiler that prevents it from picking the right
// overload between:
//
// PrintTo(const T& x, ...);
// PrintTo(T* x, ...);
DefaultPrintTo(IsContainerTest<T>(0), is_pointer<T>(), value, os);
}
// The following list of PrintTo() overloads tells
@@ -323,22 +355,6 @@ inline void PrintTo(wchar_t* s, ::std::ostream* os) {
}
#endif
// Overload for pointers that are neither char pointers nor member
// pointers. (A member variable pointer or member function pointer
// doesn't really points to a location in the address space. Their
// representation is implementation-defined. Therefore they will be
// printed as raw bytes.)
template <typename T>
void PrintTo(T* p, ::std::ostream* os) {
if (p == NULL) {
*os << "NULL";
} else {
// We cannot use implicit_cast or static_cast here, as they don't
// work when p is a function pointer.
*os << reinterpret_cast<const void*>(p);
}
}
// Overload for C arrays. Multi-dimensional arrays are printed
// properly.

View File

@@ -162,7 +162,9 @@ inline To down_cast(From* f) { // so we only accept pointers
implicit_cast<From*, To>(0);
}
#if GTEST_HAS_RTTI
assert(f == NULL || dynamic_cast<To>(f) != NULL); // RTTI: debug mode only!
#endif
return static_cast<To>(f);
}