$$ -*- mode: c++; -*- $$ This is a Pump source file. Please use Pump to convert it to $$ gmock-generated-variadic-actions.h. $$ $var n = 10 $$ The maximum arity we support. // Copyright 2008, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Google Mock - a framework for writing C++ mock classes. // // This file implements some commonly used variadic matchers. #ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ #define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ #include #include #include #include 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 class ElementsAreMatcherImpl : public MatcherInterface { public: typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container)) RawContainer; typedef typename RawContainer::value_type Element; // Constructs the matcher from a sequence of element values or // element matchers. template ElementsAreMatcherImpl(InputIter first, size_t count) { matchers_.reserve(count); InputIter it = first; for (size_t i = 0; i != count; ++i, ++it) { matchers_.push_back(MatcherCast(*it)); } } // Returns true iff 'container' matches. virtual bool Matches(Container container) const { if (container.size() != count()) return false; typename RawContainer::const_iterator container_iter = container.begin(); for (size_t i = 0; i != count(); ++container_iter, ++i) { if (!matchers_[i].Matches(*container_iter)) return false; } return true; } // Describes what this matcher does. virtual void DescribeTo(::std::ostream* os) const { if (count() == 0) { *os << "is empty"; } else if (count() == 1) { *os << "has 1 element that "; matchers_[0].DescribeTo(os); } else { *os << "has " << Elements(count()) << " where\n"; for (size_t i = 0; i != count(); ++i) { *os << "element " << i << " "; matchers_[i].DescribeTo(os); if (i + 1 < count()) { *os << ",\n"; } } } } // Describes what the negation of this matcher does. virtual void DescribeNegationTo(::std::ostream* os) const { if (count() == 0) { *os << "is not empty"; return; } *os << "does not have " << Elements(count()) << ", or\n"; for (size_t i = 0; i != count(); ++i) { *os << "element " << i << " "; matchers_[i].DescribeNegationTo(os); if (i + 1 < count()) { *os << ", or\n"; } } } // Explains why 'container' matches, or doesn't match, this matcher. virtual void ExplainMatchResultTo(Container container, ::std::ostream* os) const { if (Matches(container)) { // We need to explain why *each* element matches (the obvious // ones can be skipped). bool reason_printed = false; typename RawContainer::const_iterator container_iter = container.begin(); for (size_t i = 0; i != count(); ++container_iter, ++i) { ::std::stringstream ss; matchers_[i].ExplainMatchResultTo(*container_iter, &ss); const string s = ss.str(); if (!s.empty()) { if (reason_printed) { *os << ",\n"; } *os << "element " << i << " " << s; reason_printed = true; } } } else { // We need to explain why the container doesn't match. const size_t actual_count = container.size(); if (actual_count != count()) { // The element count doesn't match. If the container is // empty, there's no need to explain anything as Google Mock // already prints the empty container. Otherwise we just need // to show how many elements there actually are. if (actual_count != 0) { *os << "has " << Elements(actual_count); } return; } // The container has the right size but at least one element // doesn't match expectation. We need to find this element and // explain why it doesn't match. typename RawContainer::const_iterator container_iter = container.begin(); for (size_t i = 0; i != count(); ++container_iter, ++i) { if (matchers_[i].Matches(*container_iter)) { continue; } *os << "element " << i << " doesn't match"; ::std::stringstream ss; matchers_[i].ExplainMatchResultTo(*container_iter, &ss); const string s = ss.str(); if (!s.empty()) { *os << " (" << s << ")"; } return; } } } private: static Message Elements(size_t count) { return Message() << count << (count == 1 ? " element" : " elements"); } size_t count() const { return matchers_.size(); } std::vector > matchers_; }; // Implements ElementsAre() of 0-10 arguments. class ElementsAreMatcher0 { public: ElementsAreMatcher0() {} template operator Matcher() const { typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container)) RawContainer; typedef typename RawContainer::value_type Element; const Matcher* const matchers = NULL; return MakeMatcher(new ElementsAreMatcherImpl(matchers, 0)); } }; $range i 1..n $for i [[ $range j 1..i template <$for j, [[typename T$j]]> class ElementsAreMatcher$i { public: $if i==1 [[explicit ]]ElementsAreMatcher$i($for j, [[const T$j& e$j]])$if i > 0 [[ : ]] $for j, [[e$j[[]]_(e$j)]] {} template operator Matcher() const { typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container)) RawContainer; typedef typename RawContainer::value_type Element; const Matcher matchers[] = { $for j [[ MatcherCast(e$j[[]]_), ]] }; return MakeMatcher(new ElementsAreMatcherImpl(matchers, $i)); } private: $for j [[ const T$j& e$j[[]]_; ]] }; ]] // Implements ElementsAreArray(). template class ElementsAreArrayMatcher { public: ElementsAreArrayMatcher(const T* first, size_t count) : first_(first), count_(count) {} template operator Matcher() const { typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container)) RawContainer; typedef typename RawContainer::value_type Element; return MakeMatcher(new ElementsAreMatcherImpl(first_, count_)); } private: const T* const first_; const size_t count_; }; } // namespace internal // ElementsAre(e0, e1, ..., e_n) matches an STL-style container with // (n + 1) elements, where the i-th element in the container must // match the i-th argument in the list. Each argument of // ElementsAre() can be either a value or a matcher. We support up to // $n arguments. // // NOTE: Since ElementsAre() cares about the order of the elements, it // must not be used with containers whose elements's order is // undefined (e.g. hash_map). inline internal::ElementsAreMatcher0 ElementsAre() { return internal::ElementsAreMatcher0(); } $for i [[ $range j 1..i template <$for j, [[typename T$j]]> inline internal::ElementsAreMatcher$i<$for j, [[T$j]]> ElementsAre($for j, [[const T$j& e$j]]) { return internal::ElementsAreMatcher$i<$for j, [[T$j]]>($for j, [[e$j]]); } ]] // ElementsAreArray(array) and ElementAreArray(array, count) are like // ElementsAre(), except that they take an array of values or // matchers. The former form infers the size of 'array', which must // be a static C-style array. In the latter form, 'array' can either // be a static array or a pointer to a dynamically created array. template inline internal::ElementsAreArrayMatcher ElementsAreArray( const T* first, size_t count) { return internal::ElementsAreArrayMatcher(first, count); } template inline internal::ElementsAreArrayMatcher ElementsAreArray(const T (&array)[N]) { return internal::ElementsAreArrayMatcher(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 // FooMatcherPk // 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(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. 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 \ class gmock_Impl : public ::testing::MatcherInterface {\ 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 \ operator ::testing::Matcher() const {\ return ::testing::Matcher(new gmock_Impl($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 \ bool $class_name$param_types::\ gmock_Impl::Matches(arg_type arg) const ]] #endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_