diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/gmock/gmock-generated-matchers.h | 829 | ||||
-rw-r--r-- | include/gmock/gmock-generated-matchers.h.pump | 210 | ||||
-rw-r--r-- | include/gmock/gmock-printers.h | 15 | ||||
-rw-r--r-- | include/gmock/internal/gmock-internal-utils.h | 6 |
4 files changed, 1059 insertions, 1 deletions
diff --git a/include/gmock/gmock-generated-matchers.h b/include/gmock/gmock-generated-matchers.h index 09ccc9c3..f8cbf49e 100644 --- a/include/gmock/gmock-generated-matchers.h +++ b/include/gmock/gmock-generated-matchers.h @@ -44,6 +44,14 @@ namespace testing { namespace internal { +// Generates a non-fatal failure iff 'description' is not a valid +// matcher description. +inline void ValidateMatcherDescription(const char* description) { + EXPECT_STREQ("", description) + << "The description string in a MATCHER*() macro must be \"\" " + "at this moment. We will implement custom description string soon."; +} + // Implements ElementsAre() and ElementsAreArray(). template <typename Container> class ElementsAreMatcherImpl : public MatcherInterface<Container> { @@ -647,4 +655,825 @@ ElementsAreArray(const T (&array)[N]) { } // namespace testing +// The MATCHER* family of macros can be used in a namespace scope to +// define custom matchers easily. The syntax: +// +// MATCHER(name, description_string) { statements; } +// +// will define a matcher with the given name that executes the +// statements, which must return a bool to indicate if the match +// succeeds. For now, the description_string must be "", but we'll +// allow other values soon. Inside the statements, you can refer to +// the value being matched by 'arg', and refer to its type by +// 'arg_type'. For example: +// +// MATCHER(IsEven, "") { return (arg % 2) == 0; } +// +// allows you to write +// +// // Expects mock_foo.Bar(n) to be called where n is even. +// EXPECT_CALL(mock_foo, Bar(IsEven())); +// +// or, +// +// // Verifies that the value of some_expression is even. +// EXPECT_THAT(some_expression, IsEven()); +// +// If the above assertion fails, it will print something like: +// +// Value of: some_expression +// Expected: is even +// Actual: 7 +// +// where the description "is even" is automatically calculated from the +// matcher name IsEven. +// +// Note that the type of the value being matched (arg_type) 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 +// declaring it (nor can you). This allows the matcher to be +// polymorphic. For example, IsEven() can be used to match any type +// where the value of "(arg % 2) == 0" can be implicitly converted to +// a bool. In the "Bar(IsEven())" example above, if method Bar() +// takes an int, 'arg_type' will be int; if it takes an unsigned long, +// 'arg_type' will be unsigned long; and so on. +// +// Sometimes you'll want to parameterize the matcher. For that you +// can use another macro: +// +// MATCHER_P(name, param_name, description_string) { statements; } +// +// For example: +// +// MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; } +// +// will allow you to write: +// +// EXPECT_THAT(Blah("a"), HasAbsoluteValue(n)); +// +// which may lead to this message (assuming n is 10): +// +// Value of: Blah("a") +// Expected: has absolute value 10 +// Actual: -9 +// +// Note that both the matcher description and its parameter are +// printed, making the message human-friendly. +// +// In the matcher definition body, you can write 'foo_type' to +// reference the type of a parameter named 'foo'. For example, in the +// body of MATCHER_P(HasAbsoluteValue, value) above, you can write +// 'value_type' to refer to the type of 'value'. +// +// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P10 to +// support multi-parameter matchers. +// +// For the purpose of typing, you can view +// +// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... } +// +// as shorthand for +// +// template <typename p1_type, ..., typename pk_type> +// FooMatcherPk<p1_type, ..., pk_type> +// Foo(p1_type p1, ..., pk_type pk) { ... } +// +// When you write Foo(v1, ..., vk), the compiler infers the types of +// the parameters v1, ..., and vk for you. If you are not happy with +// the result of the type inference, you can specify the types by +// explicitly instantiating the template, as in Foo<long, bool>(5, +// false). As said earlier, you don't get to (or need to) specify +// 'arg_type' as that's determined by the context in which the matcher +// is used. You can assign the result of expression Foo(p1, ..., pk) +// to a variable of type FooMatcherPk<p1_type, ..., pk_type>. This +// can be useful when composing matchers. +// +// While you can instantiate a matcher template with reference types, +// passing the parameters by pointer usually makes your code more +// readable. If, however, you still want to pass a parameter by +// reference, be aware that in the failure message generated by the +// matcher you will see the value of the referenced object but not its +// address. +// +// You can overload matchers with different numbers of parameters: +// +// MATCHER_P(Blah, a, description_string1) { ... } +// MATCHER_P2(Blah, a, b, description_string2) { ... } +// +// While it's tempting to always use the MATCHER* macros when defining +// 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: +// +// 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 +// instantiate templates. The up-coming C++0x standard will fix this. +// Once that's done, we'll consider supporting using MATCHER*() inside +// a function. +// +// MORE INFORMATION: +// +// To learn more about using these macros, please search for 'MATCHER' +// on http://code.google.com/p/googlemock/wiki/CookBook. + +#define MATCHER(name, description)\ + class name##Matcher {\ + public:\ + template <typename arg_type>\ + class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\ + public:\ + gmock_Impl() {}\ + virtual bool Matches(arg_type arg) const;\ + virtual void DescribeTo(::std::ostream* os) const {\ + *os << ::testing::internal::ConvertIdentifierNameToWords(#name);\ + }\ + };\ + template <typename arg_type>\ + operator ::testing::Matcher<arg_type>() const {\ + return ::testing::Matcher<arg_type>(new gmock_Impl<arg_type>());\ + }\ + name##Matcher() {\ + ::testing::internal::ValidateMatcherDescription(description);\ + }\ + };\ + inline name##Matcher name() {\ + return name##Matcher();\ + }\ + template <typename arg_type>\ + bool name##Matcher::\ + gmock_Impl<arg_type>::Matches(arg_type arg) const + +#define MATCHER_P(name, p0, description)\ + template <typename p0##_type>\ + class name##MatcherP {\ + public:\ + template <typename arg_type>\ + class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\ + public:\ + explicit gmock_Impl(p0##_type gmock_p0) : p0(gmock_p0) {}\ + virtual bool Matches(arg_type arg) const;\ + virtual void DescribeTo(::std::ostream* os) const {\ + *os << ::testing::internal::ConvertIdentifierNameToWords(#name);\ + *os << " ";\ + ::testing::internal::UniversalPrint(p0, os);\ + }\ + p0##_type p0;\ + };\ + template <typename arg_type>\ + operator ::testing::Matcher<arg_type>() const {\ + return ::testing::Matcher<arg_type>(new gmock_Impl<arg_type>(p0));\ + }\ + name##MatcherP(p0##_type gmock_p0) : p0(gmock_p0) {\ + ::testing::internal::ValidateMatcherDescription(description);\ + }\ + p0##_type p0;\ + };\ + template <typename p0##_type>\ + inline name##MatcherP<p0##_type> name(p0##_type p0) {\ + return name##MatcherP<p0##_type>(p0);\ + }\ + template <typename p0##_type>\ + template <typename arg_type>\ + bool name##MatcherP<p0##_type>::\ + gmock_Impl<arg_type>::Matches(arg_type arg) const + +#define MATCHER_P2(name, p0, p1, description)\ + template <typename p0##_type, typename p1##_type>\ + class name##MatcherP2 {\ + public:\ + template <typename arg_type>\ + class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\ + public:\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1) : p0(gmock_p0), \ + p1(gmock_p1) {}\ + virtual bool Matches(arg_type arg) const;\ + virtual void DescribeTo(::std::ostream* os) const {\ + *os << ::testing::internal::ConvertIdentifierNameToWords(#name);\ + *os << " (";\ + ::testing::internal::UniversalPrint(p0, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p1, os);\ + *os << ")";\ + }\ + p0##_type p0;\ + p1##_type p1;\ + };\ + template <typename arg_type>\ + operator ::testing::Matcher<arg_type>() const {\ + return ::testing::Matcher<arg_type>(new gmock_Impl<arg_type>(p0, p1));\ + }\ + name##MatcherP2(p0##_type gmock_p0, p1##_type gmock_p1) : p0(gmock_p0), \ + p1(gmock_p1) {\ + ::testing::internal::ValidateMatcherDescription(description);\ + }\ + p0##_type p0;\ + p1##_type p1;\ + };\ + template <typename p0##_type, typename p1##_type>\ + inline name##MatcherP2<p0##_type, p1##_type> name(p0##_type p0, \ + p1##_type p1) {\ + return name##MatcherP2<p0##_type, p1##_type>(p0, p1);\ + }\ + template <typename p0##_type, typename p1##_type>\ + template <typename arg_type>\ + bool name##MatcherP2<p0##_type, p1##_type>::\ + gmock_Impl<arg_type>::Matches(arg_type arg) const + +#define MATCHER_P3(name, p0, p1, p2, description)\ + template <typename p0##_type, typename p1##_type, typename p2##_type>\ + class name##MatcherP3 {\ + public:\ + template <typename arg_type>\ + class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\ + public:\ + 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 Matches(arg_type arg) const;\ + virtual void DescribeTo(::std::ostream* os) const {\ + *os << ::testing::internal::ConvertIdentifierNameToWords(#name);\ + *os << " (";\ + ::testing::internal::UniversalPrint(p0, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p1, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p2, os);\ + *os << ")";\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + };\ + template <typename arg_type>\ + operator ::testing::Matcher<arg_type>() const {\ + return ::testing::Matcher<arg_type>(new gmock_Impl<arg_type>(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) {\ + ::testing::internal::ValidateMatcherDescription(description);\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + };\ + template <typename p0##_type, typename p1##_type, typename p2##_type>\ + inline name##MatcherP3<p0##_type, p1##_type, p2##_type> name(p0##_type p0, \ + p1##_type p1, p2##_type p2) {\ + return name##MatcherP3<p0##_type, p1##_type, p2##_type>(p0, p1, p2);\ + }\ + template <typename p0##_type, typename p1##_type, typename p2##_type>\ + template <typename arg_type>\ + bool name##MatcherP3<p0##_type, p1##_type, p2##_type>::\ + gmock_Impl<arg_type>::Matches(arg_type arg) const + +#define MATCHER_P4(name, p0, p1, p2, p3, description)\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type>\ + class name##MatcherP4 {\ + public:\ + template <typename arg_type>\ + class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\ + public:\ + gmock_Impl(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) {}\ + virtual bool Matches(arg_type arg) const;\ + virtual void DescribeTo(::std::ostream* os) const {\ + *os << ::testing::internal::ConvertIdentifierNameToWords(#name);\ + *os << " (";\ + ::testing::internal::UniversalPrint(p0, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p1, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p2, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p3, os);\ + *os << ")";\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + };\ + template <typename arg_type>\ + operator ::testing::Matcher<arg_type>() const {\ + return ::testing::Matcher<arg_type>(new gmock_Impl<arg_type>(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) {\ + ::testing::internal::ValidateMatcherDescription(description);\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + };\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type>\ + inline name##MatcherP4<p0##_type, p1##_type, p2##_type, \ + p3##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \ + p3##_type p3) {\ + return name##MatcherP4<p0##_type, p1##_type, p2##_type, p3##_type>(p0, \ + p1, p2, p3);\ + }\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type>\ + template <typename arg_type>\ + bool name##MatcherP4<p0##_type, p1##_type, p2##_type, p3##_type>::\ + gmock_Impl<arg_type>::Matches(arg_type arg) const + +#define MATCHER_P5(name, p0, p1, p2, p3, p4, description)\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type>\ + class name##MatcherP5 {\ + public:\ + template <typename arg_type>\ + class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\ + public:\ + gmock_Impl(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) {}\ + virtual bool Matches(arg_type arg) const;\ + virtual void DescribeTo(::std::ostream* os) const {\ + *os << ::testing::internal::ConvertIdentifierNameToWords(#name);\ + *os << " (";\ + ::testing::internal::UniversalPrint(p0, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p1, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p2, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p3, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p4, os);\ + *os << ")";\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + };\ + template <typename arg_type>\ + operator ::testing::Matcher<arg_type>() const {\ + return ::testing::Matcher<arg_type>(new gmock_Impl<arg_type>(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) {\ + ::testing::internal::ValidateMatcherDescription(description);\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + };\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type>\ + inline name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \ + p4##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ + p4##_type p4) {\ + return name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \ + p4##_type>(p0, p1, p2, p3, p4);\ + }\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type>\ + template <typename arg_type>\ + bool name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type>::\ + gmock_Impl<arg_type>::Matches(arg_type arg) const + +#define MATCHER_P6(name, p0, p1, p2, p3, p4, p5, description)\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type>\ + class name##MatcherP6 {\ + public:\ + template <typename arg_type>\ + class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\ + 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) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ + p3(gmock_p3), p4(gmock_p4), p5(gmock_p5) {}\ + virtual bool Matches(arg_type arg) const;\ + virtual void DescribeTo(::std::ostream* os) const {\ + *os << ::testing::internal::ConvertIdentifierNameToWords(#name);\ + *os << " (";\ + ::testing::internal::UniversalPrint(p0, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p1, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p2, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p3, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p4, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p5, os);\ + *os << ")";\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + };\ + template <typename arg_type>\ + operator ::testing::Matcher<arg_type>() const {\ + return ::testing::Matcher<arg_type>(new gmock_Impl<arg_type>(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) {\ + ::testing::internal::ValidateMatcherDescription(description);\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + };\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type>\ + inline name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, \ + p4##_type, p5##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \ + p3##_type p3, p4##_type p4, p5##_type p5) {\ + return name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, \ + p4##_type, p5##_type>(p0, p1, p2, p3, p4, p5);\ + }\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type>\ + template <typename arg_type>\ + bool name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ + p5##_type>::\ + gmock_Impl<arg_type>::Matches(arg_type arg) const + +#define MATCHER_P7(name, p0, p1, p2, p3, p4, p5, p6, description)\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type, \ + typename p6##_type>\ + class name##MatcherP7 {\ + public:\ + template <typename arg_type>\ + class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\ + 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, \ + 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) {}\ + virtual bool Matches(arg_type arg) const;\ + virtual void DescribeTo(::std::ostream* os) const {\ + *os << ::testing::internal::ConvertIdentifierNameToWords(#name);\ + *os << " (";\ + ::testing::internal::UniversalPrint(p0, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p1, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p2, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p3, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p4, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p5, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p6, os);\ + *os << ")";\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + };\ + template <typename arg_type>\ + operator ::testing::Matcher<arg_type>() const {\ + return ::testing::Matcher<arg_type>(new gmock_Impl<arg_type>(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) {\ + ::testing::internal::ValidateMatcherDescription(description);\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + };\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type, \ + typename p6##_type>\ + inline name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, \ + p4##_type, p5##_type, p6##_type> name(p0##_type p0, p1##_type p1, \ + p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \ + p6##_type p6) {\ + return name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, \ + p4##_type, p5##_type, p6##_type>(p0, p1, p2, p3, p4, p5, p6);\ + }\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type, \ + typename p6##_type>\ + template <typename arg_type>\ + bool name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ + p5##_type, p6##_type>::\ + gmock_Impl<arg_type>::Matches(arg_type arg) const + +#define MATCHER_P8(name, p0, p1, p2, p3, p4, p5, p6, p7, description)\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type, \ + typename p6##_type, typename p7##_type>\ + class name##MatcherP8 {\ + public:\ + template <typename arg_type>\ + class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\ + 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, \ + p6##_type gmock_p6, 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) {}\ + virtual bool Matches(arg_type arg) const;\ + virtual void DescribeTo(::std::ostream* os) const {\ + *os << ::testing::internal::ConvertIdentifierNameToWords(#name);\ + *os << " (";\ + ::testing::internal::UniversalPrint(p0, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p1, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p2, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p3, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p4, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p5, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p6, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p7, os);\ + *os << ")";\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + p7##_type p7;\ + };\ + template <typename arg_type>\ + operator ::testing::Matcher<arg_type>() const {\ + return ::testing::Matcher<arg_type>(new gmock_Impl<arg_type>(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, \ + p5##_type gmock_p5, p6##_type gmock_p6, \ + 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) {\ + ::testing::internal::ValidateMatcherDescription(description);\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + p7##_type p7;\ + };\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type, \ + typename p6##_type, typename p7##_type>\ + inline name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, \ + p4##_type, p5##_type, p6##_type, p7##_type> name(p0##_type p0, \ + p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \ + p6##_type p6, p7##_type p7) {\ + return name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, \ + p4##_type, p5##_type, p6##_type, p7##_type>(p0, p1, p2, p3, p4, p5, \ + p6, p7);\ + }\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type, \ + typename p6##_type, typename p7##_type>\ + template <typename arg_type>\ + bool name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ + p5##_type, p6##_type, p7##_type>::\ + gmock_Impl<arg_type>::Matches(arg_type arg) const + +#define MATCHER_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, description)\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type, \ + typename p6##_type, typename p7##_type, typename p8##_type>\ + class name##MatcherP9 {\ + public:\ + template <typename arg_type>\ + class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\ + 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, \ + p6##_type gmock_p6, p7##_type gmock_p7, \ + 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) {}\ + virtual bool Matches(arg_type arg) const;\ + virtual void DescribeTo(::std::ostream* os) const {\ + *os << ::testing::internal::ConvertIdentifierNameToWords(#name);\ + *os << " (";\ + ::testing::internal::UniversalPrint(p0, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p1, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p2, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p3, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p4, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p5, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p6, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p7, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p8, os);\ + *os << ")";\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + p7##_type p7;\ + p8##_type p8;\ + };\ + template <typename arg_type>\ + operator ::testing::Matcher<arg_type>() const {\ + return ::testing::Matcher<arg_type>(new gmock_Impl<arg_type>(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, \ + p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \ + 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) {\ + ::testing::internal::ValidateMatcherDescription(description);\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + p7##_type p7;\ + p8##_type p8;\ + };\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type, \ + typename p6##_type, typename p7##_type, typename p8##_type>\ + inline name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, \ + p4##_type, p5##_type, p6##_type, p7##_type, \ + p8##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ + p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, \ + p8##_type p8) {\ + return name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, \ + p4##_type, p5##_type, p6##_type, p7##_type, p8##_type>(p0, p1, p2, \ + p3, p4, p5, p6, p7, p8);\ + }\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type, \ + typename p6##_type, typename p7##_type, typename p8##_type>\ + template <typename arg_type>\ + bool name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ + p5##_type, p6##_type, p7##_type, p8##_type>::\ + gmock_Impl<arg_type>::Matches(arg_type arg) const + +#define MATCHER_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, description)\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type, \ + typename p6##_type, typename p7##_type, typename p8##_type, \ + typename p9##_type>\ + class name##MatcherP10 {\ + public:\ + template <typename arg_type>\ + class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\ + 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, \ + p6##_type gmock_p6, p7##_type gmock_p7, 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) {}\ + virtual bool Matches(arg_type arg) const;\ + virtual void DescribeTo(::std::ostream* os) const {\ + *os << ::testing::internal::ConvertIdentifierNameToWords(#name);\ + *os << " (";\ + ::testing::internal::UniversalPrint(p0, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p1, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p2, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p3, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p4, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p5, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p6, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p7, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p8, os);\ + *os << ", ";\ + ::testing::internal::UniversalPrint(p9, os);\ + *os << ")";\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + p7##_type p7;\ + p8##_type p8;\ + p9##_type p9;\ + };\ + template <typename arg_type>\ + operator ::testing::Matcher<arg_type>() const {\ + return ::testing::Matcher<arg_type>(new gmock_Impl<arg_type>(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, \ + p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \ + 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) {\ + ::testing::internal::ValidateMatcherDescription(description);\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + p7##_type p7;\ + p8##_type p8;\ + p9##_type p9;\ + };\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type, \ + typename p6##_type, typename p7##_type, typename p8##_type, \ + typename p9##_type>\ + inline name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \ + p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \ + p9##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ + p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \ + p9##_type p9) {\ + return name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \ + p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, p9##_type>(p0, \ + p1, p2, p3, p4, p5, p6, p7, p8, p9);\ + }\ + template <typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type, \ + typename p6##_type, typename p7##_type, typename p8##_type, \ + typename p9##_type>\ + template <typename arg_type>\ + bool name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \ + p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, p9##_type>::\ + gmock_Impl<arg_type>::Matches(arg_type arg) const + #endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ diff --git a/include/gmock/gmock-generated-matchers.h.pump b/include/gmock/gmock-generated-matchers.h.pump index b45028ae..2a457aad 100644 --- a/include/gmock/gmock-generated-matchers.h.pump +++ b/include/gmock/gmock-generated-matchers.h.pump @@ -47,6 +47,14 @@ $var n = 10 $$ The maximum arity we support. namespace testing { namespace internal { +// Generates a non-fatal failure iff 'description' is not a valid +// matcher description. +inline void ValidateMatcherDescription(const char* description) { + EXPECT_STREQ("", description) + << "The description string in a MATCHER*() macro must be \"\" " + "at this moment. We will implement custom description string soon."; +} + // Implements ElementsAre() and ElementsAreArray(). template <typename Container> class ElementsAreMatcherImpl : public MatcherInterface<Container> { @@ -300,4 +308,206 @@ ElementsAreArray(const T (&array)[N]) { } // namespace testing +// The MATCHER* family of macros can be used in a namespace scope to +// define custom matchers easily. The syntax: +// +// MATCHER(name, description_string) { statements; } +// +// will define a matcher with the given name that executes the +// statements, which must return a bool to indicate if the match +// succeeds. For now, the description_string must be "", but we'll +// allow other values soon. Inside the statements, you can refer to +// the value being matched by 'arg', and refer to its type by +// 'arg_type'. For example: +// +// MATCHER(IsEven, "") { return (arg % 2) == 0; } +// +// allows you to write +// +// // Expects mock_foo.Bar(n) to be called where n is even. +// EXPECT_CALL(mock_foo, Bar(IsEven())); +// +// or, +// +// // Verifies that the value of some_expression is even. +// EXPECT_THAT(some_expression, IsEven()); +// +// If the above assertion fails, it will print something like: +// +// Value of: some_expression +// Expected: is even +// Actual: 7 +// +// where the description "is even" is automatically calculated from the +// matcher name IsEven. +// +// Note that the type of the value being matched (arg_type) 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 +// declaring it (nor can you). This allows the matcher to be +// polymorphic. For example, IsEven() can be used to match any type +// where the value of "(arg % 2) == 0" can be implicitly converted to +// a bool. In the "Bar(IsEven())" example above, if method Bar() +// takes an int, 'arg_type' will be int; if it takes an unsigned long, +// 'arg_type' will be unsigned long; and so on. +// +// Sometimes you'll want to parameterize the matcher. For that you +// can use another macro: +// +// MATCHER_P(name, param_name, description_string) { statements; } +// +// For example: +// +// MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; } +// +// will allow you to write: +// +// EXPECT_THAT(Blah("a"), HasAbsoluteValue(n)); +// +// which may lead to this message (assuming n is 10): +// +// Value of: Blah("a") +// Expected: has absolute value 10 +// Actual: -9 +// +// Note that both the matcher description and its parameter are +// printed, making the message human-friendly. +// +// In the matcher definition body, you can write 'foo_type' to +// reference the type of a parameter named 'foo'. For example, in the +// body of MATCHER_P(HasAbsoluteValue, value) above, you can write +// 'value_type' to refer to the type of 'value'. +// +// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to +// support multi-parameter matchers. +// +// For the purpose of typing, you can view +// +// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... } +// +// as shorthand for +// +// template <typename p1_type, ..., typename pk_type> +// FooMatcherPk<p1_type, ..., pk_type> +// Foo(p1_type p1, ..., pk_type pk) { ... } +// +// When you write Foo(v1, ..., vk), the compiler infers the types of +// the parameters v1, ..., and vk for you. If you are not happy with +// the result of the type inference, you can specify the types by +// explicitly instantiating the template, as in Foo<long, bool>(5, +// false). As said earlier, you don't get to (or need to) specify +// 'arg_type' as that's determined by the context in which the matcher +// is used. You can assign the result of expression Foo(p1, ..., pk) +// to a variable of type FooMatcherPk<p1_type, ..., pk_type>. This +// can be useful when composing matchers. +// +// While you can instantiate a matcher template with reference types, +// passing the parameters by pointer usually makes your code more +// readable. If, however, you still want to pass a parameter by +// reference, be aware that in the failure message generated by the +// matcher you will see the value of the referenced object but not its +// address. +// +// You can overload matchers with different numbers of parameters: +// +// MATCHER_P(Blah, a, description_string1) { ... } +// MATCHER_P2(Blah, a, b, description_string2) { ... } +// +// While it's tempting to always use the MATCHER* macros when defining +// 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: +// +// 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 +// instantiate templates. The up-coming C++0x standard will fix this. +// Once that's done, we'll consider supporting using MATCHER*() inside +// a function. +// +// MORE INFORMATION: +// +// To learn more about using these macros, please search for 'MATCHER' +// on http://code.google.com/p/googlemock/wiki/CookBook. + +$range i 0..n +$for i + +[[ +$var macro_name = [[$if i==0 [[MATCHER]] $elif i==1 [[MATCHER_P]] + $else [[MATCHER_P$i]]]] +$var class_name = [[name##Matcher[[$if i==0 [[]] $elif i==1 [[P]] + $else [[P$i]]]]]] +$range j 0..i-1 +$var template = [[$if i==0 [[]] $else [[ + + template <$for j, [[typename p$j##_type]]>\ +]]]] +$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]] +$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(gmock_p$j)]]]]]] +$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]]]] +$var param_field_decls = [[$for j +[[ + + p$j##_type p$j;\ +]]]] +$var param_field_decls2 = [[$for j +[[ + + p$j##_type p$j;\ +]]]] + +#define $macro_name(name$for j [[, p$j]], description)\$template + class $class_name {\ + public:\ + template <typename arg_type>\ + class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\ + public:\ + [[$if i==1 [[explicit ]]]]gmock_Impl($ctor_param_list)$inits {}\ + virtual bool Matches(arg_type arg) const;\ + virtual void DescribeTo(::std::ostream* os) const {\ + *os << ::testing::internal::ConvertIdentifierNameToWords(#name);\ +[[$if i==1 [[ *os << " ";\ + ::testing::internal::UniversalPrint(p0, os);\ + +]] $elif i>=2 [[ *os << " (";\ + ::testing::internal::UniversalPrint(p0, os);\ +$range k 1..i-1 +$for k [[ + + *os << ", ";\ + ::testing::internal::UniversalPrint(p$k, os);\ +]] + + *os << ")";\ + +]]]] + }\$param_field_decls + };\ + template <typename arg_type>\ + operator ::testing::Matcher<arg_type>() const {\ + return ::testing::Matcher<arg_type>(new gmock_Impl<arg_type>($params));\ + }\ + $class_name($ctor_param_list)$inits {\ + ::testing::internal::ValidateMatcherDescription(description);\ + }\$param_field_decls2 + };\$template + inline $class_name$param_types name($param_types_and_names) {\ + return $class_name$param_types($params);\ + }\$template + template <typename arg_type>\ + bool $class_name$param_types::\ + gmock_Impl<arg_type>::Matches(arg_type arg) const +]] + + #endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ diff --git a/include/gmock/gmock-printers.h b/include/gmock/gmock-printers.h index 759aa347..5cd5f12e 100644 --- a/include/gmock/gmock-printers.h +++ b/include/gmock/gmock-printers.h @@ -44,9 +44,12 @@ // When T is a reference type, the address of the value is also // printed. // -// We also provide a convenient wrapper +// We also provide some convenient wrappers: // +// // Prints to a string. // string ::testing::internal::UniversalPrinter<T>::PrintAsString(value); +// // Prints a value using its inferred type. +// void ::testing::internal::UniversalPrint(const T& value, ostream*); #ifndef GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_ #define GMOCK_INCLUDE_GMOCK_GMOCK_PRINTERS_H_ @@ -585,6 +588,16 @@ class UniversalPrinter<T&> { #endif // _MSC_VER }; +// Prints a value using its inferred type. In particular, if the +// original type of the value is a reference, the *referenced* type +// (as opposed to the reference type) will be used, as C++ doesn't +// infer reference types. This is useful when you just want to know +// what the value is and don't care if it's a reference or not. +template <typename T> +void UniversalPrint(const T& value, ::std::ostream* os) { + UniversalPrinter<T>::Print(value, os); +} + } // namespace internal } // namespace testing diff --git a/include/gmock/internal/gmock-internal-utils.h b/include/gmock/internal/gmock-internal-utils.h index bdc82882..9a74d546 100644 --- a/include/gmock/internal/gmock-internal-utils.h +++ b/include/gmock/internal/gmock-internal-utils.h @@ -63,6 +63,12 @@ namespace proto2 { class Message; } namespace testing { namespace internal { +// 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 +// treated as one word. For example, both "FooBar123" and +// "foo_bar_123" are converted to "foo bar 123". +string ConvertIdentifierNameToWords(const char* id_name); + // Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a // compiler error iff T1 and T2 are different types. template <typename T1, typename T2> |