• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 // Author: jschorr@google.com (Joseph Schorr)
9 //  Based on original Protocol Buffers design by
10 //  Sanjay Ghemawat, Jeff Dean, and others.
11 
12 #include "google/protobuf/util/message_differencer.h"
13 
14 #include <algorithm>
15 #include <cstddef>
16 #include <cstdint>
17 #include <functional>
18 #include <limits>
19 #include <memory>
20 #include <utility>
21 
22 #include "google/protobuf/descriptor.pb.h"
23 #include "absl/container/fixed_array.h"
24 #include "absl/container/flat_hash_map.h"
25 #include "absl/log/absl_check.h"
26 #include "absl/log/absl_log.h"
27 #include "absl/strings/escaping.h"
28 #include "absl/strings/match.h"
29 #include "absl/strings/str_cat.h"
30 #include "absl/strings/str_format.h"
31 #include "google/protobuf/descriptor.h"
32 #include "google/protobuf/dynamic_message.h"
33 #include "google/protobuf/generated_enum_reflection.h"
34 #include "google/protobuf/io/printer.h"
35 #include "google/protobuf/io/zero_copy_stream.h"
36 #include "google/protobuf/io/zero_copy_stream_impl.h"
37 #include "google/protobuf/map_field.h"
38 #include "google/protobuf/message.h"
39 #include "google/protobuf/text_format.h"
40 #include "google/protobuf/util/field_comparator.h"
41 
42 // Always include as last one, otherwise it can break compilation
43 #include "google/protobuf/port_def.inc"
44 
45 namespace google {
46 namespace protobuf {
47 
48 namespace util {
49 
50 namespace {
51 
PrintShortTextFormat(const google::protobuf::Message & message)52 std::string PrintShortTextFormat(const google::protobuf::Message& message) {
53   std::string debug_string;
54 
55   google::protobuf::TextFormat::Printer printer;
56   printer.SetSingleLineMode(true);
57   printer.SetExpandAny(true);
58 
59   printer.PrintToString(message, &debug_string);
60   // Single line mode currently might have an extra space at the end.
61   if (!debug_string.empty() && debug_string[debug_string.size() - 1] == ' ') {
62     debug_string.resize(debug_string.size() - 1);
63   }
64 
65   return debug_string;
66 }
67 
68 }  // namespace
69 
70 // A reporter to report the total number of diffs.
71 // TODO: we can improve this to take into account the value differencers.
72 class NumDiffsReporter : public google::protobuf::util::MessageDifferencer::Reporter {
73  public:
NumDiffsReporter()74   NumDiffsReporter() : num_diffs_(0) {}
75 
76   // Returns the total number of diffs.
GetNumDiffs() const77   int32_t GetNumDiffs() const { return num_diffs_; }
Reset()78   void Reset() { num_diffs_ = 0; }
79 
80   // Report that a field has been added into Message2.
ReportAdded(const google::protobuf::Message &,const google::protobuf::Message &,const std::vector<google::protobuf::util::MessageDifferencer::SpecificField> &)81   void ReportAdded(
82       const google::protobuf::Message& /* message1 */,
83       const google::protobuf::Message& /* message2 */,
84       const std::vector<google::protobuf::util::MessageDifferencer::SpecificField>&
85       /*field_path*/) override {
86     ++num_diffs_;
87   }
88 
89   // Report that a field has been deleted from Message1.
ReportDeleted(const google::protobuf::Message &,const google::protobuf::Message &,const std::vector<google::protobuf::util::MessageDifferencer::SpecificField> &)90   void ReportDeleted(
91       const google::protobuf::Message& /* message1 */,
92       const google::protobuf::Message& /* message2 */,
93       const std::vector<google::protobuf::util::MessageDifferencer::SpecificField>&
94       /*field_path*/) override {
95     ++num_diffs_;
96   }
97 
98   // Report that the value of a field has been modified.
ReportModified(const google::protobuf::Message &,const google::protobuf::Message &,const std::vector<google::protobuf::util::MessageDifferencer::SpecificField> &)99   void ReportModified(
100       const google::protobuf::Message& /* message1 */,
101       const google::protobuf::Message& /* message2 */,
102       const std::vector<google::protobuf::util::MessageDifferencer::SpecificField>&
103       /*field_path*/) override {
104     ++num_diffs_;
105   }
106 
107  private:
108   int32_t num_diffs_;
109 };
110 
111 // When comparing a repeated field as map, MultipleFieldMapKeyComparator can
112 // be used to specify multiple fields as key for key comparison.
113 // Two elements of a repeated field will be regarded as having the same key
114 // iff they have the same value for every specified key field.
115 // Note that you can also specify only one field as key.
116 class MessageDifferencer::MultipleFieldsMapKeyComparator
117     : public MessageDifferencer::MapKeyComparator {
118  public:
MultipleFieldsMapKeyComparator(MessageDifferencer * message_differencer,const std::vector<std::vector<const FieldDescriptor * >> & key_field_paths)119   MultipleFieldsMapKeyComparator(
120       MessageDifferencer* message_differencer,
121       const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths)
122       : message_differencer_(message_differencer),
123         key_field_paths_(key_field_paths) {
124     ABSL_CHECK(!key_field_paths_.empty());
125     for (const auto& path : key_field_paths_) {
126       ABSL_CHECK(!path.empty());
127     }
128   }
MultipleFieldsMapKeyComparator(MessageDifferencer * message_differencer,const FieldDescriptor * key)129   MultipleFieldsMapKeyComparator(MessageDifferencer* message_differencer,
130                                  const FieldDescriptor* key)
131       : message_differencer_(message_differencer) {
132     std::vector<const FieldDescriptor*> key_field_path;
133     key_field_path.push_back(key);
134     key_field_paths_.push_back(key_field_path);
135   }
136   MultipleFieldsMapKeyComparator(const MultipleFieldsMapKeyComparator&) =
137       delete;
138   MultipleFieldsMapKeyComparator& operator=(
139       const MultipleFieldsMapKeyComparator&) = delete;
IsMatch(const Message & message1,const Message & message2,int unpacked_any,const std::vector<SpecificField> & parent_fields) const140   bool IsMatch(const Message& message1, const Message& message2,
141                int unpacked_any,
142                const std::vector<SpecificField>& parent_fields) const override {
143     for (const auto& path : key_field_paths_) {
144       if (!IsMatchInternal(message1, message2, unpacked_any, parent_fields,
145                            path, 0)) {
146         return false;
147       }
148     }
149     return true;
150   }
151 
152  private:
IsMatchInternal(const Message & message1,const Message & message2,int unpacked_any,const std::vector<SpecificField> & parent_fields,const std::vector<const FieldDescriptor * > & key_field_path,int path_index) const153   bool IsMatchInternal(
154       const Message& message1, const Message& message2, int unpacked_any,
155       const std::vector<SpecificField>& parent_fields,
156       const std::vector<const FieldDescriptor*>& key_field_path,
157       int path_index) const {
158     const FieldDescriptor* field = key_field_path[path_index];
159     std::vector<SpecificField> current_parent_fields(parent_fields);
160     if (path_index == static_cast<int64_t>(key_field_path.size() - 1)) {
161       if (field->is_map()) {
162         return message_differencer_->CompareMapField(
163             message1, message2, unpacked_any, field, &current_parent_fields);
164       } else if (field->is_repeated()) {
165         return message_differencer_->CompareRepeatedField(
166             message1, message2, unpacked_any, field, &current_parent_fields);
167       } else {
168         return message_differencer_->CompareFieldValueUsingParentFields(
169             message1, message2, unpacked_any, field, -1, -1,
170             &current_parent_fields);
171       }
172     } else {
173       const Reflection* reflection1 = message1.GetReflection();
174       const Reflection* reflection2 = message2.GetReflection();
175       bool has_field1 = reflection1->HasField(message1, field);
176       bool has_field2 = reflection2->HasField(message2, field);
177       if (!has_field1 && !has_field2) {
178         return true;
179       }
180       if (has_field1 != has_field2) {
181         return false;
182       }
183       SpecificField specific_field;
184       specific_field.message1 = &message1;
185       specific_field.message2 = &message2;
186       specific_field.unpacked_any = unpacked_any;
187       specific_field.field = field;
188       current_parent_fields.push_back(specific_field);
189       return IsMatchInternal(reflection1->GetMessage(message1, field),
190                              reflection2->GetMessage(message2, field),
191                              false /*key is never Any*/, current_parent_fields,
192                              key_field_path, path_index + 1);
193     }
194   }
195   MessageDifferencer* message_differencer_;
196   std::vector<std::vector<const FieldDescriptor*> > key_field_paths_;
197 };
198 
199 // Preserve the order when treating repeated field as SMART_LIST. The current
200 // implementation is to find the longest matching sequence from the first
201 // element. The optimal solution requires to use //util/diff/lcs.h, which is
202 // not open sourced yet. Overwrite this method if you want to have that.
203 // TODO: change to use LCS once it is open sourced.
MatchIndicesPostProcessorForSmartList(std::vector<int> * match_list1,std::vector<int> * match_list2)204 void MatchIndicesPostProcessorForSmartList(std::vector<int>* match_list1,
205                                            std::vector<int>* match_list2) {
206   int last_matched_index = -1;
207   for (size_t i = 0; i < match_list1->size(); ++i) {
208     if (match_list1->at(i) < 0) {
209       continue;
210     }
211     if (last_matched_index < 0 || match_list1->at(i) > last_matched_index) {
212       last_matched_index = match_list1->at(i);
213     } else {
214       match_list2->at(match_list1->at(i)) = -1;
215       match_list1->at(i) = -1;
216     }
217   }
218 }
219 
AddSpecificIndex(google::protobuf::util::MessageDifferencer::SpecificField * specific_field,const Message & message,const FieldDescriptor * field,int index)220 void AddSpecificIndex(
221     google::protobuf::util::MessageDifferencer::SpecificField* specific_field,
222     const Message& message, const FieldDescriptor* field, int index) {
223   if (field->is_map()) {
224     const Reflection* reflection = message.GetReflection();
225     specific_field->map_entry1 =
226         &reflection->GetRepeatedMessage(message, field, index);
227   }
228   specific_field->index = index;
229 }
230 
AddSpecificNewIndex(google::protobuf::util::MessageDifferencer::SpecificField * specific_field,const Message & message,const FieldDescriptor * field,int index)231 void AddSpecificNewIndex(
232     google::protobuf::util::MessageDifferencer::SpecificField* specific_field,
233     const Message& message, const FieldDescriptor* field, int index) {
234   if (field->is_map()) {
235     const Reflection* reflection = message.GetReflection();
236     specific_field->map_entry2 =
237         &reflection->GetRepeatedMessage(message, field, index);
238   }
239   specific_field->new_index = index;
240 }
241 
MapEntryKeyComparator(MessageDifferencer * message_differencer)242 MessageDifferencer::MapEntryKeyComparator::MapEntryKeyComparator(
243     MessageDifferencer* message_differencer)
244     : message_differencer_(message_differencer) {}
245 
IsMatch(const Message & message1,const Message & message2,int unpacked_any,const std::vector<SpecificField> & parent_fields) const246 bool MessageDifferencer::MapEntryKeyComparator::IsMatch(
247     const Message& message1, const Message& message2, int unpacked_any,
248     const std::vector<SpecificField>& parent_fields) const {
249   // Map entry has its key in the field with tag 1.  See the comment for
250   // map_entry in MessageOptions.
251   const FieldDescriptor* key = message1.GetDescriptor()->FindFieldByNumber(1);
252   // If key is not present in message1 and we're doing partial comparison or if
253   // map key is explicitly ignored treat the field as set instead,
254   const bool treat_as_set =
255       (message_differencer_->scope() == PARTIAL &&
256        !message1.GetReflection()->HasField(message1, key)) ||
257       message_differencer_->IsIgnored(message1, message2, key, parent_fields);
258 
259   std::vector<SpecificField> current_parent_fields(parent_fields);
260   if (treat_as_set) {
261     return message_differencer_->Compare(message1, message2, unpacked_any,
262                                          &current_parent_fields);
263   }
264   return message_differencer_->CompareFieldValueUsingParentFields(
265       message1, message2, unpacked_any, key, -1, -1, &current_parent_fields);
266 }
267 
Equals(const Message & message1,const Message & message2)268 bool MessageDifferencer::Equals(const Message& message1,
269                                 const Message& message2) {
270   MessageDifferencer differencer;
271 
272   return differencer.Compare(message1, message2);
273 }
274 
Equivalent(const Message & message1,const Message & message2)275 bool MessageDifferencer::Equivalent(const Message& message1,
276                                     const Message& message2) {
277   MessageDifferencer differencer;
278   differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT);
279 
280   return differencer.Compare(message1, message2);
281 }
282 
ApproximatelyEquals(const Message & message1,const Message & message2)283 bool MessageDifferencer::ApproximatelyEquals(const Message& message1,
284                                              const Message& message2) {
285   MessageDifferencer differencer;
286   differencer.set_float_comparison(MessageDifferencer::APPROXIMATE);
287 
288   return differencer.Compare(message1, message2);
289 }
290 
ApproximatelyEquivalent(const Message & message1,const Message & message2)291 bool MessageDifferencer::ApproximatelyEquivalent(const Message& message1,
292                                                  const Message& message2) {
293   MessageDifferencer differencer;
294   differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT);
295   differencer.set_float_comparison(MessageDifferencer::APPROXIMATE);
296 
297   return differencer.Compare(message1, message2);
298 }
299 
300 // ===========================================================================
301 
MessageDifferencer()302 MessageDifferencer::MessageDifferencer()
303     : reporter_(nullptr),
304       message_field_comparison_(EQUAL),
305       scope_(FULL),
306       repeated_field_comparison_(AS_LIST),
307       map_entry_key_comparator_(this),
308       report_matches_(false),
309       report_moves_(true),
310       report_ignores_(true),
311       output_string_(nullptr),
312       match_indices_for_smart_list_callback_(
313           MatchIndicesPostProcessorForSmartList) {}
314 
~MessageDifferencer()315 MessageDifferencer::~MessageDifferencer() {
316   for (MapKeyComparator* comparator : owned_key_comparators_) {
317     delete comparator;
318   }
319 }
320 
set_field_comparator(FieldComparator * comparator)321 void MessageDifferencer::set_field_comparator(FieldComparator* comparator) {
322   ABSL_CHECK(comparator) << "Field comparator can't be nullptr.";
323   field_comparator_kind_ = kFCBase;
324   field_comparator_.base = comparator;
325 }
326 
set_field_comparator(DefaultFieldComparator * comparator)327 void MessageDifferencer::set_field_comparator(
328     DefaultFieldComparator* comparator) {
329   ABSL_CHECK(comparator) << "Field comparator can't be nullptr.";
330   field_comparator_kind_ = kFCDefault;
331   field_comparator_.default_impl = comparator;
332 }
333 
set_message_field_comparison(MessageFieldComparison comparison)334 void MessageDifferencer::set_message_field_comparison(
335     MessageFieldComparison comparison) {
336   message_field_comparison_ = comparison;
337 }
338 
339 MessageDifferencer::MessageFieldComparison
message_field_comparison() const340 MessageDifferencer::message_field_comparison() const {
341   return message_field_comparison_;
342 }
343 
set_scope(Scope scope)344 void MessageDifferencer::set_scope(Scope scope) { scope_ = scope; }
345 
scope() const346 MessageDifferencer::Scope MessageDifferencer::scope() const { return scope_; }
347 
set_force_compare_no_presence(bool value)348 void MessageDifferencer::set_force_compare_no_presence(bool value) {
349   force_compare_no_presence_ = value;
350 }
351 
set_float_comparison(FloatComparison comparison)352 void MessageDifferencer::set_float_comparison(FloatComparison comparison) {
353   default_field_comparator_.set_float_comparison(
354       comparison == EXACT ? DefaultFieldComparator::EXACT
355                           : DefaultFieldComparator::APPROXIMATE);
356 }
357 
set_repeated_field_comparison(RepeatedFieldComparison comparison)358 void MessageDifferencer::set_repeated_field_comparison(
359     RepeatedFieldComparison comparison) {
360   repeated_field_comparison_ = comparison;
361 }
362 
363 MessageDifferencer::RepeatedFieldComparison
repeated_field_comparison() const364 MessageDifferencer::repeated_field_comparison() const {
365   return repeated_field_comparison_;
366 }
367 
CheckRepeatedFieldComparisons(const FieldDescriptor * field,const RepeatedFieldComparison & new_comparison)368 void MessageDifferencer::CheckRepeatedFieldComparisons(
369     const FieldDescriptor* field,
370     const RepeatedFieldComparison& new_comparison) {
371   ABSL_CHECK(field->is_repeated())
372       << "Field must be repeated: " << field->full_name();
373   const MapKeyComparator* key_comparator = GetMapKeyComparator(field);
374   ABSL_CHECK(key_comparator == NULL)
375       << "Cannot treat this repeated field as both MAP and " << new_comparison
376       << " for comparison.  Field name is: " << field->full_name();
377 }
378 
TreatAsSet(const FieldDescriptor * field)379 void MessageDifferencer::TreatAsSet(const FieldDescriptor* field) {
380   CheckRepeatedFieldComparisons(field, AS_SET);
381   repeated_field_comparisons_[field] = AS_SET;
382 }
383 
TreatAsSmartSet(const FieldDescriptor * field)384 void MessageDifferencer::TreatAsSmartSet(const FieldDescriptor* field) {
385   CheckRepeatedFieldComparisons(field, AS_SMART_SET);
386   repeated_field_comparisons_[field] = AS_SMART_SET;
387 }
388 
SetMatchIndicesForSmartListCallback(std::function<void (std::vector<int> *,std::vector<int> *)> callback)389 void MessageDifferencer::SetMatchIndicesForSmartListCallback(
390     std::function<void(std::vector<int>*, std::vector<int>*)> callback) {
391   match_indices_for_smart_list_callback_ = callback;
392 }
393 
TreatAsList(const FieldDescriptor * field)394 void MessageDifferencer::TreatAsList(const FieldDescriptor* field) {
395   CheckRepeatedFieldComparisons(field, AS_LIST);
396   repeated_field_comparisons_[field] = AS_LIST;
397 }
398 
TreatAsSmartList(const FieldDescriptor * field)399 void MessageDifferencer::TreatAsSmartList(const FieldDescriptor* field) {
400   CheckRepeatedFieldComparisons(field, AS_SMART_LIST);
401   repeated_field_comparisons_[field] = AS_SMART_LIST;
402 }
403 
TreatAsMap(const FieldDescriptor * field,const FieldDescriptor * key)404 void MessageDifferencer::TreatAsMap(const FieldDescriptor* field,
405                                     const FieldDescriptor* key) {
406   ABSL_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type())
407       << "Field has to be message type.  Field name is: " << field->full_name();
408   ABSL_CHECK(key->containing_type() == field->message_type())
409       << key->full_name()
410       << " must be a direct subfield within the repeated field "
411       << field->full_name() << ", not " << key->containing_type()->full_name();
412   ABSL_CHECK(repeated_field_comparisons_.find(field) ==
413              repeated_field_comparisons_.end())
414       << "Cannot treat the same field as both "
415       << repeated_field_comparisons_[field]
416       << " and MAP. Field name is: " << field->full_name();
417   MapKeyComparator* key_comparator =
418       new MultipleFieldsMapKeyComparator(this, key);
419   owned_key_comparators_.push_back(key_comparator);
420   map_field_key_comparator_[field] = key_comparator;
421 }
422 
TreatAsMapWithMultipleFieldsAsKey(const FieldDescriptor * field,const std::vector<const FieldDescriptor * > & key_fields)423 void MessageDifferencer::TreatAsMapWithMultipleFieldsAsKey(
424     const FieldDescriptor* field,
425     const std::vector<const FieldDescriptor*>& key_fields) {
426   std::vector<std::vector<const FieldDescriptor*> > key_field_paths;
427   for (const FieldDescriptor* key_filed : key_fields) {
428     std::vector<const FieldDescriptor*> key_field_path;
429     key_field_path.push_back(key_filed);
430     key_field_paths.push_back(key_field_path);
431   }
432   TreatAsMapWithMultipleFieldPathsAsKey(field, key_field_paths);
433 }
434 
TreatAsMapWithMultipleFieldPathsAsKey(const FieldDescriptor * field,const std::vector<std::vector<const FieldDescriptor * >> & key_field_paths)435 void MessageDifferencer::TreatAsMapWithMultipleFieldPathsAsKey(
436     const FieldDescriptor* field,
437     const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths) {
438   ABSL_CHECK(field->is_repeated())
439       << "Field must be repeated: " << field->full_name();
440   ABSL_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type())
441       << "Field has to be message type.  Field name is: " << field->full_name();
442   for (const auto& key_field_path : key_field_paths) {
443     for (size_t j = 0; j < key_field_path.size(); ++j) {
444       const FieldDescriptor* parent_field =
445           j == 0 ? field : key_field_path[j - 1];
446       const FieldDescriptor* child_field = key_field_path[j];
447       ABSL_CHECK(child_field->containing_type() == parent_field->message_type())
448           << child_field->full_name()
449           << " must be a direct subfield within the field: "
450           << parent_field->full_name();
451       if (j != 0) {
452         ABSL_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE,
453                       parent_field->cpp_type())
454             << parent_field->full_name() << " has to be of type message.";
455         ABSL_CHECK(!parent_field->is_repeated())
456             << parent_field->full_name() << " cannot be a repeated field.";
457       }
458     }
459   }
460   ABSL_CHECK(repeated_field_comparisons_.find(field) ==
461              repeated_field_comparisons_.end())
462       << "Cannot treat the same field as both "
463       << repeated_field_comparisons_[field]
464       << " and MAP. Field name is: " << field->full_name();
465   MapKeyComparator* key_comparator =
466       new MultipleFieldsMapKeyComparator(this, key_field_paths);
467   owned_key_comparators_.push_back(key_comparator);
468   map_field_key_comparator_[field] = key_comparator;
469 }
470 
TreatAsMapUsingKeyComparator(const FieldDescriptor * field,const MapKeyComparator * key_comparator)471 void MessageDifferencer::TreatAsMapUsingKeyComparator(
472     const FieldDescriptor* field, const MapKeyComparator* key_comparator) {
473   ABSL_CHECK(field->is_repeated())
474       << "Field must be repeated: " << field->full_name();
475   ABSL_CHECK(repeated_field_comparisons_.find(field) ==
476              repeated_field_comparisons_.end())
477       << "Cannot treat the same field as both "
478       << repeated_field_comparisons_[field]
479       << " and MAP. Field name is: " << field->full_name();
480   map_field_key_comparator_[field] = key_comparator;
481 }
482 
AddIgnoreCriteria(std::unique_ptr<IgnoreCriteria> ignore_criteria)483 void MessageDifferencer::AddIgnoreCriteria(
484     std::unique_ptr<IgnoreCriteria> ignore_criteria) {
485   ignore_criteria_.push_back(std::move(ignore_criteria));
486 }
487 
IgnoreField(const FieldDescriptor * field)488 void MessageDifferencer::IgnoreField(const FieldDescriptor* field) {
489   ignored_fields_.insert(field);
490 }
491 
SetFractionAndMargin(const FieldDescriptor * field,double fraction,double margin)492 void MessageDifferencer::SetFractionAndMargin(const FieldDescriptor* field,
493                                               double fraction, double margin) {
494   default_field_comparator_.SetFractionAndMargin(field, fraction, margin);
495 }
496 
ReportDifferencesToString(std::string * output)497 void MessageDifferencer::ReportDifferencesToString(std::string* output) {
498   ABSL_DCHECK(output) << "Specified output string was NULL";
499 
500   output_string_ = output;
501   output_string_->clear();
502 }
503 
ReportDifferencesTo(Reporter * reporter)504 void MessageDifferencer::ReportDifferencesTo(Reporter* reporter) {
505   // If an output string is set, clear it to prevent
506   // it superseding the specified reporter.
507   if (output_string_) {
508     output_string_ = NULL;
509   }
510 
511   reporter_ = reporter;
512 }
513 
FieldBefore(const FieldDescriptor * field1,const FieldDescriptor * field2)514 bool MessageDifferencer::FieldBefore(const FieldDescriptor* field1,
515                                      const FieldDescriptor* field2) {
516   // Handle sentinel values (i.e. make sure NULLs are always ordered
517   // at the end of the list).
518   if (field1 == NULL) {
519     return false;
520   }
521 
522   if (field2 == NULL) {
523     return true;
524   }
525 
526   // Always order fields by their tag number
527   return (field1->number() < field2->number());
528 }
529 
Compare(const Message & message1,const Message & message2)530 bool MessageDifferencer::Compare(const Message& message1,
531                                  const Message& message2) {
532   const Descriptor* descriptor1 = message1.GetDescriptor();
533   const Descriptor* descriptor2 = message2.GetDescriptor();
534   if (descriptor1 != descriptor2) {
535     ABSL_DLOG(FATAL) << "Comparison between two messages with different "
536                      << "descriptors. " << descriptor1->full_name() << " vs "
537                      << descriptor2->full_name();
538     return false;
539   }
540 
541   std::vector<SpecificField> parent_fields;
542   force_compare_no_presence_fields_.clear();
543   force_compare_failure_triggering_fields_.clear();
544 
545   bool result = false;
546   // Setup the internal reporter if need be.
547   if (output_string_) {
548     io::StringOutputStream output_stream(output_string_);
549     StreamReporter reporter(&output_stream);
550     reporter.SetMessages(message1, message2);
551     reporter_ = &reporter;
552     result = Compare(message1, message2, false, &parent_fields);
553     reporter_ = NULL;
554   } else {
555     result = Compare(message1, message2, false, &parent_fields);
556   }
557   return result;
558 }
559 
CompareWithFields(const Message & message1,const Message & message2,const std::vector<const FieldDescriptor * > & message1_fields_arg,const std::vector<const FieldDescriptor * > & message2_fields_arg)560 bool MessageDifferencer::CompareWithFields(
561     const Message& message1, const Message& message2,
562     const std::vector<const FieldDescriptor*>& message1_fields_arg,
563     const std::vector<const FieldDescriptor*>& message2_fields_arg) {
564   if (message1.GetDescriptor() != message2.GetDescriptor()) {
565     ABSL_DLOG(FATAL) << "Comparison between two messages with different "
566                      << "descriptors.";
567     return false;
568   }
569 
570   std::vector<SpecificField> parent_fields;
571   force_compare_no_presence_fields_.clear();
572   force_compare_failure_triggering_fields_.clear();
573 
574   bool result = false;
575 
576   std::vector<const FieldDescriptor*> message1_fields(
577       message1_fields_arg.size() + 1);
578   std::vector<const FieldDescriptor*> message2_fields(
579       message2_fields_arg.size() + 1);
580 
581   std::copy(message1_fields_arg.cbegin(), message1_fields_arg.cend(),
582             message1_fields.begin());
583   std::copy(message2_fields_arg.cbegin(), message2_fields_arg.cend(),
584             message2_fields.begin());
585 
586   // Append sentinel values.
587   message1_fields[message1_fields_arg.size()] = nullptr;
588   message2_fields[message2_fields_arg.size()] = nullptr;
589 
590   std::sort(message1_fields.begin(), message1_fields.end(), FieldBefore);
591   std::sort(message2_fields.begin(), message2_fields.end(), FieldBefore);
592 
593   // Setup the internal reporter if need be.
594   if (output_string_) {
595     io::StringOutputStream output_stream(output_string_);
596     StreamReporter reporter(&output_stream);
597     reporter_ = &reporter;
598     result = CompareRequestedFieldsUsingSettings(
599         message1, message2, false, message1_fields, message2_fields,
600         &parent_fields);
601     reporter_ = NULL;
602   } else {
603     result = CompareRequestedFieldsUsingSettings(
604         message1, message2, false, message1_fields, message2_fields,
605         &parent_fields);
606   }
607 
608   return result;
609 }
610 
Compare(const Message & message1,const Message & message2,int unpacked_any,std::vector<SpecificField> * parent_fields)611 bool MessageDifferencer::Compare(const Message& message1,
612                                  const Message& message2, int unpacked_any,
613                                  std::vector<SpecificField>* parent_fields) {
614   // Expand google.protobuf.Any payload if possible.
615   if (message1.GetDescriptor()->full_name() == internal::kAnyFullTypeName) {
616     std::unique_ptr<Message> data1;
617     std::unique_ptr<Message> data2;
618     if (unpack_any_field_.UnpackAny(message1, &data1) &&
619         unpack_any_field_.UnpackAny(message2, &data2) &&
620         data1->GetDescriptor() == data2->GetDescriptor()) {
621       return Compare(*data1, *data2, unpacked_any + 1, parent_fields);
622     }
623     // If the Any payload is unparsable, or the payload types are different
624     // between message1 and message2, fall through and treat Any as a regular
625     // proto.
626   }
627 
628   bool unknown_compare_result = true;
629   // Ignore unknown fields in EQUIVALENT mode
630   if (message_field_comparison_ != EQUIVALENT) {
631     const Reflection* reflection1 = message1.GetReflection();
632     const Reflection* reflection2 = message2.GetReflection();
633     const UnknownFieldSet& unknown_field_set1 =
634         reflection1->GetUnknownFields(message1);
635     const UnknownFieldSet& unknown_field_set2 =
636         reflection2->GetUnknownFields(message2);
637     if (!CompareUnknownFields(message1, message2, unknown_field_set1,
638                               unknown_field_set2, parent_fields)) {
639       if (reporter_ == NULL) {
640         return false;
641       }
642       unknown_compare_result = false;
643     }
644   }
645 
646   std::vector<const FieldDescriptor*> message1_fields =
647       RetrieveFields(message1, true);
648   std::vector<const FieldDescriptor*> message2_fields =
649       RetrieveFields(message2, false);
650 
651   return CompareRequestedFieldsUsingSettings(message1, message2, unpacked_any,
652                                              message1_fields, message2_fields,
653                                              parent_fields) &&
654          unknown_compare_result;
655 }
656 
RetrieveFields(const Message & message,bool base_message)657 std::vector<const FieldDescriptor*> MessageDifferencer::RetrieveFields(
658     const Message& message, bool base_message) {
659   const Descriptor* descriptor = message.GetDescriptor();
660 
661   tmp_message_fields_.clear();
662   tmp_message_fields_.reserve(descriptor->field_count() + 1);
663 
664   const Reflection* reflection = message.GetReflection();
665   if (descriptor->options().map_entry()) {
666     if (this->scope_ == PARTIAL && base_message) {
667       reflection->ListFields(message, &tmp_message_fields_);
668     } else {
669       // Map entry fields are always considered present.
670       for (int i = 0; i < descriptor->field_count(); i++) {
671         tmp_message_fields_.push_back(descriptor->field(i));
672       }
673     }
674   } else {
675     reflection->ListFields(message, &tmp_message_fields_);
676   }
677   // Add sentinel values to deal with the
678   // case where the number of the fields in
679   // each list are different.
680   tmp_message_fields_.push_back(nullptr);
681 
682   std::vector<const FieldDescriptor*> message_fields(
683       tmp_message_fields_.begin(), tmp_message_fields_.end());
684 
685   return message_fields;
686 }
687 
CompareRequestedFieldsUsingSettings(const Message & message1,const Message & message2,int unpacked_any,const std::vector<const FieldDescriptor * > & message1_fields,const std::vector<const FieldDescriptor * > & message2_fields,std::vector<SpecificField> * parent_fields)688 bool MessageDifferencer::CompareRequestedFieldsUsingSettings(
689     const Message& message1, const Message& message2, int unpacked_any,
690     const std::vector<const FieldDescriptor*>& message1_fields,
691     const std::vector<const FieldDescriptor*>& message2_fields,
692     std::vector<SpecificField>* parent_fields) {
693   if (scope_ == FULL) {
694     if (message_field_comparison_ == EQUIVALENT) {
695       // We need to merge the field lists of both messages (i.e.
696       // we are merely checking for a difference in field values,
697       // rather than the addition or deletion of fields).
698       std::vector<const FieldDescriptor*> fields_union =
699           CombineFields(message1, message1_fields, FULL, message2_fields, FULL);
700       return CompareWithFieldsInternal(message1, message2, unpacked_any,
701                                        fields_union, fields_union,
702                                        parent_fields);
703     } else {
704       // Simple equality comparison, use the unaltered field lists.
705       return CompareWithFieldsInternal(message1, message2, unpacked_any,
706                                        message1_fields, message2_fields,
707                                        parent_fields);
708     }
709   } else {
710     if (message_field_comparison_ == EQUIVALENT) {
711       // We use the list of fields for message1 for both messages when
712       // comparing.  This way, extra fields in message2 are ignored,
713       // and missing fields in message2 use their default value.
714       return CompareWithFieldsInternal(message1, message2, unpacked_any,
715                                        message1_fields, message1_fields,
716                                        parent_fields);
717     } else {
718       // We need to consider the full list of fields for message1
719       // but only the intersection for message2.  This way, any fields
720       // only present in message2 will be ignored, but any fields only
721       // present in message1 will be marked as a difference.
722       std::vector<const FieldDescriptor*> fields_intersection = CombineFields(
723           message1, message1_fields, PARTIAL, message2_fields, PARTIAL);
724       return CompareWithFieldsInternal(message1, message2, unpacked_any,
725                                        message1_fields, fields_intersection,
726                                        parent_fields);
727     }
728   }
729 }
730 
731 namespace {
ValidMissingField(const FieldDescriptor & f)732 bool ValidMissingField(const FieldDescriptor& f) {
733   switch (f.cpp_type()) {
734     case FieldDescriptor::CPPTYPE_INT32:
735     case FieldDescriptor::CPPTYPE_UINT32:
736     case FieldDescriptor::CPPTYPE_INT64:
737     case FieldDescriptor::CPPTYPE_UINT64:
738     case FieldDescriptor::CPPTYPE_FLOAT:
739     case FieldDescriptor::CPPTYPE_DOUBLE:
740     case FieldDescriptor::CPPTYPE_STRING:
741     case FieldDescriptor::CPPTYPE_BOOL:
742     case FieldDescriptor::CPPTYPE_ENUM:
743       return true;
744     default:
745       return false;
746   }
747 }
748 }  // namespace
749 
ShouldCompareNoPresence(const Message & message1,const Reflection & reflection1,const FieldDescriptor * field2) const750 bool MessageDifferencer::ShouldCompareNoPresence(
751     const Message& message1, const Reflection& reflection1,
752     const FieldDescriptor* field2) const {
753   const bool compare_no_presence_by_field = force_compare_no_presence_ &&
754                                             !field2->has_presence() &&
755                                             !field2->is_repeated();
756   if (compare_no_presence_by_field) {
757     return true;
758   }
759   const bool compare_no_presence_by_address =
760       !field2->is_repeated() && !field2->has_presence() &&
761       ValidMissingField(*field2) &&
762       require_no_presence_fields_.ids_.contains(
763           TextFormat::Parser::UnsetFieldsMetadata::GetUnsetFieldId(message1,
764                                                                    *field2));
765   return compare_no_presence_by_address;
766 }
767 
CombineFields(const Message & message1,const std::vector<const FieldDescriptor * > & fields1,Scope fields1_scope,const std::vector<const FieldDescriptor * > & fields2,Scope fields2_scope)768 std::vector<const FieldDescriptor*> MessageDifferencer::CombineFields(
769     const Message& message1, const std::vector<const FieldDescriptor*>& fields1,
770     Scope fields1_scope, const std::vector<const FieldDescriptor*>& fields2,
771     Scope fields2_scope) {
772   const Reflection* reflection1 = message1.GetReflection();
773   size_t index1 = 0;
774   size_t index2 = 0;
775 
776   tmp_message_fields_.clear();
777 
778   while (index1 < fields1.size() && index2 < fields2.size()) {
779     const FieldDescriptor* field1 = fields1[index1];
780     const FieldDescriptor* field2 = fields2[index2];
781 
782     if (FieldBefore(field1, field2)) {
783       if (fields1_scope == FULL) {
784         tmp_message_fields_.push_back(field1);
785       }
786       ++index1;
787     } else if (FieldBefore(field2, field1)) {
788       if (fields2_scope == FULL) {
789         tmp_message_fields_.push_back(field2);
790       } else if (fields2_scope == PARTIAL &&
791                  ShouldCompareNoPresence(message1, *reflection1, field2)) {
792         // In order to make MessageDifferencer play nicely with no-presence
793         // fields in unit tests, we want to check if the expected proto
794         // (message1) has some fields which are set to their default value but
795         // are not set to their default value in message2 (the actual message).
796         // Those fields will appear in fields2 (since they have non default
797         // value) but will not appear in fields1 (since they have the default
798         // value or were never set).
799         force_compare_no_presence_fields_.insert(field2);
800         tmp_message_fields_.push_back(field2);
801       }
802       ++index2;
803     } else {
804       tmp_message_fields_.push_back(field1);
805       ++index1;
806       ++index2;
807     }
808   }
809 
810   tmp_message_fields_.push_back(nullptr);
811 
812   std::vector<const FieldDescriptor*> combined_fields(
813       tmp_message_fields_.begin(), tmp_message_fields_.end());
814 
815   return combined_fields;
816 }
817 
818 // We push an element via a NOINLINE function to avoid using stack space on
819 // the caller for a temporary SpecificField object. They are quite large.
PushSpecificField(std::vector<MessageDifferencer::SpecificField> * fields)820 static PROTOBUF_NOINLINE MessageDifferencer::SpecificField& PushSpecificField(
821     std::vector<MessageDifferencer::SpecificField>* fields) {
822   fields->emplace_back();
823   return fields->back();
824 }
825 
CompareWithFieldsInternal(const Message & message1,const Message & message2,int unpacked_any,const std::vector<const FieldDescriptor * > & message1_fields,const std::vector<const FieldDescriptor * > & message2_fields,std::vector<SpecificField> * parent_fields)826 bool MessageDifferencer::CompareWithFieldsInternal(
827     const Message& message1, const Message& message2, int unpacked_any,
828     const std::vector<const FieldDescriptor*>& message1_fields,
829     const std::vector<const FieldDescriptor*>& message2_fields,
830     std::vector<SpecificField>* parent_fields) {
831   bool isDifferent = false;
832   int field_index1 = 0;
833   int field_index2 = 0;
834 
835   const Reflection* reflection1 = message1.GetReflection();
836   const Reflection* reflection2 = message2.GetReflection();
837 
838   while (true) {
839     const FieldDescriptor* field1 = message1_fields[field_index1];
840     const FieldDescriptor* field2 = message2_fields[field_index2];
841 
842     // Once we have reached sentinel values, we are done the comparison.
843     if (field1 == NULL && field2 == NULL) {
844       break;
845     }
846 
847     // Check for differences in the field itself.
848     if (FieldBefore(field1, field2)) {
849       // Field 1 is not in the field list for message 2.
850       if (IsIgnored(message1, message2, field1, *parent_fields)) {
851         // We are ignoring field1. Report the ignore and move on to
852         // the next field in message1_fields.
853         if (reporter_ != NULL) {
854           SpecificField& specific_field = PushSpecificField(parent_fields);
855           specific_field.message1 = &message1;
856           specific_field.message2 = &message2;
857           specific_field.unpacked_any = unpacked_any;
858           specific_field.field = field1;
859           if (report_ignores_) {
860             reporter_->ReportIgnored(message1, message2, *parent_fields);
861           }
862           parent_fields->pop_back();
863         }
864         ++field_index1;
865         continue;
866       }
867 
868       if (reporter_ != NULL) {
869         assert(field1 != NULL);
870         int count = field1->is_repeated()
871                         ? reflection1->FieldSize(message1, field1)
872                         : 1;
873 
874         for (int i = 0; i < count; ++i) {
875           SpecificField& specific_field = PushSpecificField(parent_fields);
876           specific_field.message1 = &message1;
877           specific_field.message2 = &message2;
878           specific_field.unpacked_any = unpacked_any;
879           specific_field.field = field1;
880           if (field1->is_repeated()) {
881             AddSpecificIndex(&specific_field, message1, field1, i);
882           } else {
883             specific_field.index = -1;
884           }
885 
886           reporter_->ReportDeleted(message1, message2, *parent_fields);
887           parent_fields->pop_back();
888         }
889 
890         isDifferent = true;
891       } else {
892         return false;
893       }
894 
895       ++field_index1;
896       continue;
897     } else if (FieldBefore(field2, field1)) {
898       const bool ignore_field =
899           IsIgnored(message1, message2, field2, *parent_fields);
900       if (!ignore_field && force_compare_no_presence_fields_.contains(field2)) {
901         force_compare_failure_triggering_fields_.emplace(field2->full_name());
902       }
903 
904       // Field 2 is not in the field list for message 1.
905       if (ignore_field) {
906         // We are ignoring field2. Report the ignore and move on to
907         // the next field in message2_fields.
908         if (reporter_ != NULL) {
909           SpecificField& specific_field = PushSpecificField(parent_fields);
910           specific_field.message1 = &message1;
911           specific_field.message2 = &message2;
912           specific_field.unpacked_any = unpacked_any;
913           specific_field.field = field2;
914           if (report_ignores_) {
915             reporter_->ReportIgnored(message1, message2, *parent_fields);
916           }
917           parent_fields->pop_back();
918         }
919         ++field_index2;
920         continue;
921       }
922 
923       if (reporter_ != NULL) {
924         int count = field2->is_repeated()
925                         ? reflection2->FieldSize(message2, field2)
926                         : 1;
927 
928         for (int i = 0; i < count; ++i) {
929           SpecificField& specific_field = PushSpecificField(parent_fields);
930           specific_field.message1 = &message1,
931           specific_field.message2 = &message2;
932           specific_field.unpacked_any = unpacked_any;
933           specific_field.field = field2;
934           if (field2->is_repeated()) {
935             specific_field.index = i;
936             AddSpecificNewIndex(&specific_field, message2, field2, i);
937           } else {
938             specific_field.index = -1;
939             specific_field.new_index = -1;
940           }
941 
942           specific_field.forced_compare_no_presence_ =
943               force_compare_no_presence_ &&
944               force_compare_no_presence_fields_.contains(specific_field.field);
945 
946           reporter_->ReportAdded(message1, message2, *parent_fields);
947           parent_fields->pop_back();
948         }
949 
950         isDifferent = true;
951       } else {
952         return false;
953       }
954 
955       ++field_index2;
956       continue;
957     }
958 
959     // By this point, field1 and field2 are guaranteed to point to the same
960     // field, so we can now compare the values.
961     if (IsIgnored(message1, message2, field1, *parent_fields)) {
962       // Ignore this field. Report and move on.
963       if (reporter_ != NULL) {
964         SpecificField& specific_field = PushSpecificField(parent_fields);
965         specific_field.message1 = &message1;
966         specific_field.message2 = &message2;
967         specific_field.unpacked_any = unpacked_any;
968         specific_field.field = field1;
969         if (report_ignores_) {
970           reporter_->ReportIgnored(message1, message2, *parent_fields);
971         }
972         parent_fields->pop_back();
973       }
974 
975       ++field_index1;
976       ++field_index2;
977       continue;
978     }
979 
980     bool fieldDifferent = false;
981     assert(field1 != NULL);
982     if (field1->is_map()) {
983       fieldDifferent = !CompareMapField(message1, message2, unpacked_any,
984                                         field1, parent_fields);
985     } else if (field1->is_repeated()) {
986       fieldDifferent = !CompareRepeatedField(message1, message2, unpacked_any,
987                                              field1, parent_fields);
988     } else {
989       fieldDifferent = !CompareFieldValueUsingParentFields(
990           message1, message2, unpacked_any, field1, -1, -1, parent_fields);
991 
992       if (force_compare_no_presence_fields_.contains(field1)) {
993         force_compare_failure_triggering_fields_.emplace(field1->full_name());
994       }
995 
996       if (reporter_ != nullptr) {
997         SpecificField& specific_field = PushSpecificField(parent_fields);
998         specific_field.message1 = &message1;
999         specific_field.message2 = &message2;
1000         specific_field.unpacked_any = unpacked_any;
1001         specific_field.field = field1;
1002         specific_field.forced_compare_no_presence_ =
1003             force_compare_no_presence_ &&
1004             force_compare_no_presence_fields_.contains(field1);
1005 
1006         if (fieldDifferent) {
1007           reporter_->ReportModified(message1, message2, *parent_fields);
1008           isDifferent = true;
1009         } else if (report_matches_) {
1010           reporter_->ReportMatched(message1, message2, *parent_fields);
1011         }
1012         parent_fields->pop_back();
1013       }
1014     }
1015     if (fieldDifferent) {
1016       if (reporter_ == nullptr) return false;
1017       isDifferent = true;
1018     }
1019     // Increment the field indices.
1020     ++field_index1;
1021     ++field_index2;
1022   }
1023 
1024   return !isDifferent;
1025 }
1026 
IsMatch(const FieldDescriptor * repeated_field,const MapKeyComparator * key_comparator,const Message * message1,const Message * message2,int unpacked_any,const std::vector<SpecificField> & parent_fields,Reporter * reporter,int index1,int index2)1027 bool MessageDifferencer::IsMatch(
1028     const FieldDescriptor* repeated_field,
1029     const MapKeyComparator* key_comparator, const Message* message1,
1030     const Message* message2, int unpacked_any,
1031     const std::vector<SpecificField>& parent_fields, Reporter* reporter,
1032     int index1, int index2) {
1033   std::vector<SpecificField> current_parent_fields(parent_fields);
1034   if (repeated_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
1035     return CompareFieldValueUsingParentFields(
1036         *message1, *message2, unpacked_any, repeated_field, index1, index2,
1037         &current_parent_fields);
1038   }
1039   // Back up the Reporter and output_string_.  They will be reset in the
1040   // following code.
1041   Reporter* backup_reporter = reporter_;
1042   std::string* output_string = output_string_;
1043   reporter_ = reporter;
1044   output_string_ = NULL;
1045   bool match;
1046 
1047   if (key_comparator == NULL) {
1048     match = CompareFieldValueUsingParentFields(
1049         *message1, *message2, unpacked_any, repeated_field, index1, index2,
1050         &current_parent_fields);
1051   } else {
1052     const Reflection* reflection1 = message1->GetReflection();
1053     const Reflection* reflection2 = message2->GetReflection();
1054     const Message& m1 =
1055         reflection1->GetRepeatedMessage(*message1, repeated_field, index1);
1056     const Message& m2 =
1057         reflection2->GetRepeatedMessage(*message2, repeated_field, index2);
1058     SpecificField specific_field;
1059     specific_field.message1 = message1;
1060     specific_field.message2 = message2;
1061     specific_field.unpacked_any = unpacked_any;
1062     specific_field.field = repeated_field;
1063     if (repeated_field->is_map()) {
1064       specific_field.map_entry1 = &m1;
1065       specific_field.map_entry2 = &m2;
1066     }
1067     specific_field.index = index1;
1068     specific_field.new_index = index2;
1069     current_parent_fields.push_back(specific_field);
1070     match = key_comparator->IsMatch(m1, m2, false, current_parent_fields);
1071   }
1072 
1073   reporter_ = backup_reporter;
1074   output_string_ = output_string;
1075   return match;
1076 }
1077 
CompareMapFieldByMapReflection(const Message & message1,const Message & message2,int unpacked_any,const FieldDescriptor * map_field,std::vector<SpecificField> * parent_fields,DefaultFieldComparator * comparator)1078 bool MessageDifferencer::CompareMapFieldByMapReflection(
1079     const Message& message1, const Message& message2, int unpacked_any,
1080     const FieldDescriptor* map_field, std::vector<SpecificField>* parent_fields,
1081     DefaultFieldComparator* comparator) {
1082   ABSL_DCHECK_EQ(nullptr, reporter_);
1083   ABSL_DCHECK(map_field->is_map());
1084   ABSL_DCHECK(map_field_key_comparator_.find(map_field) ==
1085               map_field_key_comparator_.end());
1086   ABSL_DCHECK_EQ(repeated_field_comparison_, AS_LIST);
1087   const Reflection* reflection1 = message1.GetReflection();
1088   const Reflection* reflection2 = message2.GetReflection();
1089   const int count1 = reflection1->MapSize(message1, map_field);
1090   const int count2 = reflection2->MapSize(message2, map_field);
1091   const bool treated_as_subset = IsTreatedAsSubset(map_field);
1092   if (count1 != count2 && !treated_as_subset) {
1093     return false;
1094   }
1095   if (count1 > count2) {
1096     return false;
1097   }
1098 
1099   // First pass: check whether the same keys are present.
1100   for (MapIterator it = reflection1->MapBegin(const_cast<Message*>(&message1),
1101                                               map_field),
1102                    it_end = reflection1->MapEnd(const_cast<Message*>(&message1),
1103                                                 map_field);
1104        it != it_end; ++it) {
1105     if (!reflection2->ContainsMapKey(message2, map_field, it.GetKey())) {
1106       return false;
1107     }
1108   }
1109 
1110   // Second pass: compare values for matching keys.
1111   const FieldDescriptor* val_des = map_field->message_type()->map_value();
1112   switch (val_des->cpp_type()) {
1113 #define HANDLE_TYPE(CPPTYPE, METHOD, COMPAREMETHOD)                           \
1114   case FieldDescriptor::CPPTYPE_##CPPTYPE: {                                  \
1115     for (MapIterator it = reflection1->MapBegin(                              \
1116                          const_cast<Message*>(&message1), map_field),         \
1117                      it_end = reflection1->MapEnd(                            \
1118                          const_cast<Message*>(&message1), map_field);         \
1119          it != it_end; ++it) {                                                \
1120       MapValueConstRef value2;                                                \
1121       reflection2->LookupMapValue(message2, map_field, it.GetKey(), &value2); \
1122       if (!comparator->Compare##COMPAREMETHOD(*val_des,                       \
1123                                               it.GetValueRef().Get##METHOD(), \
1124                                               value2.Get##METHOD())) {        \
1125         return false;                                                         \
1126       }                                                                       \
1127     }                                                                         \
1128     break;                                                                    \
1129   }
1130     HANDLE_TYPE(INT32, Int32Value, Int32);
1131     HANDLE_TYPE(INT64, Int64Value, Int64);
1132     HANDLE_TYPE(UINT32, UInt32Value, UInt32);
1133     HANDLE_TYPE(UINT64, UInt64Value, UInt64);
1134     HANDLE_TYPE(DOUBLE, DoubleValue, Double);
1135     HANDLE_TYPE(FLOAT, FloatValue, Float);
1136     HANDLE_TYPE(BOOL, BoolValue, Bool);
1137     HANDLE_TYPE(STRING, StringValue, String);
1138     HANDLE_TYPE(ENUM, EnumValue, Int32);
1139 #undef HANDLE_TYPE
1140     case FieldDescriptor::CPPTYPE_MESSAGE: {
1141       for (MapIterator it = reflection1->MapBegin(
1142                const_cast<Message*>(&message1), map_field);
1143            it !=
1144            reflection1->MapEnd(const_cast<Message*>(&message1), map_field);
1145            ++it) {
1146         if (!reflection2->ContainsMapKey(message2, map_field, it.GetKey())) {
1147           return false;
1148         }
1149         bool compare_result;
1150         MapValueConstRef value2;
1151         reflection2->LookupMapValue(message2, map_field, it.GetKey(), &value2);
1152         // Append currently compared field to the end of parent_fields.
1153         SpecificField specific_value_field;
1154         specific_value_field.message1 = &message1;
1155         specific_value_field.message2 = &message2;
1156         specific_value_field.unpacked_any = unpacked_any;
1157         specific_value_field.field = val_des;
1158         parent_fields->push_back(specific_value_field);
1159         compare_result =
1160             Compare(it.GetValueRef().GetMessageValue(),
1161                     value2.GetMessageValue(), false, parent_fields);
1162         parent_fields->pop_back();
1163         if (!compare_result) {
1164           return false;
1165         }
1166       }
1167       break;
1168     }
1169   }
1170   return true;
1171 }
1172 
CompareMapField(const Message & message1,const Message & message2,int unpacked_any,const FieldDescriptor * repeated_field,std::vector<SpecificField> * parent_fields)1173 bool MessageDifferencer::CompareMapField(
1174     const Message& message1, const Message& message2, int unpacked_any,
1175     const FieldDescriptor* repeated_field,
1176     std::vector<SpecificField>* parent_fields) {
1177   ABSL_DCHECK(repeated_field->is_map());
1178 
1179   // the input FieldDescriptor is guaranteed to be repeated field.
1180   const Reflection* reflection1 = message1.GetReflection();
1181   const Reflection* reflection2 = message2.GetReflection();
1182 
1183   // When both map fields are on map, do not sync to repeated field.
1184   if (reflection1->GetMapData(message1, repeated_field)->IsMapValid() &&
1185       reflection2->GetMapData(message2, repeated_field)->IsMapValid() &&
1186       // TODO: Add support for reporter
1187       reporter_ == nullptr &&
1188       // Users didn't set custom map field key comparator
1189       map_field_key_comparator_.find(repeated_field) ==
1190           map_field_key_comparator_.end() &&
1191       // Users didn't set repeated field comparison
1192       repeated_field_comparison_ == AS_LIST &&
1193       // Users didn't set their own FieldComparator implementation
1194       field_comparator_kind_ == kFCDefault) {
1195     const FieldDescriptor* key_des = repeated_field->message_type()->map_key();
1196     const FieldDescriptor* val_des =
1197         repeated_field->message_type()->map_value();
1198     std::vector<SpecificField> current_parent_fields(*parent_fields);
1199     SpecificField specific_field;
1200     specific_field.message1 = &message1;
1201     specific_field.message2 = &message2;
1202     specific_field.unpacked_any = unpacked_any;
1203     specific_field.field = repeated_field;
1204     current_parent_fields.push_back(specific_field);
1205     if (!IsIgnored(message1, message2, key_des, current_parent_fields) &&
1206         !IsIgnored(message1, message2, val_des, current_parent_fields)) {
1207       return CompareMapFieldByMapReflection(
1208           message1, message2, unpacked_any, repeated_field,
1209           &current_parent_fields, field_comparator_.default_impl);
1210     }
1211   }
1212 
1213   return CompareRepeatedRep(message1, message2, unpacked_any, repeated_field,
1214                             parent_fields);
1215 }
1216 
CompareRepeatedField(const Message & message1,const Message & message2,int unpacked_any,const FieldDescriptor * repeated_field,std::vector<SpecificField> * parent_fields)1217 bool MessageDifferencer::CompareRepeatedField(
1218     const Message& message1, const Message& message2, int unpacked_any,
1219     const FieldDescriptor* repeated_field,
1220     std::vector<SpecificField>* parent_fields) {
1221   ABSL_DCHECK(!repeated_field->is_map());
1222   return CompareRepeatedRep(message1, message2, unpacked_any, repeated_field,
1223                             parent_fields);
1224 }
1225 
CompareRepeatedRep(const Message & message1,const Message & message2,int unpacked_any,const FieldDescriptor * repeated_field,std::vector<SpecificField> * parent_fields)1226 bool MessageDifferencer::CompareRepeatedRep(
1227     const Message& message1, const Message& message2, int unpacked_any,
1228     const FieldDescriptor* repeated_field,
1229     std::vector<SpecificField>* parent_fields) {
1230   // the input FieldDescriptor is guaranteed to be repeated field.
1231   ABSL_DCHECK(repeated_field->is_repeated());
1232   const Reflection* reflection1 = message1.GetReflection();
1233   const Reflection* reflection2 = message2.GetReflection();
1234 
1235   const int count1 = reflection1->FieldSize(message1, repeated_field);
1236   const int count2 = reflection2->FieldSize(message2, repeated_field);
1237   const bool treated_as_subset = IsTreatedAsSubset(repeated_field);
1238 
1239   // If the field is not treated as subset and no detailed reports is needed,
1240   // we do a quick check on the number of the elements to avoid unnecessary
1241   // comparison.
1242   if (count1 != count2 && reporter_ == NULL && !treated_as_subset) {
1243     return false;
1244   }
1245   // A match can never be found if message1 has more items than message2.
1246   if (count1 > count2 && reporter_ == NULL) {
1247     return false;
1248   }
1249 
1250   // These two list are used for store the index of the correspondent
1251   // element in peer repeated field.
1252   std::vector<int> match_list1;
1253   std::vector<int> match_list2;
1254 
1255   const MapKeyComparator* key_comparator = GetMapKeyComparator(repeated_field);
1256   bool smart_list = IsTreatedAsSmartList(repeated_field);
1257   bool simple_list = key_comparator == nullptr &&
1258                      !IsTreatedAsSet(repeated_field) &&
1259                      !IsTreatedAsSmartSet(repeated_field) && !smart_list;
1260 
1261   // For simple lists, we avoid matching repeated field indices, saving the
1262   // memory allocations that would otherwise be needed for match_list1 and
1263   // match_list2.
1264   if (!simple_list) {
1265     // Try to match indices of the repeated fields. Return false if match fails.
1266     if (!MatchRepeatedFieldIndices(
1267             message1, message2, unpacked_any, repeated_field, key_comparator,
1268             *parent_fields, &match_list1, &match_list2) &&
1269         reporter_ == nullptr) {
1270       return false;
1271     }
1272   }
1273 
1274   bool fieldDifferent = false;
1275   SpecificField specific_field;
1276   specific_field.message1 = &message1;
1277   specific_field.message2 = &message2;
1278   specific_field.unpacked_any = unpacked_any;
1279   specific_field.field = repeated_field;
1280 
1281   // At this point, we have already matched pairs of fields (with the reporting
1282   // to be done later). Now to check if the paired elements are different.
1283   int next_unmatched_index = 0;
1284   for (int i = 0; i < count1; i++) {
1285     if (simple_list && i >= count2) {
1286       break;
1287     }
1288     if (!simple_list && match_list1[i] == -1) {
1289       if (smart_list) {
1290         if (reporter_ == nullptr) return false;
1291         AddSpecificIndex(&specific_field, message1, repeated_field, i);
1292         parent_fields->push_back(specific_field);
1293         reporter_->ReportDeleted(message1, message2, *parent_fields);
1294         parent_fields->pop_back();
1295         fieldDifferent = true;
1296         // Use -2 to mark this element has been reported.
1297         match_list1[i] = -2;
1298       }
1299       continue;
1300     }
1301     if (smart_list) {
1302       for (int j = next_unmatched_index; j < match_list1[i]; ++j) {
1303         ABSL_CHECK_LE(0, j);
1304         if (reporter_ == nullptr) return false;
1305         specific_field.index = j;
1306         AddSpecificNewIndex(&specific_field, message2, repeated_field, j);
1307         parent_fields->push_back(specific_field);
1308         reporter_->ReportAdded(message1, message2, *parent_fields);
1309         parent_fields->pop_back();
1310         fieldDifferent = true;
1311         // Use -2 to mark this element has been reported.
1312         match_list2[j] = -2;
1313       }
1314     }
1315     AddSpecificIndex(&specific_field, message1, repeated_field, i);
1316     if (simple_list) {
1317       AddSpecificNewIndex(&specific_field, message2, repeated_field, i);
1318     } else {
1319       AddSpecificNewIndex(&specific_field, message2, repeated_field,
1320                           match_list1[i]);
1321       next_unmatched_index = match_list1[i] + 1;
1322     }
1323 
1324     const bool result = CompareFieldValueUsingParentFields(
1325         message1, message2, unpacked_any, repeated_field, i,
1326         specific_field.new_index, parent_fields);
1327 
1328     // If we have found differences, either report them or terminate if
1329     // no reporter is present. Note that ReportModified, ReportMoved, and
1330     // ReportMatched are all mutually exclusive.
1331     if (!result) {
1332       if (reporter_ == NULL) return false;
1333       parent_fields->push_back(specific_field);
1334       reporter_->ReportModified(message1, message2, *parent_fields);
1335       parent_fields->pop_back();
1336       fieldDifferent = true;
1337     } else if (reporter_ != NULL &&
1338                specific_field.index != specific_field.new_index &&
1339                !specific_field.field->is_map() && report_moves_) {
1340       parent_fields->push_back(specific_field);
1341       reporter_->ReportMoved(message1, message2, *parent_fields);
1342       parent_fields->pop_back();
1343     } else if (report_matches_ && reporter_ != NULL) {
1344       parent_fields->push_back(specific_field);
1345       reporter_->ReportMatched(message1, message2, *parent_fields);
1346       parent_fields->pop_back();
1347     }
1348   }
1349 
1350   // Report any remaining additions or deletions.
1351   for (int i = 0; i < count2; ++i) {
1352     if (!simple_list && match_list2[i] != -1) continue;
1353     if (simple_list && i < count1) continue;
1354     if (!treated_as_subset) {
1355       fieldDifferent = true;
1356     }
1357 
1358     if (reporter_ == NULL) continue;
1359     specific_field.index = i;
1360     AddSpecificNewIndex(&specific_field, message2, repeated_field, i);
1361     parent_fields->push_back(specific_field);
1362     reporter_->ReportAdded(message1, message2, *parent_fields);
1363     parent_fields->pop_back();
1364   }
1365 
1366   for (int i = 0; i < count1; ++i) {
1367     if (!simple_list && match_list1[i] != -1) continue;
1368     if (simple_list && i < count2) continue;
1369     assert(reporter_ != NULL);
1370     AddSpecificIndex(&specific_field, message1, repeated_field, i);
1371     parent_fields->push_back(specific_field);
1372     reporter_->ReportDeleted(message1, message2, *parent_fields);
1373     parent_fields->pop_back();
1374     fieldDifferent = true;
1375   }
1376   return !fieldDifferent;
1377 }
1378 
CompareFieldValue(const Message & message1,const Message & message2,int unpacked_any,const FieldDescriptor * field,int index1,int index2)1379 bool MessageDifferencer::CompareFieldValue(const Message& message1,
1380                                            const Message& message2,
1381                                            int unpacked_any,
1382                                            const FieldDescriptor* field,
1383                                            int index1, int index2) {
1384   return CompareFieldValueUsingParentFields(message1, message2, unpacked_any,
1385                                             field, index1, index2, nullptr);
1386 }
1387 
CompareFieldValueUsingParentFields(const Message & message1,const Message & message2,int unpacked_any,const FieldDescriptor * field,int index1,int index2,std::vector<SpecificField> * parent_fields)1388 bool MessageDifferencer::CompareFieldValueUsingParentFields(
1389     const Message& message1, const Message& message2, int unpacked_any,
1390     const FieldDescriptor* field, int index1, int index2,
1391     std::vector<SpecificField>* parent_fields) {
1392   FieldContext field_context(parent_fields);
1393   FieldComparator::ComparisonResult result = GetFieldComparisonResult(
1394       message1, message2, field, index1, index2, &field_context);
1395 
1396   if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
1397       result == FieldComparator::RECURSE) {
1398     // Get the nested messages and compare them using one of the Compare
1399     // methods.
1400     const Reflection* reflection1 = message1.GetReflection();
1401     const Reflection* reflection2 = message2.GetReflection();
1402     const Message& m1 =
1403         field->is_repeated()
1404             ? reflection1->GetRepeatedMessage(message1, field, index1)
1405             : reflection1->GetMessage(message1, field);
1406     const Message& m2 =
1407         field->is_repeated()
1408             ? reflection2->GetRepeatedMessage(message2, field, index2)
1409             : reflection2->GetMessage(message2, field);
1410 
1411     // parent_fields is used in calls to Reporter methods.
1412     if (parent_fields != NULL) {
1413       // Append currently compared field to the end of parent_fields.
1414       SpecificField& specific_field = PushSpecificField(parent_fields);
1415       specific_field.message1 = &message1;
1416       specific_field.message2 = &message2;
1417       specific_field.unpacked_any = unpacked_any;
1418       specific_field.field = field;
1419       AddSpecificIndex(&specific_field, message1, field, index1);
1420       AddSpecificNewIndex(&specific_field, message2, field, index2);
1421       const bool compare_result = Compare(m1, m2, false, parent_fields);
1422       parent_fields->pop_back();
1423       return compare_result;
1424     } else {
1425       // Recreates parent_fields as if m1 and m2 had no parents.
1426       return Compare(m1, m2);
1427     }
1428   } else {
1429     return (result == FieldComparator::SAME);
1430   }
1431 }
1432 
CheckPathChanged(const std::vector<SpecificField> & field_path)1433 bool MessageDifferencer::CheckPathChanged(
1434     const std::vector<SpecificField>& field_path) {
1435   for (const SpecificField& specific_field : field_path) {
1436     // Don't check indexes for map entries -- maps are unordered.
1437     if (specific_field.field != nullptr && specific_field.field->is_map())
1438       continue;
1439     if (specific_field.index != specific_field.new_index) return true;
1440   }
1441   return false;
1442 }
1443 
IsTreatedAsSet(const FieldDescriptor * field)1444 bool MessageDifferencer::IsTreatedAsSet(const FieldDescriptor* field) {
1445   if (!field->is_repeated()) return false;
1446   if (repeated_field_comparisons_.find(field) !=
1447       repeated_field_comparisons_.end()) {
1448     return repeated_field_comparisons_[field] == AS_SET;
1449   }
1450   return GetMapKeyComparator(field) == nullptr &&
1451          repeated_field_comparison_ == AS_SET;
1452 }
1453 
IsTreatedAsSmartSet(const FieldDescriptor * field)1454 bool MessageDifferencer::IsTreatedAsSmartSet(const FieldDescriptor* field) {
1455   if (!field->is_repeated()) return false;
1456   if (repeated_field_comparisons_.find(field) !=
1457       repeated_field_comparisons_.end()) {
1458     return repeated_field_comparisons_[field] == AS_SMART_SET;
1459   }
1460   return GetMapKeyComparator(field) == nullptr &&
1461          repeated_field_comparison_ == AS_SMART_SET;
1462 }
1463 
IsTreatedAsSmartList(const FieldDescriptor * field)1464 bool MessageDifferencer::IsTreatedAsSmartList(const FieldDescriptor* field) {
1465   if (!field->is_repeated()) return false;
1466   if (repeated_field_comparisons_.find(field) !=
1467       repeated_field_comparisons_.end()) {
1468     return repeated_field_comparisons_[field] == AS_SMART_LIST;
1469   }
1470   return GetMapKeyComparator(field) == nullptr &&
1471          repeated_field_comparison_ == AS_SMART_LIST;
1472 }
1473 
IsTreatedAsSubset(const FieldDescriptor * field)1474 bool MessageDifferencer::IsTreatedAsSubset(const FieldDescriptor* field) {
1475   return scope_ == PARTIAL &&
1476          (IsTreatedAsSet(field) || GetMapKeyComparator(field) != NULL);
1477 }
1478 
IsIgnored(const Message & message1,const Message & message2,const FieldDescriptor * field,const std::vector<SpecificField> & parent_fields)1479 bool MessageDifferencer::IsIgnored(
1480     const Message& message1, const Message& message2,
1481     const FieldDescriptor* field,
1482     const std::vector<SpecificField>& parent_fields) {
1483   if (ignored_fields_.find(field) != ignored_fields_.end()) {
1484     return true;
1485   }
1486   for (const auto& criteria : ignore_criteria_) {
1487     if (criteria->IsIgnored(message1, message2, field, parent_fields)) {
1488       return true;
1489     }
1490   }
1491   return false;
1492 }
1493 
IsUnknownFieldIgnored(const Message & message1,const Message & message2,const SpecificField & field,const std::vector<SpecificField> & parent_fields)1494 bool MessageDifferencer::IsUnknownFieldIgnored(
1495     const Message& message1, const Message& message2,
1496     const SpecificField& field,
1497     const std::vector<SpecificField>& parent_fields) {
1498   for (const auto& criteria : ignore_criteria_) {
1499     if (criteria->IsUnknownFieldIgnored(message1, message2, field,
1500                                         parent_fields)) {
1501       return true;
1502     }
1503   }
1504   return false;
1505 }
1506 
1507 const MessageDifferencer::MapKeyComparator*
GetMapKeyComparator(const FieldDescriptor * field) const1508 MessageDifferencer ::GetMapKeyComparator(const FieldDescriptor* field) const {
1509   if (!field->is_repeated()) return nullptr;
1510   auto it = map_field_key_comparator_.find(field);
1511   if (it != map_field_key_comparator_.end()) {
1512     return it->second;
1513   }
1514   if (field->is_map()) {
1515     // field cannot already be treated as list or set since TreatAsList() and
1516     // TreatAsSet() call GetMapKeyComparator() and fail if it returns non-NULL.
1517     return &map_entry_key_comparator_;
1518   }
1519   return nullptr;
1520 }
1521 
1522 namespace {
1523 
1524 typedef std::pair<int, const UnknownField*> IndexUnknownFieldPair;
1525 
1526 struct UnknownFieldOrdering {
operator ()google::protobuf::util::__anon9a8754e90311::UnknownFieldOrdering1527   inline bool operator()(const IndexUnknownFieldPair& a,
1528                          const IndexUnknownFieldPair& b) const {
1529     if (a.second->number() < b.second->number()) return true;
1530     if (a.second->number() > b.second->number()) return false;
1531     return a.second->type() < b.second->type();
1532   }
1533 };
1534 
1535 }  // namespace
1536 
UnpackAny(const Message & any,std::unique_ptr<Message> * data)1537 bool MessageDifferencer::UnpackAnyField::UnpackAny(
1538     const Message& any, std::unique_ptr<Message>* data) {
1539   const Reflection* reflection = any.GetReflection();
1540   const FieldDescriptor* type_url_field;
1541   const FieldDescriptor* value_field;
1542   if (!internal::GetAnyFieldDescriptors(any, &type_url_field, &value_field)) {
1543     return false;
1544   }
1545   const std::string& type_url = reflection->GetString(any, type_url_field);
1546   std::string full_type_name;
1547   if (!internal::ParseAnyTypeUrl(type_url, &full_type_name)) {
1548     return false;
1549   }
1550 
1551   const Descriptor* desc =
1552       any.GetDescriptor()->file()->pool()->FindMessageTypeByName(
1553           full_type_name);
1554   if (desc == NULL) {
1555     return false;
1556   }
1557 
1558   if (dynamic_message_factory_ == NULL) {
1559     dynamic_message_factory_.reset(new DynamicMessageFactory());
1560   }
1561   data->reset(dynamic_message_factory_->GetPrototype(desc)->New());
1562   std::string serialized_value = reflection->GetString(any, value_field);
1563   if (!(*data)->ParsePartialFromString(serialized_value)) {
1564     ABSL_DLOG(ERROR) << "Failed to parse value for " << full_type_name;
1565     return false;
1566   }
1567   return true;
1568 }
1569 
CompareUnknownFields(const Message & message1,const Message & message2,const UnknownFieldSet & unknown_field_set1,const UnknownFieldSet & unknown_field_set2,std::vector<SpecificField> * parent_field)1570 bool MessageDifferencer::CompareUnknownFields(
1571     const Message& message1, const Message& message2,
1572     const UnknownFieldSet& unknown_field_set1,
1573     const UnknownFieldSet& unknown_field_set2,
1574     std::vector<SpecificField>* parent_field) {
1575   // Ignore unknown fields in EQUIVALENT mode.
1576   if (message_field_comparison_ == EQUIVALENT) return true;
1577 
1578   if (unknown_field_set1.empty() && unknown_field_set2.empty()) {
1579     return true;
1580   }
1581 
1582   bool is_different = false;
1583 
1584   // We first sort the unknown fields by field number and type (in other words,
1585   // in tag order), making sure to preserve ordering of values with the same
1586   // tag.  This allows us to report only meaningful differences between the
1587   // two sets -- that is, differing values for the same tag.  We use
1588   // IndexUnknownFieldPairs to keep track of the field's original index for
1589   // reporting purposes.
1590   std::vector<IndexUnknownFieldPair> fields1;  // unknown_field_set1, sorted
1591   std::vector<IndexUnknownFieldPair> fields2;  // unknown_field_set2, sorted
1592   fields1.reserve(unknown_field_set1.field_count());
1593   fields2.reserve(unknown_field_set2.field_count());
1594 
1595   for (int i = 0; i < unknown_field_set1.field_count(); i++) {
1596     fields1.push_back(std::make_pair(i, &unknown_field_set1.field(i)));
1597   }
1598   for (int i = 0; i < unknown_field_set2.field_count(); i++) {
1599     fields2.push_back(std::make_pair(i, &unknown_field_set2.field(i)));
1600   }
1601 
1602   UnknownFieldOrdering is_before;
1603   std::stable_sort(fields1.begin(), fields1.end(), is_before);
1604   std::stable_sort(fields2.begin(), fields2.end(), is_before);
1605 
1606   // In order to fill in SpecificField::index, we have to keep track of how
1607   // many values we've seen with the same field number and type.
1608   // current_repeated points at the first field in this range, and
1609   // current_repeated_start{1,2} are the indexes of the first field in the
1610   // range within fields1 and fields2.
1611   const UnknownField* current_repeated = NULL;
1612   int current_repeated_start1 = 0;
1613   int current_repeated_start2 = 0;
1614 
1615   // Now that we have two sorted lists, we can detect fields which appear only
1616   // in one list or the other by traversing them simultaneously.
1617   size_t index1 = 0;
1618   size_t index2 = 0;
1619   while (index1 < fields1.size() || index2 < fields2.size()) {
1620     enum {
1621       ADDITION,
1622       DELETION,
1623       MODIFICATION,
1624       COMPARE_GROUPS,
1625       NO_CHANGE
1626     } change_type;
1627 
1628     // focus_field is the field we're currently reporting on.  (In the case
1629     // of a modification, it's the field on the left side.)
1630     const UnknownField* focus_field;
1631     bool match = false;
1632 
1633     if (index2 == fields2.size() ||
1634         (index1 < fields1.size() &&
1635          is_before(fields1[index1], fields2[index2]))) {
1636       // fields1[index1] is not present in fields2.
1637       change_type = DELETION;
1638       focus_field = fields1[index1].second;
1639     } else if (index1 == fields1.size() ||
1640                is_before(fields2[index2], fields1[index1])) {
1641       // fields2[index2] is not present in fields1.
1642       if (scope_ == PARTIAL) {
1643         // Ignore.
1644         ++index2;
1645         continue;
1646       }
1647       change_type = ADDITION;
1648       focus_field = fields2[index2].second;
1649     } else {
1650       // Field type and number are the same.  See if the values differ.
1651       change_type = MODIFICATION;
1652       focus_field = fields1[index1].second;
1653 
1654       switch (focus_field->type()) {
1655         case UnknownField::TYPE_VARINT:
1656           match = fields1[index1].second->varint() ==
1657                   fields2[index2].second->varint();
1658           break;
1659         case UnknownField::TYPE_FIXED32:
1660           match = fields1[index1].second->fixed32() ==
1661                   fields2[index2].second->fixed32();
1662           break;
1663         case UnknownField::TYPE_FIXED64:
1664           match = fields1[index1].second->fixed64() ==
1665                   fields2[index2].second->fixed64();
1666           break;
1667         case UnknownField::TYPE_LENGTH_DELIMITED:
1668           match = fields1[index1].second->length_delimited() ==
1669                   fields2[index2].second->length_delimited();
1670           break;
1671         case UnknownField::TYPE_GROUP:
1672           // We must deal with this later, after building the SpecificField.
1673           change_type = COMPARE_GROUPS;
1674           break;
1675       }
1676       if (match && change_type != COMPARE_GROUPS) {
1677         change_type = NO_CHANGE;
1678       }
1679     }
1680 
1681     if (current_repeated == NULL ||
1682         focus_field->number() != current_repeated->number() ||
1683         focus_field->type() != current_repeated->type()) {
1684       // We've started a new repeated field.
1685       current_repeated = focus_field;
1686       current_repeated_start1 = index1;
1687       current_repeated_start2 = index2;
1688     }
1689 
1690     if (change_type == NO_CHANGE && reporter_ == NULL) {
1691       // Fields were already compared and matched and we have no reporter.
1692       ++index1;
1693       ++index2;
1694       continue;
1695     }
1696 
1697     // Build the SpecificField.  This is slightly complicated.
1698     SpecificField specific_field;
1699     specific_field.message1 = &message1;
1700     specific_field.message2 = &message2;
1701     specific_field.unknown_field_number = focus_field->number();
1702     specific_field.unknown_field_type = focus_field->type();
1703 
1704     specific_field.unknown_field_set1 = &unknown_field_set1;
1705     specific_field.unknown_field_set2 = &unknown_field_set2;
1706 
1707     if (change_type != ADDITION) {
1708       specific_field.unknown_field_index1 = fields1[index1].first;
1709     }
1710     if (change_type != DELETION) {
1711       specific_field.unknown_field_index2 = fields2[index2].first;
1712     }
1713 
1714     // Calculate the field index.
1715     if (change_type == ADDITION) {
1716       specific_field.index = index2 - current_repeated_start2;
1717       specific_field.new_index = index2 - current_repeated_start2;
1718     } else {
1719       specific_field.index = index1 - current_repeated_start1;
1720       specific_field.new_index = index2 - current_repeated_start2;
1721     }
1722 
1723     if (IsUnknownFieldIgnored(message1, message2, specific_field,
1724                               *parent_field)) {
1725       if (report_ignores_ && reporter_ != NULL) {
1726         parent_field->push_back(specific_field);
1727         reporter_->ReportUnknownFieldIgnored(message1, message2, *parent_field);
1728         parent_field->pop_back();
1729       }
1730       if (change_type != ADDITION) ++index1;
1731       if (change_type != DELETION) ++index2;
1732       continue;
1733     }
1734 
1735     if (change_type == ADDITION || change_type == DELETION ||
1736         change_type == MODIFICATION) {
1737       if (reporter_ == NULL) {
1738         // We found a difference and we have no reporter.
1739         return false;
1740       }
1741       is_different = true;
1742     }
1743 
1744     parent_field->push_back(specific_field);
1745 
1746     switch (change_type) {
1747       case ADDITION:
1748         reporter_->ReportAdded(message1, message2, *parent_field);
1749         ++index2;
1750         break;
1751       case DELETION:
1752         reporter_->ReportDeleted(message1, message2, *parent_field);
1753         ++index1;
1754         break;
1755       case MODIFICATION:
1756         reporter_->ReportModified(message1, message2, *parent_field);
1757         ++index1;
1758         ++index2;
1759         break;
1760       case COMPARE_GROUPS:
1761         if (!CompareUnknownFields(
1762                 message1, message2, fields1[index1].second->group(),
1763                 fields2[index2].second->group(), parent_field)) {
1764           if (reporter_ == NULL) return false;
1765           is_different = true;
1766           reporter_->ReportModified(message1, message2, *parent_field);
1767         }
1768         ++index1;
1769         ++index2;
1770         break;
1771       case NO_CHANGE:
1772         ++index1;
1773         ++index2;
1774         if (report_matches_) {
1775           reporter_->ReportMatched(message1, message2, *parent_field);
1776         }
1777     }
1778 
1779     parent_field->pop_back();
1780   }
1781 
1782   return !is_different;
1783 }
1784 
1785 namespace {
1786 
1787 // Find maximum bipartite matching using the argumenting path algorithm.
1788 class MaximumMatcher {
1789  public:
1790   typedef std::function<bool(int, int)> NodeMatchCallback;
1791   // MaximumMatcher takes ownership of the passed in callback and uses it to
1792   // determine whether a node on the left side of the bipartial graph matches
1793   // a node on the right side. count1 is the number of nodes on the left side
1794   // of the graph and count2 to is the number of nodes on the right side.
1795   // Every node is referred to using 0-based indices.
1796   // If a maximum match is found, the result will be stored in match_list1 and
1797   // match_list2. match_list1[i] == j means the i-th node on the left side is
1798   // matched to the j-th node on the right side and match_list2[x] == y means
1799   // the x-th node on the right side is matched to y-th node on the left side.
1800   // match_list1[i] == -1 means the node is not matched. Same with match_list2.
1801   MaximumMatcher(int count1, int count2, NodeMatchCallback callback,
1802                  std::vector<int>* match_list1, std::vector<int>* match_list2);
1803   MaximumMatcher(const MaximumMatcher&) = delete;
1804   MaximumMatcher& operator=(const MaximumMatcher&) = delete;
1805   // Find a maximum match and return the number of matched node pairs.
1806   // If early_return is true, this method will return 0 immediately when it
1807   // finds that not all nodes on the left side can be matched.
1808   int FindMaximumMatch(bool early_return);
1809 
1810  private:
1811   // Determines whether the node on the left side of the bipartial graph
1812   // matches the one on the right side.
1813   bool Match(int left, int right);
1814   // Find an argumenting path starting from the node v on the left side. If a
1815   // path can be found, update match_list2_ to reflect the path and return
1816   // true.
1817   bool FindArgumentPathDFS(int v, std::vector<bool>* visited);
1818 
1819   int count1_;
1820   int count2_;
1821   NodeMatchCallback match_callback_;
1822   absl::flat_hash_map<std::pair<int, int>, bool> cached_match_results_;
1823   std::vector<int>* match_list1_;
1824   std::vector<int>* match_list2_;
1825 };
1826 
MaximumMatcher(int count1,int count2,NodeMatchCallback callback,std::vector<int> * match_list1,std::vector<int> * match_list2)1827 MaximumMatcher::MaximumMatcher(int count1, int count2,
1828                                NodeMatchCallback callback,
1829                                std::vector<int>* match_list1,
1830                                std::vector<int>* match_list2)
1831     : count1_(count1),
1832       count2_(count2),
1833       match_callback_(std::move(callback)),
1834       match_list1_(match_list1),
1835       match_list2_(match_list2) {
1836   match_list1_->assign(count1, -1);
1837   match_list2_->assign(count2, -1);
1838 }
1839 
FindMaximumMatch(bool early_return)1840 int MaximumMatcher::FindMaximumMatch(bool early_return) {
1841   int result = 0;
1842   for (int i = 0; i < count1_; ++i) {
1843     std::vector<bool> visited(count1_);
1844     if (FindArgumentPathDFS(i, &visited)) {
1845       ++result;
1846     } else if (early_return) {
1847       return 0;
1848     }
1849   }
1850   // Backfill match_list1_ as we only filled match_list2_ when finding
1851   // argumenting paths.
1852   for (int i = 0; i < count2_; ++i) {
1853     if ((*match_list2_)[i] != -1) {
1854       (*match_list1_)[(*match_list2_)[i]] = i;
1855     }
1856   }
1857   return result;
1858 }
1859 
Match(int left,int right)1860 bool MaximumMatcher::Match(int left, int right) {
1861   std::pair<int, int> p(left, right);
1862   auto it = cached_match_results_.find(p);
1863   if (it != cached_match_results_.end()) {
1864     return it->second;
1865   }
1866   it = cached_match_results_.emplace_hint(it, p, match_callback_(left, right));
1867   return it->second;
1868 }
1869 
FindArgumentPathDFS(int v,std::vector<bool> * visited)1870 bool MaximumMatcher::FindArgumentPathDFS(int v, std::vector<bool>* visited) {
1871   (*visited)[v] = true;
1872   // We try to match those un-matched nodes on the right side first. This is
1873   // the step that the naive greedy matching algorithm uses. In the best cases
1874   // where the greedy algorithm can find a maximum matching, we will always
1875   // find a match in this step and the performance will be identical to the
1876   // greedy algorithm.
1877   for (int i = 0; i < count2_; ++i) {
1878     int matched = (*match_list2_)[i];
1879     if (matched == -1 && Match(v, i)) {
1880       (*match_list2_)[i] = v;
1881       return true;
1882     }
1883   }
1884   // Then we try those already matched nodes and see if we can find an
1885   // alternative match for the node matched to them.
1886   // The greedy algorithm will stop before this and fail to produce the
1887   // correct result.
1888   for (int i = 0; i < count2_; ++i) {
1889     int matched = (*match_list2_)[i];
1890     if (matched != -1 && Match(v, i)) {
1891       if (!(*visited)[matched] && FindArgumentPathDFS(matched, visited)) {
1892         (*match_list2_)[i] = v;
1893         return true;
1894       }
1895     }
1896   }
1897   return false;
1898 }
1899 
1900 }  // namespace
1901 
MatchRepeatedFieldIndices(const Message & message1,const Message & message2,int unpacked_any,const FieldDescriptor * repeated_field,const MapKeyComparator * key_comparator,const std::vector<SpecificField> & parent_fields,std::vector<int> * match_list1,std::vector<int> * match_list2)1902 bool MessageDifferencer::MatchRepeatedFieldIndices(
1903     const Message& message1, const Message& message2, int unpacked_any,
1904     const FieldDescriptor* repeated_field,
1905     const MapKeyComparator* key_comparator,
1906     const std::vector<SpecificField>& parent_fields,
1907     std::vector<int>* match_list1, std::vector<int>* match_list2) {
1908   const int count1 =
1909       message1.GetReflection()->FieldSize(message1, repeated_field);
1910   const int count2 =
1911       message2.GetReflection()->FieldSize(message2, repeated_field);
1912   const bool is_treated_as_smart_set = IsTreatedAsSmartSet(repeated_field);
1913 
1914   match_list1->assign(count1, -1);
1915   match_list2->assign(count2, -1);
1916 
1917   // In the special case where both repeated fields have exactly one element,
1918   // return without calling the comparator.  This optimization prevents the
1919   // pathological case of deeply nested repeated fields of size 1 from taking
1920   // exponential-time to compare.
1921   //
1922   // In the case where reporter_ is set, we need to do the compare here to
1923   // properly distinguish a modify from an add+delete.  The code below will not
1924   // pass the reporter along in recursive calls to nested repeated fields, so
1925   // the inner call will have the opportunity to perform this optimization and
1926   // avoid exponential-time behavior.
1927   //
1928   // In the case where key_comparator is set, we need to do the compare here to
1929   // fulfill the interface contract that keys will be compared even if the user
1930   // asked to ignore that field.  The code will only compare the key fields
1931   // which (hopefully) do not contain further repeated fields.
1932   if (count1 == 1 && count2 == 1 && reporter_ == nullptr &&
1933       key_comparator == nullptr) {
1934     match_list1->at(0) = 0;
1935     match_list2->at(0) = 0;
1936     return true;
1937   }
1938 
1939   // Ensure that we don't report differences during the matching process. Since
1940   // field comparators could potentially use this message differencer object to
1941   // perform further comparisons, turn off reporting here and re-enable it
1942   // before returning.
1943   Reporter* reporter = reporter_;
1944   reporter_ = NULL;
1945   NumDiffsReporter num_diffs_reporter;
1946   std::vector<int32_t> num_diffs_list1;
1947   if (is_treated_as_smart_set) {
1948     num_diffs_list1.assign(count1, std::numeric_limits<int32_t>::max());
1949   }
1950 
1951   bool success = true;
1952   // Find potential match if this is a special repeated field.
1953   if (scope_ == PARTIAL) {
1954     // When partial matching is enabled, Compare(a, b) && Compare(a, c)
1955     // doesn't necessarily imply Compare(b, c). Therefore a naive greedy
1956     // algorithm will fail to find a maximum matching.
1957     // Here we use the augmenting path algorithm.
1958     auto callback = [&](int i1, int i2) {
1959       return IsMatch(repeated_field, key_comparator, &message1, &message2,
1960                      unpacked_any, parent_fields, nullptr, i1, i2);
1961     };
1962     MaximumMatcher matcher(count1, count2, std::move(callback), match_list1,
1963                            match_list2);
1964     // If diff info is not needed, we should end the matching process as
1965     // soon as possible if not all items can be matched.
1966     bool early_return = (reporter == nullptr);
1967     int match_count = matcher.FindMaximumMatch(early_return);
1968     if (match_count != count1 && early_return) return false;
1969     success = success && (match_count == count1);
1970   } else {
1971     int start_offset = 0;
1972     // If the two repeated fields are treated as sets, optimize for the case
1973     // where both start with same items stored in the same order.
1974     if (IsTreatedAsSet(repeated_field) || is_treated_as_smart_set ||
1975         IsTreatedAsSmartList(repeated_field)) {
1976       start_offset = std::min(count1, count2);
1977       for (int i = 0; i < count1 && i < count2; i++) {
1978         if (IsMatch(repeated_field, key_comparator, &message1, &message2,
1979                     unpacked_any, parent_fields, nullptr, i, i)) {
1980           match_list1->at(i) = i;
1981           match_list2->at(i) = i;
1982         } else {
1983           start_offset = i;
1984           break;
1985         }
1986       }
1987     }
1988     for (int i = start_offset; i < count1; ++i) {
1989       // Indicates any matched elements for this repeated field.
1990       bool match = false;
1991       int matched_j = -1;
1992 
1993       for (int j = start_offset; j < count2; j++) {
1994         if (match_list2->at(j) != -1) {
1995           if (!is_treated_as_smart_set || num_diffs_list1[i] == 0 ||
1996               num_diffs_list1[match_list2->at(j)] == 0) {
1997             continue;
1998           }
1999         }
2000 
2001         if (is_treated_as_smart_set) {
2002           num_diffs_reporter.Reset();
2003           match =
2004               IsMatch(repeated_field, key_comparator, &message1, &message2,
2005                       unpacked_any, parent_fields, &num_diffs_reporter, i, j);
2006         } else {
2007           match = IsMatch(repeated_field, key_comparator, &message1, &message2,
2008                           unpacked_any, parent_fields, nullptr, i, j);
2009         }
2010 
2011         if (is_treated_as_smart_set) {
2012           if (match) {
2013             num_diffs_list1[i] = 0;
2014           } else if (repeated_field->cpp_type() ==
2015                      FieldDescriptor::CPPTYPE_MESSAGE) {
2016             // Replace with the one with fewer diffs.
2017             const int32_t num_diffs = num_diffs_reporter.GetNumDiffs();
2018             if (num_diffs < num_diffs_list1[i]) {
2019               // If j has been already matched to some element, ensure the
2020               // current num_diffs is smaller.
2021               if (match_list2->at(j) == -1 ||
2022                   num_diffs < num_diffs_list1[match_list2->at(j)]) {
2023                 num_diffs_list1[i] = num_diffs;
2024                 match = true;
2025               }
2026             }
2027           }
2028         }
2029 
2030         if (match) {
2031           matched_j = j;
2032           if (!is_treated_as_smart_set || num_diffs_list1[i] == 0) {
2033             break;
2034           }
2035         }
2036       }
2037 
2038       match = (matched_j != -1);
2039       if (match) {
2040         if (is_treated_as_smart_set && match_list2->at(matched_j) != -1) {
2041           // This is to revert the previously matched index in list2.
2042           match_list1->at(match_list2->at(matched_j)) = -1;
2043           match = false;
2044         }
2045         match_list1->at(i) = matched_j;
2046         match_list2->at(matched_j) = i;
2047       }
2048       if (!match && reporter == nullptr) return false;
2049       success = success && match;
2050     }
2051   }
2052 
2053   if (IsTreatedAsSmartList(repeated_field)) {
2054     match_indices_for_smart_list_callback_(match_list1, match_list2);
2055   }
2056 
2057   reporter_ = reporter;
2058 
2059   return success;
2060 }
2061 
GetFieldComparisonResult(const Message & message1,const Message & message2,const FieldDescriptor * field,int index1,int index2,const FieldContext * field_context)2062 FieldComparator::ComparisonResult MessageDifferencer::GetFieldComparisonResult(
2063     const Message& message1, const Message& message2,
2064     const FieldDescriptor* field, int index1, int index2,
2065     const FieldContext* field_context) {
2066   FieldComparator* comparator = field_comparator_kind_ == kFCBase
2067                                     ? field_comparator_.base
2068                                     : field_comparator_.default_impl;
2069   return comparator->Compare(message1, message2, field, index1, index2,
2070                              field_context);
2071 }
2072 
2073 // ===========================================================================
2074 
Reporter()2075 MessageDifferencer::Reporter::Reporter() {}
~Reporter()2076 MessageDifferencer::Reporter::~Reporter() {}
2077 
2078 // ===========================================================================
2079 
MapKeyComparator()2080 MessageDifferencer::MapKeyComparator::MapKeyComparator() {}
~MapKeyComparator()2081 MessageDifferencer::MapKeyComparator::~MapKeyComparator() {}
2082 
2083 // ===========================================================================
2084 
IgnoreCriteria()2085 MessageDifferencer::IgnoreCriteria::IgnoreCriteria() {}
~IgnoreCriteria()2086 MessageDifferencer::IgnoreCriteria::~IgnoreCriteria() {}
2087 
2088 // ===========================================================================
2089 
2090 // Note that the printer's delimiter is not used, because if we are given a
2091 // printer, we don't know its delimiter.
StreamReporter(io::ZeroCopyOutputStream * output)2092 MessageDifferencer::StreamReporter::StreamReporter(
2093     io::ZeroCopyOutputStream* output)
2094     : printer_(new io::Printer(output, '$')),
2095       delete_printer_(true),
2096       report_modified_aggregates_(false),
2097       message1_(nullptr),
2098       message2_(nullptr) {}
2099 
StreamReporter(io::Printer * printer)2100 MessageDifferencer::StreamReporter::StreamReporter(io::Printer* printer)
2101     : printer_(printer),
2102       delete_printer_(false),
2103       report_modified_aggregates_(false),
2104       message1_(nullptr),
2105       message2_(nullptr) {}
2106 
~StreamReporter()2107 MessageDifferencer::StreamReporter::~StreamReporter() {
2108   if (delete_printer_) delete printer_;
2109 }
2110 
PrintPath(const std::vector<SpecificField> & field_path,bool left_side)2111 void MessageDifferencer::StreamReporter::PrintPath(
2112     const std::vector<SpecificField>& field_path, bool left_side) {
2113   for (size_t i = 0; i < field_path.size(); ++i) {
2114     SpecificField specific_field = field_path[i];
2115 
2116     if (specific_field.field != nullptr &&
2117         specific_field.field->name() == "value") {
2118       // check to see if this the value label of a map value.  If so, skip it
2119       // because it isn't meaningful
2120       if (i > 0 && field_path[i - 1].field->is_map()) {
2121         continue;
2122       }
2123     }
2124     if (i > 0) {
2125       printer_->Print(".");
2126     }
2127     if (specific_field.field != NULL) {
2128       if (specific_field.field->is_extension()) {
2129         printer_->Print("($name$)", "name", specific_field.field->full_name());
2130       } else {
2131         printer_->PrintRaw(specific_field.field->name());
2132         if (specific_field.forced_compare_no_presence_) {
2133           printer_->Print(" (added for better PARTIAL comparison)");
2134         }
2135       }
2136 
2137       if (specific_field.field->is_map()) {
2138         PrintMapKey(left_side, specific_field);
2139         continue;
2140       }
2141     } else {
2142       printer_->PrintRaw(absl::StrCat(specific_field.unknown_field_number));
2143     }
2144     if (left_side && specific_field.index >= 0) {
2145       printer_->Print("[$name$]", "name", absl::StrCat(specific_field.index));
2146     }
2147     if (!left_side && specific_field.new_index >= 0) {
2148       printer_->Print("[$name$]", "name",
2149                       absl::StrCat(specific_field.new_index));
2150     }
2151   }
2152 }
2153 
PrintValue(const Message & message,const std::vector<SpecificField> & field_path,bool left_side)2154 void MessageDifferencer::StreamReporter::PrintValue(
2155     const Message& message, const std::vector<SpecificField>& field_path,
2156     bool left_side) {
2157   const SpecificField& specific_field = field_path.back();
2158   const FieldDescriptor* field = specific_field.field;
2159   if (field != NULL) {
2160     std::string output;
2161     int index = left_side ? specific_field.index : specific_field.new_index;
2162     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
2163       const Reflection* reflection = message.GetReflection();
2164       const Message& field_message =
2165           field->is_repeated()
2166               ? reflection->GetRepeatedMessage(message, field, index)
2167               : reflection->GetMessage(message, field);
2168       const FieldDescriptor* fd = nullptr;
2169 
2170       if (field->is_map() && message1_ != nullptr && message2_ != nullptr) {
2171         fd = field_message.GetDescriptor()->field(1);
2172         if (fd->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
2173           output = PrintShortTextFormat(
2174               field_message.GetReflection()->GetMessage(field_message, fd));
2175         } else {
2176           TextFormat::PrintFieldValueToString(field_message, fd, -1, &output);
2177         }
2178       } else {
2179         output = PrintShortTextFormat(field_message);
2180       }
2181       if (output.empty()) {
2182         printer_->Print("{ }");
2183       } else {
2184         if ((fd != nullptr) &&
2185             (fd->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)) {
2186           printer_->PrintRaw(output);
2187         } else {
2188           printer_->Print("{ $name$ }", "name", output);
2189         }
2190       }
2191     } else {
2192       TextFormat::PrintFieldValueToString(message, field, index, &output);
2193       printer_->PrintRaw(output);
2194     }
2195   } else {
2196     const UnknownFieldSet* unknown_fields =
2197         (left_side ? specific_field.unknown_field_set1
2198                    : specific_field.unknown_field_set2);
2199     const UnknownField* unknown_field =
2200         &unknown_fields->field(left_side ? specific_field.unknown_field_index1
2201                                          : specific_field.unknown_field_index2);
2202     PrintUnknownFieldValue(unknown_field);
2203   }
2204 }
2205 
PrintUnknownFieldValue(const UnknownField * unknown_field)2206 void MessageDifferencer::StreamReporter::PrintUnknownFieldValue(
2207     const UnknownField* unknown_field) {
2208   ABSL_CHECK(unknown_field != NULL) << " Cannot print NULL unknown_field.";
2209 
2210   std::string output;
2211   switch (unknown_field->type()) {
2212     case UnknownField::TYPE_VARINT:
2213       output = absl::StrCat(unknown_field->varint());
2214       break;
2215     case UnknownField::TYPE_FIXED32:
2216       output = absl::StrCat(
2217           "0x", absl::Hex(unknown_field->fixed32(), absl::kZeroPad8));
2218       break;
2219     case UnknownField::TYPE_FIXED64:
2220       output = absl::StrCat(
2221           "0x", absl::Hex(unknown_field->fixed64(), absl::kZeroPad16));
2222       break;
2223     case UnknownField::TYPE_LENGTH_DELIMITED:
2224       output = absl::StrFormat(
2225           "\"%s\"", absl::CEscape(unknown_field->length_delimited()).c_str());
2226       break;
2227     case UnknownField::TYPE_GROUP:
2228       // TODO:  Print the contents of the group like we do for
2229       //   messages.  Requires an equivalent of ShortDebugString() for
2230       //   UnknownFieldSet.
2231       output = "{ ... }";
2232       break;
2233   }
2234   printer_->PrintRaw(output);
2235 }
2236 
Print(const std::string & str)2237 void MessageDifferencer::StreamReporter::Print(const std::string& str) {
2238   printer_->Print(str.c_str());
2239 }
2240 
PrintMapKey(bool left_side,const SpecificField & specific_field)2241 void MessageDifferencer::StreamReporter::PrintMapKey(
2242     bool left_side, const SpecificField& specific_field) {
2243   if (message1_ == nullptr || message2_ == nullptr) {
2244     ABSL_LOG(INFO) << "PrintPath cannot log map keys; "
2245                       "use SetMessages to provide the messages "
2246                       "being compared prior to any processing.";
2247     return;
2248   }
2249 
2250   const Message* found_message =
2251       left_side ? specific_field.map_entry1 : specific_field.map_entry2;
2252   std::string key_string = "";
2253   if (found_message != nullptr) {
2254     // NB: the map key is always the first field
2255     const FieldDescriptor* fd = found_message->GetDescriptor()->field(0);
2256     if (fd->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
2257       // Not using PrintFieldValueToString for strings to avoid extra
2258       // characters
2259       key_string = found_message->GetReflection()->GetString(
2260           *found_message, found_message->GetDescriptor()->field(0));
2261     } else {
2262       TextFormat::PrintFieldValueToString(*found_message, fd, -1, &key_string);
2263     }
2264     if (key_string.empty()) {
2265       key_string = "''";
2266     }
2267     printer_->PrintRaw(absl::StrCat("[", key_string, "]"));
2268   }
2269 }
2270 
ReportAdded(const Message &,const Message & message2,const std::vector<SpecificField> & field_path)2271 void MessageDifferencer::StreamReporter::ReportAdded(
2272     const Message& /*message1*/, const Message& message2,
2273     const std::vector<SpecificField>& field_path) {
2274   printer_->Print("added: ");
2275   PrintPath(field_path, false);
2276   printer_->Print(": ");
2277   PrintValue(message2, field_path, false);
2278   printer_->Print("\n");  // Print for newlines.
2279 }
2280 
ReportDeleted(const Message & message1,const Message &,const std::vector<SpecificField> & field_path)2281 void MessageDifferencer::StreamReporter::ReportDeleted(
2282     const Message& message1, const Message& /*message2*/,
2283     const std::vector<SpecificField>& field_path) {
2284   printer_->Print("deleted: ");
2285   PrintPath(field_path, true);
2286   printer_->Print(": ");
2287   PrintValue(message1, field_path, true);
2288   printer_->Print("\n");  // Print for newlines
2289 }
2290 
ReportModified(const Message & message1,const Message & message2,const std::vector<SpecificField> & field_path)2291 void MessageDifferencer::StreamReporter::ReportModified(
2292     const Message& message1, const Message& message2,
2293     const std::vector<SpecificField>& field_path) {
2294   if (!report_modified_aggregates_ && field_path.back().field == NULL) {
2295     if (field_path.back().unknown_field_type == UnknownField::TYPE_GROUP) {
2296       // Any changes to the subfields have already been printed.
2297       return;
2298     }
2299   } else if (!report_modified_aggregates_) {
2300     if (field_path.back().field->cpp_type() ==
2301         FieldDescriptor::CPPTYPE_MESSAGE) {
2302       // Any changes to the subfields have already been printed.
2303       return;
2304     }
2305   }
2306 
2307   printer_->Print("modified: ");
2308   PrintPath(field_path, true);
2309   if (CheckPathChanged(field_path)) {
2310     printer_->Print(" -> ");
2311     PrintPath(field_path, false);
2312   }
2313   printer_->Print(": ");
2314   PrintValue(message1, field_path, true);
2315   printer_->Print(" -> ");
2316   PrintValue(message2, field_path, false);
2317   printer_->Print("\n");  // Print for newlines.
2318 }
2319 
ReportMoved(const Message & message1,const Message &,const std::vector<SpecificField> & field_path)2320 void MessageDifferencer::StreamReporter::ReportMoved(
2321     const Message& message1, const Message& /*message2*/,
2322     const std::vector<SpecificField>& field_path) {
2323   printer_->Print("moved: ");
2324   PrintPath(field_path, true);
2325   printer_->Print(" -> ");
2326   PrintPath(field_path, false);
2327   printer_->Print(" : ");
2328   PrintValue(message1, field_path, true);
2329   printer_->Print("\n");  // Print for newlines.
2330 }
2331 
ReportMatched(const Message & message1,const Message &,const std::vector<SpecificField> & field_path)2332 void MessageDifferencer::StreamReporter::ReportMatched(
2333     const Message& message1, const Message& /*message2*/,
2334     const std::vector<SpecificField>& field_path) {
2335   printer_->Print("matched: ");
2336   PrintPath(field_path, true);
2337   if (CheckPathChanged(field_path)) {
2338     printer_->Print(" -> ");
2339     PrintPath(field_path, false);
2340   }
2341   printer_->Print(" : ");
2342   PrintValue(message1, field_path, true);
2343   printer_->Print("\n");  // Print for newlines.
2344 }
2345 
ReportIgnored(const Message &,const Message &,const std::vector<SpecificField> & field_path)2346 void MessageDifferencer::StreamReporter::ReportIgnored(
2347     const Message& /*message1*/, const Message& /*message2*/,
2348     const std::vector<SpecificField>& field_path) {
2349   printer_->Print("ignored: ");
2350   PrintPath(field_path, true);
2351   if (CheckPathChanged(field_path)) {
2352     printer_->Print(" -> ");
2353     PrintPath(field_path, false);
2354   }
2355   printer_->Print("\n");  // Print for newlines.
2356 }
2357 
SetMessages(const Message & message1,const Message & message2)2358 void MessageDifferencer::StreamReporter::SetMessages(const Message& message1,
2359                                                      const Message& message2) {
2360   message1_ = &message1;
2361   message2_ = &message2;
2362 }
2363 
ReportUnknownFieldIgnored(const Message &,const Message &,const std::vector<SpecificField> & field_path)2364 void MessageDifferencer::StreamReporter::ReportUnknownFieldIgnored(
2365     const Message& /*message1*/, const Message& /*message2*/,
2366     const std::vector<SpecificField>& field_path) {
2367   printer_->Print("ignored: ");
2368   PrintPath(field_path, true);
2369   if (CheckPathChanged(field_path)) {
2370     printer_->Print(" -> ");
2371     PrintPath(field_path, false);
2372   }
2373   printer_->Print("\n");  // Print for newlines.
2374 }
2375 
2376 MessageDifferencer::MapKeyComparator*
CreateMultipleFieldsMapKeyComparator(const std::vector<std::vector<const FieldDescriptor * >> & key_field_paths)2377 MessageDifferencer::CreateMultipleFieldsMapKeyComparator(
2378     const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths) {
2379   return new MultipleFieldsMapKeyComparator(this, key_field_paths);
2380 }
2381 
2382 }  // namespace util
2383 }  // namespace protobuf
2384 }  // namespace google
2385 
2386 #include "google/protobuf/port_undef.inc"
2387