proto: distinguish between invalid and empty messages in Equal
The v1 proto.Equal function treats (*Message)(nil) and new(Message)
as being different, while v2 proto.Equal treated them as equal since
a typed nil pointer is functionally an empty message since the
protobuf data model has no concept of presence as a first-class
property of messages.
Unfortunately, a significant amount of code depends on this distinction
that it would be difficult to migrate users from v1 to v2 unless we
preserved similar semantics in the v2 proto.Equal.
Also, double down on these semantics for protocmp.Transform.
Fixes #965
Change-Id: I21e78ba6251401a0ac0ccf495188093973cd7f3f
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/213238
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/proto/encode_test.go b/proto/encode_test.go
index 8f02d0c..fd03468 100644
--- a/proto/encode_test.go
+++ b/proto/encode_test.go
@@ -45,7 +45,7 @@
t.Errorf("Unmarshal error: %v\nMessage:\n%v", err, marshalText(want))
return
}
- if !proto.Equal(got, want) {
+ if !proto.Equal(got, want) && got.ProtoReflect().IsValid() && want.ProtoReflect().IsValid() {
t.Errorf("Unmarshal returned unexpected result; got:\n%v\nwant:\n%v", marshalText(got), marshalText(want))
}
})
@@ -81,7 +81,7 @@
t.Errorf("Unmarshal error: %v\nMessage:\n%v", err, marshalText(want))
return
}
- if !proto.Equal(got, want) {
+ if !proto.Equal(got, want) && got.ProtoReflect().IsValid() && want.ProtoReflect().IsValid() {
t.Errorf("Unmarshal returned unexpected result; got:\n%v\nwant:\n%v", marshalText(got), marshalText(want))
}
})