diff --git a/include/gmock/gmock-generated-matchers.h b/include/gmock/gmock-generated-matchers.h index 2790e06c..2cc5746e 100644 --- a/include/gmock/gmock-generated-matchers.h +++ b/include/gmock/gmock-generated-matchers.h @@ -946,25 +946,29 @@ ElementsAreArray(const T (&array)[N]) { // Describing Parameterized Matchers // ================================= // -// When defining a parameterized matcher, you can use Python-style -// interpolations in the description string to refer to the parameter -// values. We support the following syntax currently: +// The last argument to MATCHER*() is a string-typed expression. The +// expression can reference all of the matcher's parameters and a +// special bool-typed variable named 'negation'. When 'negation' is +// false, the expression should evaluate to the matcher's description; +// otherwise it should evaluate to the description of the negation of +// the matcher. For example, // -// %% a single '%' character -// %(*)s all parameters of the matcher printed as a tuple -// %(foo)s value of the matcher parameter named 'foo' +// using testing::PrintToString; // -// For example, -// -// MATCHER_P2(InClosedRange, low, hi, "is in range [%(low)s, %(hi)s]") { +// MATCHER_P2(InClosedRange, low, hi, +// string(negation ? "is not" : "is") + " in range [" + +// PrintToString(low) + ", " + PrintToString(hi) + "]") { // return low <= arg && arg <= hi; // } // ... // EXPECT_THAT(3, InClosedRange(4, 6)); +// EXPECT_THAT(3, Not(InClosedRange(2, 4))); // -// would generate a failure that contains the message: +// would generate two failures that contain the text: // // Expected: is in range [4, 6] +// ... +// Expected: is not in range [2, 4] // // If you specify "" as the description, the failure message will // contain the sequence of words in the matcher name followed by the @@ -973,10 +977,13 @@ ElementsAreArray(const T (&array)[N]) { // MATCHER_P2(InClosedRange, low, hi, "") { ... } // ... // EXPECT_THAT(3, InClosedRange(4, 6)); +// EXPECT_THAT(3, Not(InClosedRange(2, 4))); // -// would generate a failure that contains the text: +// would generate two failures that contain the text: // // Expected: in closed range (4, 6) +// ... +// Expected: not (in closed range (2, 4)) // // Types of Matcher Parameters // =========================== @@ -1065,33 +1072,36 @@ ElementsAreArray(const T (&array)[N]) { template \ class gmock_Impl : public ::testing::MatcherInterface {\ public:\ - gmock_Impl(const ::testing::internal::Interpolations& gmock_interp)\ - : gmock_interp_(gmock_interp) {}\ + gmock_Impl()\ + {}\ virtual bool MatchAndExplain(\ arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ - const ::testing::internal::Strings& gmock_printed_params = \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tr1::tuple<>());\ - *gmock_os << ::testing::internal::FormatMatcherDescription(\ - #name, description, gmock_interp_, gmock_printed_params);\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ }\ - const ::testing::internal::Interpolations gmock_interp_;\ private:\ + ::testing::internal::string FormatDescription(bool negation) const {\ + const ::testing::internal::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name,\ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tr1::tuple<>()));\ + }\ GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ };\ template \ operator ::testing::Matcher() const {\ return ::testing::Matcher(\ - new gmock_Impl(gmock_interp_));\ + new gmock_Impl());\ }\ name##Matcher() {\ - const char* gmock_param_names[] = { NULL };\ - gmock_interp_ = ::testing::internal::ValidateMatcherDescription(\ - gmock_param_names, ("" description ""));\ }\ private:\ - ::testing::internal::Interpolations gmock_interp_;\ GTEST_DISALLOW_ASSIGN_(name##Matcher);\ };\ inline name##Matcher name() {\ @@ -1110,36 +1120,38 @@ ElementsAreArray(const T (&array)[N]) { template \ class gmock_Impl : public ::testing::MatcherInterface {\ public:\ - explicit gmock_Impl(p0##_type gmock_p0, \ - const ::testing::internal::Interpolations& gmock_interp)\ - : p0(gmock_p0), gmock_interp_(gmock_interp) {}\ + explicit gmock_Impl(p0##_type gmock_p0)\ + : p0(gmock_p0) {}\ virtual bool MatchAndExplain(\ arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ - const ::testing::internal::Strings& gmock_printed_params = \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tr1::tuple(p0));\ - *gmock_os << ::testing::internal::FormatMatcherDescription(\ - #name, description, gmock_interp_, gmock_printed_params);\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ }\ p0##_type p0;\ - const ::testing::internal::Interpolations gmock_interp_;\ private:\ + ::testing::internal::string FormatDescription(bool negation) const {\ + const ::testing::internal::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name,\ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tr1::tuple(p0)));\ + }\ GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ };\ template \ operator ::testing::Matcher() const {\ return ::testing::Matcher(\ - new gmock_Impl(p0, gmock_interp_));\ + new gmock_Impl(p0));\ }\ name##MatcherP(p0##_type gmock_p0) : p0(gmock_p0) {\ - const char* gmock_param_names[] = { #p0, NULL };\ - gmock_interp_ = ::testing::internal::ValidateMatcherDescription(\ - gmock_param_names, ("" description ""));\ }\ p0##_type p0;\ private:\ - ::testing::internal::Interpolations gmock_interp_;\ GTEST_DISALLOW_ASSIGN_(name##MatcherP);\ };\ template \ @@ -1160,39 +1172,41 @@ ElementsAreArray(const T (&array)[N]) { template \ class gmock_Impl : public ::testing::MatcherInterface {\ public:\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, \ - const ::testing::internal::Interpolations& gmock_interp)\ - : p0(gmock_p0), p1(gmock_p1), gmock_interp_(gmock_interp) {}\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1)\ + : p0(gmock_p0), p1(gmock_p1) {}\ virtual bool MatchAndExplain(\ arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ - const ::testing::internal::Strings& gmock_printed_params = \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tr1::tuple(p0, p1));\ - *gmock_os << ::testing::internal::FormatMatcherDescription(\ - #name, description, gmock_interp_, gmock_printed_params);\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ }\ p0##_type p0;\ p1##_type p1;\ - const ::testing::internal::Interpolations gmock_interp_;\ private:\ + ::testing::internal::string FormatDescription(bool negation) const {\ + const ::testing::internal::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name,\ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tr1::tuple(p0, p1)));\ + }\ GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ };\ template \ operator ::testing::Matcher() const {\ return ::testing::Matcher(\ - new gmock_Impl(p0, p1, gmock_interp_));\ + new gmock_Impl(p0, p1));\ }\ name##MatcherP2(p0##_type gmock_p0, p1##_type gmock_p1) : p0(gmock_p0), \ p1(gmock_p1) {\ - const char* gmock_param_names[] = { #p0, #p1, NULL };\ - gmock_interp_ = ::testing::internal::ValidateMatcherDescription(\ - gmock_param_names, ("" description ""));\ }\ p0##_type p0;\ p1##_type p1;\ private:\ - ::testing::internal::Interpolations gmock_interp_;\ GTEST_DISALLOW_ASSIGN_(name##MatcherP2);\ };\ template \ @@ -1215,43 +1229,44 @@ ElementsAreArray(const T (&array)[N]) { template \ class gmock_Impl : public ::testing::MatcherInterface {\ public:\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - const ::testing::internal::Interpolations& gmock_interp)\ - : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ - gmock_interp_(gmock_interp) {}\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2)\ + : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2) {}\ virtual bool MatchAndExplain(\ arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ - const ::testing::internal::Strings& gmock_printed_params = \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tr1::tuple(p0, p1, \ - p2));\ - *gmock_os << ::testing::internal::FormatMatcherDescription(\ - #name, description, gmock_interp_, gmock_printed_params);\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ }\ p0##_type p0;\ p1##_type p1;\ p2##_type p2;\ - const ::testing::internal::Interpolations gmock_interp_;\ private:\ + ::testing::internal::string FormatDescription(bool negation) const {\ + const ::testing::internal::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name,\ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tr1::tuple(p0, p1, \ + p2)));\ + }\ GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ };\ template \ operator ::testing::Matcher() const {\ return ::testing::Matcher(\ - new gmock_Impl(p0, p1, p2, gmock_interp_));\ + new gmock_Impl(p0, p1, p2));\ }\ name##MatcherP3(p0##_type gmock_p0, p1##_type gmock_p1, \ p2##_type gmock_p2) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2) {\ - const char* gmock_param_names[] = { #p0, #p1, #p2, NULL };\ - gmock_interp_ = ::testing::internal::ValidateMatcherDescription(\ - gmock_param_names, ("" description ""));\ }\ p0##_type p0;\ p1##_type p1;\ p2##_type p2;\ private:\ - ::testing::internal::Interpolations gmock_interp_;\ GTEST_DISALLOW_ASSIGN_(name##MatcherP3);\ };\ template \ @@ -1276,46 +1291,47 @@ ElementsAreArray(const T (&array)[N]) { class gmock_Impl : public ::testing::MatcherInterface {\ public:\ gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, \ - const ::testing::internal::Interpolations& gmock_interp)\ - : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \ - gmock_interp_(gmock_interp) {}\ + p3##_type gmock_p3)\ + : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3) {}\ virtual bool MatchAndExplain(\ arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ - const ::testing::internal::Strings& gmock_printed_params = \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tr1::tuple(p0, p1, p2, p3));\ - *gmock_os << ::testing::internal::FormatMatcherDescription(\ - #name, description, gmock_interp_, gmock_printed_params);\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ }\ p0##_type p0;\ p1##_type p1;\ p2##_type p2;\ p3##_type p3;\ - const ::testing::internal::Interpolations gmock_interp_;\ private:\ + ::testing::internal::string FormatDescription(bool negation) const {\ + const ::testing::internal::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name,\ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tr1::tuple(p0, p1, p2, p3)));\ + }\ GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ };\ template \ operator ::testing::Matcher() const {\ return ::testing::Matcher(\ - new gmock_Impl(p0, p1, p2, p3, gmock_interp_));\ + new gmock_Impl(p0, p1, p2, p3));\ }\ name##MatcherP4(p0##_type gmock_p0, p1##_type gmock_p1, \ p2##_type gmock_p2, p3##_type gmock_p3) : p0(gmock_p0), p1(gmock_p1), \ p2(gmock_p2), p3(gmock_p3) {\ - const char* gmock_param_names[] = { #p0, #p1, #p2, #p3, NULL };\ - gmock_interp_ = ::testing::internal::ValidateMatcherDescription(\ - gmock_param_names, ("" description ""));\ }\ p0##_type p0;\ p1##_type p1;\ p2##_type p2;\ p3##_type p3;\ private:\ - ::testing::internal::Interpolations gmock_interp_;\ GTEST_DISALLOW_ASSIGN_(name##MatcherP4);\ };\ template {\ public:\ gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, \ - const ::testing::internal::Interpolations& gmock_interp)\ + p3##_type gmock_p3, p4##_type gmock_p4)\ : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \ - p4(gmock_p4), gmock_interp_(gmock_interp) {}\ + p4(gmock_p4) {}\ virtual bool MatchAndExplain(\ arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ - const ::testing::internal::Strings& gmock_printed_params = \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tr1::tuple(p0, p1, p2, p3, p4));\ - *gmock_os << ::testing::internal::FormatMatcherDescription(\ - #name, description, gmock_interp_, gmock_printed_params);\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ }\ p0##_type p0;\ p1##_type p1;\ p2##_type p2;\ p3##_type p3;\ p4##_type p4;\ - const ::testing::internal::Interpolations gmock_interp_;\ private:\ + ::testing::internal::string FormatDescription(bool negation) const {\ + const ::testing::internal::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name,\ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tr1::tuple(p0, p1, p2, p3, p4)));\ + }\ GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ };\ template \ operator ::testing::Matcher() const {\ return ::testing::Matcher(\ - new gmock_Impl(p0, p1, p2, p3, p4, gmock_interp_));\ + new gmock_Impl(p0, p1, p2, p3, p4));\ }\ name##MatcherP5(p0##_type gmock_p0, p1##_type gmock_p1, \ p2##_type gmock_p2, p3##_type gmock_p3, \ p4##_type gmock_p4) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ p3(gmock_p3), p4(gmock_p4) {\ - const char* gmock_param_names[] = { #p0, #p1, #p2, #p3, #p4, NULL };\ - gmock_interp_ = ::testing::internal::ValidateMatcherDescription(\ - gmock_param_names, ("" description ""));\ }\ p0##_type p0;\ p1##_type p1;\ @@ -1386,7 +1405,6 @@ ElementsAreArray(const T (&array)[N]) { p3##_type p3;\ p4##_type p4;\ private:\ - ::testing::internal::Interpolations gmock_interp_;\ GTEST_DISALLOW_ASSIGN_(name##MatcherP5);\ };\ template {\ public:\ gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ - const ::testing::internal::Interpolations& gmock_interp)\ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5)\ : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \ - p4(gmock_p4), p5(gmock_p5), gmock_interp_(gmock_interp) {}\ + p4(gmock_p4), p5(gmock_p5) {}\ virtual bool MatchAndExplain(\ arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ - const ::testing::internal::Strings& gmock_printed_params = \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tr1::tuple(p0, p1, p2, p3, p4, p5));\ - *gmock_os << ::testing::internal::FormatMatcherDescription(\ - #name, description, gmock_interp_, gmock_printed_params);\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ }\ p0##_type p0;\ p1##_type p1;\ @@ -1435,22 +1450,28 @@ ElementsAreArray(const T (&array)[N]) { p3##_type p3;\ p4##_type p4;\ p5##_type p5;\ - const ::testing::internal::Interpolations gmock_interp_;\ private:\ + ::testing::internal::string FormatDescription(bool negation) const {\ + const ::testing::internal::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name,\ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tr1::tuple(p0, p1, p2, p3, p4, p5)));\ + }\ GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ };\ template \ operator ::testing::Matcher() const {\ return ::testing::Matcher(\ - new gmock_Impl(p0, p1, p2, p3, p4, p5, gmock_interp_));\ + new gmock_Impl(p0, p1, p2, p3, p4, p5));\ }\ name##MatcherP6(p0##_type gmock_p0, p1##_type gmock_p1, \ p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ p5##_type gmock_p5) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ p3(gmock_p3), p4(gmock_p4), p5(gmock_p5) {\ - const char* gmock_param_names[] = { #p0, #p1, #p2, #p3, #p4, #p5, NULL };\ - gmock_interp_ = ::testing::internal::ValidateMatcherDescription(\ - gmock_param_names, ("" description ""));\ }\ p0##_type p0;\ p1##_type p1;\ @@ -1459,7 +1480,6 @@ ElementsAreArray(const T (&array)[N]) { p4##_type p4;\ p5##_type p5;\ private:\ - ::testing::internal::Interpolations gmock_interp_;\ GTEST_DISALLOW_ASSIGN_(name##MatcherP6);\ };\ template (p0, p1, p2, p3, p4, p5, \ - p6));\ - *gmock_os << ::testing::internal::FormatMatcherDescription(\ - #name, description, gmock_interp_, gmock_printed_params);\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ }\ p0##_type p0;\ p1##_type p1;\ @@ -1513,24 +1528,30 @@ ElementsAreArray(const T (&array)[N]) { p4##_type p4;\ p5##_type p5;\ p6##_type p6;\ - const ::testing::internal::Interpolations gmock_interp_;\ private:\ + ::testing::internal::string FormatDescription(bool negation) const {\ + const ::testing::internal::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name,\ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tr1::tuple(p0, p1, p2, p3, p4, p5, \ + p6)));\ + }\ GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ };\ template \ operator ::testing::Matcher() const {\ return ::testing::Matcher(\ - new gmock_Impl(p0, p1, p2, p3, p4, p5, p6, gmock_interp_));\ + new gmock_Impl(p0, p1, p2, p3, p4, p5, p6));\ }\ name##MatcherP7(p0##_type gmock_p0, p1##_type gmock_p1, \ p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ p5##_type gmock_p5, p6##_type gmock_p6) : p0(gmock_p0), p1(gmock_p1), \ p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), \ p6(gmock_p6) {\ - const char* gmock_param_names[] = { #p0, #p1, #p2, #p3, #p4, #p5, #p6, \ - NULL };\ - gmock_interp_ = ::testing::internal::ValidateMatcherDescription(\ - gmock_param_names, ("" description ""));\ }\ p0##_type p0;\ p1##_type p1;\ @@ -1540,7 +1561,6 @@ ElementsAreArray(const T (&array)[N]) { p5##_type p5;\ p6##_type p6;\ private:\ - ::testing::internal::Interpolations gmock_interp_;\ GTEST_DISALLOW_ASSIGN_(name##MatcherP7);\ };\ template (p0, p1, p2, \ - p3, p4, p5, p6, p7));\ - *gmock_os << ::testing::internal::FormatMatcherDescription(\ - #name, description, gmock_interp_, gmock_printed_params);\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ }\ p0##_type p0;\ p1##_type p1;\ @@ -1598,15 +1613,24 @@ ElementsAreArray(const T (&array)[N]) { p5##_type p5;\ p6##_type p6;\ p7##_type p7;\ - const ::testing::internal::Interpolations gmock_interp_;\ private:\ + ::testing::internal::string FormatDescription(bool negation) const {\ + const ::testing::internal::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name,\ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tr1::tuple(p0, p1, p2, \ + p3, p4, p5, p6, p7)));\ + }\ GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ };\ template \ operator ::testing::Matcher() const {\ return ::testing::Matcher(\ - new gmock_Impl(p0, p1, p2, p3, p4, p5, p6, p7, \ - gmock_interp_));\ + new gmock_Impl(p0, p1, p2, p3, p4, p5, p6, p7));\ }\ name##MatcherP8(p0##_type gmock_p0, p1##_type gmock_p1, \ p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ @@ -1614,10 +1638,6 @@ ElementsAreArray(const T (&array)[N]) { p7##_type gmock_p7) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \ p7(gmock_p7) {\ - const char* gmock_param_names[] = { #p0, #p1, #p2, #p3, #p4, #p5, #p6, \ - #p7, NULL };\ - gmock_interp_ = ::testing::internal::ValidateMatcherDescription(\ - gmock_param_names, ("" description ""));\ }\ p0##_type p0;\ p1##_type p1;\ @@ -1628,7 +1648,6 @@ ElementsAreArray(const T (&array)[N]) { p6##_type p6;\ p7##_type p7;\ private:\ - ::testing::internal::Interpolations gmock_interp_;\ GTEST_DISALLOW_ASSIGN_(name##MatcherP8);\ };\ template (p0, p1, p2, p3, p4, p5, p6, p7, p8));\ - *gmock_os << ::testing::internal::FormatMatcherDescription(\ - #name, description, gmock_interp_, gmock_printed_params);\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ }\ p0##_type p0;\ p1##_type p1;\ @@ -1689,15 +1704,24 @@ ElementsAreArray(const T (&array)[N]) { p6##_type p6;\ p7##_type p7;\ p8##_type p8;\ - const ::testing::internal::Interpolations gmock_interp_;\ private:\ + ::testing::internal::string FormatDescription(bool negation) const {\ + const ::testing::internal::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name,\ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tr1::tuple(p0, p1, p2, p3, p4, p5, p6, p7, p8)));\ + }\ GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ };\ template \ operator ::testing::Matcher() const {\ return ::testing::Matcher(\ - new gmock_Impl(p0, p1, p2, p3, p4, p5, p6, p7, p8, \ - gmock_interp_));\ + new gmock_Impl(p0, p1, p2, p3, p4, p5, p6, p7, p8));\ }\ name##MatcherP9(p0##_type gmock_p0, p1##_type gmock_p1, \ p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ @@ -1705,10 +1729,6 @@ ElementsAreArray(const T (&array)[N]) { p8##_type gmock_p8) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \ p8(gmock_p8) {\ - const char* gmock_param_names[] = { #p0, #p1, #p2, #p3, #p4, #p5, #p6, \ - #p7, #p8, NULL };\ - gmock_interp_ = ::testing::internal::ValidateMatcherDescription(\ - gmock_param_names, ("" description ""));\ }\ p0##_type p0;\ p1##_type p1;\ @@ -1720,7 +1740,6 @@ ElementsAreArray(const T (&array)[N]) { p7##_type p7;\ p8##_type p8;\ private:\ - ::testing::internal::Interpolations gmock_interp_;\ GTEST_DISALLOW_ASSIGN_(name##MatcherP9);\ };\ template (p0, p1, p2, p3, p4, p5, p6, p7, p8, p9));\ - *gmock_os << ::testing::internal::FormatMatcherDescription(\ - #name, description, gmock_interp_, gmock_printed_params);\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ }\ p0##_type p0;\ p1##_type p1;\ @@ -1785,15 +1800,24 @@ ElementsAreArray(const T (&array)[N]) { p7##_type p7;\ p8##_type p8;\ p9##_type p9;\ - const ::testing::internal::Interpolations gmock_interp_;\ private:\ + ::testing::internal::string FormatDescription(bool negation) const {\ + const ::testing::internal::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name,\ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tr1::tuple(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)));\ + }\ GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ };\ template \ operator ::testing::Matcher() const {\ return ::testing::Matcher(\ - new gmock_Impl(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, \ - gmock_interp_));\ + new gmock_Impl(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9));\ }\ name##MatcherP10(p0##_type gmock_p0, p1##_type gmock_p1, \ p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ @@ -1801,10 +1825,6 @@ ElementsAreArray(const T (&array)[N]) { p8##_type gmock_p8, p9##_type gmock_p9) : p0(gmock_p0), p1(gmock_p1), \ p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \ p7(gmock_p7), p8(gmock_p8), p9(gmock_p9) {\ - const char* gmock_param_names[] = { #p0, #p1, #p2, #p3, #p4, #p5, #p6, \ - #p7, #p8, #p9, NULL };\ - gmock_interp_ = ::testing::internal::ValidateMatcherDescription(\ - gmock_param_names, ("" description ""));\ }\ p0##_type p0;\ p1##_type p1;\ @@ -1817,7 +1837,6 @@ ElementsAreArray(const T (&array)[N]) { p8##_type p8;\ p9##_type p9;\ private:\ - ::testing::internal::Interpolations gmock_interp_;\ GTEST_DISALLOW_ASSIGN_(name##MatcherP10);\ };\ template \ ]]]] $var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]] -$var impl_ctor_param_list = [[$for j [[p$j##_type gmock_p$j, ]] -const ::testing::internal::Interpolations& gmock_interp]] -$var impl_inits = [[ : $for j [[p$j(gmock_p$j), ]]gmock_interp_(gmock_interp)]] +$var impl_ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]] +$var impl_inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(gmock_p$j)]]]]]] $var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(gmock_p$j)]]]]]] -$var params_and_interp = [[$for j [[p$j, ]]gmock_interp_]] $var params = [[$for j, [[p$j]]]] $var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]] $var param_types_and_names = [[$for j, [[p$j##_type p$j]]]] @@ -559,28 +564,31 @@ $var param_field_decls2 = [[$for j virtual bool MatchAndExplain(\ arg_type arg, ::testing::MatchResultListener* result_listener) const;\ virtual void DescribeTo(::std::ostream* gmock_os) const {\ - const ::testing::internal::Strings& gmock_printed_params = \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tr1::tuple<$for j, [[p$j##_type]]>($for j, [[p$j]]));\ - *gmock_os << ::testing::internal::FormatMatcherDescription(\ - #name, description, gmock_interp_, gmock_printed_params);\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ }\$param_field_decls - const ::testing::internal::Interpolations gmock_interp_;\ private:\ + ::testing::internal::string FormatDescription(bool negation) const {\ + const ::testing::internal::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name,\ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tr1::tuple<$for j, [[p$j##_type]]>($for j, [[p$j]])));\ + }\ GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ };\ template \ operator ::testing::Matcher() const {\ return ::testing::Matcher(\ - new gmock_Impl($params_and_interp));\ + new gmock_Impl($params));\ }\ $class_name($ctor_param_list)$inits {\ - const char* gmock_param_names[] = { $for j [[#p$j, ]]NULL };\ - gmock_interp_ = ::testing::internal::ValidateMatcherDescription(\ - gmock_param_names, ("" description ""));\ }\$param_field_decls2 private:\ - ::testing::internal::Interpolations gmock_interp_;\ GTEST_DISALLOW_ASSIGN_($class_name);\ };\$template inline $class_name$param_types name($param_types_and_names) {\ diff --git a/include/gmock/gmock-matchers.h b/include/gmock/gmock-matchers.h index 2a42bf94..315e1f56 100644 --- a/include/gmock/gmock-matchers.h +++ b/include/gmock/gmock-matchers.h @@ -2527,41 +2527,13 @@ class ElementsAreArrayMatcher { GTEST_DISALLOW_ASSIGN_(ElementsAreArrayMatcher); }; -// Constants denoting interpolations in a matcher description string. -const int kTupleInterpolation = -1; // "%(*)s" -const int kPercentInterpolation = -2; // "%%" -const int kInvalidInterpolation = -3; // "%" followed by invalid text - -// Records the location and content of an interpolation. -struct Interpolation { - Interpolation(const char* start, const char* end, int param) - : start_pos(start), end_pos(end), param_index(param) {} - - // Points to the start of the interpolation (the '%' character). - const char* start_pos; - // Points to the first character after the interpolation. - const char* end_pos; - // 0-based index of the interpolated matcher parameter; - // kTupleInterpolation for "%(*)s"; kPercentInterpolation for "%%". - int param_index; -}; - -typedef ::std::vector Interpolations; - -// Parses a matcher description string and returns a vector of -// interpolations that appear in the string; generates non-fatal -// failures iff 'description' is an invalid matcher description. -// 'param_names' is a NULL-terminated array of parameter names in the -// order they appear in the MATCHER_P*() parameter list. -Interpolations ValidateMatcherDescription( - const char* param_names[], const char* description); - -// Returns the actual matcher description, given the matcher name, -// user-supplied description template string, interpolations in the -// string, and the printed values of the matcher parameters. -string FormatMatcherDescription( - const char* matcher_name, const char* description, - const Interpolations& interp, const Strings& param_values); +// Returns the description for a matcher defined using the MATCHER*() +// macro where the user-supplied description string is "", if +// '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. +string FormatMatcherDescription(bool negation, const char* matcher_name, + const Strings& param_values); } // namespace internal diff --git a/src/gmock-matchers.cc b/src/gmock-matchers.cc index 0abca708..89007d9f 100644 --- a/src/gmock-matchers.cc +++ b/src/gmock-matchers.cc @@ -65,74 +65,6 @@ Matcher::Matcher(const char* s) { namespace internal { -// Utilities for validating and formatting description strings in the -// MATCHER*() macros. - -// Returns the 0-based index of the given parameter in the -// NULL-terminated parameter array; if the parameter is "*", returns -// kTupleInterpolation; if it's not found in the list, returns -// kInvalidInterpolation. -int GetParamIndex(const char* param_names[], const string& param_name) { - if (param_name == "*") - return kTupleInterpolation; - - for (int i = 0; param_names[i] != NULL; i++) { - if (param_name == param_names[i]) - return i; - } - return kInvalidInterpolation; -} - -// Helper function used by ValidateMatcherDescription() to format -// error messages. -string FormatMatcherDescriptionSyntaxError(const char* description, - const char* error_pos) { - ::std::stringstream ss; - ss << "Syntax error at index " << (error_pos - description) - << " in matcher description \"" << description << "\": "; - return ss.str(); -} - -// Parses a matcher description string and returns a vector of -// interpolations that appear in the string; generates non-fatal -// failures iff 'description' is an invalid matcher description. -// 'param_names' is a NULL-terminated array of parameter names in the -// order they appear in the MATCHER_P*() parameter list. -Interpolations ValidateMatcherDescription( - const char* param_names[], const char* description) { - Interpolations interps; - for (const char* p = description; *p != '\0';) { - if (SkipPrefix("%%", &p)) { - interps.push_back(Interpolation(p - 2, p, kPercentInterpolation)); - } else if (SkipPrefix("%(", &p)) { - const char* const q = strstr(p, ")s"); - if (q == NULL) { - // TODO(wan@google.com): change the source file location in - // the failure to point to where the MATCHER*() macro is used. - ADD_FAILURE() << FormatMatcherDescriptionSyntaxError(description, p - 2) - << "an interpolation must end with \")s\", " - << "but \"" << (p - 2) << "\" does not."; - } else { - const string param_name(p, q); - const int param_index = GetParamIndex(param_names, param_name); - if (param_index == kInvalidInterpolation) { - ADD_FAILURE() << FormatMatcherDescriptionSyntaxError(description, p) - << "\"" << param_name - << "\" is an invalid parameter name."; - } else { - interps.push_back(Interpolation(p - 2, q + 2, param_index)); - p = q + 2; - } - } - } else { - EXPECT_NE(*p, '%') << FormatMatcherDescriptionSyntaxError(description, p) - << "use \"%%\" instead of \"%\" to print \"%\"."; - ++p; - } - } - return interps; -} - // Joins a vector of strings as if they are fields of a tuple; returns // the joined string. string JoinAsTuple(const Strings& fields) { @@ -152,38 +84,17 @@ string JoinAsTuple(const Strings& fields) { } } -// Returns the actual matcher description, given the matcher name, -// user-supplied description template string, interpolations in the -// string, and the printed values of the matcher parameters. -string FormatMatcherDescription( - const char* matcher_name, const char* description, - const Interpolations& interp, const Strings& param_values) { - string result; - if (*description == '\0') { - // When the user supplies an empty description, we calculate one - // from the matcher name. - result = ConvertIdentifierNameToWords(matcher_name); - if (param_values.size() >= 1) - result += " " + JoinAsTuple(param_values); - } else { - // The end position of the last interpolation. - const char* last_interp_end = description; - for (size_t i = 0; i < interp.size(); i++) { - result.append(last_interp_end, interp[i].start_pos); - const int param_index = interp[i].param_index; - if (param_index == kTupleInterpolation) { - result += JoinAsTuple(param_values); - } else if (param_index == kPercentInterpolation) { - result += '%'; - } else if (param_index != kInvalidInterpolation) { - result += param_values[param_index]; - } - last_interp_end = interp[i].end_pos; - } - result += last_interp_end; - } - - return result; +// Returns the description for a matcher defined using the MATCHER*() +// macro where the user-supplied description string is "", if +// '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. +string FormatMatcherDescription(bool negation, const char* matcher_name, + const Strings& param_values) { + string result = ConvertIdentifierNameToWords(matcher_name); + if (param_values.size() >= 1) + result += " " + JoinAsTuple(param_values); + return negation ? "not (" + result + ")" : result; } } // namespace internal diff --git a/test/gmock-generated-matchers_test.cc b/test/gmock-generated-matchers_test.cc index eebca8a0..3a028040 100644 --- a/test/gmock-generated-matchers_test.cc +++ b/test/gmock-generated-matchers_test.cc @@ -72,6 +72,7 @@ using testing::MatchResultListener; using testing::Ne; using testing::Not; using testing::Pointee; +using testing::PrintToString; using testing::Ref; using testing::StaticAssertTypeEq; using testing::StrEq; @@ -603,9 +604,8 @@ TEST(MatcherMacroTest, Works) { EXPECT_EQ("", Explain(m, 7)); } -// Tests explaining match result in a MATCHER* macro. - -MATCHER(IsEven2, "is even") { +// This also tests that the description string can reference 'negation'. +MATCHER(IsEven2, negation ? "is odd" : "is even") { if ((arg % 2) == 0) { // Verifies that we can stream to result_listener, a listener // supplied by the MATCHER macro implicitly. @@ -617,7 +617,11 @@ MATCHER(IsEven2, "is even") { } } -MATCHER_P2(EqSumOf, x, y, "") { +// This also tests that the description string can reference matcher +// parameters. +MATCHER_P2(EqSumOf, x, y, + string(negation ? "doesn't equal" : "equals") + " the sum of " + + PrintToString(x) + " and " + PrintToString(y)) { if (arg == (x + y)) { *result_listener << "OK"; return true; @@ -631,6 +635,19 @@ MATCHER_P2(EqSumOf, x, y, "") { } } +// Tests that the matcher description can reference 'negation' and the +// matcher parameters. +TEST(MatcherMacroTest, DescriptionCanReferenceNegationAndParameters) { + const Matcher m1 = IsEven2(); + EXPECT_EQ("is even", Describe(m1)); + EXPECT_EQ("is odd", DescribeNegation(m1)); + + const Matcher m2 = EqSumOf(5, 9); + EXPECT_EQ("equals the sum of 5 and 9", Describe(m2)); + EXPECT_EQ("doesn't equal the sum of 5 and 9", DescribeNegation(m2)); +} + +// Tests explaining match result in a MATCHER* macro. TEST(MatcherMacroTest, CanExplainMatchResult) { const Matcher m1 = IsEven2(); EXPECT_EQ("OK", Explain(m1, 4)); @@ -641,29 +658,6 @@ TEST(MatcherMacroTest, CanExplainMatchResult) { EXPECT_EQ("diff == -1", Explain(m2, 4)); } -// Tests that the description string supplied to MATCHER() must be -// valid. - -MATCHER(HasBadDescription, "Invalid%") { - // Uses arg to suppress "unused parameter" warning. - return arg==arg; -} - -TEST(MatcherMacroTest, - CreatingMatcherWithBadDescriptionGeneratesNonfatalFailure) { - EXPECT_NONFATAL_FAILURE( - HasBadDescription(), - "Syntax error at index 7 in matcher description \"Invalid%\": " - "use \"%%\" instead of \"%\" to print \"%\"."); -} - -MATCHER(HasGoodDescription, "good") { return arg==arg; } - -TEST(MatcherMacroTest, AcceptsValidDescription) { - const Matcher m = HasGoodDescription(); - EXPECT_EQ("good", Describe(m)); -} - // Tests that the body of MATCHER() can reference the type of the // value being matched. @@ -723,29 +717,6 @@ TEST(MatcherPMacroTest, Works) { EXPECT_EQ("", Explain(m, 5)); } -// Tests that the description string supplied to MATCHER_P() must be -// valid. - -MATCHER_P(HasBadDescription1, n, "not %(m)s good") { - return arg > n; -} - -TEST(MatcherPMacroTest, - CreatingMatcherWithBadDescriptionGeneratesNonfatalFailure) { - EXPECT_NONFATAL_FAILURE( - HasBadDescription1(2), - "Syntax error at index 6 in matcher description \"not %(m)s good\": " - "\"m\" is an invalid parameter name."); -} - - -MATCHER_P(HasGoodDescription1, n, "good %(n)s") { return arg==arg; } - -TEST(MatcherPMacroTest, AcceptsValidDescription) { - const Matcher m = HasGoodDescription1(5); - EXPECT_EQ("good 5", Describe(m)); -} - // Tests that the description is calculated correctly from the matcher name. MATCHER_P(_is_Greater_Than32and_, n, "") { return arg > 32 && arg > n; } @@ -789,32 +760,6 @@ TEST(MatcherPMacroTest, WorksWhenExplicitlyInstantiatedWithReference) { } -// Tests that the description string supplied to MATCHER_Pn() must be -// valid. - -MATCHER_P2(HasBadDescription2, m, n, "not %(good") { - return arg > m + n; -} - -TEST(MatcherPnMacroTest, - CreatingMatcherWithBadDescriptionGeneratesNonfatalFailure) { - EXPECT_NONFATAL_FAILURE( - HasBadDescription2(3, 4), - "Syntax error at index 4 in matcher description \"not %(good\": " - "an interpolation must end with \")s\", but \"%(good\" does not."); -} - -MATCHER_P2(HasComplexDescription, foo, bar, - "is as complex as %(foo)s %(bar)s (i.e. %(*)s or %%%(foo)s!)") { - return arg==arg; -} - -TEST(MatcherPnMacroTest, AcceptsValidDescription) { - Matcher m = HasComplexDescription(100, "ducks"); - EXPECT_EQ("is as complex as 100 \"ducks\" (i.e. (100, \"ducks\") or %100!)", - Describe(m)); -} - // Tests that the body of MATCHER_Pn() can reference the parameter // types. diff --git a/test/gmock-matchers_test.cc b/test/gmock-matchers_test.cc index 3b151dbd..dd2534f0 100644 --- a/test/gmock-matchers_test.cc +++ b/test/gmock-matchers_test.cc @@ -52,11 +52,7 @@ namespace testing { namespace internal { -string FormatMatcherDescriptionSyntaxError(const char* description, - const char* error_pos); -int GetParamIndex(const char* param_names[], const string& param_name); string JoinAsTuple(const Strings& fields); -bool SkipPrefix(const char* prefix, const char** pstr); } // namespace internal namespace gmock_matchers_test { @@ -126,21 +122,13 @@ using testing::_; using testing::internal::DummyMatchResultListener; using testing::internal::ExplainMatchFailureTupleTo; using testing::internal::FloatingEqMatcher; -using testing::internal::FormatMatcherDescriptionSyntaxError; -using testing::internal::GetParamIndex; -using testing::internal::Interpolation; -using testing::internal::Interpolations; +using testing::internal::FormatMatcherDescription; using testing::internal::JoinAsTuple; using testing::internal::RE; -using testing::internal::SkipPrefix; using testing::internal::StreamMatchResultListener; using testing::internal::String; using testing::internal::StringMatchResultListener; using testing::internal::Strings; -using testing::internal::ValidateMatcherDescription; -using testing::internal::kInvalidInterpolation; -using testing::internal::kPercentInterpolation; -using testing::internal::kTupleInterpolation; using testing::internal::linked_ptr; using testing::internal::scoped_ptr; using testing::internal::string; @@ -3643,176 +3631,6 @@ TEST(ContainerEqExtraTest, CopiesNativeArrayParameter) { EXPECT_THAT(a1, m); } -// Tests GetParamIndex(). - -TEST(GetParamIndexTest, WorksForEmptyParamList) { - const char* params[] = { NULL }; - EXPECT_EQ(kTupleInterpolation, GetParamIndex(params, "*")); - EXPECT_EQ(kInvalidInterpolation, GetParamIndex(params, "a")); -} - -TEST(GetParamIndexTest, RecognizesStar) { - const char* params[] = { "a", "b", NULL }; - EXPECT_EQ(kTupleInterpolation, GetParamIndex(params, "*")); -} - -TEST(GetParamIndexTest, RecognizesKnownParam) { - const char* params[] = { "foo", "bar", NULL }; - EXPECT_EQ(0, GetParamIndex(params, "foo")); - EXPECT_EQ(1, GetParamIndex(params, "bar")); -} - -TEST(GetParamIndexTest, RejectsUnknownParam) { - const char* params[] = { "foo", "bar", NULL }; - EXPECT_EQ(kInvalidInterpolation, GetParamIndex(params, "foobar")); -} - -// Tests SkipPrefix(). - -TEST(SkipPrefixTest, SkipsWhenPrefixMatches) { - const char* const str = "hello"; - - const char* p = str; - EXPECT_TRUE(SkipPrefix("", &p)); - EXPECT_EQ(str, p); - - p = str; - EXPECT_TRUE(SkipPrefix("hell", &p)); - EXPECT_EQ(str + 4, p); -} - -TEST(SkipPrefixTest, DoesNotSkipWhenPrefixDoesNotMatch) { - const char* const str = "world"; - - const char* p = str; - EXPECT_FALSE(SkipPrefix("W", &p)); - EXPECT_EQ(str, p); - - p = str; - EXPECT_FALSE(SkipPrefix("world!", &p)); - EXPECT_EQ(str, p); -} - -// Tests FormatMatcherDescriptionSyntaxError(). -TEST(FormatMatcherDescriptionSyntaxErrorTest, FormatsCorrectly) { - const char* const description = "hello%world"; - EXPECT_EQ("Syntax error at index 5 in matcher description \"hello%world\": ", - FormatMatcherDescriptionSyntaxError(description, description + 5)); -} - -// Tests ValidateMatcherDescription(). - -TEST(ValidateMatcherDescriptionTest, AcceptsEmptyDescription) { - const char* params[] = { "foo", "bar", NULL }; - EXPECT_THAT(ValidateMatcherDescription(params, ""), - ElementsAre()); -} - -TEST(ValidateMatcherDescriptionTest, - AcceptsNonEmptyDescriptionWithNoInterpolation) { - const char* params[] = { "foo", "bar", NULL }; - EXPECT_THAT(ValidateMatcherDescription(params, "a simple description"), - ElementsAre()); -} - -// The MATCHER*() macros trigger warning C4100 (unreferenced formal -// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in -// the macro definition, as the warnings are generated when the macro -// is expanded and macro expansion cannot contain #pragma. Therefore -// we suppress them here. -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4100) -#endif - -// We use MATCHER_P3() to define a matcher for testing -// ValidateMatcherDescription(); otherwise we'll end up with much -// plumbing code. This is not circular as -// ValidateMatcherDescription() doesn't affect whether the matcher -// matches a value or not. -MATCHER_P3(EqInterpolation, start, end, index, "equals Interpolation%(*)s") { - return arg.start_pos == start && arg.end_pos == end && - arg.param_index == index; -} - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -TEST(ValidateMatcherDescriptionTest, AcceptsPercentInterpolation) { - const char* params[] = { "foo", NULL }; - const char* const desc = "one %%"; - EXPECT_THAT(ValidateMatcherDescription(params, desc), - ElementsAre(EqInterpolation(desc + 4, desc + 6, - kPercentInterpolation))); -} - -TEST(ValidateMatcherDescriptionTest, AcceptsTupleInterpolation) { - const char* params[] = { "foo", "bar", "baz", NULL }; - const char* const desc = "%(*)s after"; - EXPECT_THAT(ValidateMatcherDescription(params, desc), - ElementsAre(EqInterpolation(desc, desc + 5, - kTupleInterpolation))); -} - -TEST(ValidateMatcherDescriptionTest, AcceptsParamInterpolation) { - const char* params[] = { "foo", "bar", "baz", NULL }; - const char* const desc = "a %(bar)s."; - EXPECT_THAT(ValidateMatcherDescription(params, desc), - ElementsAre(EqInterpolation(desc + 2, desc + 9, 1))); -} - -TEST(ValidateMatcherDescriptionTest, AcceptsMultiplenterpolations) { - const char* params[] = { "foo", "bar", "baz", NULL }; - const char* const desc = "%(baz)s %(foo)s %(bar)s"; - EXPECT_THAT(ValidateMatcherDescription(params, desc), - ElementsAre(EqInterpolation(desc, desc + 7, 2), - EqInterpolation(desc + 8, desc + 15, 0), - EqInterpolation(desc + 16, desc + 23, 1))); -} - -TEST(ValidateMatcherDescriptionTest, AcceptsRepeatedParams) { - const char* params[] = { "foo", "bar", NULL }; - const char* const desc = "%(foo)s and %(foo)s"; - EXPECT_THAT(ValidateMatcherDescription(params, desc), - ElementsAre(EqInterpolation(desc, desc + 7, 0), - EqInterpolation(desc + 12, desc + 19, 0))); -} - -TEST(ValidateMatcherDescriptionTest, RejectsUnknownParam) { - const char* params[] = { "a", "bar", NULL }; - EXPECT_NONFATAL_FAILURE({ - EXPECT_THAT(ValidateMatcherDescription(params, "%(foo)s"), - ElementsAre()); - }, "Syntax error at index 2 in matcher description \"%(foo)s\": " - "\"foo\" is an invalid parameter name."); -} - -TEST(ValidateMatcherDescriptionTest, RejectsUnfinishedParam) { - const char* params[] = { "a", "bar", NULL }; - EXPECT_NONFATAL_FAILURE({ - EXPECT_THAT(ValidateMatcherDescription(params, "%(foo)"), - ElementsAre()); - }, "Syntax error at index 0 in matcher description \"%(foo)\": " - "an interpolation must end with \")s\", but \"%(foo)\" does not."); - - EXPECT_NONFATAL_FAILURE({ - EXPECT_THAT(ValidateMatcherDescription(params, "x%(a"), - ElementsAre()); - }, "Syntax error at index 1 in matcher description \"x%(a\": " - "an interpolation must end with \")s\", but \"%(a\" does not."); -} - -TEST(ValidateMatcherDescriptionTest, RejectsSinglePercent) { - const char* params[] = { "a", NULL }; - EXPECT_NONFATAL_FAILURE({ - EXPECT_THAT(ValidateMatcherDescription(params, "a %."), - ElementsAre()); - }, "Syntax error at index 2 in matcher description \"a %.\": " - "use \"%%\" instead of \"%\" to print \"%\"."); - -} - // Tests JoinAsTuple(). TEST(JoinAsTupleTest, JoinsEmptyTuple) { @@ -3839,118 +3657,21 @@ TEST(JoinAsTupleTest, JoinsTenTuple) { TEST(FormatMatcherDescriptionTest, WorksForEmptyDescription) { EXPECT_EQ("is even", - FormatMatcherDescription("IsEven", "", Interpolations(), - Strings())); + FormatMatcherDescription(false, "IsEven", Strings())); + EXPECT_EQ("not (is even)", + FormatMatcherDescription(true, "IsEven", Strings())); const char* params[] = { "5" }; EXPECT_EQ("equals 5", - FormatMatcherDescription("Equals", "", Interpolations(), + FormatMatcherDescription(false, "Equals", Strings(params, params + 1))); const char* params2[] = { "5", "8" }; EXPECT_EQ("is in range (5, 8)", - FormatMatcherDescription("IsInRange", "", Interpolations(), + FormatMatcherDescription(false, "IsInRange", Strings(params2, params2 + 2))); } -TEST(FormatMatcherDescriptionTest, WorksForDescriptionWithNoInterpolation) { - EXPECT_EQ("is positive", - FormatMatcherDescription("Gt0", "is positive", Interpolations(), - Strings())); - - const char* params[] = { "5", "6" }; - EXPECT_EQ("is negative", - FormatMatcherDescription("Lt0", "is negative", Interpolations(), - Strings(params, params + 2))); -} - -TEST(FormatMatcherDescriptionTest, - WorksWhenDescriptionStartsWithInterpolation) { - const char* params[] = { "5" }; - const char* const desc = "%(num)s times bigger"; - const Interpolation interp[] = { Interpolation(desc, desc + 7, 0) }; - EXPECT_EQ("5 times bigger", - FormatMatcherDescription("Foo", desc, - Interpolations(interp, interp + 1), - Strings(params, params + 1))); -} - -TEST(FormatMatcherDescriptionTest, - WorksWhenDescriptionEndsWithInterpolation) { - const char* params[] = { "5", "6" }; - const char* const desc = "is bigger than %(y)s"; - const Interpolation interp[] = { Interpolation(desc + 15, desc + 20, 1) }; - EXPECT_EQ("is bigger than 6", - FormatMatcherDescription("Foo", desc, - Interpolations(interp, interp + 1), - Strings(params, params + 2))); -} - -TEST(FormatMatcherDescriptionTest, - WorksWhenDescriptionStartsAndEndsWithInterpolation) { - const char* params[] = { "5", "6" }; - const char* const desc = "%(x)s <= arg <= %(y)s"; - const Interpolation interp[] = { - Interpolation(desc, desc + 5, 0), - Interpolation(desc + 16, desc + 21, 1) - }; - EXPECT_EQ("5 <= arg <= 6", - FormatMatcherDescription("Foo", desc, - Interpolations(interp, interp + 2), - Strings(params, params + 2))); -} - -TEST(FormatMatcherDescriptionTest, - WorksWhenDescriptionDoesNotStartOrEndWithInterpolation) { - const char* params[] = { "5.2" }; - const char* const desc = "has %(x)s cents"; - const Interpolation interp[] = { Interpolation(desc + 4, desc + 9, 0) }; - EXPECT_EQ("has 5.2 cents", - FormatMatcherDescription("Foo", desc, - Interpolations(interp, interp + 1), - Strings(params, params + 1))); -} - -TEST(FormatMatcherDescriptionTest, - WorksWhenDescriptionContainsMultipleInterpolations) { - const char* params[] = { "5", "6" }; - const char* const desc = "in %(*)s or [%(x)s, %(y)s]"; - const Interpolation interp[] = { - Interpolation(desc + 3, desc + 8, kTupleInterpolation), - Interpolation(desc + 13, desc + 18, 0), - Interpolation(desc + 20, desc + 25, 1) - }; - EXPECT_EQ("in (5, 6) or [5, 6]", - FormatMatcherDescription("Foo", desc, - Interpolations(interp, interp + 3), - Strings(params, params + 2))); -} - -TEST(FormatMatcherDescriptionTest, - WorksWhenDescriptionContainsRepeatedParams) { - const char* params[] = { "9" }; - const char* const desc = "in [-%(x)s, %(x)s]"; - const Interpolation interp[] = { - Interpolation(desc + 5, desc + 10, 0), - Interpolation(desc + 12, desc + 17, 0) - }; - EXPECT_EQ("in [-9, 9]", - FormatMatcherDescription("Foo", desc, - Interpolations(interp, interp + 2), - Strings(params, params + 1))); -} - -TEST(FormatMatcherDescriptionTest, - WorksForDescriptionWithInvalidInterpolation) { - const char* params[] = { "9" }; - const char* const desc = "> %(x)s %(x)"; - const Interpolation interp[] = { Interpolation(desc + 2, desc + 7, 0) }; - EXPECT_EQ("> 9 %(x)", - FormatMatcherDescription("Foo", desc, - Interpolations(interp, interp + 1), - Strings(params, params + 1))); -} - // Tests PolymorphicMatcher::mutable_impl(). TEST(PolymorphicMatcherTest, CanAccessMutableImpl) { PolymorphicMatcher m(DivisibleByImpl(42));