Adds the ReturnArg<k>() action (by Tim Hockin); refactors gmock-matchers.h (by Zhanyong Wan).
This commit is contained in:
		@@ -2441,6 +2441,13 @@ ACTION_TEMPLATE(InvokeArgument,
 | 
			
		||||
      ::std::tr1::get<k>(args), p0, p1, p2, p3, p4, p5, p6, p7, p8, p9);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Action ReturnArg<k>() returns the k-th argument of the mock function.
 | 
			
		||||
ACTION_TEMPLATE(ReturnArg,
 | 
			
		||||
                HAS_1_TEMPLATE_PARAMS(int, k),
 | 
			
		||||
                AND_0_VALUE_PARAMS()) {
 | 
			
		||||
  return std::tr1::get<k>(args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Action SaveArg<k>(pointer) saves the k-th (0-based) argument of the
 | 
			
		||||
// mock function to *pointer.
 | 
			
		||||
ACTION_TEMPLATE(SaveArg,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
$$ -*- mode: c++; -*-
 | 
			
		||||
$$ This is a Pump source file.  Please use Pump to convert it to
 | 
			
		||||
$$ gmock-generated-variadic-actions.h.
 | 
			
		||||
$$ gmock-generated-actions.h.
 | 
			
		||||
$$
 | 
			
		||||
$var n = 10  $$ The maximum arity we support.
 | 
			
		||||
$$}} This meta comment fixes auto-indentation in editors.
 | 
			
		||||
@@ -940,6 +940,13 @@ ACTION_TEMPLATE(InvokeArgument,
 | 
			
		||||
 | 
			
		||||
]]
 | 
			
		||||
 | 
			
		||||
// Action ReturnArg<k>() returns the k-th argument of the mock function.
 | 
			
		||||
