proto/equal: equate nil

Modify Equal to treat nil messages as equal iff both are nil.
Of special note, a typed nil pointer to T is equal to a new(T)
since they are indistinguishable from a protobuf reflection.

Change-Id: Ibf90b43a982e7376e07b4159be198f06230ec194
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/196618
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/proto/decode_test.go b/proto/decode_test.go
index b6258da..40a627b 100644
--- a/proto/decode_test.go
+++ b/proto/decode_test.go
@@ -1789,6 +1789,9 @@
 }
 
 func marshalText(m proto.Message) string {
+	if m == nil {
+		return "<nil>\n"
+	}
 	b, _ := prototext.MarshalOptions{
 		AllowPartial: true,
 		EmitUnknown:  true,
diff --git a/proto/equal.go b/proto/equal.go
index 44f840a..7b513bd 100644
--- a/proto/equal.go
+++ b/proto/equal.go
@@ -29,6 +29,9 @@
 // Maps are equal if they have the same set of keys, where the pair of values
 // for each key is also equal.
 func Equal(x, y Message) bool {
+	if x == nil || y == nil {
+		return x == nil && y == nil
+	}
 	return equalMessage(x.ProtoReflect(), y.ProtoReflect())
 }
 
diff --git a/proto/equal_test.go b/proto/equal_test.go
index 3afca83..add1687 100644
--- a/proto/equal_test.go
+++ b/proto/equal_test.go
@@ -9,477 +9,412 @@
 	"testing"
 
 	"google.golang.org/protobuf/internal/encoding/pack"
+	"google.golang.org/protobuf/proto"
+
 	testpb "google.golang.org/protobuf/internal/testprotos/test"
 	test3pb "google.golang.org/protobuf/internal/testprotos/test3"
-	"google.golang.org/protobuf/proto"
 )
 
 func TestEqual(t *testing.T) {
-	for _, test := range inequalities {
-		if !proto.Equal(test.a, test.a) {
-			t.Errorf("Equal(a, a) = false, want true\na = %T %v", test.a, marshalText(test.a))
+	tests := []struct {
+		x, y proto.Message
+		eq   bool
+	}{
+		{
+			x:  nil,
+			y:  nil,
+			eq: true,
+		}, {
+			x:  (*testpb.TestAllTypes)(nil),
+			y:  nil,
+			eq: false,
+		}, {
+			x:  (*testpb.TestAllTypes)(nil),
+			y:  new(testpb.TestAllTypes),
+			eq: true,
+		},
+
+		// Proto2 scalars.
+		{
+			x: &testpb.TestAllTypes{OptionalInt32: proto.Int32(1)},
+			y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(2)},
+		}, {
+			x: &testpb.TestAllTypes{OptionalInt64: proto.Int64(1)},
+			y: &testpb.TestAllTypes{OptionalInt64: proto.Int64(2)},
+		}, {
+			x: &testpb.TestAllTypes{OptionalUint32: proto.Uint32(1)},
+			y: &testpb.TestAllTypes{OptionalUint32: proto.Uint32(2)},
+		}, {
+			x: &testpb.TestAllTypes{OptionalUint64: proto.Uint64(1)},
+			y: &testpb.TestAllTypes{OptionalUint64: proto.Uint64(2)},
+		}, {
+			x: &testpb.TestAllTypes{OptionalSint32: proto.Int32(1)},
+			y: &testpb.TestAllTypes{OptionalSint32: proto.Int32(2)},
+		}, {
+			x: &testpb.TestAllTypes{OptionalSint64: proto.Int64(1)},
+			y: &testpb.TestAllTypes{OptionalSint64: proto.Int64(2)},
+		}, {
+			x: &testpb.TestAllTypes{OptionalFixed32: proto.Uint32(1)},
+			y: &testpb.TestAllTypes{OptionalFixed32: proto.Uint32(2)},
+		}, {
+			x: &testpb.TestAllTypes{OptionalFixed64: proto.Uint64(1)},
+			y: &testpb.TestAllTypes{OptionalFixed64: proto.Uint64(2)},
+		}, {
+			x: &testpb.TestAllTypes{OptionalSfixed32: proto.Int32(1)},
+			y: &testpb.TestAllTypes{OptionalSfixed32: proto.Int32(2)},
+		}, {
+			x: &testpb.TestAllTypes{OptionalSfixed64: proto.Int64(1)},
+			y: &testpb.TestAllTypes{OptionalSfixed64: proto.Int64(2)},
+		}, {
+			x: &testpb.TestAllTypes{OptionalFloat: proto.Float32(1)},
+			y: &testpb.TestAllTypes{OptionalFloat: proto.Float32(2)},
+		}, {
+			x: &testpb.TestAllTypes{OptionalDouble: proto.Float64(1)},
+			y: &testpb.TestAllTypes{OptionalDouble: proto.Float64(2)},
+		}, {
+			x: &testpb.TestAllTypes{OptionalFloat: proto.Float32(float32(math.NaN()))},
+			y: &testpb.TestAllTypes{OptionalFloat: proto.Float32(0)},
+		}, {
+			x: &testpb.TestAllTypes{OptionalDouble: proto.Float64(float64(math.NaN()))},
+			y: &testpb.TestAllTypes{OptionalDouble: proto.Float64(0)},
+		}, {
+			x: &testpb.TestAllTypes{OptionalBool: proto.Bool(true)},
+			y: &testpb.TestAllTypes{OptionalBool: proto.Bool(false)},
+		}, {
+			x: &testpb.TestAllTypes{OptionalString: proto.String("a")},
+			y: &testpb.TestAllTypes{OptionalString: proto.String("b")},
+		}, {
+			x: &testpb.TestAllTypes{OptionalBytes: []byte("a")},
+			y: &testpb.TestAllTypes{OptionalBytes: []byte("b")},
+		}, {
+			x: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
+			y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_BAR.Enum()},
+		},
+
+		// Proto2 presence.
+		{
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(0)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{OptionalInt64: proto.Int64(0)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{OptionalUint32: proto.Uint32(0)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{OptionalUint64: proto.Uint64(0)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{OptionalSint32: proto.Int32(0)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{OptionalSint64: proto.Int64(0)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{OptionalFixed32: proto.Uint32(0)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{OptionalFixed64: proto.Uint64(0)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{OptionalSfixed32: proto.Int32(0)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{OptionalSfixed64: proto.Int64(0)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{OptionalFloat: proto.Float32(0)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{OptionalDouble: proto.Float64(0)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{OptionalBool: proto.Bool(false)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{OptionalString: proto.String("")},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{OptionalBytes: []byte{}},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
+		},
+
+		// Proto2 default values are not considered by Equal, so the following are still unequal.
+		{
+			x: &testpb.TestAllTypes{DefaultInt32: proto.Int32(81)},
+			y: &testpb.TestAllTypes{},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{DefaultInt32: proto.Int32(81)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{DefaultInt64: proto.Int64(82)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{DefaultUint32: proto.Uint32(83)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{DefaultUint64: proto.Uint64(84)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{DefaultSint32: proto.Int32(-85)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{DefaultSint64: proto.Int64(86)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{DefaultFixed32: proto.Uint32(87)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{DefaultFixed64: proto.Uint64(88)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{DefaultSfixed32: proto.Int32(89)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{DefaultSfixed64: proto.Int64(-90)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{DefaultFloat: proto.Float32(91.5)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{DefaultDouble: proto.Float64(92e3)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{DefaultBool: proto.Bool(true)},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{DefaultString: proto.String("hello")},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{DefaultBytes: []byte("world")},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{DefaultNestedEnum: testpb.TestAllTypes_BAR.Enum()},
+		},
+
+		// Groups.
+		{
+			x: &testpb.TestAllTypes{Optionalgroup: &testpb.TestAllTypes_OptionalGroup{
+				A: proto.Int32(1),
+			}},
+			y: &testpb.TestAllTypes{Optionalgroup: &testpb.TestAllTypes_OptionalGroup{
+				A: proto.Int32(2),
+			}},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{Optionalgroup: &testpb.TestAllTypes_OptionalGroup{}},
+		},
+
+		// Messages.
+		{
+			x: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{
+				A: proto.Int32(1),
+			}},
+			y: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{
+				A: proto.Int32(2),
+			}},
+		}, {
+			x: &testpb.TestAllTypes{},
+			y: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{}},
+		}, {
+			x: &test3pb.TestAllTypes{},
+			y: &test3pb.TestAllTypes{OptionalNestedMessage: &test3pb.TestAllTypes_NestedMessage{}},
+		},
+
+		// Lists.
+		{
+			x: &testpb.TestAllTypes{RepeatedInt32: []int32{1}},
+			y: &testpb.TestAllTypes{RepeatedInt32: []int32{1, 2}},
+		}, {
+			x: &testpb.TestAllTypes{RepeatedInt32: []int32{1, 2}},
+			y: &testpb.TestAllTypes{RepeatedInt32: []int32{1, 3}},
+		}, {
+			x: &testpb.TestAllTypes{RepeatedInt64: []int64{1, 2}},
+			y: &testpb.TestAllTypes{RepeatedInt64: []int64{1, 3}},
+		}, {
+			x: &testpb.TestAllTypes{RepeatedUint32: []uint32{1, 2}},
+			y: &testpb.TestAllTypes{RepeatedUint32: []uint32{1, 3}},
+		}, {
+			x: &testpb.TestAllTypes{RepeatedUint64: []uint64{1, 2}},
+			y: &testpb.TestAllTypes{RepeatedUint64: []uint64{1, 3}},
+		}, {
+			x: &testpb.TestAllTypes{RepeatedSint32: []int32{1, 2}},
+			y: &testpb.TestAllTypes{RepeatedSint32: []int32{1, 3}},
+		}, {
+			x: &testpb.TestAllTypes{RepeatedSint64: []int64{1, 2}},
+			y: &testpb.TestAllTypes{RepeatedSint64: []int64{1, 3}},
+		}, {
+			x: &testpb.TestAllTypes{RepeatedFixed32: []uint32{1, 2}},
+			y: &testpb.TestAllTypes{RepeatedFixed32: []uint32{1, 3}},
+		}, {
+			x: &testpb.TestAllTypes{RepeatedFixed64: []uint64{1, 2}},
+			y: &testpb.TestAllTypes{RepeatedFixed64: []uint64{1, 3}},
+		}, {
+			x: &testpb.TestAllTypes{RepeatedSfixed32: []int32{1, 2}},
+			y: &testpb.TestAllTypes{RepeatedSfixed32: []int32{1, 3}},
+		}, {
+			x: &testpb.TestAllTypes{RepeatedSfixed64: []int64{1, 2}},
+			y: &testpb.TestAllTypes{RepeatedSfixed64: []int64{1, 3}},
+		}, {
+			x: &testpb.TestAllTypes{RepeatedFloat: []float32{1, 2}},
+			y: &testpb.TestAllTypes{RepeatedFloat: []float32{1, 3}},
+		}, {
+			x: &testpb.TestAllTypes{RepeatedDouble: []float64{1, 2}},
+			y: &testpb.TestAllTypes{RepeatedDouble: []float64{1, 3}},
+		}, {
+			x: &testpb.TestAllTypes{RepeatedBool: []bool{true, false}},
+			y: &testpb.TestAllTypes{RepeatedBool: []bool{true, true}},
+		}, {
+			x: &testpb.TestAllTypes{RepeatedString: []string{"a", "b"}},
+			y: &testpb.TestAllTypes{RepeatedString: []string{"a", "c"}},
+		}, {
+			x: &testpb.TestAllTypes{RepeatedBytes: [][]byte{[]byte("a"), []byte("b")}},
+			y: &testpb.TestAllTypes{RepeatedBytes: [][]byte{[]byte("a"), []byte("c")}},
+		}, {
+			x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO}},
+			y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}},
+		}, {
+			x: &testpb.TestAllTypes{Repeatedgroup: []*testpb.TestAllTypes_RepeatedGroup{
+				{A: proto.Int32(1)},
+				{A: proto.Int32(2)},
+			}},
+			y: &testpb.TestAllTypes{Repeatedgroup: []*testpb.TestAllTypes_RepeatedGroup{
+				{A: proto.Int32(1)},
+				{A: proto.Int32(3)},
+			}},
+		}, {
+			x: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{
+				{A: proto.Int32(1)},
+				{A: proto.Int32(2)},
+			}},
+			y: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{
+				{A: proto.Int32(1)},
+				{A: proto.Int32(3)},
+			}},
+		},
+
+		// Maps: various configurations.
+		{
+			x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2}},
+			y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{3: 4}},
+		}, {
+			x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2}},
+			y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 4}},
+		}, {
+			x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 4}},
+			y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2}},
+		},
+
+		// Maps: various types.
+		{
+			x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 4}},
+			y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 5}},
+		}, {
+			x: &testpb.TestAllTypes{MapInt64Int64: map[int64]int64{1: 2, 3: 4}},
+			y: &testpb.TestAllTypes{MapInt64Int64: map[int64]int64{1: 2, 3: 5}},
+		}, {
+			x: &testpb.TestAllTypes{MapUint32Uint32: map[uint32]uint32{1: 2, 3: 4}},
+			y: &testpb.TestAllTypes{MapUint32Uint32: map[uint32]uint32{1: 2, 3: 5}},
+		}, {
+			x: &testpb.TestAllTypes{MapUint64Uint64: map[uint64]uint64{1: 2, 3: 4}},
+			y: &testpb.TestAllTypes{MapUint64Uint64: map[uint64]uint64{1: 2, 3: 5}},
+		}, {
+			x: &testpb.TestAllTypes{MapSint32Sint32: map[int32]int32{1: 2, 3: 4}},
+			y: &testpb.TestAllTypes{MapSint32Sint32: map[int32]int32{1: 2, 3: 5}},
+		}, {
+			x: &testpb.TestAllTypes{MapSint64Sint64: map[int64]int64{1: 2, 3: 4}},
+			y: &testpb.TestAllTypes{MapSint64Sint64: map[int64]int64{1: 2, 3: 5}},
+		}, {
+			x: &testpb.TestAllTypes{MapFixed32Fixed32: map[uint32]uint32{1: 2, 3: 4}},
+			y: &testpb.TestAllTypes{MapFixed32Fixed32: map[uint32]uint32{1: 2, 3: 5}},
+		}, {
+			x: &testpb.TestAllTypes{MapFixed64Fixed64: map[uint64]uint64{1: 2, 3: 4}},
+			y: &testpb.TestAllTypes{MapFixed64Fixed64: map[uint64]uint64{1: 2, 3: 5}},
+		}, {
+			x: &testpb.TestAllTypes{MapSfixed32Sfixed32: map[int32]int32{1: 2, 3: 4}},
+			y: &testpb.TestAllTypes{MapSfixed32Sfixed32: map[int32]int32{1: 2, 3: 5}},
+		}, {
+			x: &testpb.TestAllTypes{MapSfixed64Sfixed64: map[int64]int64{1: 2, 3: 4}},
+			y: &testpb.TestAllTypes{MapSfixed64Sfixed64: map[int64]int64{1: 2, 3: 5}},
+		}, {
+			x: &testpb.TestAllTypes{MapInt32Float: map[int32]float32{1: 2, 3: 4}},
+			y: &testpb.TestAllTypes{MapInt32Float: map[int32]float32{1: 2, 3: 5}},
+		}, {
+			x: &testpb.TestAllTypes{MapInt32Double: map[int32]float64{1: 2, 3: 4}},
+			y: &testpb.TestAllTypes{MapInt32Double: map[int32]float64{1: 2, 3: 5}},
+		}, {
+			x: &testpb.TestAllTypes{MapBoolBool: map[bool]bool{true: false, false: true}},
+			y: &testpb.TestAllTypes{MapBoolBool: map[bool]bool{true: false, false: false}},
+		}, {
+			x: &testpb.TestAllTypes{MapStringString: map[string]string{"a": "b", "c": "d"}},
+			y: &testpb.TestAllTypes{MapStringString: map[string]string{"a": "b", "c": "e"}},
+		}, {
+			x: &testpb.TestAllTypes{MapStringBytes: map[string][]byte{"a": []byte("b"), "c": []byte("d")}},
+			y: &testpb.TestAllTypes{MapStringBytes: map[string][]byte{"a": []byte("b"), "c": []byte("e")}},
+		}, {
+			x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{
+				"a": {A: proto.Int32(1)},
+				"b": {A: proto.Int32(2)},
+			}},
+			y: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{
+				"a": {A: proto.Int32(1)},
+				"b": {A: proto.Int32(3)},
+			}},
+		}, {
+			x: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{
+				"a": testpb.TestAllTypes_FOO,
+				"b": testpb.TestAllTypes_BAR,
+			}},
+			y: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{
+				"a": testpb.TestAllTypes_FOO,
+				"b": testpb.TestAllTypes_BAZ,
+			}},
+		},
+
+		// Extensions.
+		{
+			x: build(&testpb.TestAllExtensions{},
+				extend(testpb.E_OptionalInt32Extension, int32(1)),
+			),
+			y: build(&testpb.TestAllExtensions{},
+				extend(testpb.E_OptionalInt32Extension, int32(2)),
+			),
+		}, {
+			x: &testpb.TestAllExtensions{},
+			y: build(&testpb.TestAllExtensions{},
+				extend(testpb.E_OptionalInt32Extension, int32(2)),
+			),
+		},
+
+		// Unknown fields.
+		{
+			x: build(&testpb.TestAllTypes{}, unknown(pack.Message{
+				pack.Tag{100000, pack.VarintType}, pack.Varint(1),
+			}.Marshal())),
+			y: build(&testpb.TestAllTypes{}, unknown(pack.Message{
+				pack.Tag{100000, pack.VarintType}, pack.Varint(2),
+			}.Marshal())),
+		}, {
+			x: build(&testpb.TestAllTypes{}, unknown(pack.Message{
+				pack.Tag{100000, pack.VarintType}, pack.Varint(1),
+			}.Marshal())),
+			y: &testpb.TestAllTypes{},
+		},
+	}
+
+	for _, tt := range tests {
+		if !tt.eq && !proto.Equal(tt.x, tt.x) {
+			t.Errorf("Equal(x, x) = false, want true\n==== x ====\n%v", marshalText(tt.x))
 		}
-		if proto.Equal(test.a, test.b) {
-			t.Errorf("Equal(a, b) = true, want false\na = %T %v\nb = %T %v", test.a, marshalText(test.a), test.b, marshalText(test.b))
+		if !tt.eq && !proto.Equal(tt.y, tt.y) {
+			t.Errorf("Equal(y, y) = false, want true\n==== y ====\n%v", marshalText(tt.y))
+		}
+		if eq := proto.Equal(tt.x, tt.y); eq != tt.eq {
+			t.Errorf("Equal(x, y) = %v, want %v\n==== x ====\n%v==== y ====\n%v", eq, tt.eq, marshalText(tt.x), marshalText(tt.y))
 		}
 	}
 }
