Fix MessageDifferencer and MessagePatch to support the case where the two messages store different payload types in an Any field. Before this CL, MessageDifferencer::Compare would report false without producing any diff.

After this CL, it will compute a diff by without interpreting the payloads.

PiperOrigin-RevId: 554503691
pull/13398/head
Protobuf Team Bot 2 years ago committed by Copybara-Service
parent e3b0943412
commit 7656a6107d
  1. 10
      src/google/protobuf/util/message_differencer.cc
  2. 20
      src/google/protobuf/util/message_differencer_unittest.cc

@ -639,13 +639,13 @@ bool MessageDifferencer::Compare(const Message& message1,
std::unique_ptr<Message> data1;
std::unique_ptr<Message> data2;
if (unpack_any_field_.UnpackAny(message1, &data1) &&
unpack_any_field_.UnpackAny(message2, &data2)) {
// Avoid DFATAL for different descriptors in google.protobuf.Any payloads.
if (data1->GetDescriptor() != data2->GetDescriptor()) {
return false;
}
unpack_any_field_.UnpackAny(message2, &data2) &&
data1->GetDescriptor() == data2->GetDescriptor()) {
return Compare(*data1, *data2, unpacked_any + 1, parent_fields);
}
// If the Any payload is unparsable, or the payload types are different
// between message1 and message2, fall through and treat Any as a regular
// proto.
}
bool unknown_compare_result = true;

@ -3983,6 +3983,26 @@ TEST(AnyTest, Simple) {
EXPECT_EQ("modified: any_value.a: 20 -> 21\n", difference_string);
}
TEST(AnyTest, DifferentTypes) {
protobuf_unittest::TestField value1;
value1.set_a(20);
protobuf_unittest::ForeignMessage value2;
value2.set_c(30);
protobuf_unittest::TestAny m1, m2;
m1.mutable_any_value()->PackFrom(value1);
m2.mutable_any_value()->PackFrom(value2);
util::MessageDifferencer message_differencer;
std::string difference_string;
message_differencer.ReportDifferencesToString(&difference_string);
EXPECT_FALSE(message_differencer.Compare(m1, m2));
// Any should be treated as a regular proto when the payload types differ.
EXPECT_THAT(
difference_string,
testing::ContainsRegex(
R"(type_url: ".+/protobuf_unittest.TestField\" -> ".+/protobuf_unittest.ForeignMessage")"));
}
TEST(Anytest, TreatAsSet) {
protobuf_unittest::TestField value1, value2;
value1.set_a(20);

Loading…
Cancel
Save