ACTION_TEMPLATE(ReturnArg,
 | 
			
		||||
                HAS_1_TEMPLATE_PARAMS(int, k),
 | 
			
		||||
                AND_0_VALUE_PARAMS()) {
 | 
			
		||||
  return std::tr1::get<k>(args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Action SaveArg<k>(pointer) saves the k-th (0-based) argument of the
 | 
			
		||||
// mock function to *pointer.
 | 
			
		||||
ACTION_TEMPLATE(SaveArg,
 | 
			
		||||
 
 | 
			
		||||
@@ -290,163 +290,7 @@ class ArgsMatcher {
 | 
			
		||||
  const InnerMatcher inner_matcher_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Implements ElementsAre() and ElementsAreArray().
 | 
			
		||||
template <typename Container>
 | 
			
		||||
class ElementsAreMatcherImpl : public MatcherInterface<Container> {
 | 
			
		||||
 public:
 | 
			
		||||
  typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container)) RawContainer;
 | 
			
		||||
  typedef internal::StlContainerView<RawContainer> View;
 | 
			
		||||
  typedef typename View::type StlContainer;
 | 
			
		||||
  typedef typename View::const_reference StlContainerReference;
 | 
			
		||||
  typedef typename StlContainer::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 {
 | 
			
		||||
    StlContainerReference stl_container = View::ConstReference(container);
 | 
			
		||||
    if (stl_container.size() != count())
 | 
			
		||||
      return false;
 | 
			
		||||
 | 
			
		||||
    typename StlContainer::const_iterator it = stl_container.begin();
 | 
			
		||||
    for (size_t i = 0; i != count();  ++it, ++i) {
 | 
			
		||||
      if (!matchers_[i].Matches(*it))
 | 
			
		||||
        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 {
 | 
			
		||||
    StlContainerReference stl_container = View::ConstReference(container);
 | 
			
		||||
    if (Matches(container)) {
 | 
			
		||||
      // We need to explain why *each* element matches (the obvious
 | 
			
		||||
      // ones can be skipped).
 | 
			
		||||
 | 
			
		||||
      bool reason_printed = false;
 | 
			
		||||
      typename StlContainer::const_iterator it = stl_container.begin();
 | 
			
		||||
      for (size_t i = 0; i != count(); ++it, ++i) {
 | 
			
		||||
        ::std::stringstream ss;
 | 
			
		||||
        matchers_[i].ExplainMatchResultTo(*it, &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 = stl_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 StlContainer::const_iterator it = stl_container.begin();
 | 
			
		||||
      for (size_t i = 0; i != count(); ++it, ++i) {
 | 
			
		||||
        if (matchers_[i].Matches(*it)) {
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        *os << "element " << i << " doesn't match";
 | 
			
		||||
 | 
			
		||||
        ::std::stringstream ss;
 | 
			
		||||
        matchers_[i].ExplainMatchResultTo(*it, &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 internal::StlContainerView<RawContainer>::type::value_type
 | 
			
		||||
        Element;
 | 
			
		||||
 | 
			
		||||
    const Matcher<const Element&>* const matchers = NULL;
 | 
			
		||||
    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 0));
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
// Implements ElementsAre() of 1-10 arguments.
 | 
			
		||||
 | 
			
		||||
template <typename T1>
 | 
			
		||||
class ElementsAreMatcher1 {
 | 
			
		||||
@@ -788,28 +632,6 @@ class ElementsAreMatcher10 {
 | 
			
		||||
  const T10& e10_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 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 internal::StlContainerView<RawContainer>::type::value_type
 | 
			
		||||
        Element;
 | 
			
		||||
 | 
			
		||||
    return MakeMatcher(new ElementsAreMatcherImpl<Container>(first_, count_));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  const T* const first_;
 | 
			
		||||
  const size_t count_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace internal
 | 
			
		||||
 | 
			
		||||
// Args<N1, N2, ..., Nk>(a_matcher) matches a tuple if the selected
 | 
			
		||||
@@ -1169,48 +991,6 @@ ElementsAreArray(const T (&array)[N]) {
 | 
			
		||||
// 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
 | 
			
		||||
 | 
			
		||||
#define MATCHER(name, description)\
 | 
			
		||||
  class name##Matcher {\
 | 
			
		||||
   public:\
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
$$ -*- mode: c++; -*-
 | 
			
		||||
$$ This is a Pump source file.  Please use Pump to convert it to
 | 
			
		||||
$$ gmock-generated-variadic-actions.h.
 | 
			
		||||
$$ gmock-generated-actions.h.
 | 
			
		||||
$$
 | 
			
		||||
$var n = 10  $$ The maximum arity we support.
 | 
			
		||||
$$ }} This line fixes auto-indentation of the following code in Emacs.
 | 
			
		||||
@@ -173,163 +173,7 @@ class ArgsMatcher {
 | 
			
		||||
  const InnerMatcher inner_matcher_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Implements ElementsAre() and ElementsAreArray().
 | 
			
		||||
template <typename Container>
 | 
			
		||||
class ElementsAreMatcherImpl : public MatcherInterface<Container> {
 | 
			
		||||
 public:
 | 
			
		||||
  typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container)) RawContainer;
 | 
			
		||||
  typedef internal::StlContainerView<RawContainer> View;
 | 
			
		||||
  typedef typename View::type StlContainer;
 | 
			
		||||
  typedef typename View::const_reference StlContainerReference;
 | 
			
		||||
  typedef typename StlContainer::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 {
 | 
			
		||||
    StlContainerReference stl_container = View::ConstReference(container);
 | 
			
		||||
    if (stl_container.size() != count())
 | 
			
		||||
      return false;
 | 
			
		||||
 | 
			
		||||
    typename StlContainer::const_iterator it = stl_container.begin();
 | 
			
		||||
    for (size_t i = 0; i != count();  ++it, ++i) {
 | 
			
		||||
      if (!matchers_[i].Matches(*it))
 | 
			
		||||
        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 {
 | 
			
		||||
    StlContainerReference stl_container = View::ConstReference(container);
 | 
			
		||||
    if (Matches(container)) {
 | 
			
		||||
      // We need to explain why *each* element matches (the obvious
 | 
			
		||||
      // ones can be skipped).
 | 
			
		||||
 | 
			
		||||
      bool reason_printed = false;
 | 
			
		||||
      typename StlContainer::const_iterator it = stl_container.begin();
 | 
			
		||||
      for (size_t i = 0; i != count(); ++it, ++i) {
 | 
			
		||||
        ::std::stringstream ss;
 | 
			
		||||
        matchers_[i].ExplainMatchResultTo(*it, &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 = stl_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 StlContainer::const_iterator it = stl_container.begin();
 | 
			
		||||
      for (size_t i = 0; i != count(); ++it, ++i) {
 | 
			
		||||
        if (matchers_[i].Matches(*it)) {
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        *os << "element " << i << " doesn't match";
 | 
			
		||||
 | 
			
		||||
        ::std::stringstream ss;
 | 
			
		||||
        matchers_[i].ExplainMatchResultTo(*it, &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 internal::StlContainerView<RawContainer>::type::value_type
 | 
			
		||||
        Element;
 | 
			
		||||
 | 
			
		||||
    const Matcher<const Element&>* const matchers = NULL;
 | 
			
		||||
    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 0));
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
// Implements ElementsAre() of 1-$n arguments.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
$range i 1..n
 | 
			
		||||
@@ -369,28 +213,6 @@ $for 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 internal::StlContainerView<RawContainer>::type::value_type
 | 
			
		||||
        Element;
 | 
			
		||||
 | 
			
		||||
    return MakeMatcher(new ElementsAreMatcherImpl<Container>(first_, count_));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  const T* const first_;
 | 
			
		||||
  const size_t count_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace internal
 | 
			
		||||
 | 
			
		||||
// Args<N1, N2, ..., Nk>(a_matcher) matches a tuple if the selected
 | 
			
		||||
@@ -625,48 +447,6 @@ $$   // show up in the generated code.
 | 
			
		||||
// 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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1925,6 +1925,221 @@ class KeyMatcher {
 | 
			
		||||
  const M matcher_for_key_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Implements ElementsAre() and ElementsAreArray().
 | 
			
		||||
template <typename Container>
 | 
			
		||||
class ElementsAreMatcherImpl : public MatcherInterface<Container> {
 | 
			
		||||
 public:
 | 
			
		||||
  typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container)) RawContainer;
 | 
			
		||||
  typedef internal::StlContainerView<RawContainer> View;
 | 
			
		||||
  typedef typename View::type StlContainer;
 | 
			
		||||
  typedef typename View::const_reference StlContainerReference;
 | 
			
		||||
  typedef typename StlContainer::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 {
 | 
			
		||||
    StlContainerReference stl_container = View::ConstReference(container);
 | 
			
		||||
    if (stl_container.size() != count())
 | 
			
		||||
      return false;
 | 
			
		||||
 | 
			
		||||
    typename StlContainer::const_iterator it = stl_container.begin();
 | 
			
		||||
    for (size_t i = 0; i != count();  ++it, ++i) {
 | 
			
		||||
      if (!matchers_[i].Matches(*it))
 | 
			
		||||
        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 {
 | 
			
		||||
    StlContainerReference stl_container = View::ConstReference(container);
 | 
			
		||||
    if (Matches(container)) {
 | 
			
		||||
      // We need to explain why *each* element matches (the obvious
 | 
			
		||||
      // ones can be skipped).
 | 
			
		||||
 | 
			
		||||
      bool reason_printed = false;
 | 
			
		||||
      typename StlContainer::const_iterator it = stl_container.begin();
 | 
			
		||||
      for (size_t i = 0; i != count(); ++it, ++i) {
 | 
			
		||||
        ::std::stringstream ss;
 | 
			
		||||
        matchers_[i].ExplainMatchResultTo(*it, &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 = stl_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 StlContainer::const_iterator it = stl_container.begin();
 | 
			
		||||
      for (size_t i = 0; i != count(); ++it, ++i) {
 | 
			
		||||
        if (matchers_[i].Matches(*it)) {
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        *os << "element " << i << " doesn't match";
 | 
			
		||||
 | 
			
		||||
        ::std::stringstream ss;
 | 
			
		||||
        matchers_[i].ExplainMatchResultTo(*it, &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 arguments.
 | 
			
		||||
class ElementsAreMatcher0 {
 | 
			
		||||
 public:
 | 
			
		||||
  ElementsAreMatcher0() {}
 | 
			
		||||
 | 
			
		||||
  template <typename Container>
 | 
			
		||||
  operator Matcher<Container>() const {
 | 
			
		||||
    typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container))
 | 
			
		||||
        RawContainer;
 | 
			
		||||
    typedef typename internal::StlContainerView<RawContainer>::type::value_type
 | 
			
		||||
        Element;
 | 
			
		||||
 | 
			
		||||
    const Matcher<const Element&>* const matchers = NULL;
 | 
			
		||||
    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 0));
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 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 internal::StlContainerView<RawContainer>::type::value_type
 | 
			
		||||
        Element;
 | 
			
		||||
 | 
			
		||||
    return MakeMatcher(new ElementsAreMatcherImpl<Container>(first_, count_));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  const T* const first_;
 | 
			
		||||
  const size_t count_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
 | 
			
		||||
// Implements MatcherCast().
 | 
			
		||||
 
 | 
			
		||||
@@ -59,6 +59,7 @@ using testing::DoAll;
 | 
			
		||||
using testing::Invoke;
 | 
			
		||||
using testing::InvokeArgument;
 | 
			
		||||
using testing::Return;
 | 
			
		||||
using testing::ReturnArg;
 | 
			
		||||
using testing::ReturnNew;
 | 
			
		||||
using testing::SaveArg;
 | 
			
		||||
using testing::SetArgReferee;
 | 
			
		||||
@@ -1382,6 +1383,21 @@ TEST(ActionPnMacroTest, CanExplicitlyInstantiateWithReferenceTypes) {
 | 
			
		||||
  EXPECT_EQ(55, a.Perform(empty));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(ReturnArgActionTest, WorksForOneArgIntArg0) {
 | 
			
		||||
  const Action<int(int)> a = ReturnArg<0>();
 | 
			
		||||
  EXPECT_EQ(5, a.Perform(make_tuple(5)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(ReturnArgActionTest, WorksForMultiArgBoolArg0) {
 | 
			
		||||
  const Action<bool(bool, bool, bool)> a = ReturnArg<0>();
 | 
			
		||||
  EXPECT_TRUE(a.Perform(make_tuple(true, false, false)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(ReturnArgActionTest, WorksForMultiArgStringArg2) {
 | 
			
		||||
  const Action<string(int, int, string, int)> a = ReturnArg<2>();
 | 
			
		||||
  EXPECT_EQ("seven", a.Perform(make_tuple(5, 6, string("seven"), 8)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(SaveArgActionTest, WorksForSameType) {
 | 
			
		||||
  int result = 0;
 | 
			
		||||
  const Action<void(int n)> a1 = SaveArg<0>(&result);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user