From 6b74da4757a549563d7c37c8fae3e704662a043b Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 27 Dec 2021 08:04:50 -0800 Subject: Include the param names in the generated description of the MATCHER_P matchers. PiperOrigin-RevId: 418497526 Change-Id: Ie53c3c0810c10a32cbcb941e3ca1ee8fb1ddd9f9 --- googlemock/include/gmock/gmock-matchers.h | 36 ++++++++++++-------- .../include/gmock/internal/gmock-internal-utils.h | 6 +++- googlemock/src/gmock-internal-utils.cc | 30 +++++++++-------- googlemock/src/gmock-matchers.cc | 12 ++++--- googlemock/test/gmock-internal-utils_test.cc | 23 ++++++------- googlemock/test/gmock-matchers_test.cc | 39 +++++++++++----------- googlemock/test/gmock_output_test_golden.txt | 2 +- 7 files changed, 83 insertions(+), 65 deletions(-) diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h index d952369..2f846ba 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h @@ -3864,9 +3864,9 @@ BoundSecondMatcher MatcherBindSecond( // 'negation' is false; otherwise returns the description of the // negation of the matcher. 'param_values' contains a list of strings // that are the print-out of the matcher's parameters. -GTEST_API_ std::string FormatMatcherDescription(bool negation, - const char* matcher_name, - const Strings& param_values); +GTEST_API_ std::string FormatMatcherDescription( + bool negation, const char* matcher_name, + const std::vector& param_names, const Strings& param_values); // Implements a matcher that checks the value of a optional<> type variable. template @@ -5449,7 +5449,7 @@ PolymorphicMatcher> ThrowsMessage( return gmock_description; \ } \ return ::testing::internal::FormatMatcherDescription(negation, #name, \ - {}); \ + {}, {}); \ } \ }; \ }; \ @@ -5461,33 +5461,41 @@ PolymorphicMatcher> ThrowsMessage( const #define MATCHER_P(name, p0, description) \ - GMOCK_INTERNAL_MATCHER(name, name##MatcherP, description, (p0)) -#define MATCHER_P2(name, p0, p1, description) \ - GMOCK_INTERNAL_MATCHER(name, name##MatcherP2, description, (p0, p1)) -#define MATCHER_P3(name, p0, p1, p2, description) \ - GMOCK_INTERNAL_MATCHER(name, name##MatcherP3, description, (p0, p1, p2)) -#define MATCHER_P4(name, p0, p1, p2, p3, description) \ - GMOCK_INTERNAL_MATCHER(name, name##MatcherP4, description, (p0, p1, p2, p3)) + GMOCK_INTERNAL_MATCHER(name, name##MatcherP, description, (#p0), (p0)) +#define MATCHER_P2(name, p0, p1, description) \ + GMOCK_INTERNAL_MATCHER(name, name##MatcherP2, description, (#p0, #p1), \ + (p0, p1)) +#define MATCHER_P3(name, p0, p1, p2, description) \ + GMOCK_INTERNAL_MATCHER(name, name##MatcherP3, description, (#p0, #p1, #p2), \ + (p0, p1, p2)) +#define MATCHER_P4(name, p0, p1, p2, p3, description) \ + GMOCK_INTERNAL_MATCHER(name, name##MatcherP4, description, \ + (#p0, #p1, #p2, #p3), (p0, p1, p2, p3)) #define MATCHER_P5(name, p0, p1, p2, p3, p4, description) \ GMOCK_INTERNAL_MATCHER(name, name##MatcherP5, description, \ - (p0, p1, p2, p3, p4)) + (#p0, #p1, #p2, #p3, #p4), (p0, p1, p2, p3, p4)) #define MATCHER_P6(name, p0, p1, p2, p3, p4, p5, description) \ GMOCK_INTERNAL_MATCHER(name, name##MatcherP6, description, \ + (#p0, #p1, #p2, #p3, #p4, #p5), \ (p0, p1, p2, p3, p4, p5)) #define MATCHER_P7(name, p0, p1, p2, p3, p4, p5, p6, description) \ GMOCK_INTERNAL_MATCHER(name, name##MatcherP7, description, \ + (#p0, #p1, #p2, #p3, #p4, #p5, #p6), \ (p0, p1, p2, p3, p4, p5, p6)) #define MATCHER_P8(name, p0, p1, p2, p3, p4, p5, p6, p7, description) \ GMOCK_INTERNAL_MATCHER(name, name##MatcherP8, description, \ + (#p0, #p1, #p2, #p3, #p4, #p5, #p6, #p7), \ (p0, p1, p2, p3, p4, p5, p6, p7)) #define MATCHER_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, description) \ GMOCK_INTERNAL_MATCHER(name, name##MatcherP9, description, \ + (#p0, #p1, #p2, #p3, #p4, #p5, #p6, #p7, #p8), \ (p0, p1, p2, p3, p4, p5, p6, p7, p8)) #define MATCHER_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, description) \ GMOCK_INTERNAL_MATCHER(name, name##MatcherP10, description, \ + (#p0, #p1, #p2, #p3, #p4, #p5, #p6, #p7, #p8, #p9), \ (p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)) -#define GMOCK_INTERNAL_MATCHER(name, full_name, description, args) \ +#define GMOCK_INTERNAL_MATCHER(name, full_name, description, arg_names, args) \ template \ class full_name : public ::testing::internal::MatcherBaseImpl< \ full_name> { \ @@ -5516,7 +5524,7 @@ PolymorphicMatcher> ThrowsMessage( return gmock_description; \ } \ return ::testing::internal::FormatMatcherDescription( \ - negation, #name, \ + negation, #name, {GMOCK_PP_REMOVE_PARENS(arg_names)}, \ ::testing::internal::UniversalTersePrintTupleFieldsToStrings( \ ::std::tuple( \ GMOCK_INTERNAL_MATCHER_MEMBERS_USAGE(args)))); \ diff --git a/googlemock/include/gmock/internal/gmock-internal-utils.h b/googlemock/include/gmock/internal/gmock-internal-utils.h index 2975fad..577f52f 100644 --- a/googlemock/include/gmock/internal/gmock-internal-utils.h +++ b/googlemock/include/gmock/internal/gmock-internal-utils.h @@ -38,9 +38,12 @@ #define GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_ #include + #include // NOLINT #include #include +#include + #include "gmock/internal/gmock-port.h" #include "gtest/gtest.h" @@ -61,7 +64,8 @@ namespace internal { // Joins a vector of strings as if they are fields of a tuple; returns // the joined string. -GTEST_API_ std::string JoinAsTuple(const Strings& fields); +GTEST_API_ std::string JoinAsKeyValueTuple( + const std::vector& names, const Strings& values); // Converts an identifier name to a space-separated list of lower-case // words. Each maximum substring of the form [A-Za-z][a-z]*|\d+ is diff --git a/googlemock/src/gmock-internal-utils.cc b/googlemock/src/gmock-internal-utils.cc index 7d4ec61..6020736 100644 --- a/googlemock/src/gmock-internal-utils.cc +++ b/googlemock/src/gmock-internal-utils.cc @@ -44,6 +44,7 @@ #include #include // NOLINT #include +#include #include "gmock/gmock.h" #include "gmock/internal/gmock-port.h" @@ -54,21 +55,22 @@ namespace internal { // Joins a vector of strings as if they are fields of a tuple; returns // the joined string. -GTEST_API_ std::string JoinAsTuple(const Strings& fields) { - switch (fields.size()) { - case 0: - return ""; - case 1: - return fields[0]; - default: - std::string result = "(" + fields[0]; - for (size_t i = 1; i < fields.size(); i++) { - result += ", "; - result += fields[i]; - } - result += ")"; - return result; +GTEST_API_ std::string JoinAsKeyValueTuple( + const std::vector& names, const Strings& values) { + GTEST_CHECK_(names.size() == values.size()); + if (values.empty()) { + return ""; } + const auto build_one = [&](const size_t i) { + return std::string(names[i]) + ": " + values[i]; + }; + std::string result = "(" + build_one(0); + for (size_t i = 1; i < values.size(); i++) { + result += ", "; + result += build_one(i); + } + result += ")"; + return result; } // Converts an identifier name to a space-separated list of lower-case diff --git a/googlemock/src/gmock-matchers.cc b/googlemock/src/gmock-matchers.cc index dded437..873527b 100644 --- a/googlemock/src/gmock-matchers.cc +++ b/googlemock/src/gmock-matchers.cc @@ -36,9 +36,11 @@ #include "gmock/gmock-matchers.h" #include + #include #include #include +#include namespace testing { namespace internal { @@ -48,11 +50,13 @@ namespace internal { // 'negation' is false; otherwise returns the description of the // negation of the matcher. 'param_values' contains a list of strings // that are the print-out of the matcher's parameters. -GTEST_API_ std::string FormatMatcherDescription(bool negation, - const char* matcher_name, - const Strings& param_values) { +GTEST_API_ std::string FormatMatcherDescription( + bool negation, const char* matcher_name, + const std::vector& param_names, const Strings& param_values) { std::string result = ConvertIdentifierNameToWords(matcher_name); - if (param_values.size() >= 1) result += " " + JoinAsTuple(param_values); + if (param_values.size() >= 1) { + result += " " + JoinAsKeyValueTuple(param_names, param_values); + } return negation ? "not (" + result + ")" : result; } diff --git a/googlemock/test/gmock-internal-utils_test.cc b/googlemock/test/gmock-internal-utils_test.cc index 494b1fc..800ee8a 100644 --- a/googlemock/test/gmock-internal-utils_test.cc +++ b/googlemock/test/gmock-internal-utils_test.cc @@ -70,24 +70,23 @@ namespace internal { namespace { -TEST(JoinAsTupleTest, JoinsEmptyTuple) { - EXPECT_EQ("", JoinAsTuple(Strings())); +TEST(JoinAsKeyValueTupleTest, JoinsEmptyTuple) { + EXPECT_EQ("", JoinAsKeyValueTuple({}, Strings())); } -TEST(JoinAsTupleTest, JoinsOneTuple) { - const char* fields[] = {"1"}; - EXPECT_EQ("1", JoinAsTuple(Strings(fields, fields + 1))); +TEST(JoinAsKeyValueTupleTest, JoinsOneTuple) { + EXPECT_EQ("(a: 1)", JoinAsKeyValueTuple({"a"}, {"1"})); } -TEST(JoinAsTupleTest, JoinsTwoTuple) { - const char* fields[] = {"1", "a"}; - EXPECT_EQ("(1, a)", JoinAsTuple(Strings(fields, fields + 2))); +TEST(JoinAsKeyValueTupleTest, JoinsTwoTuple) { + EXPECT_EQ("(a: 1, b: 2)", JoinAsKeyValueTuple({"a", "b"}, {"1", "2"})); } -TEST(JoinAsTupleTest, JoinsTenTuple) { - const char* fields[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"}; - EXPECT_EQ("(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)", - JoinAsTuple(Strings(fields, fields + 10))); +TEST(JoinAsKeyValueTupleTest, JoinsTenTuple) { + EXPECT_EQ( + "(a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10)", + JoinAsKeyValueTuple({"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"}, + {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"})); } TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameContainsNoWord) { diff --git a/googlemock/test/gmock-matchers_test.cc b/googlemock/test/gmock-matchers_test.cc index ade2bc9..34282e6 100644 --- a/googlemock/test/gmock-matchers_test.cc +++ b/googlemock/test/gmock-matchers_test.cc @@ -6439,19 +6439,16 @@ TEST(IsReadableTypeNameTest, ReturnsFalseForLongFunctionTypeNames) { TEST(FormatMatcherDescriptionTest, WorksForEmptyDescription) { EXPECT_EQ("is even", - FormatMatcherDescription(false, "IsEven", Strings())); + FormatMatcherDescription(false, "IsEven", {}, Strings())); EXPECT_EQ("not (is even)", - FormatMatcherDescription(true, "IsEven", Strings())); + FormatMatcherDescription(true, "IsEven", {}, Strings())); - const char* params[] = {"5"}; - EXPECT_EQ("equals 5", - FormatMatcherDescription(false, "Equals", - Strings(params, params + 1))); + EXPECT_EQ("equals (a: 5)", + FormatMatcherDescription(false, "Equals", {"a"}, {"5"})); - const char* params2[] = {"5", "8"}; - EXPECT_EQ("is in range (5, 8)", - FormatMatcherDescription(false, "IsInRange", - Strings(params2, params2 + 2))); + EXPECT_EQ( + "is in range (a: 5, b: 8)", + FormatMatcherDescription(false, "IsInRange", {"a", "b"}, {"5", "8"})); } // Tests PolymorphicMatcher::mutable_impl(). @@ -7810,8 +7807,8 @@ TEST(MatcherPMacroTest, Works) { EXPECT_TRUE(m.Matches(36)); EXPECT_FALSE(m.Matches(5)); - EXPECT_EQ("is greater than 32 and 5", Describe(m)); - EXPECT_EQ("not (is greater than 32 and 5)", DescribeNegation(m)); + EXPECT_EQ("is greater than 32 and (n: 5)", Describe(m)); + EXPECT_EQ("not (is greater than 32 and (n: 5))", DescribeNegation(m)); EXPECT_EQ("", Explain(m, 36)); EXPECT_EQ("", Explain(m, 5)); } @@ -7822,8 +7819,8 @@ MATCHER_P(_is_Greater_Than32and_, n, "") { return arg > 32 && arg > n; } TEST(MatcherPMacroTest, GeneratesCorrectDescription) { const Matcher m = _is_Greater_Than32and_(5); - EXPECT_EQ("is greater than 32 and 5", Describe(m)); - EXPECT_EQ("not (is greater than 32 and 5)", DescribeNegation(m)); + EXPECT_EQ("is greater than 32 and (n: 5)", Describe(m)); + EXPECT_EQ("not (is greater than 32 and (n: 5))", DescribeNegation(m)); EXPECT_EQ("", Explain(m, 36)); EXPECT_EQ("", Explain(m, 5)); } @@ -7856,7 +7853,8 @@ TEST(MatcherPMacroTest, WorksWhenExplicitlyInstantiatedWithReference) { // likely it will just annoy the user. If the address is // interesting, the user should consider passing the parameter by // pointer instead. - EXPECT_EQ("references uncopyable 1-byte object <31>", Describe(m)); + EXPECT_EQ("references uncopyable (variable: 1-byte object <31>)", + Describe(m)); } // Tests that the body of MATCHER_Pn() can reference the parameter @@ -7907,8 +7905,10 @@ TEST(MatcherPnMacroTest, // likely they will just annoy the user. If the addresses are // interesting, the user should consider passing the parameters by // pointers instead. - EXPECT_EQ("references any of (1-byte object <31>, 1-byte object <32>)", - Describe(m)); + EXPECT_EQ( + "references any of (variable1: 1-byte object <31>, variable2: 1-byte " + "object <32>)", + Describe(m)); } // Tests that a simple MATCHER_P2() definition works. @@ -7920,8 +7920,9 @@ TEST(MatcherPnMacroTest, Works) { EXPECT_TRUE(m.Matches(36L)); EXPECT_FALSE(m.Matches(15L)); - EXPECT_EQ("is not in closed range (10, 20)", Describe(m)); - EXPECT_EQ("not (is not in closed range (10, 20))", DescribeNegation(m)); + EXPECT_EQ("is not in closed range (low: 10, hi: 20)", Describe(m)); + EXPECT_EQ("not (is not in closed range (low: 10, hi: 20))", + DescribeNegation(m)); EXPECT_EQ("", Explain(m, 36L)); EXPECT_EQ("", Explain(m, 15L)); } diff --git a/googlemock/test/gmock_output_test_golden.txt b/googlemock/test/gmock_output_test_golden.txt index 4846c12..fdf224f 100644 --- a/googlemock/test/gmock_output_test_golden.txt +++ b/googlemock/test/gmock_output_test_golden.txt @@ -291,7 +291,7 @@ Stack trace: [ RUN ] GMockOutputTest.PrintsMatcher FILE:#: Failure Value of: (std::pair(42, true)) -Expected: is pair (is >= 48, true) +Expected: is pair (first: is >= 48, second: true) Actual: (42, true) (of type std::pair) [ FAILED ] GMockOutputTest.PrintsMatcher [ FAILED ] GMockOutputTest.UnexpectedCall -- cgit v0.12