aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzhanyong.wan <zhanyong.wan@8415998a-534a-0410-bf83-d39667b30386>2010-09-27 17:44:16 +0000
committerzhanyong.wan <zhanyong.wan@8415998a-534a-0410-bf83-d39667b30386>2010-09-27 17:44:16 +0000
commit736baa8ac028f01a5c79ebecb6fc7043b47d3c4e (patch)
tree2ce1a86efd7d158d649842382c4ea11c64542a60
parent4c91551c3b342ec58910f3622297217615b0afb3 (diff)
downloadgoogletest-736baa8ac028f01a5c79ebecb6fc7043b47d3c4e.tar.gz
googletest-736baa8ac028f01a5c79ebecb6fc7043b47d3c4e.tar.bz2
googletest-736baa8ac028f01a5c79ebecb6fc7043b47d3c4e.zip
Prints the type of the actual value as part of a match message when appropriate.
-rw-r--r--include/gmock/gmock-matchers.h15
-rw-r--r--test/gmock-matchers_test.cc101
2 files changed, 88 insertions, 28 deletions
diff --git a/include/gmock/gmock-matchers.h b/include/gmock/gmock-matchers.h
index 1938be90..627f3ff0 100644
--- a/include/gmock/gmock-matchers.h
+++ b/include/gmock/gmock-matchers.h
@@ -461,6 +461,16 @@ inline void PrintIfNotEmpty(const internal::string& explanation,
}
}
+// Returns true if the given type name is easy to read by a human.
+// This is used to decide whether printing the type of a value might
+// be helpful.
+inline bool IsReadableTypeName(const string& type_name) {
+ // We consider a type name readable if it's short or doesn't contain
+ // a template or function type.
+ return (type_name.length() <= 20 ||
+ type_name.find_first_of("<(") == string::npos);
+}
+
// Matches the value against the given matcher, prints the value and explains
// the match result to the listener. Returns the match result.
// 'listener' must not be NULL.
@@ -479,6 +489,11 @@ bool MatchPrintAndExplain(Value& value, const Matcher<T>& matcher,
const bool match = matcher.MatchAndExplain(value, &inner_listener);
UniversalPrint(value, listener->stream());
+#if GTEST_HAS_RTTI
+ const string& type_name = GetTypeName<Value>();
+ if (IsReadableTypeName(type_name))
+ *listener->stream() << " (of type " << type_name << ")";
+#endif
PrintIfNotEmpty(inner_listener.str(), listener->stream());
return match;
diff --git a/test/gmock-matchers_test.cc b/test/gmock-matchers_test.cc
index dfa34a42..deff9b23 100644
--- a/test/gmock-matchers_test.cc
+++ b/test/gmock-matchers_test.cc
@@ -123,6 +123,7 @@ using testing::internal::DummyMatchResultListener;
using testing::internal::ExplainMatchFailureTupleTo;
using testing::internal::FloatingEqMatcher;
using testing::internal::FormatMatcherDescription;
+using testing::internal::IsReadableTypeName;
using testing::internal::JoinAsTuple;
using testing::internal::RE;
using testing::internal::StreamMatchResultListener;
@@ -164,6 +165,14 @@ Matcher<int> GreaterThan(int n) {
return MakeMatcher(new GreaterThanMatcher(n));
}
+string OfType(const string& type_name) {
+#if GTEST_HAS_RTTI
+ return " (of type " + type_name + ")";
+#else
+ return "";
+#endif
+}
+
// Returns the description of the given matcher.
template <typename T>
string Describe(const Matcher<T>& m) {
@@ -2383,7 +2392,7 @@ TEST(MatcherAssertionTest, WorksWhenMatcherIsSatisfied) {
TEST(MatcherAssertionTest, WorksWhenMatcherIsNotSatisfied) {
// 'n' must be static as it is used in an EXPECT_FATAL_FAILURE(),
// which cannot reference auto variables.
- static int n;
+ static unsigned short n; // NOLINT
n = 5;
// VC++ prior to version 8.0 SP1 has a bug where it will not see any
@@ -2394,13 +2403,13 @@ TEST(MatcherAssertionTest, WorksWhenMatcherIsNotSatisfied) {
EXPECT_FATAL_FAILURE(ASSERT_THAT(n, ::testing::Gt(10)),
"Value of: n\n"
"Expected: is > 10\n"
- " Actual: 5");
+ " Actual: 5" + OfType("unsigned short"));
n = 0;
EXPECT_NONFATAL_FAILURE(
EXPECT_THAT(n, ::testing::AllOf(::testing::Le(7), ::testing::Ge(5))),
"Value of: n\n"
"Expected: (is <= 7) and (is >= 5)\n"
- " Actual: 0");
+ " Actual: 0" + OfType("unsigned short"));
}
// Tests that ASSERT_THAT() and EXPECT_THAT() work when the argument
@@ -2416,7 +2425,7 @@ TEST(MatcherAssertionTest, WorksForByRefArguments) {
"Expected: does not reference the variable @");
// Tests the "Actual" part.
EXPECT_FATAL_FAILURE(ASSERT_THAT(n, ::testing::Not(::testing::Ref(n))),
- "Actual: 0, which is located @");
+ "Actual: 0" + OfType("int") + ", which is located @");
}
#if !GTEST_OS_SYMBIAN
@@ -2439,12 +2448,16 @@ TEST(MatcherAssertionTest, WorksForMonomorphicMatcher) {
Matcher<const string&> ends_with_ok = EndsWith("ok");
ASSERT_THAT("book", ends_with_ok);
-
+ const string bad = "bad";
+ EXPECT_NONFATAL_FAILURE(EXPECT_THAT(bad, ends_with_ok),
+ "Value of: bad\n"
+ "Expected: ends with \"ok\"\n"
+ " Actual: \"bad\"");
Matcher<int> is_greater_than_5 = Gt(5);
EXPECT_NONFATAL_FAILURE(EXPECT_THAT(5, is_greater_than_5),
"Value of: 5\n"
"Expected: is > 5\n"
- " Actual: 5");
+ " Actual: 5" + OfType("int"));
}
#endif // !GTEST_OS_SYMBIAN
@@ -2768,16 +2781,16 @@ TEST(PointeeTest, CanExplainMatchResult) {
EXPECT_EQ("", Explain(m, static_cast<const string*>(NULL)));
- const Matcher<int*> m2 = Pointee(GreaterThan(1));
- int n = 3;
- EXPECT_EQ("which points to 3, which is 2 more than 1",
+ const Matcher<long*> m2 = Pointee(GreaterThan(1)); // NOLINT
+ long n = 3; // NOLINT
+ EXPECT_EQ("which points to 3" + OfType("long") + ", which is 2 more than 1",
Explain(m2, &n));
}
TEST(PointeeTest, AlwaysExplainsPointee) {
const Matcher<int*> m = Pointee(0);
int n = 42;
- EXPECT_EQ("which points to 42", Explain(m, &n));
+ EXPECT_EQ("which points to 42" + OfType("int"), Explain(m, &n));
}
// An uncopyable class.
@@ -2914,10 +2927,12 @@ TEST(FieldTest, CanExplainMatchResult) {
AStruct a;
a.x = 1;
- EXPECT_EQ("whose given field is 1", Explain(m, a));
+ EXPECT_EQ("whose given field is 1" + OfType("int"), Explain(m, a));
m = Field(&AStruct::x, GreaterThan(0));
- EXPECT_EQ("whose given field is 1, which is 1 more than 0", Explain(m, a));
+ EXPECT_EQ(
+ "whose given field is 1" + OfType("int") + ", which is 1 more than 0",
+ Explain(m, a));
}
// Tests that Field() works when the argument is a pointer to const.
@@ -2984,11 +2999,12 @@ TEST(FieldForPointerTest, CanExplainMatchResult) {
AStruct a;
a.x = 1;
EXPECT_EQ("", Explain(m, static_cast<const AStruct*>(NULL)));
- EXPECT_EQ("which points to an object whose given field is 1", Explain(m, &a));
+ EXPECT_EQ("which points to an object whose given field is 1" + OfType("int"),
+ Explain(m, &a));
m = Field(&AStruct::x, GreaterThan(0));
- EXPECT_EQ("which points to an object whose given field is 1, "
- "which is 1 more than 0", Explain(m, &a));
+ EXPECT_EQ("which points to an object whose given field is 1" + OfType("int") +
+ ", which is 1 more than 0", Explain(m, &a));
}
// A user-defined class for testing Property().
@@ -3118,10 +3134,12 @@ TEST(PropertyTest, CanExplainMatchResult) {
AClass a;
a.set_n(1);
- EXPECT_EQ("whose given property is 1", Explain(m, a));
+ EXPECT_EQ("whose given property is 1" + OfType("int"), Explain(m, a));
m = Property(&AClass::n, GreaterThan(0));
- EXPECT_EQ("whose given property is 1, which is 1 more than 0", Explain(m, a));
+ EXPECT_EQ(
+ "whose given property is 1" + OfType("int") + ", which is 1 more than 0",
+ Explain(m, a));
}
// Tests that Property() works when the argument is a pointer to const.
@@ -3198,12 +3216,14 @@ TEST(PropertyForPointerTest, CanExplainMatchResult) {
AClass a;
a.set_n(1);
EXPECT_EQ("", Explain(m, static_cast<const AClass*>(NULL)));
- EXPECT_EQ("which points to an object whose given property is 1",
- Explain(m, &a));
+ EXPECT_EQ(
+ "which points to an object whose given property is 1" + OfType("int"),
+ Explain(m, &a));
m = Property(&AClass::n, GreaterThan(0));
- EXPECT_EQ("which points to an object whose given property is 1, "
- "which is 1 more than 0", Explain(m, &a));
+ EXPECT_EQ("which points to an object whose given property is 1" +
+ OfType("int") + ", which is 1 more than 0",
+ Explain(m, &a));
}
// Tests ResultOf.
@@ -3234,12 +3254,12 @@ int IntFunction(int input) { return input == 42 ? 80 : 90; }
TEST(ResultOfTest, CanExplainMatchResult) {
Matcher<int> matcher = ResultOf(&IntFunction, Ge(85));
- EXPECT_EQ("which is mapped by the given callable to 90",
+ EXPECT_EQ("which is mapped by the given callable to 90" + OfType("int"),
Explain(matcher, 36));
matcher = ResultOf(&IntFunction, GreaterThan(85));
- EXPECT_EQ("which is mapped by the given callable to 90, "
- "which is 5 more than 85", Explain(matcher, 36));
+ EXPECT_EQ("which is mapped by the given callable to 90" + OfType("int") +
+ ", which is 5 more than 85", Explain(matcher, 36));
}
// Tests that ResultOf(f, ...) compiles and works as expected when f(x)
@@ -3253,9 +3273,9 @@ TEST(ResultOfTest, WorksForNonReferenceResults) {
// Tests that ResultOf(f, ...) compiles and works as expected when f(x)
// returns a reference to non-const.
-double& DoubleFunction(double& input) { return input; }
+double& DoubleFunction(double& input) { return input; } // NOLINT
-Uncopyable& RefUncopyableFunction(Uncopyable& obj) {
+Uncopyable& RefUncopyableFunction(Uncopyable& obj) { // NOLINT
return obj;
}
@@ -3304,7 +3324,7 @@ TEST(ResultOfTest, WorksForCompatibleMatcherTypes) {
// a NULL function pointer.
TEST(ResultOfDeathTest, DiesOnNullFunctionPointers) {
EXPECT_DEATH_IF_SUPPORTED(
- ResultOf(static_cast<string(*)(int)>(NULL), Eq(string("foo"))),
+ ResultOf(static_cast<string(*)(int dummy)>(NULL), Eq(string("foo"))),
"NULL function pointer is passed into ResultOf\\(\\)\\.");
}
@@ -3682,6 +3702,31 @@ TEST(ContainerEqExtraTest, CopiesNativeArrayParameter) {
EXPECT_THAT(a1, m);
}
+// Tests IsReadableTypeName().
+
+TEST(IsReadableTypeNameTest, ReturnsTrueForShortNames) {
+ EXPECT_TRUE(IsReadableTypeName("int"));
+ EXPECT_TRUE(IsReadableTypeName("const unsigned char*"));
+ EXPECT_TRUE(IsReadableTypeName("MyMap<int, void*>"));
+ EXPECT_TRUE(IsReadableTypeName("void (*)(int, bool)"));
+}
+
+TEST(IsReadableTypeNameTest, ReturnsTrueForLongNonTemplateNonFunctionNames) {
+ EXPECT_TRUE(IsReadableTypeName("my_long_namespace::MyClassName"));
+ EXPECT_TRUE(IsReadableTypeName("int [5][6][7][8][9][10][11]"));
+ EXPECT_TRUE(IsReadableTypeName("my_namespace::MyOuterClass::MyInnerClass"));
+}
+
+TEST(IsReadableTypeNameTest, ReturnsFalseForLongTemplateNames) {
+ EXPECT_FALSE(
+ IsReadableTypeName("basic_string<char, std::char_traits<char> >"));
+ EXPECT_FALSE(IsReadableTypeName("std::vector<int, std::alloc_traits<int> >"));
+}
+
+TEST(IsReadableTypeNameTest, ReturnsFalseForLongFunctionTypeNames) {
+ EXPECT_FALSE(IsReadableTypeName("void (&)(int, bool, char, float)"));
+}
+
// Tests JoinAsTuple().
TEST(JoinAsTupleTest, JoinsEmptyTuple) {
@@ -3772,7 +3817,7 @@ TEST(EachTest, ExplainsMatchResultCorrectly) {
Matcher<set<int> > m = Each(2);
EXPECT_EQ("", Explain(m, a));
- Matcher<const int(&)[1]> n = Each(1);
+ Matcher<const int(&)[1]> n = Each(1); // NOLINT
const int b[1] = { 1 };
EXPECT_EQ("", Explain(n, b));