• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Author: jschorr@google.com (Joseph Schorr)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 //
35 // This file defines static methods and classes for comparing Protocol
36 // Messages (see //google/protobuf/util/message_differencer.h for more
37 // information).
38 
39 #include <google/protobuf/util/message_differencer.h>
40 
41 #include <algorithm>
42 #include <memory>
43 #ifndef _SHARED_PTR_H
44 #include <google/protobuf/stubs/shared_ptr.h>
45 #endif
46 #include <utility>
47 
48 #include <google/protobuf/stubs/callback.h>
49 #include <google/protobuf/stubs/common.h>
50 #include <google/protobuf/stubs/logging.h>
51 #include <google/protobuf/stubs/stringprintf.h>
52 #include <google/protobuf/any.h>
53 #include <google/protobuf/io/printer.h>
54 #include <google/protobuf/io/zero_copy_stream.h>
55 #include <google/protobuf/io/zero_copy_stream_impl.h>
56 #include <google/protobuf/dynamic_message.h>
57 #include <google/protobuf/text_format.h>
58 #include <google/protobuf/util/field_comparator.h>
59 #include <google/protobuf/stubs/strutil.h>
60 
61 namespace google {
62 namespace protobuf {
63 
64 namespace util {
65 
66 // When comparing a repeated field as map, MultipleFieldMapKeyComparator can
67 // be used to specify multiple fields as key for key comparison.
68 // Two elements of a repeated field will be regarded as having the same key
69 // iff they have the same value for every specified key field.
70 // Note that you can also specify only one field as key.
71 class MessageDifferencer::MultipleFieldsMapKeyComparator
72     : public MessageDifferencer::MapKeyComparator {
73  public:
MultipleFieldsMapKeyComparator(MessageDifferencer * message_differencer,const vector<vector<const FieldDescriptor * >> & key_field_paths)74   MultipleFieldsMapKeyComparator(
75       MessageDifferencer* message_differencer,
76       const vector<vector<const FieldDescriptor*> >& key_field_paths)
77         : message_differencer_(message_differencer),
78           key_field_paths_(key_field_paths) {
79     GOOGLE_CHECK(!key_field_paths_.empty());
80     for (int i = 0; i < key_field_paths_.size(); ++i) {
81       GOOGLE_CHECK(!key_field_paths_[i].empty());
82     }
83   }
MultipleFieldsMapKeyComparator(MessageDifferencer * message_differencer,const FieldDescriptor * key)84   MultipleFieldsMapKeyComparator(
85       MessageDifferencer* message_differencer,
86       const FieldDescriptor* key)
87         : message_differencer_(message_differencer) {
88     vector<const FieldDescriptor*> key_field_path;
89     key_field_path.push_back(key);
90     key_field_paths_.push_back(key_field_path);
91   }
IsMatch(const Message & message1,const Message & message2,const vector<SpecificField> & parent_fields) const92   virtual bool IsMatch(
93       const Message& message1,
94       const Message& message2,
95       const vector<SpecificField>& parent_fields) const {
96     for (int i = 0; i < key_field_paths_.size(); ++i) {
97       if (!IsMatchInternal(message1, message2, parent_fields,
98                            key_field_paths_[i], 0)) {
99         return false;
100       }
101     }
102     return true;
103   }
104  private:
IsMatchInternal(const Message & message1,const Message & message2,const vector<SpecificField> & parent_fields,const vector<const FieldDescriptor * > & key_field_path,int path_index) const105   bool IsMatchInternal(
106       const Message& message1,
107       const Message& message2,
108       const vector<SpecificField>& parent_fields,
109       const vector<const FieldDescriptor*>& key_field_path,
110       int path_index) const {
111     const FieldDescriptor* field = key_field_path[path_index];
112     vector<SpecificField> current_parent_fields(parent_fields);
113     if (path_index == key_field_path.size() - 1) {
114       if (field->is_repeated()) {
115         if (!message_differencer_->CompareRepeatedField(
116             message1, message2, field, &current_parent_fields)) {
117           return false;
118         }
119       } else {
120         if (!message_differencer_->CompareFieldValueUsingParentFields(
121             message1, message2, field, -1, -1, &current_parent_fields)) {
122           return false;
123         }
124       }
125       return true;
126     } else {
127       const Reflection* reflection1 = message1.GetReflection();
128       const Reflection* reflection2 = message2.GetReflection();
129       bool has_field1 = reflection1->HasField(message1, field);
130       bool has_field2 = reflection2->HasField(message2, field);
131       if (!has_field1 && !has_field2) {
132         return true;
133       }
134       if (has_field1 != has_field2) {
135         return false;
136       }
137       SpecificField specific_field;
138       specific_field.field = field;
139       current_parent_fields.push_back(specific_field);
140       return IsMatchInternal(
141           reflection1->GetMessage(message1, field),
142           reflection2->GetMessage(message2, field),
143           current_parent_fields,
144           key_field_path,
145           path_index + 1);
146     }
147   }
148   MessageDifferencer* message_differencer_;
149   vector<vector<const FieldDescriptor*> > key_field_paths_;
150   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultipleFieldsMapKeyComparator);
151 };
152 
Equals(const Message & message1,const Message & message2)153 bool MessageDifferencer::Equals(const Message& message1,
154                                 const Message& message2) {
155   MessageDifferencer differencer;
156 
157   return differencer.Compare(message1, message2);
158 }
159 
Equivalent(const Message & message1,const Message & message2)160 bool MessageDifferencer::Equivalent(const Message& message1,
161                                     const Message& message2) {
162   MessageDifferencer differencer;
163   differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT);
164 
165   return differencer.Compare(message1, message2);
166 }
167 
ApproximatelyEquals(const Message & message1,const Message & message2)168 bool MessageDifferencer::ApproximatelyEquals(const Message& message1,
169                                              const Message& message2) {
170   MessageDifferencer differencer;
171   differencer.set_float_comparison(
172       MessageDifferencer::APPROXIMATE);
173 
174   return differencer.Compare(message1, message2);
175 }
176 
ApproximatelyEquivalent(const Message & message1,const Message & message2)177 bool MessageDifferencer::ApproximatelyEquivalent(const Message& message1,
178                                                  const Message& message2) {
179   MessageDifferencer differencer;
180   differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT);
181   differencer.set_float_comparison(MessageDifferencer::APPROXIMATE);
182 
183   return differencer.Compare(message1, message2);
184 }
185 
186 // ===========================================================================
187 
MessageDifferencer()188 MessageDifferencer::MessageDifferencer()
189     : reporter_(NULL),
190       field_comparator_(NULL),
191       message_field_comparison_(EQUAL),
192       scope_(FULL),
193       repeated_field_comparison_(AS_LIST),
194       report_matches_(false),
195       output_string_(NULL) { }
196 
~MessageDifferencer()197 MessageDifferencer::~MessageDifferencer() {
198   for (int i = 0; i < owned_key_comparators_.size(); ++i) {
199     delete owned_key_comparators_[i];
200   }
201   for (int i = 0; i < ignore_criteria_.size(); ++i) {
202     delete ignore_criteria_[i];
203   }
204 }
205 
set_field_comparator(FieldComparator * comparator)206 void MessageDifferencer::set_field_comparator(FieldComparator* comparator) {
207   GOOGLE_CHECK(comparator) << "Field comparator can't be NULL.";
208   field_comparator_ = comparator;
209 }
210 
set_message_field_comparison(MessageFieldComparison comparison)211 void MessageDifferencer::set_message_field_comparison(
212     MessageFieldComparison comparison) {
213   message_field_comparison_ = comparison;
214 }
215 
set_scope(Scope scope)216 void MessageDifferencer::set_scope(Scope scope) {
217   scope_ = scope;
218 }
219 
scope()220 MessageDifferencer::Scope MessageDifferencer::scope() {
221   return scope_;
222 }
223 
set_float_comparison(FloatComparison comparison)224 void MessageDifferencer::set_float_comparison(FloatComparison comparison) {
225   default_field_comparator_.set_float_comparison(
226       comparison == EXACT ?
227       DefaultFieldComparator::EXACT : DefaultFieldComparator::APPROXIMATE);
228 }
229 
set_repeated_field_comparison(RepeatedFieldComparison comparison)230 void MessageDifferencer::set_repeated_field_comparison(
231     RepeatedFieldComparison comparison) {
232   repeated_field_comparison_ = comparison;
233 }
234 
TreatAsSet(const FieldDescriptor * field)235 void MessageDifferencer::TreatAsSet(const FieldDescriptor* field) {
236   GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: "
237                                << field->full_name();
238   const MapKeyComparator* key_comparator = GetMapKeyComparator(field);
239   GOOGLE_CHECK(key_comparator == NULL)
240       << "Cannot treat this repeated field as both Map and Set for"
241       << " comparison.  Field name is: " << field->full_name();
242   GOOGLE_CHECK(list_fields_.find(field) == list_fields_.end())
243       << "Cannot treat the same field as both SET and LIST. Field name is: "
244       << field->full_name();
245   set_fields_.insert(field);
246 }
247 
TreatAsList(const FieldDescriptor * field)248 void MessageDifferencer::TreatAsList(const FieldDescriptor* field) {
249   GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: "
250                               << field->full_name();
251   const MapKeyComparator* key_comparator = GetMapKeyComparator(field);
252   GOOGLE_CHECK(key_comparator == NULL)
253       << "Cannot treat this repeated field as both Map and Set for"
254       << " comparison.  Field name is: " << field->full_name();
255   GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end())
256       << "Cannot treat the same field as both SET and LIST. Field name is: "
257       << field->full_name();
258   list_fields_.insert(field);
259 }
260 
TreatAsMap(const FieldDescriptor * field,const FieldDescriptor * key)261 void MessageDifferencer::TreatAsMap(const FieldDescriptor* field,
262                                     const FieldDescriptor* key) {
263   GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: "
264                                << field->full_name();
265   GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type())
266       << "Field has to be message type.  Field name is: "
267       << field->full_name();
268   GOOGLE_CHECK(key->containing_type() == field->message_type())
269       << key->full_name()
270       << " must be a direct subfield within the repeated field "
271       << field->full_name() << ", not " << key->containing_type()->full_name();
272   GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end())
273       << "Cannot treat this repeated field as both Map and Set for "
274       << "comparison.";
275   GOOGLE_CHECK(list_fields_.find(field) == list_fields_.end())
276       << "Cannot treat this repeated field as both Map and List for "
277       << "comparison.";
278   MapKeyComparator* key_comparator =
279       new MultipleFieldsMapKeyComparator(this, key);
280   owned_key_comparators_.push_back(key_comparator);
281   map_field_key_comparator_[field] = key_comparator;
282 }
283 
TreatAsMapWithMultipleFieldsAsKey(const FieldDescriptor * field,const vector<const FieldDescriptor * > & key_fields)284 void MessageDifferencer::TreatAsMapWithMultipleFieldsAsKey(
285     const FieldDescriptor* field,
286     const vector<const FieldDescriptor*>& key_fields) {
287   vector<vector<const FieldDescriptor*> > key_field_paths;
288   for (int i = 0; i < key_fields.size(); ++i) {
289     vector<const FieldDescriptor*> key_field_path;
290     key_field_path.push_back(key_fields[i]);
291     key_field_paths.push_back(key_field_path);
292   }
293   TreatAsMapWithMultipleFieldPathsAsKey(field, key_field_paths);
294 }
295 
TreatAsMapWithMultipleFieldPathsAsKey(const FieldDescriptor * field,const vector<vector<const FieldDescriptor * >> & key_field_paths)296 void MessageDifferencer::TreatAsMapWithMultipleFieldPathsAsKey(
297     const FieldDescriptor* field,
298     const vector<vector<const FieldDescriptor*> >& key_field_paths) {
299   GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: "
300                               << field->full_name();
301   GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type())
302       << "Field has to be message type.  Field name is: "
303       << field->full_name();
304   for (int i = 0; i < key_field_paths.size(); ++i) {
305     const vector<const FieldDescriptor*>& key_field_path = key_field_paths[i];
306     for (int j = 0; j < key_field_path.size(); ++j) {
307       const FieldDescriptor* parent_field =
308           j == 0 ? field : key_field_path[j - 1];
309       const FieldDescriptor* child_field = key_field_path[j];
310       GOOGLE_CHECK(child_field->containing_type() == parent_field->message_type())
311           << child_field->full_name()
312           << " must be a direct subfield within the field: "
313           << parent_field->full_name();
314       if (j != 0) {
315         GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, parent_field->cpp_type())
316             << parent_field->full_name() << " has to be of type message.";
317         GOOGLE_CHECK(!parent_field->is_repeated())
318             << parent_field->full_name() << " cannot be a repeated field.";
319       }
320     }
321   }
322   GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end())
323       << "Cannot treat this repeated field as both Map and Set for "
324       << "comparison.";
325   MapKeyComparator* key_comparator =
326       new MultipleFieldsMapKeyComparator(this, key_field_paths);
327   owned_key_comparators_.push_back(key_comparator);
328   map_field_key_comparator_[field] = key_comparator;
329 }
330 
TreatAsMapUsingKeyComparator(const FieldDescriptor * field,const MapKeyComparator * key_comparator)331 void MessageDifferencer::TreatAsMapUsingKeyComparator(
332     const FieldDescriptor* field,
333     const MapKeyComparator* key_comparator) {
334   GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: "
335                                << field->full_name();
336   GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type())
337       << "Field has to be message type.  Field name is: "
338       << field->full_name();
339   GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end())
340       << "Cannot treat this repeated field as both Map and Set for "
341       << "comparison.";
342   map_field_key_comparator_[field] = key_comparator;
343 }
344 
AddIgnoreCriteria(IgnoreCriteria * ignore_criteria)345 void MessageDifferencer::AddIgnoreCriteria(IgnoreCriteria* ignore_criteria) {
346   ignore_criteria_.push_back(ignore_criteria);
347 }
348 
IgnoreField(const FieldDescriptor * field)349 void MessageDifferencer::IgnoreField(const FieldDescriptor* field) {
350   ignored_fields_.insert(field);
351 }
352 
SetFractionAndMargin(const FieldDescriptor * field,double fraction,double margin)353 void MessageDifferencer::SetFractionAndMargin(const FieldDescriptor* field,
354                                               double fraction, double margin) {
355   default_field_comparator_.SetFractionAndMargin(field, fraction, margin);
356 }
357 
ReportDifferencesToString(string * output)358 void MessageDifferencer::ReportDifferencesToString(string* output) {
359   GOOGLE_DCHECK(output) << "Specified output string was NULL";
360 
361   output_string_ = output;
362   output_string_->clear();
363 }
364 
ReportDifferencesTo(Reporter * reporter)365 void MessageDifferencer::ReportDifferencesTo(Reporter* reporter) {
366   // If an output string is set, clear it to prevent
367   // it superceding the specified reporter.
368   if (output_string_) {
369     output_string_ = NULL;
370   }
371 
372   reporter_ = reporter;
373 }
374 
FieldBefore(const FieldDescriptor * field1,const FieldDescriptor * field2)375 bool MessageDifferencer::FieldBefore(const FieldDescriptor* field1,
376                                      const FieldDescriptor* field2) {
377   // Handle sentinel values (i.e. make sure NULLs are always ordered
378   // at the end of the list).
379   if (field1 == NULL) {
380     return false;
381   }
382 
383   if (field2 == NULL) {
384     return true;
385   }
386 
387   // Always order fields by their tag number
388   return (field1->number() < field2->number());
389 }
390 
Compare(const Message & message1,const Message & message2)391 bool MessageDifferencer::Compare(const Message& message1,
392                                  const Message& message2) {
393   vector<SpecificField> parent_fields;
394 
395   bool result = false;
396 
397   // Setup the internal reporter if need be.
398   if (output_string_) {
399     io::StringOutputStream output_stream(output_string_);
400     StreamReporter reporter(&output_stream);
401     reporter_ = &reporter;
402     result = Compare(message1, message2, &parent_fields);
403     reporter_ = NULL;
404   } else {
405     result = Compare(message1, message2, &parent_fields);
406   }
407 
408   return result;
409 }
410 
CompareWithFields(const Message & message1,const Message & message2,const vector<const FieldDescriptor * > & message1_fields_arg,const vector<const FieldDescriptor * > & message2_fields_arg)411 bool MessageDifferencer::CompareWithFields(
412     const Message& message1,
413     const Message& message2,
414     const vector<const FieldDescriptor*>& message1_fields_arg,
415     const vector<const FieldDescriptor*>& message2_fields_arg) {
416   if (message1.GetDescriptor() != message2.GetDescriptor()) {
417     GOOGLE_LOG(DFATAL) << "Comparison between two messages with different "
418                 << "descriptors.";
419     return false;
420   }
421 
422   vector<SpecificField> parent_fields;
423 
424   bool result = false;
425 
426   vector<const FieldDescriptor*> message1_fields(message1_fields_arg);
427   vector<const FieldDescriptor*> message2_fields(message2_fields_arg);
428 
429   std::sort(message1_fields.begin(), message1_fields.end(), FieldBefore);
430   std::sort(message2_fields.begin(), message2_fields.end(), FieldBefore);
431   // Append NULL sentinel values.
432   message1_fields.push_back(NULL);
433   message2_fields.push_back(NULL);
434 
435   // Setup the internal reporter if need be.
436   if (output_string_) {
437     io::StringOutputStream output_stream(output_string_);
438     StreamReporter reporter(&output_stream);
439     reporter_ = &reporter;
440     result = CompareRequestedFieldsUsingSettings(
441         message1, message2, message1_fields, message2_fields, &parent_fields);
442     reporter_ = NULL;
443   } else {
444     result = CompareRequestedFieldsUsingSettings(
445         message1, message2, message1_fields, message2_fields, &parent_fields);
446   }
447 
448   return result;
449 }
450 
Compare(const Message & message1,const Message & message2,vector<SpecificField> * parent_fields)451 bool MessageDifferencer::Compare(
452     const Message& message1,
453     const Message& message2,
454     vector<SpecificField>* parent_fields) {
455   const Descriptor* descriptor1 = message1.GetDescriptor();
456   const Descriptor* descriptor2 = message2.GetDescriptor();
457   if (descriptor1 != descriptor2) {
458     GOOGLE_LOG(DFATAL) << "Comparison between two messages with different "
459                 << "descriptors. "
460                 << descriptor1->full_name() << " vs "
461                 << descriptor2->full_name();
462     return false;
463   }
464   // Expand google.protobuf.Any payload if possible.
465   if (descriptor1->full_name() == internal::kAnyFullTypeName) {
466     google::protobuf::scoped_ptr<Message> data1;
467     google::protobuf::scoped_ptr<Message> data2;
468     if (UnpackAny(message1, &data1) && UnpackAny(message2, &data2)) {
469       return Compare(*data1, *data2, parent_fields);
470     }
471   }
472   const Reflection* reflection1 = message1.GetReflection();
473   const Reflection* reflection2 = message2.GetReflection();
474 
475   // Retrieve all the set fields, including extensions.
476   vector<const FieldDescriptor*> message1_fields;
477   message1_fields.reserve(1 + message1.GetDescriptor()->field_count());
478 
479   vector<const FieldDescriptor*> message2_fields;
480   message2_fields.reserve(1 + message2.GetDescriptor()->field_count());
481 
482   reflection1->ListFields(message1, &message1_fields);
483   reflection2->ListFields(message2, &message2_fields);
484 
485   // Add sentinel values to deal with the
486   // case where the number of the fields in
487   // each list are different.
488   message1_fields.push_back(NULL);
489   message2_fields.push_back(NULL);
490 
491   bool unknown_compare_result = true;
492   // Ignore unknown fields in EQUIVALENT mode
493   if (message_field_comparison_ != EQUIVALENT) {
494     const google::protobuf::UnknownFieldSet* unknown_field_set1 =
495         &reflection1->GetUnknownFields(message1);
496     const google::protobuf::UnknownFieldSet* unknown_field_set2 =
497         &reflection2->GetUnknownFields(message2);
498     if (!CompareUnknownFields(message1, message2,
499                               *unknown_field_set1, *unknown_field_set2,
500                               parent_fields)) {
501       if (reporter_ == NULL) {
502         return false;
503       };
504       unknown_compare_result = false;
505     }
506   }
507 
508   return CompareRequestedFieldsUsingSettings(
509       message1, message2,
510       message1_fields, message2_fields,
511       parent_fields) && unknown_compare_result;
512 }
513 
CompareRequestedFieldsUsingSettings(const Message & message1,const Message & message2,const vector<const FieldDescriptor * > & message1_fields,const vector<const FieldDescriptor * > & message2_fields,vector<SpecificField> * parent_fields)514 bool MessageDifferencer::CompareRequestedFieldsUsingSettings(
515     const Message& message1,
516     const Message& message2,
517     const vector<const FieldDescriptor*>& message1_fields,
518     const vector<const FieldDescriptor*>& message2_fields,
519     vector<SpecificField>* parent_fields) {
520   if (scope_ == FULL) {
521     if (message_field_comparison_ == EQUIVALENT) {
522       // We need to merge the field lists of both messages (i.e.
523       // we are merely checking for a difference in field values,
524       // rather than the addition or deletion of fields).
525       vector<const FieldDescriptor*> fields_union;
526       CombineFields(message1_fields, FULL, message2_fields, FULL,
527                     &fields_union);
528       return CompareWithFieldsInternal(message1, message2, fields_union,
529                                        fields_union, parent_fields);
530     } else {
531       // Simple equality comparison, use the unaltered field lists.
532       return CompareWithFieldsInternal(message1, message2, message1_fields,
533                                        message2_fields, parent_fields);
534     }
535   } else {
536     if (message_field_comparison_ == EQUIVALENT) {
537       // We use the list of fields for message1 for both messages when
538       // comparing.  This way, extra fields in message2 are ignored,
539       // and missing fields in message2 use their default value.
540       return CompareWithFieldsInternal(message1, message2, message1_fields,
541                                        message1_fields, parent_fields);
542     } else {
543       // We need to consider the full list of fields for message1
544       // but only the intersection for message2.  This way, any fields
545       // only present in message2 will be ignored, but any fields only
546       // present in message1 will be marked as a difference.
547       vector<const FieldDescriptor*> fields_intersection;
548       CombineFields(message1_fields, PARTIAL, message2_fields, PARTIAL,
549                     &fields_intersection);
550       return CompareWithFieldsInternal(message1, message2, message1_fields,
551                                        fields_intersection, parent_fields);
552     }
553   }
554 }
555 
CombineFields(const vector<const FieldDescriptor * > & fields1,Scope fields1_scope,const vector<const FieldDescriptor * > & fields2,Scope fields2_scope,vector<const FieldDescriptor * > * combined_fields)556 void MessageDifferencer::CombineFields(
557     const vector<const FieldDescriptor*>& fields1,
558     Scope fields1_scope,
559     const vector<const FieldDescriptor*>& fields2,
560     Scope fields2_scope,
561     vector<const FieldDescriptor*>* combined_fields) {
562 
563   int index1 = 0;
564   int index2 = 0;
565 
566   while (index1 < fields1.size() && index2 < fields2.size()) {
567     const FieldDescriptor* field1 = fields1[index1];
568     const FieldDescriptor* field2 = fields2[index2];
569 
570     if (FieldBefore(field1, field2)) {
571       if (fields1_scope == FULL) {
572         combined_fields->push_back(fields1[index1]);
573       }
574       ++index1;
575     } else if (FieldBefore(field2, field1)) {
576       if (fields2_scope == FULL) {
577         combined_fields->push_back(fields2[index2]);
578       }
579       ++index2;
580     } else {
581       combined_fields->push_back(fields1[index1]);
582       ++index1;
583       ++index2;
584     }
585   }
586 }
587 
CompareWithFieldsInternal(const Message & message1,const Message & message2,const vector<const FieldDescriptor * > & message1_fields,const vector<const FieldDescriptor * > & message2_fields,vector<SpecificField> * parent_fields)588 bool MessageDifferencer::CompareWithFieldsInternal(
589     const Message& message1,
590     const Message& message2,
591     const vector<const FieldDescriptor*>& message1_fields,
592     const vector<const FieldDescriptor*>& message2_fields,
593     vector<SpecificField>* parent_fields) {
594   bool isDifferent = false;
595   int field_index1 = 0;
596   int field_index2 = 0;
597 
598   const Reflection* reflection1 = message1.GetReflection();
599   const Reflection* reflection2 = message2.GetReflection();
600 
601   while (true) {
602     const FieldDescriptor* field1 = message1_fields[field_index1];
603     const FieldDescriptor* field2 = message2_fields[field_index2];
604 
605     // Once we have reached sentinel values, we are done the comparison.
606     if (field1 == NULL && field2 == NULL) {
607       break;
608     }
609 
610     // Check for differences in the field itself.
611     if (FieldBefore(field1, field2)) {
612       // Field 1 is not in the field list for message 2.
613       if (IsIgnored(message1, message2, field1, *parent_fields)) {
614         // We are ignoring field1. Report the ignore and move on to
615         // the next field in message1_fields.
616         if (reporter_ != NULL) {
617           SpecificField specific_field;
618           specific_field.field = field1;
619 
620           parent_fields->push_back(specific_field);
621           reporter_->ReportIgnored(message1, message2, *parent_fields);
622           parent_fields->pop_back();
623         }
624         ++field_index1;
625         continue;
626       }
627 
628       if (reporter_ != NULL) {
629         int count = field1->is_repeated() ?
630             reflection1->FieldSize(message1, field1) : 1;
631 
632         for (int i = 0; i < count; ++i) {
633           SpecificField specific_field;
634           specific_field.field = field1;
635           specific_field.index = field1->is_repeated() ? i : -1;
636 
637           parent_fields->push_back(specific_field);
638           reporter_->ReportDeleted(message1, message2, *parent_fields);
639           parent_fields->pop_back();
640         }
641 
642         isDifferent = true;
643       } else {
644         return false;
645       }
646 
647       ++field_index1;
648       continue;
649     } else if (FieldBefore(field2, field1)) {
650       // Field 2 is not in the field list for message 1.
651       if (IsIgnored(message1, message2, field2, *parent_fields)) {
652         // We are ignoring field2. Report the ignore and move on to
653         // the next field in message2_fields.
654         if (reporter_ != NULL) {
655           SpecificField specific_field;
656           specific_field.field = field2;
657 
658           parent_fields->push_back(specific_field);
659           reporter_->ReportIgnored(message1, message2, *parent_fields);
660           parent_fields->pop_back();
661         }
662         ++field_index2;
663         continue;
664       }
665 
666       if (reporter_ != NULL) {
667         int count = field2->is_repeated() ?
668             reflection2->FieldSize(message2, field2) : 1;
669 
670         for (int i = 0; i < count; ++i) {
671           SpecificField specific_field;
672           specific_field.field = field2;
673           specific_field.index = field2->is_repeated() ? i : -1;
674           specific_field.new_index = specific_field.index;
675 
676           parent_fields->push_back(specific_field);
677           reporter_->ReportAdded(message1, message2, *parent_fields);
678           parent_fields->pop_back();
679         }
680 
681         isDifferent = true;
682       } else {
683         return false;
684       }
685 
686       ++field_index2;
687       continue;
688     }
689 
690     // By this point, field1 and field2 are guarenteed to point to the same
691     // field, so we can now compare the values.
692     if (IsIgnored(message1, message2, field1, *parent_fields)) {
693       // Ignore this field. Report and move on.
694       if (reporter_ != NULL) {
695         SpecificField specific_field;
696         specific_field.field = field1;
697 
698         parent_fields->push_back(specific_field);
699         reporter_->ReportIgnored(message1, message2, *parent_fields);
700         parent_fields->pop_back();
701       }
702 
703       ++field_index1;
704       ++field_index2;
705       continue;
706     }
707 
708     bool fieldDifferent = false;
709     if (field1->is_repeated()) {
710       fieldDifferent = !CompareRepeatedField(message1, message2, field1,
711                                              parent_fields);
712       if (fieldDifferent) {
713         if (reporter_ == NULL) return false;
714         isDifferent = true;
715       }
716     } else {
717       fieldDifferent = !CompareFieldValueUsingParentFields(
718           message1, message2, field1, -1, -1, parent_fields);
719 
720       // If we have found differences, either report them or terminate if
721       // no reporter is present.
722       if (fieldDifferent && reporter_ == NULL) {
723         return false;
724       }
725 
726       if (reporter_ != NULL) {
727         SpecificField specific_field;
728         specific_field.field = field1;
729         parent_fields->push_back(specific_field);
730         if (fieldDifferent) {
731           reporter_->ReportModified(message1, message2, *parent_fields);
732           isDifferent = true;
733         } else if (report_matches_) {
734           reporter_->ReportMatched(message1, message2, *parent_fields);
735         }
736         parent_fields->pop_back();
737       }
738     }
739     // Increment the field indicies.
740     ++field_index1;
741     ++field_index2;
742   }
743 
744   return !isDifferent;
745 }
746 
IsMatch(const FieldDescriptor * repeated_field,const MapKeyComparator * key_comparator,const Message * message1,const Message * message2,const vector<SpecificField> & parent_fields,int index1,int index2)747 bool MessageDifferencer::IsMatch(const FieldDescriptor* repeated_field,
748                                  const MapKeyComparator* key_comparator,
749                                  const Message* message1,
750                                  const Message* message2,
751                                  const vector<SpecificField>& parent_fields,
752                                  int index1, int index2) {
753   vector<SpecificField> current_parent_fields(parent_fields);
754   if (repeated_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
755     return CompareFieldValueUsingParentFields(
756         *message1, *message2, repeated_field, index1, index2,
757         &current_parent_fields);
758   }
759   // Back up the Reporter and output_string_.  They will be reset in the
760   // following code.
761   Reporter* backup_reporter = reporter_;
762   string* output_string = output_string_;
763   reporter_ = NULL;
764   output_string_ = NULL;
765   bool match;
766 
767   if (key_comparator == NULL) {
768     match = CompareFieldValueUsingParentFields(
769         *message1, *message2, repeated_field, index1, index2,
770         &current_parent_fields);
771   } else {
772     const Reflection* reflection1 = message1->GetReflection();
773     const Reflection* reflection2 = message2->GetReflection();
774     const Message& m1 =
775         reflection1->GetRepeatedMessage(*message1, repeated_field, index1);
776     const Message& m2 =
777         reflection2->GetRepeatedMessage(*message2, repeated_field, index2);
778     SpecificField specific_field;
779     specific_field.field = repeated_field;
780     current_parent_fields.push_back(specific_field);
781     match = key_comparator->IsMatch(m1, m2, current_parent_fields);
782   }
783 
784   reporter_ = backup_reporter;
785   output_string_ = output_string;
786   return match;
787 }
788 
CompareRepeatedField(const Message & message1,const Message & message2,const FieldDescriptor * repeated_field,vector<SpecificField> * parent_fields)789 bool MessageDifferencer::CompareRepeatedField(
790     const Message& message1,
791     const Message& message2,
792     const FieldDescriptor* repeated_field,
793     vector<SpecificField>* parent_fields) {
794   // the input FieldDescriptor is guaranteed to be repeated field.
795   const Reflection* reflection1 = message1.GetReflection();
796   const Reflection* reflection2 = message2.GetReflection();
797   const int count1 = reflection1->FieldSize(message1, repeated_field);
798   const int count2 = reflection2->FieldSize(message2, repeated_field);
799   const bool treated_as_subset = IsTreatedAsSubset(repeated_field);
800 
801   // If the field is not treated as subset and no detailed reports is needed,
802   // we do a quick check on the number of the elements to avoid unnecessary
803   // comparison.
804   if (count1 != count2 && reporter_ == NULL && !treated_as_subset) {
805     return false;
806   }
807   // A match can never be found if message1 has more items than message2.
808   if (count1 > count2 && reporter_ == NULL) {
809     return false;
810   }
811 
812   // These two list are used for store the index of the correspondent
813   // element in peer repeated field.
814   vector<int> match_list1;
815   vector<int> match_list2;
816 
817   // Try to match indices of the repeated fields. Return false if match fails
818   // and there's no detailed report needed.
819   if (!MatchRepeatedFieldIndices(message1, message2, repeated_field,
820                                  *parent_fields, &match_list1, &match_list2) &&
821       reporter_ == NULL) {
822     return false;
823   }
824 
825   bool fieldDifferent = false;
826   SpecificField specific_field;
827   specific_field.field = repeated_field;
828 
829   // At this point, we have already matched pairs of fields (with the reporting
830   // to be done later). Now to check if the paired elements are different.
831   for (int i = 0; i < count1; i++) {
832     if (match_list1[i] == -1) continue;
833     specific_field.index = i;
834     specific_field.new_index = match_list1[i];
835 
836     const bool result = CompareFieldValueUsingParentFields(
837         message1, message2, repeated_field, i, specific_field.new_index,
838         parent_fields);
839 
840     // If we have found differences, either report them or terminate if
841     // no reporter is present. Note that ReportModified, ReportMoved, and
842     // ReportMatched are all mutually exclusive.
843     if (!result) {
844       if (reporter_ == NULL) return false;
845       parent_fields->push_back(specific_field);
846       reporter_->ReportModified(message1, message2, *parent_fields);
847       parent_fields->pop_back();
848       fieldDifferent = true;
849     } else if (reporter_ != NULL &&
850                specific_field.index != specific_field.new_index) {
851       parent_fields->push_back(specific_field);
852       reporter_->ReportMoved(message1, message2, *parent_fields);
853       parent_fields->pop_back();
854     } else if (report_matches_ && reporter_ != NULL) {
855       parent_fields->push_back(specific_field);
856       reporter_->ReportMatched(message1, message2, *parent_fields);
857       parent_fields->pop_back();
858     }
859   }
860 
861   // Report any remaining additions or deletions.
862   for (int i = 0; i < count2; ++i) {
863     if (match_list2[i] != -1) continue;
864     if (!treated_as_subset) {
865       fieldDifferent = true;
866     }
867 
868     if (reporter_ == NULL) continue;
869     specific_field.index = i;
870     specific_field.new_index = i;
871     parent_fields->push_back(specific_field);
872     reporter_->ReportAdded(message1, message2, *parent_fields);
873     parent_fields->pop_back();
874   }
875 
876   for (int i = 0; i < count1; ++i) {
877     if (match_list1[i] != -1) continue;
878     specific_field.index = i;
879     parent_fields->push_back(specific_field);
880     reporter_->ReportDeleted(message1, message2, *parent_fields);
881     parent_fields->pop_back();
882     fieldDifferent = true;
883   }
884   return !fieldDifferent;
885 }
886 
CompareFieldValue(const Message & message1,const Message & message2,const FieldDescriptor * field,int index1,int index2)887 bool MessageDifferencer::CompareFieldValue(const Message& message1,
888                                            const Message& message2,
889                                            const FieldDescriptor* field,
890                                            int index1,
891                                            int index2) {
892   return CompareFieldValueUsingParentFields(message1, message2, field, index1,
893                                             index2, NULL);
894 }
895 
CompareFieldValueUsingParentFields(const Message & message1,const Message & message2,const FieldDescriptor * field,int index1,int index2,vector<SpecificField> * parent_fields)896 bool MessageDifferencer::CompareFieldValueUsingParentFields(
897     const Message& message1, const Message& message2,
898     const FieldDescriptor* field, int index1, int index2,
899     vector<SpecificField>* parent_fields) {
900   FieldContext field_context(parent_fields);
901   FieldComparator::ComparisonResult result = GetFieldComparisonResult(
902       message1, message2, field, index1, index2, &field_context);
903 
904   if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
905       result == FieldComparator::RECURSE) {
906     // Get the nested messages and compare them using one of the Compare
907     // methods.
908     const Reflection* reflection1 = message1.GetReflection();
909     const Reflection* reflection2 = message2.GetReflection();
910     const Message& m1 = field->is_repeated() ?
911         reflection1->GetRepeatedMessage(message1, field, index1) :
912         reflection1->GetMessage(message1, field);
913     const Message& m2 = field->is_repeated() ?
914         reflection2->GetRepeatedMessage(message2, field, index2) :
915         reflection2->GetMessage(message2, field);
916 
917     // parent_fields is used in calls to Reporter methods.
918     if (parent_fields != NULL) {
919       // Append currently compared field to the end of parent_fields.
920       SpecificField specific_field;
921       specific_field.field = field;
922       specific_field.index = index1;
923       specific_field.new_index = index2;
924       parent_fields->push_back(specific_field);
925       const bool compare_result = Compare(m1, m2, parent_fields);
926       parent_fields->pop_back();
927       return compare_result;
928     } else {
929       // Recreates parent_fields as if m1 and m2 had no parents.
930       return Compare(m1, m2);
931     }
932   } else {
933     return (result == FieldComparator::SAME);
934   }
935 }
936 
CheckPathChanged(const vector<SpecificField> & field_path)937 bool MessageDifferencer::CheckPathChanged(
938     const vector<SpecificField>& field_path) {
939   for (int i = 0; i < field_path.size(); ++i) {
940     if (field_path[i].index != field_path[i].new_index) return true;
941   }
942   return false;
943 }
944 
IsTreatedAsSet(const FieldDescriptor * field)945 bool MessageDifferencer::IsTreatedAsSet(const FieldDescriptor* field) {
946   if (!field->is_repeated()) return false;
947   if (field->is_map()) return true;
948   if (repeated_field_comparison_ == AS_SET)
949     return list_fields_.find(field) == list_fields_.end();
950   return (set_fields_.find(field) != set_fields_.end());
951 }
952 
IsTreatedAsSubset(const FieldDescriptor * field)953 bool MessageDifferencer::IsTreatedAsSubset(const FieldDescriptor* field) {
954   return scope_ == PARTIAL &&
955       (IsTreatedAsSet(field) || GetMapKeyComparator(field) != NULL);
956 }
957 
IsIgnored(const Message & message1,const Message & message2,const FieldDescriptor * field,const vector<SpecificField> & parent_fields)958 bool MessageDifferencer::IsIgnored(
959     const Message& message1,
960     const Message& message2,
961     const FieldDescriptor* field,
962     const vector<SpecificField>& parent_fields) {
963   if (ignored_fields_.find(field) != ignored_fields_.end()) {
964     return true;
965   }
966   for (int i = 0; i < ignore_criteria_.size(); ++i) {
967     if (ignore_criteria_[i]->IsIgnored(message1, message2, field,
968                                        parent_fields)) {
969       return true;
970     }
971   }
972   return false;
973 }
974 
IsUnknownFieldIgnored(const Message & message1,const Message & message2,const SpecificField & field,const vector<SpecificField> & parent_fields)975 bool MessageDifferencer::IsUnknownFieldIgnored(
976     const Message& message1, const Message& message2,
977     const SpecificField& field, const vector<SpecificField>& parent_fields) {
978   for (int i = 0; i < ignore_criteria_.size(); ++i) {
979     if (ignore_criteria_[i]->IsUnknownFieldIgnored(message1, message2, field,
980                                                    parent_fields)) {
981       return true;
982     }
983   }
984   return false;
985 }
986 
987 const MessageDifferencer::MapKeyComparator* MessageDifferencer
GetMapKeyComparator(const FieldDescriptor * field)988     ::GetMapKeyComparator(const FieldDescriptor* field) {
989   if (!field->is_repeated()) return NULL;
990   if (map_field_key_comparator_.find(field) !=
991       map_field_key_comparator_.end()) {
992     return map_field_key_comparator_[field];
993   }
994   return NULL;
995 }
996 
997 namespace {
998 
999 typedef pair<int, const UnknownField*> IndexUnknownFieldPair;
1000 
1001 struct UnknownFieldOrdering {
operator ()google::protobuf::util::__anonc30b99df0111::UnknownFieldOrdering1002   inline bool operator()(const IndexUnknownFieldPair& a,
1003                          const IndexUnknownFieldPair& b) const {
1004     if (a.second->number() < b.second->number()) return true;
1005     if (a.second->number() > b.second->number()) return false;
1006     return a.second->type() < b.second->type();
1007   }
1008 };
1009 
1010 }  // namespace
1011 
UnpackAny(const Message & any,google::protobuf::scoped_ptr<Message> * data)1012 bool MessageDifferencer::UnpackAny(const Message& any,
1013                                    google::protobuf::scoped_ptr<Message>* data) {
1014   const Reflection* reflection = any.GetReflection();
1015   const FieldDescriptor* type_url_field;
1016   const FieldDescriptor* value_field;
1017   if (!internal::GetAnyFieldDescriptors(any, &type_url_field, &value_field)) {
1018     return false;
1019   }
1020   const string& type_url = reflection->GetString(any, type_url_field);
1021   string full_type_name;
1022   if (!internal::ParseAnyTypeUrl(type_url, &full_type_name)) {
1023     return false;
1024   }
1025 
1026   const google::protobuf::Descriptor* desc =
1027       any.GetDescriptor()->file()->pool()->FindMessageTypeByName(
1028           full_type_name);
1029   if (desc == NULL) {
1030     GOOGLE_DLOG(ERROR) << "Proto type '" << full_type_name << "' not found";
1031     return false;
1032   }
1033 
1034   if (dynamic_message_factory_ == NULL) {
1035     dynamic_message_factory_.reset(new DynamicMessageFactory());
1036   }
1037   data->reset(dynamic_message_factory_->GetPrototype(desc)->New());
1038   string serialized_value = reflection->GetString(any, value_field);
1039   if (!(*data)->ParseFromString(serialized_value)) {
1040     GOOGLE_DLOG(ERROR) << "Failed to parse value for " << full_type_name;
1041     return false;
1042   }
1043   return true;
1044 }
1045 
CompareUnknownFields(const Message & message1,const Message & message2,const google::protobuf::UnknownFieldSet & unknown_field_set1,const google::protobuf::UnknownFieldSet & unknown_field_set2,vector<SpecificField> * parent_field)1046 bool MessageDifferencer::CompareUnknownFields(
1047     const Message& message1, const Message& message2,
1048     const google::protobuf::UnknownFieldSet& unknown_field_set1,
1049     const google::protobuf::UnknownFieldSet& unknown_field_set2,
1050     vector<SpecificField>* parent_field) {
1051   // Ignore unknown fields in EQUIVALENT mode.
1052   if (message_field_comparison_ == EQUIVALENT) return true;
1053 
1054   if (unknown_field_set1.empty() && unknown_field_set2.empty()) {
1055     return true;
1056   }
1057 
1058   bool is_different = false;
1059 
1060   // We first sort the unknown fields by field number and type (in other words,
1061   // in tag order), making sure to preserve ordering of values with the same
1062   // tag.  This allows us to report only meaningful differences between the
1063   // two sets -- that is, differing values for the same tag.  We use
1064   // IndexUnknownFieldPairs to keep track of the field's original index for
1065   // reporting purposes.
1066   vector<IndexUnknownFieldPair> fields1;  // unknown_field_set1, sorted
1067   vector<IndexUnknownFieldPair> fields2;  // unknown_field_set2, sorted
1068   fields1.reserve(unknown_field_set1.field_count());
1069   fields2.reserve(unknown_field_set2.field_count());
1070 
1071   for (int i = 0; i < unknown_field_set1.field_count(); i++) {
1072     fields1.push_back(std::make_pair(i, &unknown_field_set1.field(i)));
1073   }
1074   for (int i = 0; i < unknown_field_set2.field_count(); i++) {
1075     fields2.push_back(std::make_pair(i, &unknown_field_set2.field(i)));
1076   }
1077 
1078   UnknownFieldOrdering is_before;
1079   std::stable_sort(fields1.begin(), fields1.end(), is_before);
1080   std::stable_sort(fields2.begin(), fields2.end(), is_before);
1081 
1082   // In order to fill in SpecificField::index, we have to keep track of how
1083   // many values we've seen with the same field number and type.
1084   // current_repeated points at the first field in this range, and
1085   // current_repeated_start{1,2} are the indexes of the first field in the
1086   // range within fields1 and fields2.
1087   const UnknownField* current_repeated = NULL;
1088   int current_repeated_start1 = 0;
1089   int current_repeated_start2 = 0;
1090 
1091   // Now that we have two sorted lists, we can detect fields which appear only
1092   // in one list or the other by traversing them simultaneously.
1093   int index1 = 0;
1094   int index2 = 0;
1095   while (index1 < fields1.size() || index2 < fields2.size()) {
1096     enum { ADDITION, DELETION, MODIFICATION, COMPARE_GROUPS,
1097       NO_CHANGE } change_type;
1098 
1099     // focus_field is the field we're currently reporting on.  (In the case
1100     // of a modification, it's the field on the left side.)
1101     const UnknownField* focus_field;
1102     bool match = false;
1103 
1104     if (index2 == fields2.size() ||
1105         (index1 < fields1.size() &&
1106           is_before(fields1[index1], fields2[index2]))) {
1107       // fields1[index1] is not present in fields2.
1108       change_type = DELETION;
1109       focus_field = fields1[index1].second;
1110     } else if (index1 == fields1.size() ||
1111                is_before(fields2[index2], fields1[index1])) {
1112       // fields2[index2] is not present in fields1.
1113       if (scope_ == PARTIAL) {
1114         // Ignore.
1115         ++index2;
1116         continue;
1117       }
1118       change_type = ADDITION;
1119       focus_field = fields2[index2].second;
1120     } else {
1121       // Field type and number are the same.  See if the values differ.
1122       change_type = MODIFICATION;
1123       focus_field = fields1[index1].second;
1124 
1125       switch (focus_field->type()) {
1126         case UnknownField::TYPE_VARINT:
1127           match = fields1[index1].second->varint() ==
1128                   fields2[index2].second->varint();
1129           break;
1130         case UnknownField::TYPE_FIXED32:
1131           match = fields1[index1].second->fixed32() ==
1132                   fields2[index2].second->fixed32();
1133           break;
1134         case UnknownField::TYPE_FIXED64:
1135           match = fields1[index1].second->fixed64() ==
1136                   fields2[index2].second->fixed64();
1137           break;
1138         case UnknownField::TYPE_LENGTH_DELIMITED:
1139           match = fields1[index1].second->length_delimited() ==
1140                   fields2[index2].second->length_delimited();
1141           break;
1142         case UnknownField::TYPE_GROUP:
1143           // We must deal with this later, after building the SpecificField.
1144           change_type = COMPARE_GROUPS;
1145           break;
1146       }
1147       if (match && change_type != COMPARE_GROUPS) {
1148         change_type = NO_CHANGE;
1149       }
1150     }
1151 
1152     if (current_repeated == NULL ||
1153         focus_field->number() != current_repeated->number() ||
1154         focus_field->type() != current_repeated->type()) {
1155       // We've started a new repeated field.
1156       current_repeated = focus_field;
1157       current_repeated_start1 = index1;
1158       current_repeated_start2 = index2;
1159     }
1160 
1161     if (change_type == NO_CHANGE && reporter_ == NULL) {
1162       // Fields were already compared and matched and we have no reporter.
1163       ++index1;
1164       ++index2;
1165       continue;
1166     }
1167 
1168     // Build the SpecificField.  This is slightly complicated.
1169     SpecificField specific_field;
1170     specific_field.unknown_field_number = focus_field->number();
1171     specific_field.unknown_field_type = focus_field->type();
1172 
1173     specific_field.unknown_field_set1 = &unknown_field_set1;
1174     specific_field.unknown_field_set2 = &unknown_field_set2;
1175 
1176     if (change_type != ADDITION) {
1177       specific_field.unknown_field_index1 = fields1[index1].first;
1178     }
1179     if (change_type != DELETION) {
1180       specific_field.unknown_field_index2 = fields2[index2].first;
1181     }
1182 
1183     // Calculate the field index.
1184     if (change_type == ADDITION) {
1185       specific_field.index = index2 - current_repeated_start2;
1186       specific_field.new_index = index2 - current_repeated_start2;
1187     } else {
1188       specific_field.index = index1 - current_repeated_start1;
1189       specific_field.new_index = index2 - current_repeated_start2;
1190     }
1191 
1192     if (IsUnknownFieldIgnored(message1, message2, specific_field,
1193                               *parent_field)) {
1194       if (reporter_ != NULL) {
1195         parent_field->push_back(specific_field);
1196         reporter_->ReportUnknownFieldIgnored(message1, message2, *parent_field);
1197         parent_field->pop_back();
1198       }
1199       return true;
1200     }
1201 
1202     if (change_type == ADDITION || change_type == DELETION ||
1203         change_type == MODIFICATION) {
1204       if (reporter_ == NULL) {
1205         // We found a difference and we have no reproter.
1206         return false;
1207       }
1208       is_different = true;
1209     }
1210 
1211     parent_field->push_back(specific_field);
1212 
1213     switch (change_type) {
1214       case ADDITION:
1215         reporter_->ReportAdded(message1, message2, *parent_field);
1216         ++index2;
1217         break;
1218       case DELETION:
1219         reporter_->ReportDeleted(message1, message2, *parent_field);
1220         ++index1;
1221         break;
1222       case MODIFICATION:
1223         reporter_->ReportModified(message1, message2, *parent_field);
1224         ++index1;
1225         ++index2;
1226         break;
1227       case COMPARE_GROUPS:
1228         if (!CompareUnknownFields(message1, message2,
1229                                   fields1[index1].second->group(),
1230                                   fields2[index2].second->group(),
1231                                   parent_field)) {
1232           if (reporter_ == NULL) return false;
1233           is_different = true;
1234           reporter_->ReportModified(message1, message2, *parent_field);
1235         }
1236         ++index1;
1237         ++index2;
1238         break;
1239       case NO_CHANGE:
1240         ++index1;
1241         ++index2;
1242         if (report_matches_) {
1243           reporter_->ReportMatched(message1, message2, *parent_field);
1244         }
1245     }
1246 
1247     parent_field->pop_back();
1248   }
1249 
1250   return !is_different;
1251 }
1252 
1253 namespace {
1254 
1255 // Find maximum bipartite matching using the argumenting path algorithm.
1256 class MaximumMatcher {
1257  public:
1258   typedef ResultCallback2<bool, int, int> NodeMatchCallback;
1259   // MaximumMatcher takes ownership of the passed in callback and uses it to
1260   // determine whether a node on the left side of the bipartial graph matches
1261   // a node on the right side. count1 is the number of nodes on the left side
1262   // of the graph and count2 to is the number of nodes on the right side.
1263   // Every node is referred to using 0-based indices.
1264   // If a maximum match is found, the result will be stored in match_list1 and
1265   // match_list2. match_list1[i] == j means the i-th node on the left side is
1266   // matched to the j-th node on the right side and match_list2[x] == y means
1267   // the x-th node on the right side is matched to y-th node on the left side.
1268   // match_list1[i] == -1 means the node is not matched. Same with match_list2.
1269   MaximumMatcher(int count1, int count2, NodeMatchCallback* callback,
1270                  vector<int>* match_list1, vector<int>* match_list2);
1271   // Find a maximum match and return the number of matched node pairs.
1272   // If early_return is true, this method will return 0 immediately when it
1273   // finds that not all nodes on the left side can be matched.
1274   int FindMaximumMatch(bool early_return);
1275  private:
1276   // Determines whether the node on the left side of the bipartial graph
1277   // matches the one on the right side.
1278   bool Match(int left, int right);
1279   // Find an argumenting path starting from the node v on the left side. If a
1280   // path can be found, update match_list2_ to reflect the path and return
1281   // true.
1282   bool FindArgumentPathDFS(int v, vector<bool>* visited);
1283 
1284   int count1_;
1285   int count2_;
1286   google::protobuf::scoped_ptr<NodeMatchCallback> match_callback_;
1287   map<pair<int, int>, bool> cached_match_results_;
1288   vector<int>* match_list1_;
1289   vector<int>* match_list2_;
1290   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MaximumMatcher);
1291 };
1292 
MaximumMatcher(int count1,int count2,NodeMatchCallback * callback,vector<int> * match_list1,vector<int> * match_list2)1293 MaximumMatcher::MaximumMatcher(int count1, int count2,
1294                                NodeMatchCallback* callback,
1295                                vector<int>* match_list1,
1296                                vector<int>* match_list2)
1297     : count1_(count1), count2_(count2), match_callback_(callback),
1298       match_list1_(match_list1), match_list2_(match_list2) {
1299   match_list1_->assign(count1, -1);
1300   match_list2_->assign(count2, -1);
1301 }
1302 
FindMaximumMatch(bool early_return)1303 int MaximumMatcher::FindMaximumMatch(bool early_return) {
1304   int result = 0;
1305   for (int i = 0; i < count1_; ++i) {
1306     vector<bool> visited(count1_);
1307     if (FindArgumentPathDFS(i, &visited)) {
1308       ++result;
1309     } else if (early_return) {
1310       return 0;
1311     }
1312   }
1313   // Backfill match_list1_ as we only filled match_list2_ when finding
1314   // argumenting pathes.
1315   for (int i = 0; i < count2_; ++i) {
1316     if ((*match_list2_)[i] != -1) {
1317       (*match_list1_)[(*match_list2_)[i]] = i;
1318     }
1319   }
1320   return result;
1321 }
1322 
Match(int left,int right)1323 bool MaximumMatcher::Match(int left, int right) {
1324   pair<int, int> p(left, right);
1325   map<pair<int, int>, bool>::iterator it = cached_match_results_.find(p);
1326   if (it != cached_match_results_.end()) {
1327     return it->second;
1328   }
1329   cached_match_results_[p] = match_callback_->Run(left, right);
1330   return cached_match_results_[p];
1331 }
1332 
FindArgumentPathDFS(int v,vector<bool> * visited)1333 bool MaximumMatcher::FindArgumentPathDFS(int v, vector<bool>* visited) {
1334   (*visited)[v] = true;
1335   // We try to match those un-matched nodes on the right side first. This is
1336   // the step that the navie greedy matching algorithm uses. In the best cases
1337   // where the greedy algorithm can find a maximum matching, we will always
1338   // find a match in this step and the performance will be identical to the
1339   // greedy algorithm.
1340   for (int i = 0; i < count2_; ++i) {
1341     int matched = (*match_list2_)[i];
1342     if (matched == -1 && Match(v, i)) {
1343       (*match_list2_)[i] = v;
1344       return true;
1345     }
1346   }
1347   // Then we try those already matched nodes and see if we can find an
1348   // alternaive match for the node matched to them.
1349   // The greedy algorithm will stop before this and fail to produce the
1350   // correct result.
1351   for (int i = 0; i < count2_; ++i) {
1352     int matched = (*match_list2_)[i];
1353     if (matched != -1 && Match(v, i)) {
1354       if (!(*visited)[matched] && FindArgumentPathDFS(matched, visited)) {
1355         (*match_list2_)[i] = v;
1356         return true;
1357       }
1358     }
1359   }
1360   return false;
1361 }
1362 
1363 }  // namespace
1364 
MatchRepeatedFieldIndices(const Message & message1,const Message & message2,const FieldDescriptor * repeated_field,const vector<SpecificField> & parent_fields,vector<int> * match_list1,vector<int> * match_list2)1365 bool MessageDifferencer::MatchRepeatedFieldIndices(
1366     const Message& message1,
1367     const Message& message2,
1368     const FieldDescriptor* repeated_field,
1369     const vector<SpecificField>& parent_fields,
1370     vector<int>* match_list1,
1371     vector<int>* match_list2) {
1372   const int count1 =
1373       message1.GetReflection()->FieldSize(message1, repeated_field);
1374   const int count2 =
1375       message2.GetReflection()->FieldSize(message2, repeated_field);
1376   const MapKeyComparator* key_comparator = GetMapKeyComparator(repeated_field);
1377 
1378   match_list1->assign(count1, -1);
1379   match_list2->assign(count2, -1);
1380 
1381   SpecificField specific_field;
1382   specific_field.field = repeated_field;
1383 
1384   bool success = true;
1385   // Find potential match if this is a special repeated field.
1386   if (key_comparator != NULL || IsTreatedAsSet(repeated_field)) {
1387     if (scope_ == PARTIAL) {
1388       // When partial matching is enabled, Compare(a, b) && Compare(a, c)
1389       // doesn't necessarily imply Compare(b, c). Therefore a naive greedy
1390       // algorithm will fail to find a maximum matching.
1391       // Here we use the argumenting path algorithm.
1392       MaximumMatcher::NodeMatchCallback* callback =
1393           ::google::protobuf::internal::NewPermanentCallback(
1394               this, &MessageDifferencer::IsMatch,
1395               repeated_field, key_comparator,
1396               &message1, &message2, parent_fields);
1397       MaximumMatcher matcher(count1, count2, callback, match_list1,
1398                              match_list2);
1399       // If diff info is not needed, we should end the matching process as
1400       // soon as possible if not all items can be matched.
1401       bool early_return = (reporter_ == NULL);
1402       int match_count = matcher.FindMaximumMatch(early_return);
1403       if (match_count != count1 && reporter_ == NULL) return false;
1404       success = success && (match_count == count1);
1405     } else {
1406       for (int i = 0; i < count1; ++i) {
1407         // Indicates any matched elements for this repeated field.
1408         bool match = false;
1409 
1410         specific_field.index = i;
1411         specific_field.new_index = i;
1412 
1413         for (int j = 0; j < count2; j++) {
1414           if (match_list2->at(j) != -1) continue;
1415           specific_field.index = i;
1416           specific_field.new_index = j;
1417 
1418           match = IsMatch(repeated_field, key_comparator,
1419                           &message1, &message2, parent_fields, i, j);
1420 
1421           if (match) {
1422             match_list1->at(specific_field.index) = specific_field.new_index;
1423             match_list2->at(specific_field.new_index) = specific_field.index;
1424             break;
1425           }
1426         }
1427         if (!match && reporter_ == NULL) return false;
1428         success = success && match;
1429       }
1430     }
1431   } else {
1432     // If this field should be treated as list, just label the match_list.
1433     for (int i = 0; i < count1 && i < count2; i++) {
1434       match_list1->at(i) = i;
1435       match_list2->at(i) = i;
1436     }
1437   }
1438 
1439   return success;
1440 }
1441 
GetFieldComparisonResult(const Message & message1,const Message & message2,const FieldDescriptor * field,int index1,int index2,const FieldContext * field_context)1442 FieldComparator::ComparisonResult MessageDifferencer::GetFieldComparisonResult(
1443     const Message& message1, const Message& message2,
1444     const FieldDescriptor* field, int index1, int index2,
1445     const FieldContext* field_context) {
1446   FieldComparator* comparator = field_comparator_ != NULL ?
1447       field_comparator_ : &default_field_comparator_;
1448   return comparator->Compare(message1, message2, field,
1449                              index1, index2, field_context);
1450 }
1451 
1452 // ===========================================================================
1453 
Reporter()1454 MessageDifferencer::Reporter::Reporter() { }
~Reporter()1455 MessageDifferencer::Reporter::~Reporter() {}
1456 
1457 // ===========================================================================
1458 
MapKeyComparator()1459 MessageDifferencer::MapKeyComparator::MapKeyComparator() {}
~MapKeyComparator()1460 MessageDifferencer::MapKeyComparator::~MapKeyComparator() {}
1461 
1462 // ===========================================================================
1463 
IgnoreCriteria()1464 MessageDifferencer::IgnoreCriteria::IgnoreCriteria() {}
~IgnoreCriteria()1465 MessageDifferencer::IgnoreCriteria::~IgnoreCriteria() {}
1466 
1467 // ===========================================================================
1468 
1469 // Note that the printer's delimiter is not used, because if we are given a
1470 // printer, we don't know its delimiter.
StreamReporter(io::ZeroCopyOutputStream * output)1471 MessageDifferencer::StreamReporter::StreamReporter(
1472     io::ZeroCopyOutputStream* output) : printer_(new io::Printer(output, '$')),
1473                                         delete_printer_(true),
1474                                         report_modified_aggregates_(false) { }
1475 
StreamReporter(io::Printer * printer)1476 MessageDifferencer::StreamReporter::StreamReporter(
1477     io::Printer* printer) : printer_(printer),
1478                             delete_printer_(false),
1479                             report_modified_aggregates_(false) { }
1480 
~StreamReporter()1481 MessageDifferencer::StreamReporter::~StreamReporter() {
1482   if (delete_printer_) delete printer_;
1483 }
1484 
PrintPath(const vector<SpecificField> & field_path,bool left_side)1485 void MessageDifferencer::StreamReporter::PrintPath(
1486     const vector<SpecificField>& field_path, bool left_side) {
1487   for (int i = 0; i < field_path.size(); ++i) {
1488     if (i > 0) {
1489       printer_->Print(".");
1490     }
1491 
1492     SpecificField specific_field = field_path[i];
1493 
1494     if (specific_field.field != NULL) {
1495       if (specific_field.field->is_extension()) {
1496         printer_->Print("($name$)", "name",
1497                         specific_field.field->full_name());
1498       } else {
1499         printer_->PrintRaw(specific_field.field->name());
1500       }
1501     } else {
1502       printer_->PrintRaw(SimpleItoa(specific_field.unknown_field_number));
1503     }
1504     if (left_side && specific_field.index >= 0) {
1505       printer_->Print("[$name$]", "name", SimpleItoa(specific_field.index));
1506     }
1507     if (!left_side && specific_field.new_index >= 0) {
1508       printer_->Print("[$name$]", "name", SimpleItoa(specific_field.new_index));
1509     }
1510   }
1511 }
1512 
1513 void MessageDifferencer::
PrintValue(const Message & message,const vector<SpecificField> & field_path,bool left_side)1514 StreamReporter::PrintValue(const Message& message,
1515                            const vector<SpecificField>& field_path,
1516                            bool left_side) {
1517   const SpecificField& specific_field = field_path.back();
1518   const FieldDescriptor* field = specific_field.field;
1519   if (field != NULL) {
1520     string output;
1521     int index = left_side ? specific_field.index : specific_field.new_index;
1522     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
1523       const Reflection* reflection = message.GetReflection();
1524       const Message& field_message = field->is_repeated() ?
1525           reflection->GetRepeatedMessage(message, field, index) :
1526           reflection->GetMessage(message, field);
1527       output = field_message.ShortDebugString();
1528       if (output.empty()) {
1529         printer_->Print("{ }");
1530       } else {
1531         printer_->Print("{ $name$ }", "name", output);
1532       }
1533     } else {
1534       TextFormat::PrintFieldValueToString(message, field, index, &output);
1535       printer_->PrintRaw(output);
1536     }
1537   } else {
1538     const UnknownFieldSet* unknown_fields =
1539         (left_side ?
1540          specific_field.unknown_field_set1 :
1541          specific_field.unknown_field_set2);
1542     const UnknownField* unknown_field = &unknown_fields->field(
1543         left_side ?
1544         specific_field.unknown_field_index1 :
1545         specific_field.unknown_field_index2);
1546     PrintUnknownFieldValue(unknown_field);
1547   }
1548 }
1549 
1550 void MessageDifferencer::
PrintUnknownFieldValue(const UnknownField * unknown_field)1551 StreamReporter::PrintUnknownFieldValue(const UnknownField* unknown_field) {
1552   GOOGLE_CHECK(unknown_field != NULL) << " Cannot print NULL unknown_field.";
1553 
1554   string output;
1555   switch (unknown_field->type()) {
1556     case UnknownField::TYPE_VARINT:
1557       output = SimpleItoa(unknown_field->varint());
1558       break;
1559     case UnknownField::TYPE_FIXED32:
1560       output = StrCat("0x", strings::Hex(unknown_field->fixed32(),
1561                                          strings::ZERO_PAD_8));
1562       break;
1563     case UnknownField::TYPE_FIXED64:
1564       output = StrCat("0x", strings::Hex(unknown_field->fixed64(),
1565                                          strings::ZERO_PAD_16));
1566       break;
1567     case UnknownField::TYPE_LENGTH_DELIMITED:
1568       output = StringPrintf("\"%s\"",
1569           CEscape(unknown_field->length_delimited()).c_str());
1570       break;
1571     case UnknownField::TYPE_GROUP:
1572       // TODO(kenton):  Print the contents of the group like we do for
1573       //   messages.  Requires an equivalent of ShortDebugString() for
1574       //   UnknownFieldSet.
1575       output = "{ ... }";
1576       break;
1577   }
1578   printer_->PrintRaw(output);
1579 }
1580 
Print(const string & str)1581 void MessageDifferencer::StreamReporter::Print(const string& str) {
1582   printer_->Print(str.c_str());
1583 }
1584 
ReportAdded(const Message & message1,const Message & message2,const vector<SpecificField> & field_path)1585 void MessageDifferencer::StreamReporter::ReportAdded(
1586     const Message& message1,
1587     const Message& message2,
1588     const vector<SpecificField>& field_path) {
1589   printer_->Print("added: ");
1590   PrintPath(field_path, false);
1591   printer_->Print(": ");
1592   PrintValue(message2, field_path, false);
1593   printer_->Print("\n");  // Print for newlines.
1594 }
1595 
ReportDeleted(const Message & message1,const Message & message2,const vector<SpecificField> & field_path)1596 void MessageDifferencer::StreamReporter::ReportDeleted(
1597     const Message& message1,
1598     const Message& message2,
1599     const vector<SpecificField>& field_path) {
1600   printer_->Print("deleted: ");
1601   PrintPath(field_path, true);
1602   printer_->Print(": ");
1603   PrintValue(message1, field_path, true);
1604   printer_->Print("\n");  // Print for newlines
1605 }
1606 
ReportModified(const Message & message1,const Message & message2,const vector<SpecificField> & field_path)1607 void MessageDifferencer::StreamReporter::ReportModified(
1608     const Message& message1,
1609     const Message& message2,
1610     const vector<SpecificField>& field_path) {
1611   if (!report_modified_aggregates_ && field_path.back().field == NULL) {
1612     if (field_path.back().unknown_field_type == UnknownField::TYPE_GROUP) {
1613       // Any changes to the subfields have already been printed.
1614       return;
1615     }
1616   } else if (!report_modified_aggregates_) {
1617     if (field_path.back().field->cpp_type() ==
1618         FieldDescriptor::CPPTYPE_MESSAGE) {
1619       // Any changes to the subfields have already been printed.
1620       return;
1621     }
1622   }
1623 
1624   printer_->Print("modified: ");
1625   PrintPath(field_path, true);
1626   if (CheckPathChanged(field_path)) {
1627     printer_->Print(" -> ");
1628     PrintPath(field_path, false);
1629   }
1630   printer_->Print(": ");
1631   PrintValue(message1, field_path, true);
1632   printer_->Print(" -> ");
1633   PrintValue(message2, field_path, false);
1634   printer_->Print("\n");  // Print for newlines.
1635 }
1636 
ReportMoved(const Message & message1,const Message & message2,const vector<SpecificField> & field_path)1637 void MessageDifferencer::StreamReporter::ReportMoved(
1638     const Message& message1,
1639     const Message& message2,
1640     const vector<SpecificField>& field_path) {
1641   printer_->Print("moved: ");
1642   PrintPath(field_path, true);
1643   printer_->Print(" -> ");
1644   PrintPath(field_path, false);
1645   printer_->Print(" : ");
1646   PrintValue(message1, field_path, true);
1647   printer_->Print("\n");  // Print for newlines.
1648 }
1649 
ReportMatched(const Message & message1,const Message & message2,const vector<SpecificField> & field_path)1650 void MessageDifferencer::StreamReporter::ReportMatched(
1651     const Message& message1,
1652     const Message& message2,
1653     const vector<SpecificField>& field_path) {
1654   printer_->Print("matched: ");
1655   PrintPath(field_path, true);
1656   if (CheckPathChanged(field_path)) {
1657     printer_->Print(" -> ");
1658     PrintPath(field_path, false);
1659   }
1660   printer_->Print(" : ");
1661   PrintValue(message1, field_path, true);
1662   printer_->Print("\n");  // Print for newlines.
1663 }
1664 
ReportIgnored(const Message & message1,const Message & message2,const vector<SpecificField> & field_path)1665 void MessageDifferencer::StreamReporter::ReportIgnored(
1666     const Message& message1,
1667     const Message& message2,
1668     const vector<SpecificField>& field_path) {
1669   printer_->Print("ignored: ");
1670   PrintPath(field_path, true);
1671   if (CheckPathChanged(field_path)) {
1672     printer_->Print(" -> ");
1673     PrintPath(field_path, false);
1674   }
1675   printer_->Print("\n");  // Print for newlines.
1676 }
1677 
ReportUnknownFieldIgnored(const Message & message1,const Message & message2,const vector<SpecificField> & field_path)1678 void MessageDifferencer::StreamReporter::ReportUnknownFieldIgnored(
1679     const Message& message1, const Message& message2,
1680     const vector<SpecificField>& field_path) {
1681   printer_->Print("ignored: ");
1682   PrintPath(field_path, true);
1683   if (CheckPathChanged(field_path)) {
1684     printer_->Print(" -> ");
1685     PrintPath(field_path, false);
1686   }
1687   printer_->Print("\n");  // Print for newlines.
1688 }
1689 
1690 }  // namespace util
1691 }  // namespace protobuf
1692 }  // namespace google
1693