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, ¤t_parent_fields);
164 } else if (field->is_repeated()) {
165 return message_differencer_->CompareRepeatedField(
166 message1, message2, unpacked_any, field, ¤t_parent_fields);
167 } else {
168 return message_differencer_->CompareFieldValueUsingParentFields(
169 message1, message2, unpacked_any, field, -1, -1,
170 ¤t_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 ¤t_parent_fields);
263 }
264 return message_differencer_->CompareFieldValueUsingParentFields(
265 message1, message2, unpacked_any, key, -1, -1, ¤t_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 ¤t_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 ¤t_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 ¤t_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