Commit 82113318 by zhanyong.wan

Implements the new matcher API.

parent 7f8eb725
...@@ -116,8 +116,9 @@ class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> { ...@@ -116,8 +116,9 @@ class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
explicit ArgsMatcherImpl(const InnerMatcher& inner_matcher) explicit ArgsMatcherImpl(const InnerMatcher& inner_matcher)
: inner_matcher_(SafeMatcherCast<const SelectedArgs&>(inner_matcher)) {} : inner_matcher_(SafeMatcherCast<const SelectedArgs&>(inner_matcher)) {}
virtual bool Matches(ArgsTuple args) const { virtual bool MatchAndExplain(ArgsTuple args,
return inner_matcher_.Matches(GetSelectedArgs(args)); MatchResultListener* listener) const {
return inner_matcher_.MatchAndExplain(GetSelectedArgs(args), listener);
} }
virtual void DescribeTo(::std::ostream* os) const { virtual void DescribeTo(::std::ostream* os) const {
...@@ -130,11 +131,6 @@ class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> { ...@@ -130,11 +131,6 @@ class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
inner_matcher_.DescribeNegationTo(os); inner_matcher_.DescribeNegationTo(os);
} }
virtual void ExplainMatchResultTo(ArgsTuple args,
::std::ostream* os) const {
inner_matcher_.ExplainMatchResultTo(GetSelectedArgs(args), os);
}
private: private:
static SelectedArgs GetSelectedArgs(ArgsTuple args) { static SelectedArgs GetSelectedArgs(ArgsTuple args) {
return TupleFields<RawArgsTuple, $ks>::GetSelectedFields(args); return TupleFields<RawArgsTuple, $ks>::GetSelectedFields(args);
...@@ -301,14 +297,19 @@ $$ // show up in the generated code. ...@@ -301,14 +297,19 @@ $$ // show up in the generated code.
// The MATCHER* family of macros can be used in a namespace scope to // The MATCHER* family of macros can be used in a namespace scope to
// define custom matchers easily. The syntax: // define custom matchers easily.
//
// Basic Usage
// ===========
//
// The syntax
// //
// MATCHER(name, description_string) { statements; } // MATCHER(name, description_string) { statements; }
// //
// will define a matcher with the given name that executes the // defines a matcher with the given name that executes the statements,
// statements, which must return a bool to indicate if the match // which must return a bool to indicate if the match succeeds. Inside
// succeeds. Inside the statements, you can refer to the value being // the statements, you can refer to the value being matched by 'arg',
// matched by 'arg', and refer to its type by 'arg_type'. // and refer to its type by 'arg_type'.
// //
// The description string documents what the matcher does, and is used // The description string documents what the matcher does, and is used
// to generate the failure message when the match fails. Since a // to generate the failure message when the match fails. Since a
...@@ -341,6 +342,9 @@ $$ // show up in the generated code. ...@@ -341,6 +342,9 @@ $$ // show up in the generated code.
// where the description "is even" is automatically calculated from the // where the description "is even" is automatically calculated from the
// matcher name IsEven. // matcher name IsEven.
// //
// Argument Type
// =============
//
// Note that the type of the value being matched (arg_type) is // Note that the type of the value being matched (arg_type) is
// determined by the context in which you use the matcher and is // determined by the context in which you use the matcher and is
// supplied to you by the compiler, so you don't need to worry about // supplied to you by the compiler, so you don't need to worry about
...@@ -351,6 +355,9 @@ $$ // show up in the generated code. ...@@ -351,6 +355,9 @@ $$ // show up in the generated code.
// takes an int, 'arg_type' will be int; if it takes an unsigned long, // takes an int, 'arg_type' will be int; if it takes an unsigned long,
// 'arg_type' will be unsigned long; and so on. // 'arg_type' will be unsigned long; and so on.
// //
// Parameterizing Matchers
// =======================
//
// Sometimes you'll want to parameterize the matcher. For that you // Sometimes you'll want to parameterize the matcher. For that you
// can use another macro: // can use another macro:
// //
...@@ -381,6 +388,9 @@ $$ // show up in the generated code. ...@@ -381,6 +388,9 @@ $$ // show up in the generated code.
// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to // We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to
// support multi-parameter matchers. // support multi-parameter matchers.
// //
// Describing Parameterized Matchers
// =================================
//
// When defining a parameterized matcher, you can use Python-style // When defining a parameterized matcher, you can use Python-style
// interpolations in the description string to refer to the parameter // interpolations in the description string to refer to the parameter
// values. We support the following syntax currently: // values. We support the following syntax currently:
...@@ -413,6 +423,9 @@ $$ // show up in the generated code. ...@@ -413,6 +423,9 @@ $$ // show up in the generated code.
// //
// Expected: in closed range (4, 6) // Expected: in closed range (4, 6)
// //
// Types of Matcher Parameters
// ===========================
//
// For the purpose of typing, you can view // For the purpose of typing, you can view
// //
// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... } // MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
...@@ -440,23 +453,44 @@ $$ // show up in the generated code. ...@@ -440,23 +453,44 @@ $$ // show up in the generated code.
// matcher you will see the value of the referenced object but not its // matcher you will see the value of the referenced object but not its
// address. // address.
// //
// Explaining Match Results
// ========================
//
// Sometimes the matcher description alone isn't enough to explain why
// the match has failed or succeeded. For example, when expecting a
// long string, it can be very helpful to also print the diff between
// the expected string and the actual one. To achieve that, you can
// optionally stream additional information to a special variable
// named result_listener, whose type is a pointer to class
// MatchResultListener:
//
// MATCHER_P(EqualsLongString, str, "") {
// if (arg == str) return true;
//
// *result_listener << "the difference: "
/// << DiffStrings(str, arg);
// return false;
// }
//
// Overloading Matchers
// ====================
//
// You can overload matchers with different numbers of parameters: // You can overload matchers with different numbers of parameters:
// //
// MATCHER_P(Blah, a, description_string1) { ... } // MATCHER_P(Blah, a, description_string1) { ... }
// MATCHER_P2(Blah, a, b, description_string2) { ... } // MATCHER_P2(Blah, a, b, description_string2) { ... }
// //
// While it's tempting to always use the MATCHER* macros when defining // Caveats
// a new matcher, you should also consider implementing // =======
// MatcherInterface or using MakePolymorphicMatcher() instead,
// especially if you need to use the matcher a lot. While these
// approaches require more work, they give you more control on the
// types of the value being matched and the matcher parameters, which
// in general leads to better compiler error messages that pay off in
// the long run. They also allow overloading matchers based on
// parameter types (as opposed to just based on the number of
// parameters).
// //
// CAVEAT: // When defining a new matcher, you should also consider implementing
// MatcherInterface or using MakePolymorphicMatcher(). These
// approaches require more work than the MATCHER* macros, but also
// give you more control on the types of the value being matched and
// the matcher parameters, which may leads to better compiler error
// messages when the matcher is used wrong. They also allow
// overloading matchers based on parameter types (as opposed to just
// based on the number of parameters).
// //
// MATCHER*() can only be used in a namespace scope. The reason is // MATCHER*() can only be used in a namespace scope. The reason is
// that C++ doesn't yet allow function-local types to be used to // that C++ doesn't yet allow function-local types to be used to
...@@ -464,7 +498,8 @@ $$ // show up in the generated code. ...@@ -464,7 +498,8 @@ $$ // show up in the generated code.
// Once that's done, we'll consider supporting using MATCHER*() inside // Once that's done, we'll consider supporting using MATCHER*() inside
// a function. // a function.
// //
// MORE INFORMATION: // More Information
// ================
// //
// To learn more about using these macros, please search for 'MATCHER' // To learn more about using these macros, please search for 'MATCHER'
// on http://code.google.com/p/googlemock/wiki/CookBook. // on http://code.google.com/p/googlemock/wiki/CookBook.
...@@ -510,7 +545,8 @@ $var param_field_decls2 = [[$for j ...@@ -510,7 +545,8 @@ $var param_field_decls2 = [[$for j
public:\ public:\
[[$if i==1 [[explicit ]]]]gmock_Impl($impl_ctor_param_list)\ [[$if i==1 [[explicit ]]]]gmock_Impl($impl_ctor_param_list)\
$impl_inits {}\ $impl_inits {}\
virtual bool Matches(arg_type arg) const;\ virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\ virtual void DescribeTo(::std::ostream* gmock_os) const {\
const ::testing::internal::Strings& gmock_printed_params = \ const ::testing::internal::Strings& gmock_printed_params = \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
...@@ -540,8 +576,10 @@ $var param_field_decls2 = [[$for j ...@@ -540,8 +576,10 @@ $var param_field_decls2 = [[$for j
return $class_name$param_types($params);\ return $class_name$param_types($params);\
}\$template }\$template
template <typename arg_type>\ template <typename arg_type>\
bool $class_name$param_types::\ bool $class_name$param_types::gmock_Impl<arg_type>::MatchAndExplain(\
gmock_Impl<arg_type>::Matches(arg_type arg) const arg_type arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
]] ]]
......
...@@ -1004,13 +1004,13 @@ class TypedExpectation : public ExpectationBase { ...@@ -1004,13 +1004,13 @@ class TypedExpectation : public ExpectationBase {
if (!TupleMatches(matchers_, args)) { if (!TupleMatches(matchers_, args)) {
DescribeMatchFailureTupleTo(matchers_, args, os); DescribeMatchFailureTupleTo(matchers_, args, os);
} }
if (!extra_matcher_.Matches(args)) { StringMatchResultListener listener;
if (!extra_matcher_.MatchAndExplain(args, &listener)) {
*os << " Expected args: "; *os << " Expected args: ";
extra_matcher_.DescribeTo(os); extra_matcher_.DescribeTo(os);
*os << "\n Actual: don't match"; *os << "\n Actual: don't match";
internal::ExplainMatchResultAsNeededTo<const ArgumentTuple&>( internal::StreamInParensAsNeeded(listener.str(), os);
extra_matcher_, args, os);
*os << "\n"; *os << "\n";
} }
} else if (!AllPrerequisitesAreSatisfied()) { } else if (!AllPrerequisitesAreSatisfied()) {
......
...@@ -136,6 +136,16 @@ TEST(ArgsTest, AcceptsDecreasingTemplateArgs) { ...@@ -136,6 +136,16 @@ TEST(ArgsTest, AcceptsDecreasingTemplateArgs) {
EXPECT_THAT(t, Not(Args<2, 1>(Lt()))); EXPECT_THAT(t, Not(Args<2, 1>(Lt())));
} }
// 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
MATCHER(SumIsZero, "") { MATCHER(SumIsZero, "") {
return get<0>(arg) + get<1>(arg) + get<2>(arg) == 0; return get<0>(arg) + get<1>(arg) + get<2>(arg) == 0;
} }
...@@ -553,6 +563,44 @@ TEST(MatcherMacroTest, Works) { ...@@ -553,6 +563,44 @@ TEST(MatcherMacroTest, Works) {
EXPECT_EQ("", Explain(m, 7)); EXPECT_EQ("", Explain(m, 7));
} }
// Tests explaining match result in a MATCHER* macro.
MATCHER(IsEven2, "is even") {
if ((arg % 2) == 0) {
// Verifies that we can stream to result_listener, a listener
// supplied by the MATCHER macro implicitly.
*result_listener << "OK";
return true;
} else {
*result_listener << "% 2 == " << (arg % 2);
return false;
}
}
MATCHER_P2(EqSumOf, x, y, "") {
if (arg == (x + y)) {
*result_listener << "OK";
return true;
} else {
// Verifies that we can stream to the underlying stream of
// result_listener.
if (result_listener->stream() != NULL) {
*result_listener->stream() << "diff == " << (x + y - arg);
}
return false;
}
}
TEST(MatcherMacroTest, CanExplainMatchResult) {
const Matcher<int> m1 = IsEven2();
EXPECT_EQ("OK", Explain(m1, 4));
EXPECT_EQ("% 2 == 1", Explain(m1, 5));
const Matcher<int> m2 = EqSumOf(1, 2);
EXPECT_EQ("OK", Explain(m2, 3));
EXPECT_EQ("diff == -1", Explain(m2, 4));
}
// Tests that the description string supplied to MATCHER() must be // Tests that the description string supplied to MATCHER() must be
// valid. // valid.
...@@ -1052,4 +1100,8 @@ TEST(ContainsTest, WorksForTwoDimensionalNativeArray) { ...@@ -1052,4 +1100,8 @@ TEST(ContainsTest, WorksForTwoDimensionalNativeArray) {
EXPECT_THAT(a, Contains(Not(Contains(5)))); EXPECT_THAT(a, Contains(Not(Contains(5))));
} }
#ifdef _MSC_VER
#pragma warning(pop)
#endif
} // namespace } // namespace
...@@ -88,6 +88,7 @@ using testing::Matcher; ...@@ -88,6 +88,7 @@ using testing::Matcher;
using testing::MatcherCast; using testing::MatcherCast;
using testing::MatcherInterface; using testing::MatcherInterface;
using testing::Matches; using testing::Matches;
using testing::MatchResultListener;
using testing::NanSensitiveDoubleEq; using testing::NanSensitiveDoubleEq;
using testing::NanSensitiveFloatEq; using testing::NanSensitiveFloatEq;
using testing::Ne; using testing::Ne;
...@@ -200,10 +201,39 @@ class EvenMatcherImpl : public MatcherInterface<int> { ...@@ -200,10 +201,39 @@ class EvenMatcherImpl : public MatcherInterface<int> {
// two methods is optional. // two methods is optional.
}; };
TEST(MatcherInterfaceTest, CanBeImplemented) { TEST(MatcherInterfaceTest, CanBeImplementedUsingDeprecatedAPI) {
EvenMatcherImpl m; EvenMatcherImpl m;
} }
// Tests implementing a monomorphic matcher using MatchAndExplain().
class NewEvenMatcherImpl : public MatcherInterface<int> {
public:
virtual bool MatchAndExplain(int x, MatchResultListener* listener) const {
const bool match = x % 2 == 0;
// Verifies that we can stream to a listener directly.
*listener << "value % " << 2;
if (listener->stream() != NULL) {
// Verifies that we can stream to a listener's underlying stream
// too.
*listener->stream() << " == " << (x % 2);
}
return match;
}
virtual void DescribeTo(::std::ostream* os) const {
*os << "is an even number";
}
};
TEST(MatcherInterfaceTest, CanBeImplementedUsingNewAPI) {
Matcher<int> m = MakeMatcher(new NewEvenMatcherImpl);
EXPECT_TRUE(m.Matches(2));
EXPECT_FALSE(m.Matches(3));
EXPECT_EQ("value % 2 == 0", Explain(m, 2));
EXPECT_EQ("value % 2 == 1", Explain(m, 3));
}
// Tests default-constructing a matcher. // Tests default-constructing a matcher.
TEST(MatcherTest, CanBeDefaultConstructed) { TEST(MatcherTest, CanBeDefaultConstructed) {
Matcher<double> m; Matcher<double> m;
...@@ -252,6 +282,18 @@ TEST(MatcherTest, CanDescribeItself) { ...@@ -252,6 +282,18 @@ TEST(MatcherTest, CanDescribeItself) {
Describe(Matcher<int>(new EvenMatcherImpl))); Describe(Matcher<int>(new EvenMatcherImpl)));
} }
// Tests Matcher<T>::MatchAndExplain().
TEST(MatcherTest, MatchAndExplain) {
Matcher<int> m = GreaterThan(0);
::testing::internal::StringMatchResultListener listener1;
EXPECT_TRUE(m.MatchAndExplain(42, &listener1));
EXPECT_EQ("is 42 more than 0", listener1.str());
::testing::internal::StringMatchResultListener listener2;
EXPECT_FALSE(m.MatchAndExplain(-9, &listener2));
EXPECT_EQ("is 9 less than 0", listener2.str());
}
// Tests that a C-string literal can be implicitly converted to a // Tests that a C-string literal can be implicitly converted to a
// Matcher<string> or Matcher<const string&>. // Matcher<string> or Matcher<const string&>.
TEST(StringMatcherTest, CanBeImplicitlyConstructedFromCStringLiteral) { TEST(StringMatcherTest, CanBeImplicitlyConstructedFromCStringLiteral) {
...@@ -284,8 +326,8 @@ TEST(MakeMatcherTest, ConstructsMatcherFromMatcherInterface) { ...@@ -284,8 +326,8 @@ TEST(MakeMatcherTest, ConstructsMatcherFromMatcherInterface) {
Matcher<int> m = MakeMatcher(dummy_impl); Matcher<int> m = MakeMatcher(dummy_impl);
} }
// Tests that MakePolymorphicMatcher() constructs a polymorphic // Tests that MakePolymorphicMatcher() can construct a polymorphic
// matcher from its implementation. // matcher from its implementation using the old API.
const int bar = 1; const int bar = 1;
class ReferencesBarOrIsZeroImpl { class ReferencesBarOrIsZeroImpl {
public: public:
...@@ -308,7 +350,7 @@ PolymorphicMatcher<ReferencesBarOrIsZeroImpl> ReferencesBarOrIsZero() { ...@@ -308,7 +350,7 @@ PolymorphicMatcher<ReferencesBarOrIsZeroImpl> ReferencesBarOrIsZero() {
return MakePolymorphicMatcher(ReferencesBarOrIsZeroImpl()); return MakePolymorphicMatcher(ReferencesBarOrIsZeroImpl());
} }
TEST(MakePolymorphicMatcherTest, ConstructsMatcherFromImpl) { TEST(MakePolymorphicMatcherTest, ConstructsMatcherUsingOldAPI) {
// Using a polymorphic matcher to match a reference type. // Using a polymorphic matcher to match a reference type.
Matcher<const int&> m1 = ReferencesBarOrIsZero(); Matcher<const int&> m1 = ReferencesBarOrIsZero();
EXPECT_TRUE(m1.Matches(0)); EXPECT_TRUE(m1.Matches(0));
...@@ -324,6 +366,58 @@ TEST(MakePolymorphicMatcherTest, ConstructsMatcherFromImpl) { ...@@ -324,6 +366,58 @@ TEST(MakePolymorphicMatcherTest, ConstructsMatcherFromImpl) {
EXPECT_EQ("bar or zero", Describe(m2)); EXPECT_EQ("bar or zero", Describe(m2));
} }
// Tests implementing a polymorphic matcher using MatchAndExplain().
class PolymorphicIsEvenImpl {
public:
void DescribeTo(::std::ostream* os) const { *os << "is even"; }
void DescribeNegationTo(::std::ostream* os) const {
*os << "is odd";
}
};
template <typename T>
bool MatchAndExplain(const PolymorphicIsEvenImpl& /* impl */,
T x, MatchResultListener* listener) {
// Verifies that we can stream to the listener directly.
*listener << "% " << 2;
if (listener->stream() != NULL) {
// Verifies that we can stream to the listener's underlying stream
// too.
*listener->stream() << " == " << (x % 2);
}
return (x % 2) == 0;
}
PolymorphicMatcher<PolymorphicIsEvenImpl> PolymorphicIsEven() {
return MakePolymorphicMatcher(PolymorphicIsEvenImpl());
}
TEST(MakePolymorphicMatcherTest, ConstructsMatcherUsingNewAPI) {
// Using PolymorphicIsEven() as a Matcher<int>.
const Matcher<int> m1 = PolymorphicIsEven();
EXPECT_TRUE(m1.Matches(42));
EXPECT_FALSE(m1.Matches(43));
EXPECT_EQ("is even", Describe(m1));
const Matcher<int> not_m1 = Not(m1);
EXPECT_EQ("is odd", Describe(not_m1));
EXPECT_EQ("% 2 == 0", Explain(m1, 42));
// Using PolymorphicIsEven() as a Matcher<char>.
const Matcher<char> m2 = PolymorphicIsEven();
EXPECT_TRUE(m2.Matches('\x42'));
EXPECT_FALSE(m2.Matches('\x43'));
EXPECT_EQ("is even", Describe(m2));
const Matcher<char> not_m2 = Not(m2);
EXPECT_EQ("is odd", Describe(not_m2));
EXPECT_EQ("% 2 == 0", Explain(m2, '\x42'));
}
// Tests that MatcherCast<T>(m) works when m is a polymorphic matcher. // Tests that MatcherCast<T>(m) works when m is a polymorphic matcher.
TEST(MatcherCastTest, FromPolymorphicMatcher) { TEST(MatcherCastTest, FromPolymorphicMatcher) {
Matcher<int> m = MatcherCast<int>(Eq(5)); Matcher<int> m = MatcherCast<int>(Eq(5));
...@@ -1050,21 +1144,26 @@ TEST(PairTest, CanDescribeSelf) { ...@@ -1050,21 +1144,26 @@ TEST(PairTest, CanDescribeSelf) {
} }
TEST(PairTest, CanExplainMatchResultTo) { TEST(PairTest, CanExplainMatchResultTo) {
const Matcher<std::pair<int, int> > m0 = Pair(0, 0); // If neither field matches, Pair() should explain about the first
EXPECT_EQ("", Explain(m0, std::make_pair(25, 42))); // field.
const Matcher<std::pair<int, int> > m = Pair(GreaterThan(0), GreaterThan(0));
EXPECT_EQ("the first field is 1 less than 0",
Explain(m, std::make_pair(-1, -2)));
const Matcher<std::pair<int, int> > m1 = Pair(GreaterThan(0), 0); // If the first field matches but the second doesn't, Pair() should
EXPECT_EQ("the first field is 25 more than 0", // explain about the second field.
Explain(m1, std::make_pair(25, 42))); EXPECT_EQ("the second field is 2 less than 0",
Explain(m, std::make_pair(1, -2)));
const Matcher<std::pair<int, int> > m2 = Pair(0, GreaterThan(0)); // If the first field doesn't match but the second does, Pair()
EXPECT_EQ("the second field is 42 more than 0", // should explain about the first field.
Explain(m2, std::make_pair(25, 42))); EXPECT_EQ("the first field is 1 less than 0",
Explain(m, std::make_pair(-1, 2)));
const Matcher<std::pair<int, int> > m3 = Pair(GreaterThan(0), GreaterThan(0)); // If both fields match, Pair() should explain about them both.
EXPECT_EQ("the first field is 25 more than 0" EXPECT_EQ("the first field is 1 more than 0"
", and the second field is 42 more than 0", ", and the second field is 2 more than 0",
Explain(m3, std::make_pair(25, 42))); Explain(m, std::make_pair(1, 2)));
} }
TEST(PairTest, MatchesCorrectly) { TEST(PairTest, MatchesCorrectly) {
...@@ -3335,6 +3434,16 @@ TEST(ValidateMatcherDescriptionTest, ...@@ -3335,6 +3434,16 @@ TEST(ValidateMatcherDescriptionTest,
ElementsAre()); 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 // We use MATCHER_P3() to define a matcher for testing
// ValidateMatcherDescription(); otherwise we'll end up with much // ValidateMatcherDescription(); otherwise we'll end up with much
// plumbing code. This is not circular as // plumbing code. This is not circular as
...@@ -3345,6 +3454,10 @@ MATCHER_P3(EqInterpolation, start, end, index, "equals Interpolation%(*)s") { ...@@ -3345,6 +3454,10 @@ MATCHER_P3(EqInterpolation, start, end, index, "equals Interpolation%(*)s") {
arg.param_index == index; arg.param_index == index;
} }
#ifdef _MSC_VER
#pragma warning(pop)
#endif
TEST(ValidateMatcherDescriptionTest, AcceptsPercentInterpolation) { TEST(ValidateMatcherDescriptionTest, AcceptsPercentInterpolation) {
const char* params[] = { "foo", NULL }; const char* params[] = { "foo", NULL };
const char* const desc = "one %%"; const char* const desc = "one %%";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment