From 736baa8ac028f01a5c79ebecb6fc7043b47d3c4e Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Mon, 27 Sep 2010 17:44:16 +0000 Subject: [PATCH] Prints the type of the actual value as part of a match message when appropriate. --- include/gmock/gmock-matchers.h | 15 +++++ test/gmock-matchers_test.cc | 101 ++++++++++++++++++++++++--------- 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& matcher, const bool match = matcher.MatchAndExplain(value, &inner_listener); UniversalPrint(value, listener->stream()); +#if GTEST_HAS_RTTI + const string& type_name = GetTypeName(); + 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 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 string Describe(const Matcher& 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 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 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(NULL))); - const Matcher m2 = Pointee(GreaterThan(1)); - int n = 3; - EXPECT_EQ("which points to 3, which is 2 more than 1", + const Matcher 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 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(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(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 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(NULL), Eq(string("foo"))), + ResultOf(static_cast(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")); + 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 >")); + EXPECT_FALSE(IsReadableTypeName("std::vector >")); +} + +TEST(IsReadableTypeNameTest, ReturnsFalseForLongFunctionTypeNames) { + EXPECT_FALSE(IsReadableTypeName("void (&)(int, bool, char, float)")); +} + // Tests JoinAsTuple(). TEST(JoinAsTupleTest, JoinsEmptyTuple) { @@ -3772,7 +3817,7 @@ TEST(EachTest, ExplainsMatchResultCorrectly) { Matcher > m = Each(2); EXPECT_EQ("", Explain(m, a)); - Matcher n = Each(1); + Matcher n = Each(1); // NOLINT const int b[1] = { 1 }; EXPECT_EQ("", Explain(n, b));