1 /*
2  * Copyright 2018 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // gMock matchers used to validate protocol buffer arguments.
18 
19 // WHAT THIS IS
20 // ============
21 //
22 // This library defines the following matchers in the ::android namespace:
23 //
24 //   EqualsProto(pb)              The argument equals pb.
25 //   EqualsInitializedProto(pb)   The argument is initialized and equals pb.
26 //   EquivToProto(pb)             The argument is equivalent to pb.
27 //   EquivToInitializedProto(pb)  The argument is initialized and equivalent
28 //                                to pb.
29 //   IsInitializedProto()         The argument is an initialized protobuf.
30 //
31 // where:
32 //
33 //   - pb can be either a protobuf value or a human-readable string
34 //     representation of it.
35 //   - When pb is a string, the matcher can optionally accept a
36 //     template argument for the type of the protobuf,
37 //     e.g. EqualsProto<Foo>("foo: 1").
38 //   - "equals" is defined as the argument's Equals(pb) method returns true.
39 //   - "equivalent to" is defined as the argument's Equivalent(pb) method
40 //     returns true.
41 //   - "initialized" means that the argument's IsInitialized() method returns
42 //     true.
43 //
44 // These matchers can match either a protobuf value or a pointer to
45 // it.  They make a copy of pb, and thus can out-live pb.  When the
46 // match fails, the matchers print a detailed message (the value of
47 // the actual protobuf, the value of the expected protobuf, and which
48 // fields are different).
49 //
50 // This library also defines the following matcher transformer
51 // functions in the ::android::proto namespace:
52 //
53 //   Approximately(m, margin, fraction)
54 //                     The same as m, except that it compares
55 //                     floating-point fields approximately (using
56 //                     google::protobuf::util::MessageDifferencer's APPROXIMATE
57 //                     comparison option).  m can be any of the
58 //                     Equals* and EquivTo* protobuf matchers above. If margin
59 //                     is specified, floats and doubles will be considered
60 //                     approximately equal if they are within that margin, i.e.
61 //                     abs(expected - actual) <= margin. If fraction is
62 //                     specified, floats and doubles will be considered
63 //                     approximately equal if they are within a fraction of
64 //                     their magnitude, i.e. abs(expected - actual) <=
65 //                     fraction * max(abs(expected), abs(actual)). Two fields
66 //                     will be considered equal if they're within the fraction
67 //                     _or_ within the margin, so omitting or setting the
68 //                     fraction to 0.0 will only check against the margin.
69 //                     Similarly, setting the margin to 0.0 will only check
70 //                     using the fraction. If margin and fraction are omitted,
71 //                     MathLimits<T>::kStdError for that type (T=float or
72 //                     T=double) is used for both the margin and fraction.
73 //   TreatingNaNsAsEqual(m)
74 //                     The same as m, except that treats floating-point fields
75 //                     that are NaN as equal. m can be any of the Equals* and
76 //                     EquivTo* protobuf matchers above.
77 //   IgnoringFields(fields, m)
78 //                     The same as m, except the specified fields will be
79 //                     ignored when matching (using
80 //                     google::protobuf::util::MessageDifferencer::IgnoreField).
81 //                     fields is represented as a container or an initializer
82 //                     list of strings and each element is specified by their
83 //                     fully qualified names, i.e., the names corresponding to
84 //                     FieldDescriptor.full_name().  m can be
85 //                     any of the Equals* and EquivTo* protobuf matchers above.
86 //                     It can also be any of the transformer matchers listed
87 //                     here (e.g. Approximately, TreatingNaNsAsEqual) as long as
88 //                     the intent of the each concatenated matcher is mutually
89 //                     exclusive (e.g. using IgnoringFields in conjunction with
90 //                     Partially can have different results depending on whether
91 //                     the fields specified in IgnoringFields is part of the
92 //                     fields covered by Partially).
93 //   IgnoringRepeatedFieldOrdering(m)
94 //                     The same as m, except that it ignores the relative
95 //                     ordering of elements within each repeated field in m.
96 //                     See
97 //                     google::protobuf::util::MessageDifferencer::TreatAsSet()
98 //                     for more details.
99 //   Partially(m)
100 //                     The same as m, except that only fields present in
101 //                     the expected protobuf are considered (using
102 //                     google::protobuf::util::MessageDifferencer's PARTIAL
103 //                     comparison option).   m can be any of the
104 //                     Equals* and EquivTo* protobuf matchers above.
105 //   WhenDeserialized(typed_pb_matcher)
106 //                     The string argument is a serialization of a
107 //                     protobuf that matches typed_pb_matcher.
108 //                     typed_pb_matcher can be an Equals* or EquivTo*
109 //                     protobuf matcher (possibly with Approximately()
110 //                     or Partially() modifiers) where the type of the
111 //                     protobuf is known at run time (e.g. it cannot
112 //                     be EqualsProto("...") as it's unclear what type
113 //                     the string represents).
114 //   WhenDeserializedAs<PB>(pb_matcher)
115 //                     Like WhenDeserialized(), except that the type
116 //                     of the deserialized protobuf must be PB.  Since
117 //                     the protobuf type is known, pb_matcher can be *any*
118 //                     valid protobuf matcher, including EqualsProto("...").
119 //
120 // Approximately(), TreatingNaNsAsEqual(), Partially(), IgnoringFields(), and
121 // IgnoringRepeatedFieldOrdering() can be combined (nested)
122 // and the composition order is irrelevant:
123 //
124 //   Approximately(Partially(EquivToProto(pb)))
125 // and
126 //   Partially(Approximately(EquivToProto(pb)))
127 // are the same thing.
128 //
129 // EXAMPLES
130 // ========
131 //
132 //   using ::android::EqualsProto;
133 //   using ::android::EquivToProto;
134 //   using ::android::proto::Approximately;
135 //   using ::android::proto::Partially;
136 //   using ::android::proto::WhenDeserialized;
137 //
138 //   // my_pb.Equals(expected_pb).
139 //   EXPECT_THAT(my_pb, EqualsProto(expected_pb));
140 //
141 //   // my_pb is equivalent to a protobuf whose foo field is 1 and
142 //   // whose bar field is "x".
143 //   EXPECT_THAT(my_pb, EquivToProto("foo: 1 "
144 //                                   "bar: 'x'"));
145 //
146 //   // my_pb is equal to expected_pb, comparing all floating-point
147 //   // fields approximately.
148 //   EXPECT_THAT(my_pb, Approximately(EqualsProto(expected_pb)));
149 //
150 //   // my_pb is equivalent to expected_pb.  A field is ignored in the
151 //   // comparison if it's present in my_pb but not in expected_pb.
152 //   EXPECT_THAT(my_pb, Partially(EquivToProto(expected_pb)));
153 //
154 //   string data;
155 //   my_pb.SerializeToString(&data);
156 //   // data can be deserialized to a protobuf that equals expected_pb.
157 //   EXPECT_THAT(data, WhenDeserialized(EqualsProto(expected_pb)));
158 //   // The following line doesn't compile, as the matcher doesn't know
159 //   // the type of the protobuf.
160 //   // EXPECT_THAT(data, WhenDeserialized(EqualsProto("foo: 1")));
161 
162 #pragma once
163 
164 #include <initializer_list>
165 #include <iostream>  // NOLINT
166 #include <memory>
167 #include <sstream>  // NOLINT
168 #include <string>   // NOLINT
169 #include <string_view>
170 #include <vector>  // NOLINT
171 
172 #include "gmock/gmock-matchers.h"
173 #include "gmock/gmock-more-matchers.h"
174 #include "google/protobuf/descriptor.h"
175 #include "google/protobuf/io/zero_copy_stream.h"
176 #include "google/protobuf/io/zero_copy_stream_impl.h"
177 #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
178 #include "google/protobuf/message.h"
179 #include "google/protobuf/text_format.h"
180 #include "google/protobuf/util/field_comparator.h"
181 #include "google/protobuf/util/message_differencer.h"
182 
183 namespace android {
184 
185 namespace internal {
186 
187 // Utilities.
188 
189 // How to compare two fields (equal vs. equivalent).
190 typedef google::protobuf::util::MessageDifferencer::MessageFieldComparison ProtoFieldComparison;
191 
192 // How to compare two floating-points (exact vs. approximate).
193 typedef google::protobuf::util::DefaultFieldComparator::FloatComparison ProtoFloatComparison;
194 
195 // How to compare repeated fields (whether the order of elements matters).
196 typedef google::protobuf::util::MessageDifferencer::RepeatedFieldComparison RepeatedFieldComparison;
197 
198 // Whether to compare all fields (full) or only fields present in the
199 // expected protobuf (partial).
200 typedef google::protobuf::util::MessageDifferencer::Scope ProtoComparisonScope;
201 
202 const ProtoFieldComparison kProtoEqual = google::protobuf::util::MessageDifferencer::EQUAL;
203 const ProtoFieldComparison kProtoEquiv = google::protobuf::util::MessageDifferencer::EQUIVALENT;
204 const ProtoFloatComparison kProtoExact = google::protobuf::util::DefaultFieldComparator::EXACT;
205 const ProtoFloatComparison kProtoApproximate =
206     google::protobuf::util::DefaultFieldComparator::APPROXIMATE;
207 const RepeatedFieldComparison kProtoCompareRepeatedFieldsRespectOrdering =
208     google::protobuf::util::MessageDifferencer::AS_LIST;
209 const RepeatedFieldComparison kProtoCompareRepeatedFieldsIgnoringOrdering =
210     google::protobuf::util::MessageDifferencer::AS_SET;
211 const ProtoComparisonScope kProtoFull = google::protobuf::util::MessageDifferencer::FULL;
212 const ProtoComparisonScope kProtoPartial = google::protobuf::util::MessageDifferencer::PARTIAL;
213 
214 // Options for comparing two protobufs.
215 struct ProtoComparison {
ProtoComparisonProtoComparison216     ProtoComparison()
217         : field_comp(kProtoEqual),
218           float_comp(kProtoExact),
219           treating_nan_as_equal(false),
220           has_custom_margin(false),
221           has_custom_fraction(false),
222           repeated_field_comp(kProtoCompareRepeatedFieldsRespectOrdering),
223           scope(kProtoFull),
224           float_margin(0.0),
225           float_fraction(0.0) {}
226 
227     ProtoFieldComparison field_comp;
228     ProtoFloatComparison float_comp;
229     bool treating_nan_as_equal;
230     bool has_custom_margin;    // only used when float_comp = APPROXIMATE
231     bool has_custom_fraction;  // only used when float_comp = APPROXIMATE
232     RepeatedFieldComparison repeated_field_comp;
233     ProtoComparisonScope scope;
234     double float_margin;    // only used when has_custom_margin is set.
235     double float_fraction;  // only used when has_custom_fraction is set.
236     std::vector<std::string> ignore_fields;
237 };
238 
239 // Whether the protobuf must be initialized.
240 const bool kMustBeInitialized = true;
241 const bool kMayBeUninitialized = false;
242 
243 // Parses the TextFormat representation of a protobuf, allowing required fields
244 // to be missing.  Returns true iff successful.
245 bool ParsePartialFromAscii(const std::string& pb_ascii, google::protobuf::Message* proto,
246                            std::string* error_text);
247 
248 // Returns a protobuf of type Proto by parsing the given TextFormat
249 // representation of it.  Required fields can be missing, in which case the
250 // returned protobuf will not be fully initialized.
251 template <class Proto>
MakePartialProtoFromAscii(const std::string & str)252 Proto MakePartialProtoFromAscii(const std::string& str) {
253     Proto proto;
254     std::string error_text;
255     if (!ParsePartialFromAscii(str, &proto, &error_text)) {
256         std::cerr << "Failed to parse \"" << str << "\" as a " << proto.GetDescriptor()->full_name()
257                   << ":\n"
258                   << error_text;
259     }
260     return proto;
261 }
262 
263 // Returns true iff p and q can be compared (i.e. have the same descriptor).
264 bool ProtoComparable(const google::protobuf::Message& p, const google::protobuf::Message& q);
265 
266 // Returns true iff actual and expected are comparable and match.  The
267 // comp argument specifies how the two are compared.
268 bool ProtoCompare(const ProtoComparison& comp, const google::protobuf::Message& actual,
269                   const google::protobuf::Message& expected);
270 
271 // Overload for ProtoCompare where the expected message is specified as a text
272 // proto.  If the text cannot be parsed as a message of the same type as the
273 // actual message, a // DCHECK failure will cause the test to fail and no subsequent
274 // tests will be run.
275 template <typename Proto>
ProtoCompare(const ProtoComparison & comp,const Proto & actual,const std::string & expected)276 inline bool ProtoCompare(const ProtoComparison& comp, const Proto& actual,
277                          const std::string& expected) {
278     return ProtoCompare(comp, actual, MakePartialProtoFromAscii<Proto>(expected));
279 }
280 
281 // Describes the types of the expected and the actual protocol buffer.
282 std::string DescribeTypes(const google::protobuf::Message& expected,
283                           const google::protobuf::Message& actual);
284 
285 // Prints the protocol buffer pointed to by proto.
286 std::string PrintProtoPointee(const google::protobuf::Message* proto);
287 
288 // Describes the differences between the two protocol buffers.
289 std::string DescribeDiff(const ProtoComparison& comp, const google::protobuf::Message& actual,
290                          const google::protobuf::Message& expected);
291 
292 // Common code for implementing EqualsProto, EquivToProto,
293 // EqualsInitializedProto, and EquivToInitializedProto.
294 class ProtoMatcherBase {
295    public:
ProtoMatcherBase(bool must_be_initialized,const ProtoComparison & comp)296     ProtoMatcherBase(bool must_be_initialized,     // Must the argument be fully
297                                                    // initialized?
298                      const ProtoComparison& comp)  // How to compare the two protobufs.
299         : must_be_initialized_(must_be_initialized), comp_(new auto(comp)) {}
300 
ProtoMatcherBase(const ProtoMatcherBase & other)301     ProtoMatcherBase(const ProtoMatcherBase& other)
302         : must_be_initialized_(other.must_be_initialized_), comp_(new auto(*other.comp_)) {}
303 
304     ProtoMatcherBase(ProtoMatcherBase&& other) = default;
305 
~ProtoMatcherBase()306     virtual ~ProtoMatcherBase() {}
307 
308     // Prints the expected protocol buffer.
309     virtual void PrintExpectedTo(::std::ostream* os) const = 0;
310 
311     // Returns the expected value as a protobuf object; if the object
312     // cannot be created (e.g. in ProtoStringMatcher), explains why to
313     // 'listener' and returns NULL.  The caller must call
314     // DeleteExpectedProto() on the returned value later.
315     virtual const google::protobuf::Message* CreateExpectedProto(
316         const google::protobuf::Message& arg,  // For determining the type of the
317                                                // expected protobuf.
318         ::testing::MatchResultListener* listener) const = 0;
319 
320     // Deletes the given expected protobuf, which must be obtained from
321     // a call to CreateExpectedProto() earlier.
322     virtual void DeleteExpectedProto(const google::protobuf::Message* expected) const = 0;
323 
324     // Makes this matcher compare floating-points approximately.
SetCompareApproximately()325     void SetCompareApproximately() { comp_->float_comp = kProtoApproximate; }
326 
327     // Makes this matcher treating NaNs as equal when comparing floating-points.
SetCompareTreatingNaNsAsEqual()328     void SetCompareTreatingNaNsAsEqual() { comp_->treating_nan_as_equal = true; }
329 
330     // Makes this matcher ignore string elements specified by their fully
331     // qualified names, i.e., names corresponding to
332     // FieldDescriptor.full_name().
333     template <class Iterator>
AddCompareIgnoringFields(Iterator first,Iterator last)334     void AddCompareIgnoringFields(Iterator first, Iterator last) {
335         comp_->ignore_fields.insert(comp_->ignore_fields.end(), first, last);
336     }
337 
338     // Makes this matcher compare repeated fields ignoring ordering of elements.
SetCompareRepeatedFieldsIgnoringOrdering()339     void SetCompareRepeatedFieldsIgnoringOrdering() {
340         comp_->repeated_field_comp = kProtoCompareRepeatedFieldsIgnoringOrdering;
341     }
342 
343     // Sets the margin of error for approximate floating point comparison.
SetMargin(double margin)344     void SetMargin(double margin) {
345         comp_->has_custom_margin = true;
346         comp_->float_margin = margin;
347     }
348 
349     // Sets the relative fraction of error for approximate floating point
350     // comparison.
SetFraction(double fraction)351     void SetFraction(double fraction) {
352         comp_->has_custom_fraction = true;
353         comp_->float_fraction = fraction;
354     }
355 
356     // Makes this matcher compare protobufs partially.
SetComparePartially()357     void SetComparePartially() { comp_->scope = kProtoPartial; }
358 
MatchAndExplain(const google::protobuf::Message & arg,::testing::MatchResultListener * listener)359     bool MatchAndExplain(const google::protobuf::Message& arg,
360                          ::testing::MatchResultListener* listener) const {
361         return MatchAndExplain(arg, false, listener);
362     }
363 
MatchAndExplain(const google::protobuf::Message * arg,::testing::MatchResultListener * listener)364     bool MatchAndExplain(const google::protobuf::Message* arg,
365                          ::testing::MatchResultListener* listener) const {
366         return (arg != NULL) && MatchAndExplain(*arg, true, listener);
367     }
368 
369     // Describes the expected relation between the actual protobuf and
370     // the expected one.
DescribeRelationToExpectedProto(::std::ostream * os)371     void DescribeRelationToExpectedProto(::std::ostream* os) const {
372         if (comp_->repeated_field_comp == kProtoCompareRepeatedFieldsIgnoringOrdering) {
373             *os << "(ignoring repeated field ordering) ";
374         }
375         if (!comp_->ignore_fields.empty()) {
376             *os << "(ignoring fields: ";
377             const char* sep = "";
378             for (size_t i = 0; i < comp_->ignore_fields.size(); ++i, sep = ", ")
379                 *os << sep << comp_->ignore_fields[i];
380             *os << ") ";
381         }
382         if (comp_->float_comp == kProtoApproximate) {
383             *os << "approximately ";
384             if (comp_->has_custom_margin || comp_->has_custom_fraction) {
385                 *os << "(";
386                 if (comp_->has_custom_margin) {
387                     std::stringstream ss;
388                     ss << std::setprecision(std::numeric_limits<double>::digits10 + 2)
389                        << comp_->float_margin;
390                     *os << "absolute error of float or double fields <= " << ss.str();
391                 }
392                 if (comp_->has_custom_margin && comp_->has_custom_fraction) {
393                     *os << " or ";
394                 }
395                 if (comp_->has_custom_fraction) {
396                     std::stringstream ss;
397                     ss << std::setprecision(std::numeric_limits<double>::digits10 + 2)
398                        << comp_->float_fraction;
399                     *os << "relative error of float or double fields <= " << ss.str();
400                 }
401                 *os << ") ";
402             }
403         }
404 
405         *os << (comp_->scope == kProtoPartial ? "partially " : "")
406             << (comp_->field_comp == kProtoEqual ? "equal" : "equivalent")
407             << (comp_->treating_nan_as_equal ? " (treating NaNs as equal)" : "") << " to ";
408         PrintExpectedTo(os);
409     }
410 
DescribeTo(::std::ostream * os)411     void DescribeTo(::std::ostream* os) const {
412         *os << "is " << (must_be_initialized_ ? "fully initialized and " : "");
413         DescribeRelationToExpectedProto(os);
414     }
415 
DescribeNegationTo(::std::ostream * os)416     void DescribeNegationTo(::std::ostream* os) const {
417         *os << "is " << (must_be_initialized_ ? "not fully initialized or " : "") << "not ";
418         DescribeRelationToExpectedProto(os);
419     }
420 
must_be_initialized()421     bool must_be_initialized() const { return must_be_initialized_; }
422 
comp()423     const ProtoComparison& comp() const { return *comp_; }
424 
425    private:
426     bool MatchAndExplain(const google::protobuf::Message& arg, bool is_matcher_for_pointer,
427                          ::testing::MatchResultListener* listener) const;
428 
429     const bool must_be_initialized_;
430     std::unique_ptr<ProtoComparison> comp_;
431 };
432 
433 // Returns a copy of the given proto2 message.
CloneProto2(const google::protobuf::Message & src)434 inline google::protobuf::Message* CloneProto2(const google::protobuf::Message& src) {
435     google::protobuf::Message* clone = src.New();
436     clone->CopyFrom(src);
437     return clone;
438 }
439 
440 // Implements EqualsProto, EquivToProto, EqualsInitializedProto, and
441 // EquivToInitializedProto, where the matcher parameter is a protobuf.
442 class ProtoMatcher : public ProtoMatcherBase {
443    public:
ProtoMatcher(const google::protobuf::Message & expected,bool must_be_initialized,const ProtoComparison & comp)444     ProtoMatcher(const google::protobuf::Message& expected,  // The expected protobuf.
445                  bool must_be_initialized,                   // Must the argument be fully
446                                                              // initialized?
447                  const ProtoComparison& comp)                // How to compare the two protobufs.
448         : ProtoMatcherBase(must_be_initialized, comp), expected_(CloneProto2(expected)) {
449         if (must_be_initialized) {
450             if (expected.IsInitialized()) {
451                 std::cerr << "The protocol buffer given to *InitializedProto() "
452                           << "must itself be initialized, but the following required "
453                              "fields "
454                           << "are missing: " << expected.InitializationErrorString() << ".";
455             }
456         }
457     }
458 
PrintExpectedTo(::std::ostream * os)459     virtual void PrintExpectedTo(::std::ostream* os) const {
460         *os << expected_->GetDescriptor()->full_name() << " ";
461         ::testing::internal::UniversalPrint(*expected_, os);
462     }
463 
CreateExpectedProto(const google::protobuf::Message &,::testing::MatchResultListener *)464     virtual const google::protobuf::Message* CreateExpectedProto(
465         const google::protobuf::Message& /* arg */,
466         ::testing::MatchResultListener* /* listener */) const {
467         return expected_.get();
468     }
469 
DeleteExpectedProto(const google::protobuf::Message * expected)470     virtual void DeleteExpectedProto(const google::protobuf::Message* expected) const {}
471 
expected()472     const std::shared_ptr<const google::protobuf::Message>& expected() const { return expected_; }
473 
474    private:
475     const std::shared_ptr<const google::protobuf::Message> expected_;
476 };
477 
478 // Implements EqualsProto, EquivToProto, EqualsInitializedProto, and
479 // EquivToInitializedProto, where the matcher parameter is a string.
480 class ProtoStringMatcher : public ProtoMatcherBase {
481    public:
ProtoStringMatcher(const std::string & expected,bool must_be_initialized,const ProtoComparison comp)482     ProtoStringMatcher(const std::string& expected,  // The text representing the expected protobuf.
483                        bool must_be_initialized,     // Must the argument be fully
484                                                      // initialized?
485                        const ProtoComparison comp)   // How to compare the two protobufs.
486         : ProtoMatcherBase(must_be_initialized, comp), expected_(expected) {}
487 
488     // Parses the expected string as a protobuf of the same type as arg,
489     // and returns the parsed protobuf (or NULL when the parse fails).
490     // The caller must call DeleteExpectedProto() on the return value
491     // later.
CreateExpectedProto(const google::protobuf::Message & arg,::testing::MatchResultListener * listener)492     virtual const google::protobuf::Message* CreateExpectedProto(
493         const google::protobuf::Message& arg, ::testing::MatchResultListener* listener) const {
494         google::protobuf::Message* expected_proto = arg.New();
495         // We don't insist that the expected string parses as an
496         // *initialized* protobuf.  Otherwise EqualsProto("...") may
497         // wrongfully fail when the actual protobuf is not fully
498         // initialized.  If the user wants to ensure that the actual
499         // protobuf is initialized, they should use
500         // EqualsInitializedProto("...") instead of EqualsProto("..."),
501         // and the MatchAndExplain() function in ProtoMatcherBase will
502         // enforce it.
503         std::string error_text;
504         if (ParsePartialFromAscii(expected_, expected_proto, &error_text)) {
505             return expected_proto;
506         } else {
507             delete expected_proto;
508             if (listener->IsInterested()) {
509                 *listener << "where ";
510                 PrintExpectedTo(listener->stream());
511                 *listener << " doesn't parse as a " << arg.GetDescriptor()->full_name() << ":\n"
512                           << error_text;
513             }
514             return NULL;
515         }
516     }
517 
DeleteExpectedProto(const google::protobuf::Message * expected)518     virtual void DeleteExpectedProto(const google::protobuf::Message* expected) const {
519         delete expected;
520     }
521 
PrintExpectedTo(::std::ostream * os)522     virtual void PrintExpectedTo(::std::ostream* os) const { *os << "<" << expected_ << ">"; }
523 
524    private:
525     const std::string expected_;
526 };
527 
528 typedef ::testing::PolymorphicMatcher<ProtoMatcher> PolymorphicProtoMatcher;
529 
530 // Common code for implementing WhenDeserialized(proto_matcher) and
531 // WhenDeserializedAs<PB>(proto_matcher).
532 template <class Proto>
533 class WhenDeserializedMatcherBase {
534    public:
535     typedef ::testing::Matcher<const Proto&> InnerMatcher;
536 
WhenDeserializedMatcherBase(const InnerMatcher & proto_matcher)537     explicit WhenDeserializedMatcherBase(const InnerMatcher& proto_matcher)
538         : proto_matcher_(proto_matcher) {}
539 
~WhenDeserializedMatcherBase()540     virtual ~WhenDeserializedMatcherBase() {}
541 
542     // Creates an empty protobuf with the expected type.
543     virtual Proto* MakeEmptyProto() const = 0;
544 
545     // Type name of the expected protobuf.
546     virtual std::string ExpectedTypeName() const = 0;
547 
548     // Name of the type argument given to WhenDeserializedAs<>(), or
549     // "protobuf" for WhenDeserialized().
550     virtual std::string TypeArgName() const = 0;
551 
552     // Deserializes the string as a protobuf of the same type as the expected
553     // protobuf.
Deserialize(google::protobuf::io::ZeroCopyInputStream * input)554     Proto* Deserialize(google::protobuf::io::ZeroCopyInputStream* input) const {
555         Proto* proto = MakeEmptyProto();
556         // ParsePartialFromString() parses a serialized representation of a
557         // protobuf, allowing required fields to be missing.  This means
558         // that we don't insist on the parsed protobuf being fully
559         // initialized.  This allows the user to choose whether it should
560         // be initialized using EqualsProto vs EqualsInitializedProto, for
561         // example.
562         if (proto->ParsePartialFromZeroCopyStream(input)) {
563             return proto;
564         } else {
565             delete proto;
566             return NULL;
567         }
568     }
569 
DescribeTo(::std::ostream * os)570     void DescribeTo(::std::ostream* os) const {
571         *os << "can be deserialized as a " << TypeArgName() << " that ";
572         proto_matcher_.DescribeTo(os);
573     }
574 
DescribeNegationTo(::std::ostream * os)575     void DescribeNegationTo(::std::ostream* os) const {
576         *os << "cannot be deserialized as a " << TypeArgName() << " that ";
577         proto_matcher_.DescribeTo(os);
578     }
579 
MatchAndExplain(google::protobuf::io::ZeroCopyInputStream * arg,::testing::MatchResultListener * listener)580     bool MatchAndExplain(google::protobuf::io::ZeroCopyInputStream* arg,
581                          ::testing::MatchResultListener* listener) const {
582         // Deserializes the string arg as a protobuf of the same type as the
583         // expected protobuf.
584         ::std::unique_ptr<const Proto> deserialized_arg(Deserialize(arg));
585         if (!listener->IsInterested()) {
586             // No need to explain the match result.
587             return (deserialized_arg != NULL) && proto_matcher_.Matches(*deserialized_arg);
588         }
589 
590         ::std::ostream* const os = listener->stream();
591         if (deserialized_arg == NULL) {
592             *os << "which cannot be deserialized as a " << ExpectedTypeName();
593             return false;
594         }
595 
596         *os << "which deserializes to ";
597         UniversalPrint(*deserialized_arg, os);
598 
599         ::testing::StringMatchResultListener inner_listener;
600         const bool match = proto_matcher_.MatchAndExplain(*deserialized_arg, &inner_listener);
601         const std::string explain = inner_listener.str();
602         if (explain != "") {
603             *os << ",\n" << explain;
604         }
605 
606         return match;
607     }
608 
MatchAndExplain(const std::string & str,::testing::MatchResultListener * listener)609     bool MatchAndExplain(const std::string& str, ::testing::MatchResultListener* listener) const {
610         google::protobuf::io::ArrayInputStream input(str.data(), str.size());
611         return MatchAndExplain(&input, listener);
612     }
613 
MatchAndExplain(std::string_view sp,::testing::MatchResultListener * listener)614     bool MatchAndExplain(std::string_view sp, ::testing::MatchResultListener* listener) const {
615         google::protobuf::io::ArrayInputStream input(sp.data(), sp.size());
616         return MatchAndExplain(&input, listener);
617     }
618 
MatchAndExplain(const char * str,::testing::MatchResultListener * listener)619     bool MatchAndExplain(const char* str, ::testing::MatchResultListener* listener) const {
620         google::protobuf::io::ArrayInputStream input(str, strlen(str));
621         return MatchAndExplain(&input, listener);
622     }
623 
624    private:
625     const InnerMatcher proto_matcher_;
626 };
627 
628 // Implements WhenDeserialized(proto_matcher).
629 class WhenDeserializedMatcher : public WhenDeserializedMatcherBase<google::protobuf::Message> {
630                                 public
WhenDeserializedMatcher(const PolymorphicProtoMatcher & proto_matcher)631     : explicit WhenDeserializedMatcher(const PolymorphicProtoMatcher& proto_matcher)
632     : WhenDeserializedMatcherBase<google::protobuf::Message>(proto_matcher),
633       expected_proto_(proto_matcher.impl().expected()) {}
634 
MakeEmptyProto()635 virtual google::protobuf::Message* MakeEmptyProto() const { return expected_proto_->New(); }
636 
ExpectedTypeName()637 virtual std::string ExpectedTypeName() const {
638     return expected_proto_->GetDescriptor()->full_name();
639 }
640 
TypeArgName()641 virtual std::string TypeArgName() const { return "protobuf"; }
642 
643 private:
644 // The expected protobuf specified in the inner matcher
645 // (proto_matcher_).  We only need a std::shared_ptr to it instead of
646 // making a copy, as the expected protobuf will never be changed
647 // once created.
648 const std::shared_ptr<const google::protobuf::Message> expected_proto_;
649 };
650 
651 // Implements WhenDeserializedAs<Proto>(proto_matcher).
652 template <class Proto>
653 class WhenDeserializedAsMatcher : public WhenDeserializedMatcherBase<Proto> {
654    public:
655     typedef ::testing::Matcher<const Proto&> InnerMatcher;
656 
WhenDeserializedAsMatcher(const InnerMatcher & inner_matcher)657     explicit WhenDeserializedAsMatcher(const InnerMatcher& inner_matcher)
658         : WhenDeserializedMatcherBase<Proto>(inner_matcher) {}
659 
MakeEmptyProto()660     virtual Proto* MakeEmptyProto() const { return new Proto; }
661 
ExpectedTypeName()662     virtual std::string ExpectedTypeName() const { return Proto().GetDescriptor()->full_name(); }
663 
TypeArgName()664     virtual std::string TypeArgName() const { return ExpectedTypeName(); }
665 };
666 
667 // Implements the IsInitializedProto matcher, which is used to verify that a
668 // protocol buffer is valid using the IsInitialized method.
669 class IsInitializedProtoMatcher {
670    public:
DescribeTo(::std::ostream * os)671     void DescribeTo(::std::ostream* os) const { *os << "is a fully initialized protocol buffer"; }
672 
DescribeNegationTo(::std::ostream * os)673     void DescribeNegationTo(::std::ostream* os) const {
674         *os << "is not a fully initialized protocol buffer";
675     }
676 
677     template <typename T>
MatchAndExplain(T & arg,::testing::MatchResultListener * listener)678     bool MatchAndExplain(T& arg,  // NOLINT
679                          ::testing::MatchResultListener* listener) const {
680         if (!arg.IsInitialized()) {
681             *listener << "which is missing the following required fields: "
682                       << arg.InitializationErrorString();
683             return false;
684         }
685         return true;
686     }
687 
688     // It's critical for this overload to take a T* instead of a const
689     // T*.  Otherwise the other version would be a better match when arg
690     // is a pointer to a non-const value.
691     template <typename T>
MatchAndExplain(T * arg,::testing::MatchResultListener * listener)692     bool MatchAndExplain(T* arg, ::testing::MatchResultListener* listener) const {
693         if (listener->IsInterested() && arg != NULL) {
694             *listener << PrintProtoPointee(arg);
695         }
696         if (arg == NULL) {
697             *listener << "which is null";
698             return false;
699         } else if (!arg->IsInitialized()) {
700             *listener << ", which is missing the following required fields: "
701                       << arg->InitializationErrorString();
702             return false;
703         } else {
704             return true;
705         }
706     }
707 };
708 
709 // Implements EqualsProto and EquivToProto for 2-tuple matchers.
710 class TupleProtoMatcher {
711    public:
TupleProtoMatcher(const ProtoComparison & comp)712     explicit TupleProtoMatcher(const ProtoComparison& comp) : comp_(new auto(comp)) {}
713 
TupleProtoMatcher(const TupleProtoMatcher & other)714     TupleProtoMatcher(const TupleProtoMatcher& other) : comp_(new auto(*other.comp_)) {}
715     TupleProtoMatcher(TupleProtoMatcher&& other) = default;
716 
717     template <typename T1, typename T2>
718     operator ::testing::Matcher<::testing::tuple<T1, T2>>() const {
719         return MakeMatcher(new Impl<::testing::tuple<T1, T2>>(*comp_));
720     }
721     template <typename T1, typename T2>
722     operator ::testing::Matcher<const ::testing::tuple<T1, T2>&>() const {
723         return MakeMatcher(new Impl<const ::testing::tuple<T1, T2>&>(*comp_));
724     }
725 
726     // Allows matcher transformers, e.g., Approximately(), Partially(), etc. to
727     // change the behavior of this 2-tuple matcher.
mutable_impl()728     TupleProtoMatcher& mutable_impl() { return *this; }
729 
730     // Makes this matcher compare floating-points approximately.
SetCompareApproximately()731     void SetCompareApproximately() { comp_->float_comp = kProtoApproximate; }
732 
733     // Makes this matcher treating NaNs as equal when comparing floating-points.
SetCompareTreatingNaNsAsEqual()734     void SetCompareTreatingNaNsAsEqual() { comp_->treating_nan_as_equal = true; }
735 
736     // Makes this matcher ignore string elements specified by their fully
737     // qualified names, i.e., names corresponding to
738     // FieldDescriptor.full_name().
739     template <class Iterator>
AddCompareIgnoringFields(Iterator first,Iterator last)740     void AddCompareIgnoringFields(Iterator first, Iterator last) {
741         comp_->ignore_fields.insert(comp_->ignore_fields.end(), first, last);
742     }
743 
744     // Makes this matcher compare repeated fields ignoring ordering of elements.
SetCompareRepeatedFieldsIgnoringOrdering()745     void SetCompareRepeatedFieldsIgnoringOrdering() {
746         comp_->repeated_field_comp = kProtoCompareRepeatedFieldsIgnoringOrdering;
747     }
748 
749     // Sets the margin of error for approximate floating point comparison.
SetMargin(double margin)750     void SetMargin(double margin) {
751         // DCHECK(margin >= 0.0) << "Using a negative margin for Approximately";
752         comp_->has_custom_margin = true;
753         comp_->float_margin = margin;
754     }
755 
756     // Sets the relative fraction of error for approximate floating point
757     // comparison.
SetFraction(double fraction)758     void SetFraction(double fraction) {
759         comp_->has_custom_fraction = true;
760         comp_->float_fraction = fraction;
761     }
762 
763     // Makes this matcher compares protobufs partially.
SetComparePartially()764     void SetComparePartially() { comp_->scope = kProtoPartial; }
765 
766    private:
767     template <typename Tuple>
768     class Impl : public ::testing::MatcherInterface<Tuple> {
769        public:
Impl(const ProtoComparison & comp)770         explicit Impl(const ProtoComparison& comp) : comp_(comp) {}
MatchAndExplain(Tuple args,::testing::MatchResultListener *)771         virtual bool MatchAndExplain(Tuple args,
772                                      ::testing::MatchResultListener* /* listener */) const {
773             using ::testing::get;
774             return ProtoCompare(comp_, get<0>(args), get<1>(args));
775         }
DescribeTo(::std::ostream * os)776         virtual void DescribeTo(::std::ostream* os) const {
777             *os << (comp_.field_comp == kProtoEqual ? "are equal" : "are equivalent");
778         }
DescribeNegationTo(::std::ostream * os)779         virtual void DescribeNegationTo(::std::ostream* os) const {
780             *os << (comp_.field_comp == kProtoEqual ? "are not equal" : "are not equivalent");
781         }
782 
783        private:
784         const ProtoComparison comp_;
785     };
786 
787     std::unique_ptr<ProtoComparison> comp_;
788 };
789 
790 }  // namespace internal
791 
792 // Creates a polymorphic matcher that matches a 2-tuple where
793 // first.Equals(second) is true.
EqualsProto()794 inline internal::TupleProtoMatcher EqualsProto() {
795     internal::ProtoComparison comp;
796     comp.field_comp = internal::kProtoEqual;
797     return internal::TupleProtoMatcher(comp);
798 }
799 
800 // Creates a polymorphic matcher that matches a 2-tuple where
801 // first.Equivalent(second) is true.
EquivToProto()802 inline internal::TupleProtoMatcher EquivToProto() {
803     internal::ProtoComparison comp;
804     comp.field_comp = internal::kProtoEquiv;
805     return internal::TupleProtoMatcher(comp);
806 }
807 
808 // Constructs a matcher that matches the argument if
809 // argument.Equals(x) or argument->Equals(x) returns true.
EqualsProto(const google::protobuf::Message & x)810 inline internal::PolymorphicProtoMatcher EqualsProto(const google::protobuf::Message& x) {
811     internal::ProtoComparison comp;
812     comp.field_comp = internal::kProtoEqual;
813     return ::testing::MakePolymorphicMatcher(
814         internal::ProtoMatcher(x, internal::kMayBeUninitialized, comp));
815 }
EqualsProto(const std::string & x)816 inline ::testing::PolymorphicMatcher<internal::ProtoStringMatcher> EqualsProto(
817     const std::string& x) {
818     internal::ProtoComparison comp;
819     comp.field_comp = internal::kProtoEqual;
820     return ::testing::MakePolymorphicMatcher(
821         internal::ProtoStringMatcher(x, internal::kMayBeUninitialized, comp));
822 }
823 template <class Proto>
EqualsProto(const std::string & str)824 inline internal::PolymorphicProtoMatcher EqualsProto(const std::string& str) {
825     return EqualsProto(internal::MakePartialProtoFromAscii<Proto>(str));
826 }
827 
828 // Constructs a matcher that matches the argument if
829 // argument.Equivalent(x) or argument->Equivalent(x) returns true.
EquivToProto(const google::protobuf::Message & x)830 inline internal::PolymorphicProtoMatcher EquivToProto(const google::protobuf::Message& x) {
831     internal::ProtoComparison comp;
832     comp.field_comp = internal::kProtoEquiv;
833     return ::testing::MakePolymorphicMatcher(
834         internal::ProtoMatcher(x, internal::kMayBeUninitialized, comp));
835 }
EquivToProto(const std::string & x)836 inline ::testing::PolymorphicMatcher<internal::ProtoStringMatcher> EquivToProto(
837     const std::string& x) {
838     internal::ProtoComparison comp;
839     comp.field_comp = internal::kProtoEquiv;
840     return ::testing::MakePolymorphicMatcher(
841         internal::ProtoStringMatcher(x, internal::kMayBeUninitialized, comp));
842 }
843 template <class Proto>
EquivToProto(const std::string & str)844 inline internal::PolymorphicProtoMatcher EquivToProto(const std::string& str) {
845     return EquivToProto(internal::MakePartialProtoFromAscii<Proto>(str));
846 }
847 
848 // Constructs a matcher that matches the argument if
849 // argument.IsInitialized() or argument->IsInitialized() returns true.
IsInitializedProto()850 inline ::testing::PolymorphicMatcher<internal::IsInitializedProtoMatcher> IsInitializedProto() {
851     return ::testing::MakePolymorphicMatcher(internal::IsInitializedProtoMatcher());
852 }
853 
854 // Constructs a matcher that matches an argument whose IsInitialized()
855 // and Equals(x) methods both return true.  The argument can be either
856 // a protocol buffer or a pointer to it.
EqualsInitializedProto(const google::protobuf::Message & x)857 inline internal::PolymorphicProtoMatcher EqualsInitializedProto(
858     const google::protobuf::Message& x) {
859     internal::ProtoComparison comp;
860     comp.field_comp = internal::kProtoEqual;
861     return ::testing::MakePolymorphicMatcher(
862         internal::ProtoMatcher(x, internal::kMustBeInitialized, comp));
863 }
EqualsInitializedProto(const std::string & x)864 inline ::testing::PolymorphicMatcher<internal::ProtoStringMatcher> EqualsInitializedProto(
865     const std::string& x) {
866     internal::ProtoComparison comp;
867     comp.field_comp = internal::kProtoEqual;
868     return ::testing::MakePolymorphicMatcher(
869         internal::ProtoStringMatcher(x, internal::kMustBeInitialized, comp));
870 }
871 template <class Proto>
EqualsInitializedProto(const std::string & str)872 inline internal::PolymorphicProtoMatcher EqualsInitializedProto(const std::string& str) {
873     return EqualsInitializedProto(internal::MakePartialProtoFromAscii<Proto>(str));
874 }
875 
876 // Constructs a matcher that matches an argument whose IsInitialized()
877 // and Equivalent(x) methods both return true.  The argument can be
878 // either a protocol buffer or a pointer to it.
EquivToInitializedProto(const google::protobuf::Message & x)879 inline internal::PolymorphicProtoMatcher EquivToInitializedProto(
880     const google::protobuf::Message& x) {
881     internal::ProtoComparison comp;
882     comp.field_comp = internal::kProtoEquiv;
883     return ::testing::MakePolymorphicMatcher(
884         internal::ProtoMatcher(x, internal::kMustBeInitialized, comp));
885 }
EquivToInitializedProto(const std::string & x)886 inline ::testing::PolymorphicMatcher<internal::ProtoStringMatcher> EquivToInitializedProto(
887     const std::string& x) {
888     internal::ProtoComparison comp;
889     comp.field_comp = internal::kProtoEquiv;
890     return ::testing::MakePolymorphicMatcher(
891         internal::ProtoStringMatcher(x, internal::kMustBeInitialized, comp));
892 }
893 template <class Proto>
EquivToInitializedProto(const std::string & str)894 inline internal::PolymorphicProtoMatcher EquivToInitializedProto(const std::string& str) {
895     return EquivToInitializedProto(internal::MakePartialProtoFromAscii<Proto>(str));
896 }
897 
898 namespace proto {
899 
900 // Approximately(m) returns a matcher that is the same as m, except
901 // that it compares floating-point fields approximately (using
902 // google::protobuf::util::MessageDifferencer's APPROXIMATE comparison option).
903 // The inner matcher m can be any of the Equals* and EquivTo* protobuf
904 // matchers above.
905 template <class InnerProtoMatcher>
Approximately(InnerProtoMatcher inner_proto_matcher)906 inline InnerProtoMatcher Approximately(InnerProtoMatcher inner_proto_matcher) {
907     inner_proto_matcher.mutable_impl().SetCompareApproximately();
908     return inner_proto_matcher;
909 }
910 
911 // Alternative version of Approximately which takes an explicit margin of error.
912 template <class InnerProtoMatcher>
Approximately(InnerProtoMatcher inner_proto_matcher,double margin)913 inline InnerProtoMatcher Approximately(InnerProtoMatcher inner_proto_matcher, double margin) {
914     inner_proto_matcher.mutable_impl().SetCompareApproximately();
915     inner_proto_matcher.mutable_impl().SetMargin(margin);
916     return inner_proto_matcher;
917 }
918 
919 // Alternative version of Approximately which takes an explicit margin of error
920 // and a relative fraction of error and will match if either is satisfied.
921 template <class InnerProtoMatcher>
Approximately(InnerProtoMatcher inner_proto_matcher,double margin,double fraction)922 inline InnerProtoMatcher Approximately(InnerProtoMatcher inner_proto_matcher, double margin,
923                                        double fraction) {
924     inner_proto_matcher.mutable_impl().SetCompareApproximately();
925     inner_proto_matcher.mutable_impl().SetMargin(margin);
926     inner_proto_matcher.mutable_impl().SetFraction(fraction);
927     return inner_proto_matcher;
928 }
929 
930 // TreatingNaNsAsEqual(m) returns a matcher that is the same as m, except that
931 // it compares floating-point fields such that NaNs are equal.
932 // The inner matcher m can be any of the Equals* and EquivTo* protobuf matchers
933 // above.
934 template <class InnerProtoMatcher>
TreatingNaNsAsEqual(InnerProtoMatcher inner_proto_matcher)935 inline InnerProtoMatcher TreatingNaNsAsEqual(InnerProtoMatcher inner_proto_matcher) {
936     inner_proto_matcher.mutable_impl().SetCompareTreatingNaNsAsEqual();
937     return inner_proto_matcher;
938 }
939 
940 // IgnoringFields(fields, m) returns a matcher that is the same as m, except the
941 // specified fields will be ignored when matching
942 // (using google::protobuf::util::MessageDifferencer::IgnoreField). Each element
943 // in fields are specified by their fully qualified names, i.e., the names
944 // corresponding to FieldDescriptor.full_name(). (e.g.
945 // testing.internal.FooProto2.member). m can be any of the Equals* and EquivTo*
946 // protobuf matchers above. It can also be any of the transformer matchers
947 // listed here (e.g. Approximately, TreatingNaNsAsEqual) as long as the intent
948 // of the each concatenated matcher is mutually exclusive (e.g. using
949 // IgnoringFields in conjunction with Partially can have different results
950 // depending on whether the fields specified in IgnoringFields is part of the
951 // fields covered by Partially).
952 template <class InnerProtoMatcher, class Container>
IgnoringFields(const Container & ignore_fields,InnerProtoMatcher inner_proto_matcher)953 inline InnerProtoMatcher IgnoringFields(const Container& ignore_fields,
954                                         InnerProtoMatcher inner_proto_matcher) {
955     inner_proto_matcher.mutable_impl().AddCompareIgnoringFields(ignore_fields.begin(),
956                                                                 ignore_fields.end());
957     return inner_proto_matcher;
958 }
959 
960 #ifdef LANG_CXX11
961 template <class InnerProtoMatcher, class T>
IgnoringFields(std::initializer_list<T> il,InnerProtoMatcher inner_proto_matcher)962 inline InnerProtoMatcher IgnoringFields(std::initializer_list<T> il,
963                                         InnerProtoMatcher inner_proto_matcher) {
964     inner_proto_matcher.mutable_impl().AddCompareIgnoringFields(il.begin(), il.end());
965     return inner_proto_matcher;
966 }
967 #endif  // LANG_CXX11
968 
969 // IgnoringRepeatedFieldOrdering(m) returns a matcher that is the same as m,
970 // except that it ignores the relative ordering of elements within each repeated
971 // field in m. See google::protobuf::MessageDifferencer::TreatAsSet() for more
972 // details.
973 template <class InnerProtoMatcher>
IgnoringRepeatedFieldOrdering(InnerProtoMatcher inner_proto_matcher)974 inline InnerProtoMatcher IgnoringRepeatedFieldOrdering(InnerProtoMatcher inner_proto_matcher) {
975     inner_proto_matcher.mutable_impl().SetCompareRepeatedFieldsIgnoringOrdering();
976     return inner_proto_matcher;
977 }
978 
979 // Partially(m) returns a matcher that is the same as m, except that
980 // only fields present in the expected protobuf are considered (using
981 // google::protobuf::util::MessageDifferencer's PARTIAL comparison option).  For
982 // example, Partially(EqualsProto(p)) will ignore any field that's
983 // not set in p when comparing the protobufs. The inner matcher m can
984 // be any of the Equals* and EquivTo* protobuf matchers above.
985 template <class InnerProtoMatcher>
Partially(InnerProtoMatcher inner_proto_matcher)986 inline InnerProtoMatcher Partially(InnerProtoMatcher inner_proto_matcher) {
987     inner_proto_matcher.mutable_impl().SetComparePartially();
988     return inner_proto_matcher;
989 }
990 
991 // WhenDeserialized(m) is a matcher that matches a string that can be
992 // deserialized as a protobuf that matches m.  m must be a protobuf
993 // matcher where the expected protobuf type is known at run time.
WhenDeserialized(const internal::PolymorphicProtoMatcher & proto_matcher)994 inline ::testing::PolymorphicMatcher<internal::WhenDeserializedMatcher> WhenDeserialized(
995     const internal::PolymorphicProtoMatcher& proto_matcher) {
996     return ::testing::MakePolymorphicMatcher(internal::WhenDeserializedMatcher(proto_matcher));
997 }
998 
999 // WhenDeserializedAs<Proto>(m) is a matcher that matches a string
1000 // that can be deserialized as a protobuf of type Proto that matches
1001 // m, which can be any valid protobuf matcher.
1002 template <class Proto, class InnerMatcher>
WhenDeserializedAs(const InnerMatcher & inner_matcher)1003 inline ::testing::PolymorphicMatcher<internal::WhenDeserializedAsMatcher<Proto>> WhenDeserializedAs(
1004     const InnerMatcher& inner_matcher) {
1005     return MakePolymorphicMatcher(internal::WhenDeserializedAsMatcher<Proto>(
1006         ::testing::SafeMatcherCast<const Proto&>(inner_matcher)));
1007 }
1008 
1009 }  // namespace proto
1010 }  // namespace android
1011