1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef GOOGLE_CACHEINVALIDATION_DEPS_GMOCK_H_
6#define GOOGLE_CACHEINVALIDATION_DEPS_GMOCK_H_
7
8#include "testing/gmock/include/gmock/gmock.h"
9
10namespace testing {
11namespace internal {
12
13// WhenDeserializedAs and EqualsProto are utilities that aren't part of gmock.
14
15// Implements WhenDeserializedAs<Proto>(proto_matcher).
16template <class Proto>
17class WhenDeserializedAsMatcher {
18 public:
19  typedef Matcher<const Proto&> InnerMatcher;
20
21  explicit WhenDeserializedAsMatcher(const InnerMatcher& proto_matcher)
22      : proto_matcher_(proto_matcher) {}
23
24  virtual ~WhenDeserializedAsMatcher() {}
25
26  // Deserializes the string as a protobuf of the same type as the expected
27  // protobuf.
28  Proto* Deserialize(const string& str) const {
29    Proto* proto = new Proto;
30    if (proto->ParsePartialFromString(str)) {
31      return proto;
32    } else {
33      delete proto;
34      return NULL;
35    }
36  }
37
38  void DescribeTo(::std::ostream* os) const {
39    *os << "can be deserialized as a protobuf that ";
40    proto_matcher_.DescribeTo(os);
41  }
42
43  void DescribeNegationTo(::std::ostream* os) const {
44    *os << "cannot be deserialized as a protobuf that ";
45    proto_matcher_.DescribeTo(os);
46  }
47
48  bool MatchAndExplain(const string& arg, MatchResultListener* listener) const {
49    // Deserializes the string arg as a protobuf of the same type as the
50    // expected protobuf.
51    scoped_ptr<const Proto> deserialized_arg(Deserialize(arg));
52    // No need to explain the match result.
53    return (deserialized_arg.get() != NULL) &&
54        proto_matcher_.Matches(*deserialized_arg);
55  }
56
57 private:
58  const InnerMatcher proto_matcher_;
59};
60
61}  // namespace internal
62
63namespace proto {
64
65// WhenDeserializedAs<Proto>(m) is a matcher that matches a string
66// that can be deserialized as a protobuf of type Proto that matches
67// m, which can be any valid protobuf matcher.
68template <class Proto, class InnerMatcher>
69inline PolymorphicMatcher<internal::WhenDeserializedAsMatcher<Proto> >
70WhenDeserializedAs(const InnerMatcher& inner_matcher) {
71  return MakePolymorphicMatcher(
72      internal::WhenDeserializedAsMatcher<Proto>(
73          SafeMatcherCast<const Proto&>(inner_matcher)));
74}
75
76}  // namespace proto
77
78MATCHER_P(EqualsProto, message, "") {
79  // TOOD(ghc): This implementation assume protobuf serialization is
80  // deterministic, which is true in practice but technically not something that
81  // code is supposed to rely on.  However, it vastly simplifies the
82  // implementation...
83  std::string expected_serialized, actual_serialized;
84  message.SerializeToString(&expected_serialized);
85  arg.SerializeToString(&actual_serialized);
86  return expected_serialized == actual_serialized;
87}
88
89}  // namespace testing
90
91#endif  // GOOGLE_CACHEINVALIDATION_DEPS_GMOCK_H_
92