35 #include <google/protobuf/util/message_differencer.h>
45 #include <google/protobuf/stubs/logging.h>
46 #include <google/protobuf/stubs/common.h>
47 #include <google/protobuf/stubs/stringprintf.h>
48 #include <google/protobuf/io/printer.h>
49 #include <google/protobuf/io/zero_copy_stream.h>
50 #include <google/protobuf/io/zero_copy_stream_impl.h>
51 #include <google/protobuf/descriptor.pb.h>
52 #include <google/protobuf/descriptor.h>
53 #include <google/protobuf/dynamic_message.h>
54 #include <google/protobuf/generated_enum_reflection.h>
55 #include <google/protobuf/map_field.h>
56 #include <google/protobuf/message.h>
57 #include <google/protobuf/text_format.h>
58 #include <google/protobuf/util/field_comparator.h>
59 #include <google/protobuf/stubs/strutil.h>
62 #include <google/protobuf/port_def.inc>
83 const std::vector<google::protobuf::util::MessageDifferencer::SpecificField>&
92 const std::vector<google::protobuf::util::MessageDifferencer::SpecificField>&
101 const std::vector<google::protobuf::util::MessageDifferencer::SpecificField>&
120 const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths)
131 std::vector<const FieldDescriptor*> key_field_path;
132 key_field_path.push_back(
key);
136 const std::vector<SpecificField>& parent_fields)
const override {
148 const std::vector<SpecificField>& parent_fields,
149 const std::vector<const FieldDescriptor*>& key_field_path,
150 int path_index)
const {
152 std::vector<SpecificField> current_parent_fields(parent_fields);
153 if (path_index ==
static_cast<int64_t>(key_field_path.size() - 1)) {
154 if (
field->is_map()) {
156 ¤t_parent_fields);
157 }
else if (
field->is_repeated()) {
159 message1, message2,
field, ¤t_parent_fields);
162 message1, message2,
field, -1, -1, ¤t_parent_fields);
169 if (!has_field1 && !has_field2) {
172 if (has_field1 != has_field2) {
177 current_parent_fields.push_back(specific_field);
180 current_parent_fields, key_field_path,
195 std::vector<int>* match_list2) {
196 int last_matched_index = -1;
197 for (
size_t i = 0;
i < match_list1->size(); ++
i) {
198 if (match_list1->at(i) < 0) {
201 if (last_matched_index < 0 || match_list1->at(i) > last_matched_index) {
202 last_matched_index = match_list1->at(i);
204 match_list2->at(match_list1->at(i)) = -1;
205 match_list1->at(i) = -1;
213 if (
field->is_map()) {
224 if (
field->is_map()) {
233 MessageDifferencer* message_differencer)
234 : message_differencer_(message_differencer) {}
238 const std::vector<SpecificField>& parent_fields)
const {
244 const bool treat_as_set =
245 (message_differencer_->scope() == PARTIAL &&
246 !message1.GetReflection()->HasField(message1,
key)) ||
247 message_differencer_->IsIgnored(message1, message2,
key, parent_fields);
249 std::vector<SpecificField> current_parent_fields(parent_fields);
251 return message_differencer_->Compare(message1, message2,
252 ¤t_parent_fields);
254 return message_differencer_->CompareFieldValueUsingParentFields(
255 message1, message2,
key, -1, -1, ¤t_parent_fields);
260 MessageDifferencer differencer;
262 return differencer.Compare(message1, message2);
265 bool MessageDifferencer::Equivalent(
const Message& message1,
267 MessageDifferencer differencer;
268 differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT);
270 return differencer.Compare(message1, message2);
273 bool MessageDifferencer::ApproximatelyEquals(
const Message& message1,
275 MessageDifferencer differencer;
276 differencer.set_float_comparison(MessageDifferencer::APPROXIMATE);
278 return differencer.Compare(message1, message2);
281 bool MessageDifferencer::ApproximatelyEquivalent(
const Message& message1,
283 MessageDifferencer differencer;
284 differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT);
285 differencer.set_float_comparison(MessageDifferencer::APPROXIMATE);
287 return differencer.Compare(message1, message2);
292 MessageDifferencer::MessageDifferencer()
294 message_field_comparison_(EQUAL),
296 repeated_field_comparison_(AS_LIST),
297 map_entry_key_comparator_(this),
298 report_matches_(
false),
300 report_ignores_(
true),
301 output_string_(nullptr),
302 match_indices_for_smart_list_callback_(
305 MessageDifferencer::~MessageDifferencer() {
306 for (MapKeyComparator* comparator : owned_key_comparators_) {
309 for (IgnoreCriteria* criteria : ignore_criteria_) {
314 void MessageDifferencer::set_field_comparator(FieldComparator* comparator) {
315 GOOGLE_CHECK(comparator) <<
"Field comparator can't be NULL.";
316 field_comparator_kind_ = kFCBase;
317 field_comparator_.base = comparator;
320 #ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
321 void MessageDifferencer::set_field_comparator(
322 DefaultFieldComparator* comparator) {
323 GOOGLE_CHECK(comparator) <<
"Field comparator can't be NULL.";
324 field_comparator_kind_ = kFCDefault;
325 field_comparator_.default_impl = comparator;
327 #endif // PROTOBUF_FUTURE_BREAKING_CHANGES
329 void MessageDifferencer::set_message_field_comparison(
330 MessageFieldComparison comparison) {
331 message_field_comparison_ = comparison;
334 void MessageDifferencer::set_scope(Scope scope) {
scope_ = scope; }
336 MessageDifferencer::Scope MessageDifferencer::scope() {
return scope_; }
338 void MessageDifferencer::set_float_comparison(FloatComparison comparison) {
339 default_field_comparator_.set_float_comparison(
340 comparison == EXACT ? DefaultFieldComparator::EXACT
341 : DefaultFieldComparator::APPROXIMATE);
344 void MessageDifferencer::set_repeated_field_comparison(
345 RepeatedFieldComparison comparison) {
346 repeated_field_comparison_ = comparison;
349 MessageDifferencer::RepeatedFieldComparison
350 MessageDifferencer::repeated_field_comparison() {
351 return repeated_field_comparison_;
354 void MessageDifferencer::CheckRepeatedFieldComparisons(
356 const RepeatedFieldComparison& new_comparison) {
359 const MapKeyComparator* key_comparator = GetMapKeyComparator(
field);
361 <<
"Cannot treat this repeated field as both MAP and " << new_comparison
366 CheckRepeatedFieldComparisons(
field, AS_SET);
367 repeated_field_comparisons_[
field] = AS_SET;
371 CheckRepeatedFieldComparisons(
field, AS_SMART_SET);
372 repeated_field_comparisons_[
field] = AS_SMART_SET;
375 void MessageDifferencer::SetMatchIndicesForSmartListCallback(
377 match_indices_for_smart_list_callback_ =
callback;
381 CheckRepeatedFieldComparisons(
field, AS_LIST);
382 repeated_field_comparisons_[
field] = AS_LIST;
386 CheckRepeatedFieldComparisons(
field, AS_SMART_LIST);
387 repeated_field_comparisons_[
field] = AS_SMART_LIST;
393 <<
"Field has to be message type. Field name is: " <<
field->
full_name();
396 <<
" must be a direct subfield within the repeated field "
399 repeated_field_comparisons_.end())
400 <<
"Cannot treat the same field as both "
401 << repeated_field_comparisons_[
field]
403 MapKeyComparator* key_comparator =
404 new MultipleFieldsMapKeyComparator(
this,
key);
405 owned_key_comparators_.push_back(key_comparator);
406 map_field_key_comparator_[
field] = key_comparator;
409 void MessageDifferencer::TreatAsMapWithMultipleFieldsAsKey(
411 const std::vector<const FieldDescriptor*>& key_fields) {
412 std::vector<std::vector<const FieldDescriptor*> > key_field_paths;
414 std::vector<const FieldDescriptor*> key_field_path;
415 key_field_path.push_back(key_filed);
416 key_field_paths.push_back(key_field_path);
418 TreatAsMapWithMultipleFieldPathsAsKey(
field, key_field_paths);
421 void MessageDifferencer::TreatAsMapWithMultipleFieldPathsAsKey(
423 const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths) {
427 <<
"Field has to be message type. Field name is: " <<
field->
full_name();
428 for (
const auto& key_field_path : key_field_paths) {
429 for (
size_t j = 0;
j < key_field_path.size(); ++
j) {
431 j == 0 ?
field : key_field_path[
j - 1];
433 GOOGLE_CHECK(child_field->containing_type() == parent_field->message_type())
434 << child_field->full_name()
435 <<
" must be a direct subfield within the field: "
436 << parent_field->full_name();
439 << parent_field->full_name() <<
" has to be of type message.";
441 << parent_field->full_name() <<
" cannot be a repeated field.";
446 repeated_field_comparisons_.end())
447 <<
"Cannot treat the same field as both "
448 << repeated_field_comparisons_[
field]
450 MapKeyComparator* key_comparator =
451 new MultipleFieldsMapKeyComparator(
this, key_field_paths);
452 owned_key_comparators_.push_back(key_comparator);
453 map_field_key_comparator_[
field] = key_comparator;
456 void MessageDifferencer::TreatAsMapUsingKeyComparator(
461 repeated_field_comparisons_.end())
462 <<
"Cannot treat the same field as both "
463 << repeated_field_comparisons_[
field]
465 map_field_key_comparator_[
field] = key_comparator;
468 void MessageDifferencer::AddIgnoreCriteria(IgnoreCriteria* ignore_criteria) {
469 ignore_criteria_.push_back(ignore_criteria);
473 ignored_fields_.insert(
field);
477 double fraction,
double margin) {
478 default_field_comparator_.SetFractionAndMargin(
field, fraction, margin);
485 output_string_->clear();
488 void MessageDifferencer::ReportDifferencesTo(Reporter* reporter) {
491 if (output_string_) {
492 output_string_ = NULL;
495 reporter_ = reporter;
502 if (field1 == NULL) {
506 if (field2 == NULL) {
511 return (field1->number() < field2->number());
516 std::vector<SpecificField> parent_fields;
520 if (output_string_) {
522 StreamReporter reporter(&output_stream);
523 reporter.SetMessages(message1, message2);
524 reporter_ = &reporter;
533 bool MessageDifferencer::CompareWithFields(
535 const std::vector<const FieldDescriptor*>& message1_fields_arg,
536 const std::vector<const FieldDescriptor*>& message2_fields_arg) {
537 if (message1.GetDescriptor() != message2.GetDescriptor()) {
538 GOOGLE_LOG(DFATAL) <<
"Comparison between two messages with different "
543 std::vector<SpecificField> parent_fields;
550 std::copy(message1_fields_arg.cbegin(), message1_fields_arg.cend(),
551 message1_fields.begin());
552 std::copy(message2_fields_arg.cbegin(), message2_fields_arg.cend(),
553 message2_fields.begin());
556 message1_fields[message1_fields_arg.size()] =
nullptr;
557 message2_fields[message2_fields_arg.size()] =
nullptr;
559 std::sort(message1_fields.begin(), message1_fields.end(), FieldBefore);
560 std::sort(message2_fields.begin(), message2_fields.end(), FieldBefore);
563 if (output_string_) {
565 StreamReporter reporter(&output_stream);
566 reporter_ = &reporter;
567 result = CompareRequestedFieldsUsingSettings(
568 message1, message2, message1_fields, message2_fields, &parent_fields);
571 result = CompareRequestedFieldsUsingSettings(
572 message1, message2, message1_fields, message2_fields, &parent_fields);
580 std::vector<SpecificField>* parent_fields) {
581 const Descriptor* descriptor1 = message1.GetDescriptor();
582 const Descriptor* descriptor2 = message2.GetDescriptor();
583 if (descriptor1 != descriptor2) {
584 GOOGLE_LOG(DFATAL) <<
"Comparison between two messages with different "
585 <<
"descriptors. " << descriptor1->full_name() <<
" vs "
586 << descriptor2->full_name();
592 std::unique_ptr<Message> data1;
593 std::unique_ptr<Message> data2;
594 if (unpack_any_field_.UnpackAny(message1, &data1) &&
595 unpack_any_field_.UnpackAny(message2, &data2)) {
597 if (data1->GetDescriptor() != data2->GetDescriptor()) {
600 return Compare(*data1, *data2, parent_fields);
603 const Reflection* reflection1 = message1.GetReflection();
604 const Reflection* reflection2 = message2.GetReflection();
606 bool unknown_compare_result =
true;
608 if (message_field_comparison_ != EQUIVALENT) {
610 reflection1->GetUnknownFields(message1);
612 reflection2->GetUnknownFields(message2);
613 if (!CompareUnknownFields(message1, message2, unknown_field_set1,
614 unknown_field_set2, parent_fields)) {
615 if (reporter_ == NULL) {
618 unknown_compare_result =
false;
625 return CompareRequestedFieldsUsingSettings(message1, message2,
626 message1_fields, message2_fields,
628 unknown_compare_result;
635 tmp_message_fields_.clear();
636 tmp_message_fields_.reserve(
descriptor->field_count() + 1);
638 const Reflection* reflection =
message.GetReflection();
640 if (this->
scope_ == PARTIAL && base_message) {
641 reflection->ListFields(
message, &tmp_message_fields_);
645 tmp_message_fields_.push_back(
descriptor->field(i));
649 reflection->ListFields(
message, &tmp_message_fields_);
654 tmp_message_fields_.push_back(
nullptr);
657 tmp_message_fields_.end());
659 return message_fields;
662 bool MessageDifferencer::CompareRequestedFieldsUsingSettings(
666 std::vector<SpecificField>* parent_fields) {
668 if (message_field_comparison_ == EQUIVALENT) {
673 CombineFields(message1_fields, FULL, message2_fields, FULL);
674 return CompareWithFieldsInternal(message1, message2, fields_union,
675 fields_union, parent_fields);
678 return CompareWithFieldsInternal(message1, message2, message1_fields,
679 message2_fields, parent_fields);
682 if (message_field_comparison_ == EQUIVALENT) {
686 return CompareWithFieldsInternal(message1, message2, message1_fields,
687 message1_fields, parent_fields);
694 CombineFields(message1_fields, PARTIAL, message2_fields, PARTIAL);
695 return CompareWithFieldsInternal(message1, message2, message1_fields,
696 fields_intersection, parent_fields);
707 tmp_message_fields_.clear();
709 while (index1 < fields1.size() && index2 < fields2.size()) {
713 if (FieldBefore(field1, field2)) {
714 if (fields1_scope == FULL) {
715 tmp_message_fields_.push_back(fields1[index1]);
718 }
else if (FieldBefore(field2, field1)) {
719 if (fields2_scope == FULL) {
720 tmp_message_fields_.push_back(fields2[index2]);
724 tmp_message_fields_.push_back(fields1[index1]);
730 tmp_message_fields_.push_back(
nullptr);
733 tmp_message_fields_.end());
735 return combined_fields;
738 bool MessageDifferencer::CompareWithFieldsInternal(
742 std::vector<SpecificField>* parent_fields) {
743 bool isDifferent =
false;
744 int field_index1 = 0;
745 int field_index2 = 0;
747 const Reflection* reflection1 = message1.GetReflection();
748 const Reflection* reflection2 = message2.GetReflection();
755 if (field1 == NULL && field2 == NULL) {
760 if (FieldBefore(field1, field2)) {
762 if (IsIgnored(message1, message2, field1, *parent_fields)) {
765 if (reporter_ != NULL) {
766 SpecificField specific_field;
767 specific_field.field = field1;
768 parent_fields->push_back(specific_field);
769 if (report_ignores_) {
770 reporter_->ReportIgnored(message1, message2, *parent_fields);
772 parent_fields->pop_back();
778 if (reporter_ != NULL) {
779 assert(field1 != NULL);
780 int count = field1->is_repeated()
781 ? reflection1->FieldSize(message1, field1)
784 for (
int i = 0;
i <
count; ++
i) {
785 SpecificField specific_field;
786 specific_field.field = field1;
787 if (field1->is_repeated()) {
790 specific_field.index = -1;
793 parent_fields->push_back(specific_field);
794 reporter_->ReportDeleted(message1, message2, *parent_fields);
795 parent_fields->pop_back();
805 }
else if (FieldBefore(field2, field1)) {
807 if (IsIgnored(message1, message2, field2, *parent_fields)) {
810 if (reporter_ != NULL) {
811 SpecificField specific_field;
812 specific_field.field = field2;
813 parent_fields->push_back(specific_field);
814 if (report_ignores_) {
815 reporter_->ReportIgnored(message1, message2, *parent_fields);
817 parent_fields->pop_back();
823 if (reporter_ != NULL) {
824 int count = field2->is_repeated()
825 ? reflection2->FieldSize(message2, field2)
828 for (
int i = 0;
i <
count; ++
i) {
829 SpecificField specific_field;
830 specific_field.field = field2;
831 if (field2->is_repeated()) {
832 specific_field.index =
i;
835 specific_field.index = -1;
836 specific_field.new_index = -1;
839 parent_fields->push_back(specific_field);
840 reporter_->ReportAdded(message1, message2, *parent_fields);
841 parent_fields->pop_back();
855 if (IsIgnored(message1, message2, field1, *parent_fields)) {
857 if (reporter_ != NULL) {
858 SpecificField specific_field;
859 specific_field.field = field1;
860 parent_fields->push_back(specific_field);
861 if (report_ignores_) {
862 reporter_->ReportIgnored(message1, message2, *parent_fields);
864 parent_fields->pop_back();
872 bool fieldDifferent =
false;
873 assert(field1 != NULL);
874 if (field1->is_map()) {
876 !CompareMapField(message1, message2, field1, parent_fields);
877 }
else if (field1->is_repeated()) {
879 !CompareRepeatedField(message1, message2, field1, parent_fields);
881 fieldDifferent = !CompareFieldValueUsingParentFields(
882 message1, message2, field1, -1, -1, parent_fields);
884 if (reporter_ !=
nullptr) {
885 SpecificField specific_field;
886 specific_field.field = field1;
887 parent_fields->push_back(specific_field);
888 if (fieldDifferent) {
889 reporter_->ReportModified(message1, message2, *parent_fields);
891 }
else if (report_matches_) {
892 reporter_->ReportMatched(message1, message2, *parent_fields);
894 parent_fields->pop_back();
897 if (fieldDifferent) {
898 if (reporter_ ==
nullptr)
return false;
911 const MapKeyComparator* key_comparator,
const Message* message1,
912 const Message* message2,
const std::vector<SpecificField>& parent_fields,
913 Reporter* reporter,
int index1,
int index2) {
914 std::vector<SpecificField> current_parent_fields(parent_fields);
916 return CompareFieldValueUsingParentFields(*message1, *message2,
918 ¤t_parent_fields);
922 Reporter* backup_reporter = reporter_;
924 reporter_ = reporter;
925 output_string_ = NULL;
928 if (key_comparator == NULL) {
929 match = CompareFieldValueUsingParentFields(*message1, *message2,
931 ¤t_parent_fields);
933 const Reflection* reflection1 = message1->GetReflection();
934 const Reflection* reflection2 = message2->GetReflection();
936 reflection1->GetRepeatedMessage(*message1,
repeated_field, index1);
938 reflection2->GetRepeatedMessage(*message2,
repeated_field, index2);
939 SpecificField specific_field;
942 specific_field.map_entry1 = &m1;
943 specific_field.map_entry2 = &m2;
945 specific_field.index = index1;
946 specific_field.new_index = index2;
947 current_parent_fields.push_back(specific_field);
948 match = key_comparator->IsMatch(m1, m2, current_parent_fields);
951 reporter_ = backup_reporter;
952 output_string_ = output_string;
956 bool MessageDifferencer::CompareMapFieldByMapReflection(
958 const FieldDescriptor* map_field, std::vector<SpecificField>* parent_fields,
963 map_field_key_comparator_.end());
967 const int count1 = reflection1->
MapSize(message1, map_field);
968 const int count2 = reflection2->
MapSize(message2, map_field);
969 const bool treated_as_subset = IsTreatedAsSubset(map_field);
970 if (count1 != count2 && !treated_as_subset) {
973 if (count1 > count2) {
980 it_end = reflection1->
MapEnd(
const_cast<Message*
>(&message1),
982 it != it_end; ++
it) {
991 #define HANDLE_TYPE(CPPTYPE, METHOD, COMPAREMETHOD) \
992 case FieldDescriptor::CPPTYPE_##CPPTYPE: { \
993 for (MapIterator it = reflection1->MapBegin( \
994 const_cast<Message*>(&message1), map_field), \
995 it_end = reflection1->MapEnd( \
996 const_cast<Message*>(&message1), map_field); \
997 it != it_end; ++it) { \
998 MapValueConstRef value2; \
999 reflection2->LookupMapValue(message2, map_field, it.GetKey(), &value2); \
1000 if (!comparator->Compare##COMPAREMETHOD(*val_des, \
1001 it.GetValueRef().Get##METHOD(), \
1002 value2.Get##METHOD())) { \
1020 const_cast<Message*
>(&message1), map_field);
1022 reflection1->
MapEnd(
const_cast<Message*
>(&message1), map_field);
1027 bool compare_result;
1032 specific_value_field.
field = val_des;
1033 parent_fields->push_back(specific_value_field);
1034 compare_result =
Compare(
it.GetValueRef().GetMessageValue(),
1036 parent_fields->pop_back();
1037 if (!compare_result) {
1047 bool MessageDifferencer::CompareMapField(
1050 std::vector<SpecificField>* parent_fields) {
1061 reporter_ ==
nullptr &&
1064 map_field_key_comparator_.end() &&
1066 repeated_field_comparison_ == AS_LIST &&
1068 field_comparator_kind_ == kFCDefault) {
1072 std::vector<SpecificField> current_parent_fields(*parent_fields);
1075 current_parent_fields.push_back(specific_field);
1076 if (!IsIgnored(message1, message2, key_des, current_parent_fields) &&
1077 !IsIgnored(message1, message2, val_des, current_parent_fields)) {
1078 return CompareMapFieldByMapReflection(message1, message2,
repeated_field,
1079 ¤t_parent_fields,
1080 field_comparator_.default_impl);
1084 return CompareRepeatedRep(message1, message2,
repeated_field, parent_fields);
1087 bool MessageDifferencer::CompareRepeatedField(
1090 std::vector<SpecificField>* parent_fields) {
1092 return CompareRepeatedRep(message1, message2,
repeated_field, parent_fields);
1095 bool MessageDifferencer::CompareRepeatedRep(
1098 std::vector<SpecificField>* parent_fields) {
1106 const bool treated_as_subset = IsTreatedAsSubset(
repeated_field);
1111 if (count1 != count2 && reporter_ == NULL && !treated_as_subset) {
1115 if (count1 > count2 && reporter_ == NULL) {
1121 std::vector<int> match_list1;
1122 std::vector<int> match_list2;
1126 bool simple_list = key_comparator ==
nullptr &&
1135 if (!MatchRepeatedFieldIndices(message1, message2,
repeated_field,
1136 key_comparator, *parent_fields, &match_list1,
1138 reporter_ ==
nullptr) {
1143 bool fieldDifferent =
false;
1149 int next_unmatched_index = 0;
1150 for (
int i = 0;
i < count1;
i++) {
1151 if (simple_list &&
i >= count2) {
1154 if (!simple_list && match_list1[
i] == -1) {
1156 if (reporter_ ==
nullptr)
return false;
1158 parent_fields->push_back(specific_field);
1159 reporter_->ReportDeleted(message1, message2, *parent_fields);
1160 parent_fields->pop_back();
1161 fieldDifferent =
true;
1163 match_list1[
i] = -2;
1168 for (
int j = next_unmatched_index; j < match_list1[
i]; ++j) {
1170 if (reporter_ ==
nullptr)
return false;
1171 specific_field.
index = j;
1173 parent_fields->push_back(specific_field);
1174 reporter_->ReportAdded(message1, message2, *parent_fields);
1175 parent_fields->pop_back();
1176 fieldDifferent =
true;
1178 match_list2[j] = -2;
1187 next_unmatched_index = match_list1[
i] + 1;
1190 const bool result = CompareFieldValueUsingParentFields(
1198 if (reporter_ == NULL)
return false;
1199 parent_fields->push_back(specific_field);
1200 reporter_->ReportModified(message1, message2, *parent_fields);
1201 parent_fields->pop_back();
1202 fieldDifferent =
true;
1203 }
else if (reporter_ != NULL &&
1205 !specific_field.
field->
is_map() && report_moves_) {
1206 parent_fields->push_back(specific_field);
1207 reporter_->ReportMoved(message1, message2, *parent_fields);
1208 parent_fields->pop_back();
1209 }
else if (report_matches_ && reporter_ != NULL) {
1210 parent_fields->push_back(specific_field);
1211 reporter_->ReportMatched(message1, message2, *parent_fields);
1212 parent_fields->pop_back();
1217 for (
int i = 0;
i < count2; ++
i) {
1218 if (!simple_list && match_list2[
i] != -1)
continue;
1219 if (simple_list &&
i < count1)
continue;
1220 if (!treated_as_subset) {
1221 fieldDifferent =
true;
1224 if (reporter_ == NULL)
continue;
1225 specific_field.
index =
i;
1227 parent_fields->push_back(specific_field);
1228 reporter_->ReportAdded(message1, message2, *parent_fields);
1229 parent_fields->pop_back();
1232 for (
int i = 0;
i < count1; ++
i) {
1233 if (!simple_list && match_list1[
i] != -1)
continue;
1234 if (simple_list &&
i < count2)
continue;
1235 assert(reporter_ != NULL);
1237 parent_fields->push_back(specific_field);
1238 reporter_->ReportDeleted(message1, message2, *parent_fields);
1239 parent_fields->pop_back();
1240 fieldDifferent =
true;
1242 return !fieldDifferent;
1245 bool MessageDifferencer::CompareFieldValue(
const Message& message1,
1248 int index1,
int index2) {
1249 return CompareFieldValueUsingParentFields(message1, message2,
field, index1,
1253 bool MessageDifferencer::CompareFieldValueUsingParentFields(
1256 std::vector<SpecificField>* parent_fields) {
1257 FieldContext field_context(parent_fields);
1258 FieldComparator::ComparisonResult
result = GetFieldComparisonResult(
1259 message1, message2,
field, index1, index2, &field_context);
1262 result == FieldComparator::RECURSE) {
1277 if (parent_fields != NULL) {
1279 SpecificField specific_field;
1280 specific_field.field =
field;
1283 parent_fields->push_back(specific_field);
1284 const bool compare_result =
Compare(m1, m2, parent_fields);
1285 parent_fields->pop_back();
1286 return compare_result;
1292 return (
result == FieldComparator::SAME);
1296 bool MessageDifferencer::CheckPathChanged(
1297 const std::vector<SpecificField>& field_path) {
1298 for (
const SpecificField& specific_field : field_path) {
1300 if (specific_field.field !=
nullptr && specific_field.field->is_map())
1302 if (specific_field.index != specific_field.new_index)
return true;
1309 if (repeated_field_comparisons_.find(
field) !=
1310 repeated_field_comparisons_.end()) {
1311 return repeated_field_comparisons_[
field] == AS_SET;
1313 return GetMapKeyComparator(
field) ==
nullptr &&
1314 repeated_field_comparison_ == AS_SET;
1319 if (repeated_field_comparisons_.find(
field) !=
1320 repeated_field_comparisons_.end()) {
1321 return repeated_field_comparisons_[
field] == AS_SMART_SET;
1323 return GetMapKeyComparator(
field) ==
nullptr &&
1324 repeated_field_comparison_ == AS_SMART_SET;
1329 if (repeated_field_comparisons_.find(
field) !=
1330 repeated_field_comparisons_.end()) {
1331 return repeated_field_comparisons_[
field] == AS_SMART_LIST;
1333 return GetMapKeyComparator(
field) ==
nullptr &&
1334 repeated_field_comparison_ == AS_SMART_LIST;
1338 return scope_ == PARTIAL &&
1339 (IsTreatedAsSet(
field) || GetMapKeyComparator(
field) != NULL);
1342 bool MessageDifferencer::IsIgnored(
1345 const std::vector<SpecificField>& parent_fields) {
1346 if (ignored_fields_.find(
field) != ignored_fields_.end()) {
1349 for (IgnoreCriteria* criteria : ignore_criteria_) {
1350 if (criteria->IsIgnored(message1, message2,
field, parent_fields)) {
1357 bool MessageDifferencer::IsUnknownFieldIgnored(
1359 const SpecificField&
field,
1360 const std::vector<SpecificField>& parent_fields) {
1361 for (IgnoreCriteria* criteria : ignore_criteria_) {
1362 if (criteria->IsUnknownFieldIgnored(message1, message2,
field,
1370 const MessageDifferencer::MapKeyComparator*
1373 FieldKeyComparatorMap::const_iterator
it =
1374 map_field_key_comparator_.find(
field);
1375 if (
it != map_field_key_comparator_.end()) {
1381 return &map_entry_key_comparator_;
1388 typedef std::pair<int, const UnknownField*> IndexUnknownFieldPair;
1390 struct UnknownFieldOrdering {
1391 inline bool operator()(
const IndexUnknownFieldPair& a,
1392 const IndexUnknownFieldPair&
b)
const {
1393 if (
a.second->number() <
b.second->number())
return true;
1394 if (
a.second->number() >
b.second->number())
return false;
1395 return a.second->type() <
b.second->type();
1401 bool MessageDifferencer::UnpackAnyField::UnpackAny(
1402 const Message& any, std::unique_ptr<Message>*
data) {
1419 GOOGLE_LOG(
INFO) <<
"Proto type '" << full_type_name <<
"' not found";
1423 if (dynamic_message_factory_ == NULL) {
1426 data->reset(dynamic_message_factory_->GetPrototype(
desc)->New());
1428 if (!(*data)->ParsePartialFromString(serialized_value)) {
1435 bool MessageDifferencer::CompareUnknownFields(
1439 std::vector<SpecificField>* parent_field) {
1441 if (message_field_comparison_ == EQUIVALENT)
return true;
1443 if (unknown_field_set1.
empty() && unknown_field_set2.
empty()) {
1447 bool is_different =
false;
1455 std::vector<IndexUnknownFieldPair> fields1;
1456 std::vector<IndexUnknownFieldPair> fields2;
1457 fields1.reserve(unknown_field_set1.
field_count());
1458 fields2.reserve(unknown_field_set2.
field_count());
1460 for (
int i = 0;
i < unknown_field_set1.
field_count();
i++) {
1461 fields1.push_back(std::make_pair(i, &unknown_field_set1.
field(i)));
1463 for (
int i = 0;
i < unknown_field_set2.
field_count();
i++) {
1464 fields2.push_back(std::make_pair(i, &unknown_field_set2.
field(i)));
1467 UnknownFieldOrdering is_before;
1468 std::stable_sort(fields1.begin(), fields1.end(), is_before);
1469 std::stable_sort(fields2.begin(), fields2.end(), is_before);
1477 int current_repeated_start1 = 0;
1478 int current_repeated_start2 = 0;
1484 while (index1 < fields1.size() || index2 < fields2.size()) {
1498 if (index2 == fields2.size() ||
1499 (index1 < fields1.size() &&
1500 is_before(fields1[index1], fields2[index2]))) {
1502 change_type = DELETION;
1503 focus_field = fields1[index1].second;
1504 }
else if (index1 == fields1.size() ||
1505 is_before(fields2[index2], fields1[index1])) {
1512 change_type = ADDITION;
1513 focus_field = fields2[index2].second;
1516 change_type = MODIFICATION;
1517 focus_field = fields1[index1].second;
1519 switch (focus_field->type()) {
1521 match = fields1[index1].second->varint() ==
1522 fields2[index2].second->varint();
1525 match = fields1[index1].second->fixed32() ==
1526 fields2[index2].second->fixed32();
1529 match = fields1[index1].second->fixed64() ==
1530 fields2[index2].second->fixed64();
1533 match = fields1[index1].second->length_delimited() ==
1534 fields2[index2].second->length_delimited();
1538 change_type = COMPARE_GROUPS;
1541 if (
match && change_type != COMPARE_GROUPS) {
1542 change_type = NO_CHANGE;
1546 if (current_repeated == NULL ||
1547 focus_field->number() != current_repeated->number() ||
1548 focus_field->type() != current_repeated->type()) {
1550 current_repeated = focus_field;
1551 current_repeated_start1 = index1;
1552 current_repeated_start2 = index2;
1555 if (change_type == NO_CHANGE && reporter_ == NULL) {
1563 SpecificField specific_field;
1564 specific_field.unknown_field_number = focus_field->number();
1565 specific_field.unknown_field_type = focus_field->type();
1567 specific_field.unknown_field_set1 = &unknown_field_set1;
1568 specific_field.unknown_field_set2 = &unknown_field_set2;
1570 if (change_type != ADDITION) {
1571 specific_field.unknown_field_index1 = fields1[index1].first;
1573 if (change_type != DELETION) {
1574 specific_field.unknown_field_index2 = fields2[index2].first;
1578 if (change_type == ADDITION) {
1579 specific_field.index = index2 - current_repeated_start2;
1580 specific_field.new_index = index2 - current_repeated_start2;
1582 specific_field.index = index1 - current_repeated_start1;
1583 specific_field.new_index = index2 - current_repeated_start2;
1586 if (IsUnknownFieldIgnored(message1, message2, specific_field,
1588 if (report_ignores_ && reporter_ != NULL) {
1589 parent_field->push_back(specific_field);
1590 reporter_->ReportUnknownFieldIgnored(message1, message2, *parent_field);
1591 parent_field->pop_back();
1593 if (change_type != ADDITION) ++index1;
1594 if (change_type != DELETION) ++index2;
1598 if (change_type == ADDITION || change_type == DELETION ||
1599 change_type == MODIFICATION) {
1600 if (reporter_ == NULL) {
1604 is_different =
true;
1607 parent_field->push_back(specific_field);
1609 switch (change_type) {
1611 reporter_->ReportAdded(message1, message2, *parent_field);
1615 reporter_->ReportDeleted(message1, message2, *parent_field);
1619 reporter_->ReportModified(message1, message2, *parent_field);
1623 case COMPARE_GROUPS:
1624 if (!CompareUnknownFields(
1625 message1, message2, fields1[index1].
second->group(),
1626 fields2[index2].second->group(), parent_field)) {
1627 if (reporter_ == NULL)
return false;
1628 is_different =
true;
1629 reporter_->ReportModified(message1, message2, *parent_field);
1637 if (report_matches_) {
1638 reporter_->ReportMatched(message1, message2, *parent_field);
1642 parent_field->pop_back();
1645 return !is_different;
1651 class MaximumMatcher {
1664 MaximumMatcher(
int count1,
int count2, NodeMatchCallback
callback,
1665 std::vector<int>* match_list1, std::vector<int>* match_list2);
1669 int FindMaximumMatch(
bool early_return);
1674 bool Match(
int left,
int right);
1678 bool FindArgumentPathDFS(
int v, std::vector<bool>*
visited);
1689 MaximumMatcher::MaximumMatcher(
int count1,
int count2,
1691 std::vector<int>* match_list1,
1692 std::vector<int>* match_list2)
1702 int MaximumMatcher::FindMaximumMatch(
bool early_return) {
1706 if (FindArgumentPathDFS(
i, &
visited)) {
1708 }
else if (early_return) {
1716 (*match_list1_)[(*match_list2_)[
i]] =
i;
1723 std::pair<int, int>
p(left, right);
1733 bool MaximumMatcher::FindArgumentPathDFS(
int v, std::vector<bool>*
visited) {
1734 (*visited)[
v] =
true;
1741 int matched = (*match_list2_)[
i];
1742 if (matched == -1 &&
Match(
v,
i)) {
1743 (*match_list2_)[
i] =
v;
1752 int matched = (*match_list2_)[
i];
1753 if (matched != -1 &&
Match(
v,
i)) {
1754 if (!(*
visited)[matched] && FindArgumentPathDFS(matched,
visited)) {
1755 (*match_list2_)[
i] =
v;
1765 bool MessageDifferencer::MatchRepeatedFieldIndices(
1768 const MapKeyComparator* key_comparator,
1769 const std::vector<SpecificField>& parent_fields,
1770 std::vector<int>* match_list1, std::vector<int>* match_list2) {
1775 const bool is_treated_as_smart_set = IsTreatedAsSmartSet(
repeated_field);
1777 match_list1->assign(count1, -1);
1778 match_list2->assign(count2, -1);
1783 Reporter* reporter = reporter_;
1785 NumDiffsReporter num_diffs_reporter;
1786 std::vector<int32_t> num_diffs_list1;
1787 if (is_treated_as_smart_set) {
1791 bool success =
true;
1800 parent_fields,
nullptr,
i1,
i2);
1806 bool early_return = (reporter ==
nullptr);
1807 int match_count = matcher.FindMaximumMatch(early_return);
1808 if (match_count != count1 && early_return)
return false;
1809 success = success && (match_count == count1);
1817 for (
int i = 0;
i < count1 &&
i < count2;
i++) {
1819 parent_fields,
nullptr,
i,
i)) {
1820 match_list1->at(
i) =
i;
1821 match_list2->at(
i) =
i;
1834 if (match_list2->at(j) != -1) {
1835 if (!is_treated_as_smart_set || num_diffs_list1[
i] == 0 ||
1836 num_diffs_list1[match_list2->at(j)] == 0) {
1841 if (is_treated_as_smart_set) {
1842 num_diffs_reporter.Reset();
1844 parent_fields, &num_diffs_reporter,
i, j);
1847 parent_fields,
nullptr,
i, j);
1850 if (is_treated_as_smart_set) {
1852 num_diffs_list1[
i] = 0;
1854 FieldDescriptor::CPPTYPE_MESSAGE) {
1856 const int32_t num_diffs = num_diffs_reporter.GetNumDiffs();
1857 if (num_diffs < num_diffs_list1[
i]) {
1860 if (match_list2->at(j) == -1 ||
1861 num_diffs < num_diffs_list1[match_list2->at(j)]) {
1862 num_diffs_list1[
i] = num_diffs;
1871 if (!is_treated_as_smart_set || num_diffs_list1[
i] == 0) {
1877 match = (matched_j != -1);
1879 if (is_treated_as_smart_set && match_list2->at(matched_j) != -1) {
1881 match_list1->at(match_list2->at(matched_j)) = -1;
1884 match_list1->at(
i) = matched_j;
1885 match_list2->at(matched_j) =
i;
1887 if (!
match && reporter ==
nullptr)
return false;
1888 success = success &&
match;
1893 match_indices_for_smart_list_callback_(match_list1, match_list2);
1896 reporter_ = reporter;
1901 FieldComparator::ComparisonResult MessageDifferencer::GetFieldComparisonResult(
1904 const FieldContext* field_context) {
1905 FieldComparator* comparator = field_comparator_kind_ == kFCBase
1906 ? field_comparator_.base
1907 : field_comparator_.default_impl;
1908 return comparator->Compare(message1, message2,
field, index1, index2,
1914 MessageDifferencer::Reporter::Reporter() {}
1915 MessageDifferencer::Reporter::~Reporter() {}
1919 MessageDifferencer::MapKeyComparator::MapKeyComparator() {}
1920 MessageDifferencer::MapKeyComparator::~MapKeyComparator() {}
1924 MessageDifferencer::IgnoreCriteria::IgnoreCriteria() {}
1925 MessageDifferencer::IgnoreCriteria::~IgnoreCriteria() {}
1931 MessageDifferencer::StreamReporter::StreamReporter(
1934 delete_printer_(
true),
1935 report_modified_aggregates_(
false),
1937 message2_(nullptr) {}
1939 MessageDifferencer::StreamReporter::StreamReporter(
io::Printer* printer)
1941 delete_printer_(
false),
1942 report_modified_aggregates_(
false),
1944 message2_(nullptr) {}
1946 MessageDifferencer::StreamReporter::~StreamReporter() {
1947 if (delete_printer_)
delete printer_;
1950 void MessageDifferencer::StreamReporter::PrintPath(
1951 const std::vector<SpecificField>& field_path,
bool left_side) {
1952 for (
size_t i = 0;
i < field_path.size(); ++
i) {
1953 SpecificField specific_field = field_path[
i];
1955 if (specific_field.field !=
nullptr &&
1956 specific_field.field->name() ==
"value") {
1959 if (
i > 0 && field_path[
i - 1].
field->is_map()) {
1966 if (specific_field.field != NULL) {
1967 if (specific_field.field->is_extension()) {
1968 printer_->
Print(
"($name$)",
"name", specific_field.field->full_name());
1973 if (specific_field.field->is_map()) {
1974 PrintMapKey(left_side, specific_field);
1980 if (left_side && specific_field.index >= 0) {
1983 if (!left_side && specific_field.new_index >= 0) {
1985 StrCat(specific_field.new_index));
1992 const Message&
message,
const std::vector<SpecificField>& field_path,
1994 const SpecificField& specific_field = field_path.back();
1996 if (
field != NULL) {
1998 int index = left_side ? specific_field.index : specific_field.new_index;
1999 if (
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
2000 const Reflection* reflection =
message.GetReflection();
2001 const Message& field_message =
2002 field->is_repeated()
2007 if (
field->is_map() && message1_ !=
nullptr && message2_ !=
nullptr) {
2008 fd = field_message.GetDescriptor()->field(1);
2009 if (fd->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
2010 output = field_message.GetReflection()
2011 ->GetMessage(field_message, fd)
2012 .ShortDebugString();
2014 TextFormat::PrintFieldValueToString(field_message, fd, -1, &
output);
2017 output = field_message.ShortDebugString();
2022 if ((fd !=
nullptr) &&
2023 (fd->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)) {
2035 (left_side ? specific_field.unknown_field_set1
2036 : specific_field.unknown_field_set2);
2038 &unknown_fields->field(left_side ? specific_field.unknown_field_index1
2039 : specific_field.unknown_field_index2);
2040 PrintUnknownFieldValue(unknown_field);
2044 void MessageDifferencer::StreamReporter::PrintUnknownFieldValue(
2046 GOOGLE_CHECK(unknown_field != NULL) <<
" Cannot print NULL unknown_field.";
2049 switch (unknown_field->type()) {
2050 case UnknownField::TYPE_VARINT:
2053 case UnknownField::TYPE_FIXED32:
2057 case UnknownField::TYPE_FIXED64:
2061 case UnknownField::TYPE_LENGTH_DELIMITED:
2063 "\"%s\"",
CEscape(unknown_field->length_delimited()).c_str());
2065 case UnknownField::TYPE_GROUP:
2079 void MessageDifferencer::StreamReporter::PrintMapKey(
2081 if (message1_ ==
nullptr || message2_ ==
nullptr) {
2083 "use SetMessages to provide the messages "
2084 "being compared prior to any processing.";
2088 const Message* found_message =
2091 if (found_message !=
nullptr) {
2094 if (fd->
cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
2100 TextFormat::PrintFieldValueToString(*found_message, fd, -1, &key_string);
2102 if (key_string.empty()) {
2109 void MessageDifferencer::StreamReporter::ReportAdded(
2111 const std::vector<SpecificField>& field_path) {
2113 PrintPath(field_path,
false);
2119 void MessageDifferencer::StreamReporter::ReportDeleted(
2121 const std::vector<SpecificField>& field_path) {
2123 PrintPath(field_path,
true);
2129 void MessageDifferencer::StreamReporter::ReportModified(
2131 const std::vector<SpecificField>& field_path) {
2132 if (!report_modified_aggregates_ && field_path.back().field == NULL) {
2133 if (field_path.back().unknown_field_type == UnknownField::TYPE_GROUP) {
2137 }
else if (!report_modified_aggregates_) {
2138 if (field_path.back().field->cpp_type() ==
2139 FieldDescriptor::CPPTYPE_MESSAGE) {
2146 PrintPath(field_path,
true);
2147 if (CheckPathChanged(field_path)) {
2149 PrintPath(field_path,
false);
2158 void MessageDifferencer::StreamReporter::ReportMoved(
2160 const std::vector<SpecificField>& field_path) {
2162 PrintPath(field_path,
true);
2164 PrintPath(field_path,
false);
2170 void MessageDifferencer::StreamReporter::ReportMatched(
2172 const std::vector<SpecificField>& field_path) {
2174 PrintPath(field_path,
true);
2175 if (CheckPathChanged(field_path)) {
2177 PrintPath(field_path,
false);
2184 void MessageDifferencer::StreamReporter::ReportIgnored(
2186 const std::vector<SpecificField>& field_path) {
2188 PrintPath(field_path,
true);
2189 if (CheckPathChanged(field_path)) {
2191 PrintPath(field_path,
false);
2196 void MessageDifferencer::StreamReporter::SetMessages(
const Message& message1,
2198 message1_ = &message1;
2199 message2_ = &message2;
2202 void MessageDifferencer::StreamReporter::ReportUnknownFieldIgnored(
2204 const std::vector<SpecificField>& field_path) {
2206 PrintPath(field_path,
true);
2207 if (CheckPathChanged(field_path)) {
2209 PrintPath(field_path,
false);
2214 MessageDifferencer::MapKeyComparator*
2215 MessageDifferencer::CreateMultipleFieldsMapKeyComparator(
2216 const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths) {
2217 return new MultipleFieldsMapKeyComparator(
this, key_field_paths);