diff options
Diffstat (limited to 'testing/gmock/include/gmock/gmock-generated-matchers.h.pump')
-rw-r--r-- | testing/gmock/include/gmock/gmock-generated-matchers.h.pump | 634 |
1 files changed, 634 insertions, 0 deletions
diff --git a/testing/gmock/include/gmock/gmock-generated-matchers.h.pump b/testing/gmock/include/gmock/gmock-generated-matchers.h.pump new file mode 100644 index 0000000..09dfedf --- /dev/null +++ b/testing/gmock/include/gmock/gmock-generated-matchers.h.pump @@ -0,0 +1,634 @@ +$$ -*- 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 <sstream> +#include <string> +#include <vector> +#include <gmock/gmock-matchers.h> +#include <gmock/gmock-printers.h> + +namespace testing { +namespace internal { + +// Implements ElementsAre() and ElementsAreArray(). +template <typename Container> +class ElementsAreMatcherImpl : public MatcherInterface<Container> { + 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 <typename InputIter> + 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<const Element&>(*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<Matcher<const Element&> > matchers_; +}; + +// Implements ElementsAre() of 0-10 arguments. + +class ElementsAreMatcher0 { + public: + ElementsAreMatcher0() {} + + template <typename Container> + operator Matcher<Container>() const { + typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container)) + RawContainer; + typedef typename RawContainer::value_type Element; + + const Matcher<const Element&>* const matchers = NULL; + return MakeMatcher(new ElementsAreMatcherImpl<Container>(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 <typename Container> + operator Matcher<Container>() const { + typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container)) + RawContainer; + typedef typename RawContainer::value_type Element; + + const Matcher<const Element&> matchers[] = { + +$for j [[ + MatcherCast<const Element&>(e$j[[]]_), + +]] + }; + + return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, $i)); + } + + private: + +$for j [[ + const T$j& e$j[[]]_; + +]] +}; + + +]] +// Implements ElementsAreArray(). +template <typename T> +class ElementsAreArrayMatcher { + public: + ElementsAreArrayMatcher(const T* first, size_t count) : + first_(first), count_(count) {} + + template <typename Container> + operator Matcher<Container>() const { + typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container)) + RawContainer; + typedef typename RawContainer::value_type Element; + + return MakeMatcher(new ElementsAreMatcherImpl<Container>(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 <typename T> +inline internal::ElementsAreArrayMatcher<T> ElementsAreArray( + const T* first, size_t count) { + return internal::ElementsAreArrayMatcher<T>(first, count); +} + +template <typename T, size_t N> +inline internal::ElementsAreArrayMatcher<T> +ElementsAreArray(const T (&array)[N]) { + return internal::ElementsAreArrayMatcher<T>(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 <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. + +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<Interpolation> 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 <typename arg_type>\ + class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\ + 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 <typename arg_type>\ + operator ::testing::Matcher<arg_type>() const {\ + return ::testing::Matcher<arg_type>(\ + new gmock_Impl<arg_type>($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 <typename arg_type>\ + bool $class_name$param_types::\ + gmock_Impl<arg_type>::Matches(arg_type arg) const +]] + + +namespace testing { +namespace internal { + +// Returns true iff element is in the STL-style container. +template <typename Container, typename Element> +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 <typename ArrayElement, size_t N, typename Element> +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<int> 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<int, size_t> page_lengths; +// page_lengths[1] = 100; +// EXPECT_THAT(map_int, Contains(::std::pair<const int, size_t>(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_ |