-
-var inequalities = []struct{ a, b proto.Message }{
-	// Scalar values.
-	{
-		&testpb.TestAllTypes{OptionalInt32: proto.Int32(1)},
-		&testpb.TestAllTypes{OptionalInt32: proto.Int32(2)},
-	},
-	{
-		&testpb.TestAllTypes{OptionalInt64: proto.Int64(1)},
-		&testpb.TestAllTypes{OptionalInt64: proto.Int64(2)},
-	},
-	{
-		&testpb.TestAllTypes{OptionalUint32: proto.Uint32(1)},
-		&testpb.TestAllTypes{OptionalUint32: proto.Uint32(2)},
-	},
-	{
-		&testpb.TestAllTypes{OptionalUint64: proto.Uint64(1)},
-		&testpb.TestAllTypes{OptionalUint64: proto.Uint64(2)},
-	},
-	{
-		&testpb.TestAllTypes{OptionalSint32: proto.Int32(1)},
-		&testpb.TestAllTypes{OptionalSint32: proto.Int32(2)},
-	},
-	{
-		&testpb.TestAllTypes{OptionalSint64: proto.Int64(1)},
-		&testpb.TestAllTypes{OptionalSint64: proto.Int64(2)},
-	},
-	{
-		&testpb.TestAllTypes{OptionalFixed32: proto.Uint32(1)},
-		&testpb.TestAllTypes{OptionalFixed32: proto.Uint32(2)},
-	},
-	{
-		&testpb.TestAllTypes{OptionalFixed64: proto.Uint64(1)},
-		&testpb.TestAllTypes{OptionalFixed64: proto.Uint64(2)},
-	},
-	{
-		&testpb.TestAllTypes{OptionalSfixed32: proto.Int32(1)},
-		&testpb.TestAllTypes{OptionalSfixed32: proto.Int32(2)},
-	},
-	{
-		&testpb.TestAllTypes{OptionalSfixed64: proto.Int64(1)},
-		&testpb.TestAllTypes{OptionalSfixed64: proto.Int64(2)},
-	},
-	{
-		&testpb.TestAllTypes{OptionalFloat: proto.Float32(1)},
-		&testpb.TestAllTypes{OptionalFloat: proto.Float32(2)},
-	},
-	{
-		&testpb.TestAllTypes{OptionalDouble: proto.Float64(1)},
-		&testpb.TestAllTypes{OptionalDouble: proto.Float64(2)},
-	},
-	{
-		&testpb.TestAllTypes{OptionalFloat: proto.Float32(float32(math.NaN()))},
-		&testpb.TestAllTypes{OptionalFloat: proto.Float32(0)},
-	},
-	{
-		&testpb.TestAllTypes{OptionalDouble: proto.Float64(float64(math.NaN()))},
-		&testpb.TestAllTypes{OptionalDouble: proto.Float64(0)},
-	},
-	{
-		&testpb.TestAllTypes{OptionalBool: proto.Bool(true)},
-		&testpb.TestAllTypes{OptionalBool: proto.Bool(false)},
-	},
-	{
-		&testpb.TestAllTypes{OptionalString: proto.String("a")},
-		&testpb.TestAllTypes{OptionalString: proto.String("b")},
-	},
-	{
-		&testpb.TestAllTypes{OptionalBytes: []byte("a")},
-		&testpb.TestAllTypes{OptionalBytes: []byte("b")},
-	},
-	{
-		&testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
-		&testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_BAR.Enum()},
-	},
-	// Proto2 presence.
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{OptionalInt32: proto.Int32(0)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{OptionalInt64: proto.Int64(0)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{OptionalUint32: proto.Uint32(0)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{OptionalUint64: proto.Uint64(0)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{OptionalSint32: proto.Int32(0)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{OptionalSint64: proto.Int64(0)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{OptionalFixed32: proto.Uint32(0)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{OptionalFixed64: proto.Uint64(0)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{OptionalSfixed32: proto.Int32(0)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{OptionalSfixed64: proto.Int64(0)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{OptionalFloat: proto.Float32(0)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{OptionalDouble: proto.Float64(0)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{OptionalBool: proto.Bool(false)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{OptionalString: proto.String("")},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{OptionalBytes: []byte{}},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
-	},
-	// Groups.
-	{
-		&testpb.TestAllTypes{Optionalgroup: &testpb.TestAllTypes_OptionalGroup{
-			A: proto.Int32(1),
-		}},
-		&testpb.TestAllTypes{Optionalgroup: &testpb.TestAllTypes_OptionalGroup{
-			A: proto.Int32(2),
-		}},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{Optionalgroup: &testpb.TestAllTypes_OptionalGroup{}},
-	},
-	// Messages.
-	{
-		&testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{
-			A: proto.Int32(1),
-		}},
-		&testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{
-			A: proto.Int32(2),
-		}},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{}},
-	},
-	{
-		&test3pb.TestAllTypes{},
-		&test3pb.TestAllTypes{OptionalNestedMessage: &test3pb.TestAllTypes_NestedMessage{}},
-	},
-	// Lists.
-	{
-		&testpb.TestAllTypes{RepeatedInt32: []int32{1}},
-		&testpb.TestAllTypes{RepeatedInt32: []int32{1, 2}},
-	},
-	{
-		&testpb.TestAllTypes{RepeatedInt32: []int32{1, 2}},
-		&testpb.TestAllTypes{RepeatedInt32: []int32{1, 3}},
-	},
-	{
-		&testpb.TestAllTypes{RepeatedInt64: []int64{1, 2}},
-		&testpb.TestAllTypes{RepeatedInt64: []int64{1, 3}},
-	},
-	{
-		&testpb.TestAllTypes{RepeatedUint32: []uint32{1, 2}},
-		&testpb.TestAllTypes{RepeatedUint32: []uint32{1, 3}},
-	},
-	{
-		&testpb.TestAllTypes{RepeatedUint64: []uint64{1, 2}},
-		&testpb.TestAllTypes{RepeatedUint64: []uint64{1, 3}},
-	},
-	{
-		&testpb.TestAllTypes{RepeatedSint32: []int32{1, 2}},
-		&testpb.TestAllTypes{RepeatedSint32: []int32{1, 3}},
-	},
-	{
-		&testpb.TestAllTypes{RepeatedSint64: []int64{1, 2}},
-		&testpb.TestAllTypes{RepeatedSint64: []int64{1, 3}},
-	},
-	{
-		&testpb.TestAllTypes{RepeatedFixed32: []uint32{1, 2}},
-		&testpb.TestAllTypes{RepeatedFixed32: []uint32{1, 3}},
-	},
-	{
-		&testpb.TestAllTypes{RepeatedFixed64: []uint64{1, 2}},
-		&testpb.TestAllTypes{RepeatedFixed64: []uint64{1, 3}},
-	},
-	{
-		&testpb.TestAllTypes{RepeatedSfixed32: []int32{1, 2}},
-		&testpb.TestAllTypes{RepeatedSfixed32: []int32{1, 3}},
-	},
-	{
-		&testpb.TestAllTypes{RepeatedSfixed64: []int64{1, 2}},
-		&testpb.TestAllTypes{RepeatedSfixed64: []int64{1, 3}},
-	},
-	{
-		&testpb.TestAllTypes{RepeatedFloat: []float32{1, 2}},
-		&testpb.TestAllTypes{RepeatedFloat: []float32{1, 3}},
-	},
-	{
-		&testpb.TestAllTypes{RepeatedDouble: []float64{1, 2}},
-		&testpb.TestAllTypes{RepeatedDouble: []float64{1, 3}},
-	},
-	{
-		&testpb.TestAllTypes{RepeatedBool: []bool{true, false}},
-		&testpb.TestAllTypes{RepeatedBool: []bool{true, true}},
-	},
-	{
-		&testpb.TestAllTypes{RepeatedString: []string{"a", "b"}},
-		&testpb.TestAllTypes{RepeatedString: []string{"a", "c"}},
-	},
-	{
-		&testpb.TestAllTypes{RepeatedBytes: [][]byte{[]byte("a"), []byte("b")}},
-		&testpb.TestAllTypes{RepeatedBytes: [][]byte{[]byte("a"), []byte("c")}},
-	},
-	{
-		&testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO}},
-		&testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}},
-	},
-	{
-		&testpb.TestAllTypes{Repeatedgroup: []*testpb.TestAllTypes_RepeatedGroup{
-			{A: proto.Int32(1)},
-			{A: proto.Int32(2)},
-		}},
-		&testpb.TestAllTypes{Repeatedgroup: []*testpb.TestAllTypes_RepeatedGroup{
-			{A: proto.Int32(1)},
-			{A: proto.Int32(3)},
-		}},
-	},
-	{
-		&testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{
-			{A: proto.Int32(1)},
-			{A: proto.Int32(2)},
-		}},
-		&testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{
-			{A: proto.Int32(1)},
-			{A: proto.Int32(3)},
-		}},
-	},
-	// Maps: various configurations.
-	{
-		&testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2}},
-		&testpb.TestAllTypes{MapInt32Int32: map[int32]int32{3: 4}},
-	},
-	{
-		&testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2}},
-		&testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 4}},
-	},
-	{
-		&testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 4}},
-		&testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2}},
-	},
-	// Maps: various types.
-	{
-		&testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 4}},
-		&testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 5}},
-	},
-	{
-		&testpb.TestAllTypes{MapInt64Int64: map[int64]int64{1: 2, 3: 4}},
-		&testpb.TestAllTypes{MapInt64Int64: map[int64]int64{1: 2, 3: 5}},
-	},
-	{
-		&testpb.TestAllTypes{MapUint32Uint32: map[uint32]uint32{1: 2, 3: 4}},
-		&testpb.TestAllTypes{MapUint32Uint32: map[uint32]uint32{1: 2, 3: 5}},
-	},
-	{
-		&testpb.TestAllTypes{MapUint64Uint64: map[uint64]uint64{1: 2, 3: 4}},
-		&testpb.TestAllTypes{MapUint64Uint64: map[uint64]uint64{1: 2, 3: 5}},
-	},
-	{
-		&testpb.TestAllTypes{MapSint32Sint32: map[int32]int32{1: 2, 3: 4}},
-		&testpb.TestAllTypes{MapSint32Sint32: map[int32]int32{1: 2, 3: 5}},
-	},
-	{
-		&testpb.TestAllTypes{MapSint64Sint64: map[int64]int64{1: 2, 3: 4}},
-		&testpb.TestAllTypes{MapSint64Sint64: map[int64]int64{1: 2, 3: 5}},
-	},
-	{
-		&testpb.TestAllTypes{MapFixed32Fixed32: map[uint32]uint32{1: 2, 3: 4}},
-		&testpb.TestAllTypes{MapFixed32Fixed32: map[uint32]uint32{1: 2, 3: 5}},
-	},
-	{
-		&testpb.TestAllTypes{MapFixed64Fixed64: map[uint64]uint64{1: 2, 3: 4}},
-		&testpb.TestAllTypes{MapFixed64Fixed64: map[uint64]uint64{1: 2, 3: 5}},
-	},
-	{
-		&testpb.TestAllTypes{MapSfixed32Sfixed32: map[int32]int32{1: 2, 3: 4}},
-		&testpb.TestAllTypes{MapSfixed32Sfixed32: map[int32]int32{1: 2, 3: 5}},
-	},
-	{
-		&testpb.TestAllTypes{MapSfixed64Sfixed64: map[int64]int64{1: 2, 3: 4}},
-		&testpb.TestAllTypes{MapSfixed64Sfixed64: map[int64]int64{1: 2, 3: 5}},
-	},
-	{
-		&testpb.TestAllTypes{MapInt32Float: map[int32]float32{1: 2, 3: 4}},
-		&testpb.TestAllTypes{MapInt32Float: map[int32]float32{1: 2, 3: 5}},
-	},
-	{
-		&testpb.TestAllTypes{MapInt32Double: map[int32]float64{1: 2, 3: 4}},
-		&testpb.TestAllTypes{MapInt32Double: map[int32]float64{1: 2, 3: 5}},
-	},
-	{
-		&testpb.TestAllTypes{MapBoolBool: map[bool]bool{true: false, false: true}},
-		&testpb.TestAllTypes{MapBoolBool: map[bool]bool{true: false, false: false}},
-	},
-	{
-		&testpb.TestAllTypes{MapStringString: map[string]string{"a": "b", "c": "d"}},
-		&testpb.TestAllTypes{MapStringString: map[string]string{"a": "b", "c": "e"}},
-	},
-	{
-		&testpb.TestAllTypes{MapStringBytes: map[string][]byte{"a": []byte("b"), "c": []byte("d")}},
-		&testpb.TestAllTypes{MapStringBytes: map[string][]byte{"a": []byte("b"), "c": []byte("e")}},
-	},
-	{
-		&testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{
-			"a": {A: proto.Int32(1)},
-			"b": {A: proto.Int32(2)},
-		}},
-		&testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{
-			"a": {A: proto.Int32(1)},
-			"b": {A: proto.Int32(3)},
-		}},
-	},
-	{
-		&testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{
-			"a": testpb.TestAllTypes_FOO,
-			"b": testpb.TestAllTypes_BAR,
-		}},
-		&testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{
-			"a": testpb.TestAllTypes_FOO,
-			"b": testpb.TestAllTypes_BAZ,
-		}},
-	},
-	// Unknown fields.
-	{
-		build(&testpb.TestAllTypes{}, unknown(pack.Message{
-			pack.Tag{100000, pack.VarintType}, pack.Varint(1),
-		}.Marshal())),
-		build(&testpb.TestAllTypes{}, unknown(pack.Message{
-			pack.Tag{100000, pack.VarintType}, pack.Varint(2),
-		}.Marshal())),
-	},
-	{
-		build(&testpb.TestAllTypes{}, unknown(pack.Message{
-			pack.Tag{100000, pack.VarintType}, pack.Varint(1),
-		}.Marshal())),
-		&testpb.TestAllTypes{},
-	},
-	{
-		&testpb.TestAllTypes{},
-		build(&testpb.TestAllTypes{}, unknown(pack.Message{
-			pack.Tag{100000, pack.VarintType}, pack.Varint(1),
-		}.Marshal())),
-	},
-	// Extensions.
-	{
-		build(&testpb.TestAllExtensions{},
-			extend(testpb.E_OptionalInt32Extension, int32(1)),
-		),
-		build(&testpb.TestAllExtensions{},
-			extend(testpb.E_OptionalInt32Extension, int32(2)),
-		),
-	},
-	{
-		&testpb.TestAllExtensions{},
-		build(&testpb.TestAllExtensions{},
-			extend(testpb.E_OptionalInt32Extension, int32(2)),
-		),
-	},
-	// Proto2 default values are not considered by Equal, so the following are still unequal.
-	{
-		&testpb.TestAllTypes{DefaultInt32: proto.Int32(81)},
-		&testpb.TestAllTypes{},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{DefaultInt32: proto.Int32(81)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{DefaultInt64: proto.Int64(82)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{DefaultUint32: proto.Uint32(83)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{DefaultUint64: proto.Uint64(84)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{DefaultSint32: proto.Int32(-85)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{DefaultSint64: proto.Int64(86)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{DefaultFixed32: proto.Uint32(87)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{DefaultFixed64: proto.Uint64(88)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{DefaultSfixed32: proto.Int32(89)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{DefaultSfixed64: proto.Int64(-90)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{DefaultFloat: proto.Float32(91.5)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{DefaultDouble: proto.Float64(92e3)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{DefaultBool: proto.Bool(true)},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{DefaultString: proto.String("hello")},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{DefaultBytes: []byte("world")},
-	},
-	{
-		&testpb.TestAllTypes{},
-		&testpb.TestAllTypes{DefaultNestedEnum: testpb.TestAllTypes_BAR.Enum()},
-	},
-}