$$ -*- 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 #include namespace testing { namespace internal { // 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 $$ } // This Pump meta comment fixes auto-indentation in Emacs. It will not $$ // show up in the generated code. // 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. Inside the statements, you can refer to the value being // matched by 'arg', and refer to its type by 'arg_type'. // // The description string documents what the matcher does, and is used // to generate the failure message when the match fails. Since a // MATCHER() is usually defined in a header file shared by multiple // C++ source files, we require the description to be a C-string // literal to avoid possible side effects. It can be empty, in which // case we'll use the sequence of words in the matcher name as the // description. // // 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. // // 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: // // %% a single '%' character // %(*)s all parameters of the matcher printed as a tuple // %(foo)s value of the matcher parameter named 'foo' // // For example, // // MATCHER_P2(InClosedRange, low, hi, "is in range [%(low)s, %(hi)s]") { // return low <= arg && arg <= hi; // } // ... // EXPECT_THAT(3, InClosedRange(4, 6)); // // would generate a failure that contains the message: // // Expected: is in range [4, 6] // // If you specify "" as the description, the failure message will // contain the sequence of words in the matcher name followed by the // parameter values printed as a tuple. For example, // // MATCHER_P2(InClosedRange, low, hi, "") { ... } // ... // EXPECT_THAT(3, InClosedRange(4, 6)); // // would generate a failure that contains the text: // // Expected: in closed range (4, 6) // // 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. namespace testing { namespace internal { // 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); } // namespace internal } // namespace testing $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 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 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]]]] $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($impl_ctor_param_list)\ $impl_inits {}\ virtual bool Matches(arg_type arg) 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);\ }\$param_field_decls const ::testing::internal::Interpolations gmock_interp_;\ };\ template \ operator ::testing::Matcher() const {\ return ::testing::Matcher(\ new gmock_Impl($params_and_interp));\ }\ $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 ::testing::internal::Interpolations gmock_interp_;\ };\$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 ]] namespace testing { namespace internal { // Returns true iff element is in the STL-style container. template inline bool Contains(const Container& container, const Element& element) { return ::std::find(container.begin(), container.end(), element) != container.end(); } // Returns true iff element is in the C-style array. template inline bool Contains(const ArrayElement (&array)[N], const Element& element) { return ::std::find(array, array + N, element) != array + N; } } // namespace internal // Matches an STL-style container or a C-style array that contains the given // element. // // Examples: // ::std::set page_ids; // page_ids.insert(3); // page_ids.insert(1); // EXPECT_THAT(page_ids, Contains(1)); // EXPECT_THAT(page_ids, Contains(3.0)); // EXPECT_THAT(page_ids, Not(Contains(4))); // // ::std::map page_lengths; // page_lengths[1] = 100; // EXPECT_THAT(map_int, Contains(::std::pair(1, 100))); // // const char* user_ids[] = { "joe", "mike", "tom" }; // EXPECT_THAT(user_ids, Contains(::std::string("tom"))); MATCHER_P(Contains, element, "") { return internal::Contains(arg, element); } } // namespace testing #endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_