protobuf-go/proto/equal_test.go
Michael Stapelberg 496557b1d5 proto: refactor equal_test from explicit table to use makeMessages()
This is important for test coverage: the makeMessages() function is where we
declare the various different test message types. Using this central function is
better than explicitly having to spell out all the various cases in the test
table.

This CL is roughly neutral in terms of lines changed, but actually increases
coverage: in the existing table, not every group of tests had coverage for all
cases (proto2, proto3, editions). This was difficult to spot previously, but now
the different test message types are now clearly spelled out (allTypesNoProto3).

Also, the test now prints the description and message types as subtest name.
This makes it easy to verify coverage by just reading the test output.

Change-Id: I08f541548d087233cbb4686785c456674371c2a3
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/623115
Reviewed-by: Chressie Himpel <chressie@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2024-10-29 12:41:43 +00:00

1011 lines
28 KiB
Go

// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package proto_test
import (
"fmt"
"math"
"testing"
"google.golang.org/protobuf/encoding/prototext"
"google.golang.org/protobuf/internal/pragma"
"google.golang.org/protobuf/internal/protobuild"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/testing/protopack"
testpb "google.golang.org/protobuf/internal/testprotos/test"
test3pb "google.golang.org/protobuf/internal/testprotos/test3"
testeditionspb "google.golang.org/protobuf/internal/testprotos/testeditions"
)
func TestEqual(t *testing.T) {
identicalPtrPb := &testpb.TestAllTypes{MapStringString: map[string]string{"a": "b", "c": "d"}}
type incomparableMessage struct {
*testpb.TestAllTypes
pragma.DoNotCompare
}
type test struct {
desc string
x, y proto.Message
eq bool
}
tests := []test{
{
x: nil,
y: nil,
eq: true,
}, {
x: (*testpb.TestAllTypes)(nil),
y: nil,
eq: false,
}, {
x: (*testpb.TestAllTypes)(nil),
y: (*testpb.TestAllTypes)(nil),
eq: true,
}, {
x: new(testpb.TestAllTypes),
y: (*testpb.TestAllTypes)(nil),
eq: false,
}, {
x: new(testpb.TestAllTypes),
y: new(testpb.TestAllTypes),
eq: true,
}, {
x: (*testpb.TestAllTypes)(nil),
y: (*testpb.TestAllExtensions)(nil),
eq: false,
}, {
x: (*testpb.TestAllTypes)(nil),
y: new(testpb.TestAllExtensions),
eq: false,
}, {
x: new(testpb.TestAllTypes),
y: new(testpb.TestAllExtensions),
eq: false,
},
// Identical input pointers
{
x: identicalPtrPb,
y: identicalPtrPb,
eq: true,
},
// Incomparable types. The top-level types are not actually directly
// compared (which would panic), but rather the comparison happens on the
// objects returned by ProtoReflect(). These tests are here just to ensure
// that any short-circuit checks do not accidentally try to compare
// incomparable top-level types.
{
x: incomparableMessage{TestAllTypes: identicalPtrPb},
y: incomparableMessage{TestAllTypes: identicalPtrPb},
eq: true,
},
{
x: identicalPtrPb,
y: incomparableMessage{TestAllTypes: identicalPtrPb},
eq: true,
},
{
x: identicalPtrPb,
y: &incomparableMessage{TestAllTypes: identicalPtrPb},
eq: true,
},
}
type xy struct {
X proto.Message
Y proto.Message
}
cloneAll := func(in []proto.Message) []proto.Message {
out := make([]proto.Message, len(in))
for idx, msg := range in {
out[idx] = proto.Clone(msg)
}
return out
}
makeXY := func(x protobuild.Message, y protobuild.Message, messages ...proto.Message) []xy {
xs := makeMessages(x, cloneAll(messages)...)
ys := makeMessages(y, cloneAll(messages)...)
result := make([]xy, len(xs))
for idx := range xs {
result[idx] = xy{
X: xs[idx],
Y: ys[idx],
}
}
return result
}
makeTest := func(tmpl test, msgs []xy) []test {
result := make([]test, 0, len(msgs))
for _, msg := range msgs {
tmpl.x = msg.X
tmpl.y = msg.Y
result = append(result, tmpl)
}
return result
}
// Scalars.
tests = append(tests, makeTest(test{desc: "Scalars"}, makeXY(
protobuild.Message{"optional_int32": 1},
protobuild.Message{"optional_int32": 2},
))...)
tests = append(tests, makeTest(test{desc: "Scalars"}, makeXY(
protobuild.Message{"optional_int64": 1},
protobuild.Message{"optional_int64": 2},
))...)
tests = append(tests, makeTest(test{desc: "Scalars"}, makeXY(
protobuild.Message{"optional_uint32": 1},
protobuild.Message{"optional_uint32": 2},
))...)
tests = append(tests, makeTest(test{desc: "Scalars"}, makeXY(
protobuild.Message{"optional_uint64": 1},
protobuild.Message{"optional_uint64": 2},
))...)
tests = append(tests, makeTest(test{desc: "Scalars"}, makeXY(
protobuild.Message{"optional_sint32": 1},
protobuild.Message{"optional_sint32": 2},
))...)
tests = append(tests, makeTest(test{desc: "Scalars"}, makeXY(
protobuild.Message{"optional_sint64": 1},
protobuild.Message{"optional_sint64": 2},
))...)
tests = append(tests, makeTest(test{desc: "Scalars"}, makeXY(
protobuild.Message{"optional_fixed32": 1},
protobuild.Message{"optional_fixed32": 2},
))...)
tests = append(tests, makeTest(test{desc: "Scalars"}, makeXY(
protobuild.Message{"optional_fixed64": 1},
protobuild.Message{"optional_fixed64": 2},
))...)
tests = append(tests, makeTest(test{desc: "Scalars"}, makeXY(
protobuild.Message{"optional_sfixed32": 1},
protobuild.Message{"optional_sfixed32": 2},
))...)
tests = append(tests, makeTest(test{desc: "Scalars"}, makeXY(
protobuild.Message{"optional_sfixed64": 1},
protobuild.Message{"optional_sfixed64": 2},
))...)
tests = append(tests, makeTest(test{desc: "Scalars"}, makeXY(
protobuild.Message{"optional_float": 1},
protobuild.Message{"optional_float": 2},
))...)
tests = append(tests, makeTest(test{desc: "Scalars"}, makeXY(
protobuild.Message{"optional_double": 1},
protobuild.Message{"optional_double": 2},
))...)
tests = append(tests, makeTest(test{desc: "Scalars"}, makeXY(
protobuild.Message{"optional_float": math.NaN()},
protobuild.Message{"optional_float": 0},
))...)
tests = append(tests, makeTest(test{desc: "Scalars"}, makeXY(
protobuild.Message{"optional_double": math.NaN()},
protobuild.Message{"optional_double": 0},
))...)
tests = append(tests, makeTest(test{desc: "Scalars"}, makeXY(
protobuild.Message{"optional_bool": true},
protobuild.Message{"optional_bool": false},
))...)
tests = append(tests, makeTest(test{desc: "Scalars"}, makeXY(
protobuild.Message{"optional_string": "a"},
protobuild.Message{"optional_string": "b"},
))...)
tests = append(tests, makeTest(test{desc: "Scalars"}, makeXY(
protobuild.Message{"optional_bytes": []byte("a")},
protobuild.Message{"optional_bytes": []byte("b")},
))...)
tests = append(tests, makeTest(test{desc: "Scalars"}, makeXY(
protobuild.Message{"optional_nested_enum": "FOO"},
protobuild.Message{"optional_nested_enum": "BAR"},
))...)
// Scalars (equal).
tests = append(tests, makeTest(test{
desc: "Scalars",
eq: true,
}, makeXY(
protobuild.Message{"optional_int32": 2},
protobuild.Message{"optional_int32": 2},
))...)
tests = append(tests, makeTest(test{
desc: "Scalars",
eq: true,
}, makeXY(
protobuild.Message{"optional_int64": 2},
protobuild.Message{"optional_int64": 2},
))...)
tests = append(tests, makeTest(test{
desc: "Scalars",
eq: true,
}, makeXY(
protobuild.Message{"optional_uint32": 2},
protobuild.Message{"optional_uint32": 2},
))...)
tests = append(tests, makeTest(test{
desc: "Scalars",
eq: true,
}, makeXY(
protobuild.Message{"optional_uint64": 2},
protobuild.Message{"optional_uint64": 2},
))...)
tests = append(tests, makeTest(test{
desc: "Scalars",
eq: true,
}, makeXY(
protobuild.Message{"optional_sint32": 2},
protobuild.Message{"optional_sint32": 2},
))...)
tests = append(tests, makeTest(test{
desc: "Scalars",
eq: true,
}, makeXY(
protobuild.Message{"optional_sint64": 2},
protobuild.Message{"optional_sint64": 2},
))...)
tests = append(tests, makeTest(test{
desc: "Scalars",
eq: true,
}, makeXY(
protobuild.Message{"optional_fixed32": 2},
protobuild.Message{"optional_fixed32": 2},
))...)
tests = append(tests, makeTest(test{
desc: "Scalars",
eq: true,
}, makeXY(
protobuild.Message{"optional_fixed64": 2},
protobuild.Message{"optional_fixed64": 2},
))...)
tests = append(tests, makeTest(test{
desc: "Scalars",
eq: true,
}, makeXY(
protobuild.Message{"optional_sfixed32": 2},
protobuild.Message{"optional_sfixed32": 2},
))...)
tests = append(tests, makeTest(test{
desc: "Scalars",
eq: true,
}, makeXY(
protobuild.Message{"optional_sfixed64": 2},
protobuild.Message{"optional_sfixed64": 2},
))...)
tests = append(tests, makeTest(test{
desc: "Scalars",
eq: true,
}, makeXY(
protobuild.Message{"optional_float": 2},
protobuild.Message{"optional_float": 2},
))...)
tests = append(tests, makeTest(test{
desc: "Scalars",
eq: true,
}, makeXY(
protobuild.Message{"optional_double": 2},
protobuild.Message{"optional_double": 2},
))...)
tests = append(tests, makeTest(test{
desc: "Scalars",
eq: true,
}, makeXY(
protobuild.Message{"optional_float": math.NaN()},
protobuild.Message{"optional_float": math.NaN()},
))...)
tests = append(tests, makeTest(test{
desc: "Scalars",
eq: true,
}, makeXY(
protobuild.Message{"optional_double": math.NaN()},
protobuild.Message{"optional_double": math.NaN()},
))...)
tests = append(tests, makeTest(test{
desc: "Scalars",
eq: true,
}, makeXY(
protobuild.Message{"optional_bool": true},
protobuild.Message{"optional_bool": true},
))...)
tests = append(tests, makeTest(test{
desc: "Scalars",
eq: true,
}, makeXY(
protobuild.Message{"optional_string": "abc"},
protobuild.Message{"optional_string": "abc"},
))...)
tests = append(tests, makeTest(test{
desc: "Scalars",
eq: true,
}, makeXY(
protobuild.Message{"optional_bytes": []byte("abc")},
protobuild.Message{"optional_bytes": []byte("abc")},
))...)
tests = append(tests, makeTest(test{
desc: "Scalars",
eq: true,
}, makeXY(
protobuild.Message{"optional_nested_enum": "FOO"},
protobuild.Message{"optional_nested_enum": "FOO"},
))...)
// Presence.
tests = append(tests, makeTest(test{desc: "Presence"}, makeXY(
protobuild.Message{},
protobuild.Message{"optional_int32": 0},
))...)
tests = append(tests, makeTest(test{desc: "Presence"}, makeXY(
protobuild.Message{},
protobuild.Message{"optional_int64": 0},
))...)
tests = append(tests, makeTest(test{desc: "Presence"}, makeXY(
protobuild.Message{},
protobuild.Message{"optional_uint32": 0},
))...)
tests = append(tests, makeTest(test{desc: "Presence"}, makeXY(
protobuild.Message{},
protobuild.Message{"optional_uint64": 0},
))...)
tests = append(tests, makeTest(test{desc: "Presence"}, makeXY(
protobuild.Message{},
protobuild.Message{"optional_sint32": 0},
))...)
tests = append(tests, makeTest(test{desc: "Presence"}, makeXY(
protobuild.Message{},
protobuild.Message{"optional_sint64": 0},
))...)
tests = append(tests, makeTest(test{desc: "Presence"}, makeXY(
protobuild.Message{},
protobuild.Message{"optional_fixed32": 0},
))...)
tests = append(tests, makeTest(test{desc: "Presence"}, makeXY(
protobuild.Message{},
protobuild.Message{"optional_fixed64": 0},
))...)
tests = append(tests, makeTest(test{desc: "Presence"}, makeXY(
protobuild.Message{},
protobuild.Message{"optional_sfixed32": 0},
))...)
tests = append(tests, makeTest(test{desc: "Presence"}, makeXY(
protobuild.Message{},
protobuild.Message{"optional_sfixed64": 0},
))...)
tests = append(tests, makeTest(test{desc: "Presence"}, makeXY(
protobuild.Message{},
protobuild.Message{"optional_float": 0},
))...)
tests = append(tests, makeTest(test{desc: "Presence"}, makeXY(
protobuild.Message{},
protobuild.Message{"optional_double": 0},
))...)
tests = append(tests, makeTest(test{desc: "Presence"}, makeXY(
protobuild.Message{},
protobuild.Message{"optional_bool": false},
))...)
tests = append(tests, makeTest(test{desc: "Presence"}, makeXY(
protobuild.Message{},
protobuild.Message{"optional_string": ""},
))...)
tests = append(tests, makeTest(test{desc: "Presence"}, makeXY(
protobuild.Message{},
protobuild.Message{"optional_bytes": []byte{}},
))...)
tests = append(tests, makeTest(test{desc: "Presence"}, makeXY(
protobuild.Message{},
protobuild.Message{"optional_nested_enum": "FOO"},
))...)
// Proto2 default values are not considered by Equal, so the following are still unequal.
allTypesNoProto3 := []proto.Message{
&testpb.TestAllTypes{},
// test3pb.TestAllTypes is intentionally missing:
// proto3 does not support default values.
// proto3 does not support groups.
&testpb.TestAllExtensions{},
&testeditionspb.TestAllTypes{},
}
tests = append(tests, makeTest(test{desc: "Default"}, makeXY(
protobuild.Message{"default_int32": 81},
protobuild.Message{},
allTypesNoProto3...,
))...)
tests = append(tests, makeTest(test{desc: "Default"}, makeXY(
protobuild.Message{},
protobuild.Message{"default_int32": 81},
allTypesNoProto3...,
))...)
tests = append(tests, makeTest(test{desc: "Default"}, makeXY(
protobuild.Message{},
protobuild.Message{"default_int64": 82},
allTypesNoProto3...,
))...)
tests = append(tests, makeTest(test{desc: "Default"}, makeXY(
protobuild.Message{},
protobuild.Message{"default_uint32": 83},
allTypesNoProto3...,
))...)
tests = append(tests, makeTest(test{desc: "Default"}, makeXY(
protobuild.Message{},
protobuild.Message{"default_uint64": 84},
allTypesNoProto3...,
))...)
tests = append(tests, makeTest(test{desc: "Default"}, makeXY(
protobuild.Message{},
protobuild.Message{"default_sint32": -85},
allTypesNoProto3...,
))...)
tests = append(tests, makeTest(test{desc: "Default"}, makeXY(
protobuild.Message{},
protobuild.Message{"default_sint64": 86},
allTypesNoProto3...,
))...)
tests = append(tests, makeTest(test{desc: "Default"}, makeXY(
protobuild.Message{},
protobuild.Message{"default_fixed32": 87},
allTypesNoProto3...,
))...)
tests = append(tests, makeTest(test{desc: "Default"}, makeXY(
protobuild.Message{},
protobuild.Message{"default_fixed64": 87},
allTypesNoProto3...,
))...)
tests = append(tests, makeTest(test{desc: "Default"}, makeXY(
protobuild.Message{},
protobuild.Message{"default_sfixed32": 89},
allTypesNoProto3...,
))...)
tests = append(tests, makeTest(test{desc: "Default"}, makeXY(
protobuild.Message{},
protobuild.Message{"default_sfixed64": -90},
allTypesNoProto3...,
))...)
tests = append(tests, makeTest(test{desc: "Default"}, makeXY(
protobuild.Message{},
protobuild.Message{"default_float": 91.5},
allTypesNoProto3...,
))...)
tests = append(tests, makeTest(test{desc: "Default"}, makeXY(
protobuild.Message{},
protobuild.Message{"default_double": 92e3},
allTypesNoProto3...,
))...)
tests = append(tests, makeTest(test{desc: "Default"}, makeXY(
protobuild.Message{},
protobuild.Message{"default_bool": true},
allTypesNoProto3...,
))...)
tests = append(tests, makeTest(test{desc: "Default"}, makeXY(
protobuild.Message{},
protobuild.Message{"default_string": "hello"},
allTypesNoProto3...,
))...)
tests = append(tests, makeTest(test{desc: "Default"}, makeXY(
protobuild.Message{},
protobuild.Message{"default_bytes": []byte("world")},
allTypesNoProto3...,
))...)
tests = append(tests, makeTest(test{desc: "Default"}, makeXY(
protobuild.Message{},
protobuild.Message{"default_nested_enum": "BAR"},
&testpb.TestAllTypes{},
// test3pb.TestAllTypes is intentionally missing:
// proto3 does not support default values.
// testpb.TestAllExtensions is intentionally missing:
// extensions cannot declare nested enums.
&testeditionspb.TestAllTypes{},
))...)
// Groups.
tests = append(tests, makeTest(test{desc: "Groups"}, makeXY(
protobuild.Message{"optionalgroup": protobuild.Message{
"a": 1,
}},
protobuild.Message{"optionalgroup": protobuild.Message{
"a": 2,
}},
allTypesNoProto3...,
))...)
tests = append(tests, makeTest(test{desc: "Groups"}, makeXY(
protobuild.Message{},
protobuild.Message{"optionalgroup": protobuild.Message{}},
allTypesNoProto3...,
))...)
// Messages.
tests = append(tests, makeTest(test{desc: "Messages"}, makeXY(
protobuild.Message{"optional_nested_message": protobuild.Message{
"a": 1,
}},
protobuild.Message{"optional_nested_message": protobuild.Message{
"a": 2,
}},
))...)
tests = append(tests, makeTest(test{desc: "Messages"}, makeXY(
protobuild.Message{},
protobuild.Message{"optional_nested_message": protobuild.Message{}},
))...)
// Lists.
tests = append(tests, makeTest(test{desc: "Lists"}, makeXY(
protobuild.Message{"repeated_int32": []int32{1}},
protobuild.Message{"repeated_int32": []int32{1, 2}},
))...)
tests = append(tests, makeTest(test{desc: "Lists"}, makeXY(
protobuild.Message{"repeated_int32": []int32{1, 2}},
protobuild.Message{"repeated_int32": []int32{1, 3}},
))...)
tests = append(tests, makeTest(test{desc: "Lists"}, makeXY(
protobuild.Message{"repeated_int64": []int64{1, 2}},
protobuild.Message{"repeated_int64": []int64{1, 3}},
))...)
tests = append(tests, makeTest(test{desc: "Lists"}, makeXY(
protobuild.Message{"repeated_uint32": []uint32{1, 2}},
protobuild.Message{"repeated_uint32": []uint32{1, 3}},
))...)
tests = append(tests, makeTest(test{desc: "Lists"}, makeXY(
protobuild.Message{"repeated_uint64": []uint64{1, 2}},
protobuild.Message{"repeated_uint64": []uint64{1, 3}},
))...)
tests = append(tests, makeTest(test{desc: "Lists"}, makeXY(
protobuild.Message{"repeated_sint32": []int32{1, 2}},
protobuild.Message{"repeated_sint32": []int32{1, 3}},
))...)
tests = append(tests, makeTest(test{desc: "Lists"}, makeXY(
protobuild.Message{"repeated_sint64": []int64{1, 2}},
protobuild.Message{"repeated_sint64": []int64{1, 3}},
))...)
tests = append(tests, makeTest(test{desc: "Lists"}, makeXY(
protobuild.Message{"repeated_fixed32": []uint32{1, 2}},
protobuild.Message{"repeated_fixed32": []uint32{1, 3}},
))...)
tests = append(tests, makeTest(test{desc: "Lists"}, makeXY(
protobuild.Message{"repeated_fixed64": []uint64{1, 2}},
protobuild.Message{"repeated_fixed64": []uint64{1, 3}},
))...)
tests = append(tests, makeTest(test{desc: "Lists"}, makeXY(
protobuild.Message{"repeated_sfixed32": []int32{1, 2}},
protobuild.Message{"repeated_sfixed32": []int32{1, 3}},
))...)
tests = append(tests, makeTest(test{desc: "Lists"}, makeXY(
protobuild.Message{"repeated_sfixed64": []int32{1, 2}},
protobuild.Message{"repeated_sfixed64": []int32{1, 3}},
))...)
tests = append(tests, makeTest(test{desc: "Lists"}, makeXY(
protobuild.Message{"repeated_float": []float32{1, 2}},
protobuild.Message{"repeated_float": []float32{1, 3}},
))...)
tests = append(tests, makeTest(test{desc: "Lists"}, makeXY(
protobuild.Message{"repeated_double": []float64{1, 2}},
protobuild.Message{"repeated_double": []float64{1, 3}},
))...)
tests = append(tests, makeTest(test{desc: "Lists"}, makeXY(
protobuild.Message{"repeated_bool": []bool{true, false}},
protobuild.Message{"repeated_bool": []bool{true, true}},
))...)
tests = append(tests, makeTest(test{desc: "Lists"}, makeXY(
protobuild.Message{"repeated_string": []string{"a", "b"}},
protobuild.Message{"repeated_string": []string{"a", "c"}},
))...)
tests = append(tests, makeTest(test{desc: "Lists"}, makeXY(
protobuild.Message{"repeated_bytes": [][]byte{[]byte("a"), []byte("b")}},
protobuild.Message{"repeated_bytes": [][]byte{[]byte("a"), []byte("c")}},
))...)
tests = append(tests, makeTest(test{desc: "Lists"}, makeXY(
protobuild.Message{"repeated_nested_enum": []string{"FOO"}},
protobuild.Message{"repeated_nested_enum": []string{"BAR"}},
))...)
tests = append(tests, makeTest(test{desc: "Lists"}, makeXY(
protobuild.Message{"repeatedgroup": []protobuild.Message{
{"a": 1},
{"a": 2},
}},
protobuild.Message{"repeatedgroup": []protobuild.Message{
{"a": 1},
{"a": 3},
}},
allTypesNoProto3...,
))...)
tests = append(tests, makeTest(test{desc: "Lists"}, makeXY(
protobuild.Message{"repeated_nested_message": []protobuild.Message{
{"a": 1},
{"a": 2},
}},
protobuild.Message{"repeated_nested_message": []protobuild.Message{
{"a": 1},
{"a": 3},
}},
))...)
// Maps: various configurations.
allTypesNoExt := []proto.Message{
&testpb.TestAllTypes{},
&test3pb.TestAllTypes{},
// TestAllExtensions is intentionally missing:
// protoc prevents adding a map field to an extension:
// Map fields are not allowed to be extensions.
&testeditionspb.TestAllTypes{},
}
tests = append(tests, makeTest(test{desc: "MapsDifferent"}, makeXY(
protobuild.Message{"map_int32_int32": map[int32]int32{1: 2}},
protobuild.Message{"map_int32_int32": map[int32]int32{3: 4}},
allTypesNoExt...,
))...)
tests = append(tests, makeTest(test{desc: "MapsAdditionalY"}, makeXY(
protobuild.Message{"map_int32_int32": map[int32]int32{1: 2}},
protobuild.Message{"map_int32_int32": map[int32]int32{1: 2, 3: 4}},
allTypesNoExt...,
))...)
tests = append(tests, makeTest(test{desc: "MapsAdditionalX"}, makeXY(
protobuild.Message{"map_int32_int32": map[int32]int32{1: 2, 3: 4}},
protobuild.Message{"map_int32_int32": map[int32]int32{1: 2}},
allTypesNoExt...,
))...)
// Maps: various types.
tests = append(tests, makeTest(test{desc: "MapsTypes"}, makeXY(
protobuild.Message{"map_int32_int32": map[int32]int32{1: 2, 3: 4}},
protobuild.Message{"map_int32_int32": map[int32]int32{1: 2, 3: 5}},
allTypesNoExt...,
))...)
tests = append(tests, makeTest(test{desc: "MapsTypes"}, makeXY(
protobuild.Message{"map_int64_int64": map[int64]int64{1: 2, 3: 4}},
protobuild.Message{"map_int64_int64": map[int64]int64{1: 2, 3: 5}},
allTypesNoExt...,
))...)
tests = append(tests, makeTest(test{desc: "MapsTypes"}, makeXY(
protobuild.Message{"map_uint32_uint32": map[uint32]uint32{1: 2, 3: 4}},
protobuild.Message{"map_uint32_uint32": map[uint32]uint32{1: 2, 3: 5}},
allTypesNoExt...,
))...)
tests = append(tests, makeTest(test{desc: "MapsTypes"}, makeXY(
protobuild.Message{"map_uint64_uint64": map[uint64]uint64{1: 2, 3: 4}},
protobuild.Message{"map_uint64_uint64": map[uint64]uint64{1: 2, 3: 5}},
allTypesNoExt...,
))...)
tests = append(tests, makeTest(test{desc: "MapsTypes"}, makeXY(
protobuild.Message{"map_sint32_sint32": map[int32]int32{1: 2, 3: 4}},
protobuild.Message{"map_sint32_sint32": map[int32]int32{1: 2, 3: 5}},
allTypesNoExt...,
))...)
tests = append(tests, makeTest(test{desc: "MapsTypes"}, makeXY(
protobuild.Message{"map_sint64_sint64": map[int64]int64{1: 2, 3: 4}},
protobuild.Message{"map_sint64_sint64": map[int64]int64{1: 2, 3: 5}},
allTypesNoExt...,
))...)
tests = append(tests, makeTest(test{desc: "MapsTypes"}, makeXY(
protobuild.Message{"map_fixed32_fixed32": map[uint32]uint32{1: 2, 3: 4}},
protobuild.Message{"map_fixed32_fixed32": map[uint32]uint32{1: 2, 3: 5}},
allTypesNoExt...,
))...)
tests = append(tests, makeTest(test{desc: "MapsTypes"}, makeXY(
protobuild.Message{"map_fixed64_fixed64": map[uint64]uint64{1: 2, 3: 4}},
protobuild.Message{"map_fixed64_fixed64": map[uint64]uint64{1: 2, 3: 5}},
allTypesNoExt...,
))...)
tests = append(tests, makeTest(test{desc: "MapsTypes"}, makeXY(
protobuild.Message{"map_sfixed32_sfixed32": map[int32]int32{1: 2, 3: 4}},
protobuild.Message{"map_sfixed32_sfixed32": map[int32]int32{1: 2, 3: 5}},
allTypesNoExt...,
))...)
tests = append(tests, makeTest(test{desc: "MapsTypes"}, makeXY(
protobuild.Message{"map_sfixed64_sfixed64": map[int64]int64{1: 2, 3: 4}},
protobuild.Message{"map_sfixed64_sfixed64": map[int64]int64{1: 2, 3: 5}},
allTypesNoExt...,
))...)
tests = append(tests, makeTest(test{desc: "MapsTypes"}, makeXY(
protobuild.Message{"map_int32_float": map[int32]float32{1: 2, 3: 4}},
protobuild.Message{"map_int32_float": map[int32]float32{1: 2, 3: 5}},
allTypesNoExt...,
))...)
tests = append(tests, makeTest(test{desc: "MapsTypes"}, makeXY(
protobuild.Message{"map_int32_double": map[int32]float64{1: 2, 3: 4}},
protobuild.Message{"map_int32_double": map[int32]float64{1: 2, 3: 5}},
allTypesNoExt...,
))...)
tests = append(tests, makeTest(test{desc: "MapsTypes"}, makeXY(
protobuild.Message{"map_bool_bool": map[bool]bool{true: false, false: true}},
protobuild.Message{"map_bool_bool": map[bool]bool{true: false, false: false}},
allTypesNoExt...,
))...)
tests = append(tests, makeTest(test{desc: "MapsTypes"}, makeXY(
protobuild.Message{"map_string_string": map[string]string{"a": "b", "c": "d"}},
protobuild.Message{"map_string_string": map[string]string{"a": "b", "c": "e"}},
allTypesNoExt...,
))...)
tests = append(tests, makeTest(test{desc: "MapsTypes"}, makeXY(
protobuild.Message{"map_string_bytes": map[string][]byte{"a": []byte("b"), "c": []byte("d")}},
protobuild.Message{"map_string_bytes": map[string][]byte{"a": []byte("b"), "c": []byte("e")}},
allTypesNoExt...,
))...)
tests = append(tests, makeTest(test{desc: "MapsTypes"}, makeXY(
protobuild.Message{"map_string_nested_message": map[string]protobuild.Message{
"a": {"a": int32(1)},
"b": {"a": int32(2)},
}},
protobuild.Message{"map_string_nested_message": map[string]protobuild.Message{
"a": {"a": int32(1)},
"b": {"a": int32(3)},
}},
allTypesNoExt...,
))...)
tests = append(tests, makeTest(test{desc: "MapsTypes"}, makeXY(
protobuild.Message{"map_string_nested_enum": map[string]string{
"a": "FOO",
"b": "BAR",
}},
protobuild.Message{"map_string_nested_enum": map[string]string{
"a": "FOO",
"b": "BAZ",
}},
allTypesNoExt...,
))...)
// Unknown fields.
tests = append(tests, makeTest(test{desc: "Unknown"}, makeXY(
protobuild.Message{protobuild.Unknown: protopack.Message{
protopack.Tag{100000, protopack.VarintType}, protopack.Varint(1),
}.Marshal()},
protobuild.Message{protobuild.Unknown: protopack.Message{
protopack.Tag{100000, protopack.VarintType}, protopack.Varint(2),
}.Marshal()},
))...)
tests = append(tests, makeTest(test{desc: "Unknown"}, makeXY(
protobuild.Message{protobuild.Unknown: protopack.Message{
protopack.Tag{100000, protopack.VarintType}, protopack.Varint(1),
}.Marshal()},
protobuild.Message{},
))...)
// Extensions.
onlyExts := []proto.Message{
&testpb.TestAllExtensions{},
&testeditionspb.TestAllExtensions{},
}
tests = append(tests, makeTest(test{desc: "Extensions"}, makeXY(
protobuild.Message{"optional_int32": 1},
protobuild.Message{"optional_int32": 2},
onlyExts...,
))...)
tests = append(tests, makeTest(test{desc: "Extensions"}, makeXY(
protobuild.Message{},
protobuild.Message{"optional_int32": 2},
onlyExts...,
))...)
for _, tt := range tests {
desc := tt.desc
if desc == "" {
desc = "Untitled"
}
desc += fmt.Sprintf("/x=%T y=%T", tt.x, tt.y)
t.Run(desc, func(t *testing.T) {
if !tt.eq && !proto.Equal(tt.x, tt.x) {
t.Errorf("Equal(x, x) = false, want true\n==== x ====\n%v", prototext.Format(tt.x))
}
if !tt.eq && !proto.Equal(tt.y, tt.y) {
t.Errorf("Equal(y, y) = false, want true\n==== y ====\n%v", prototext.Format(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, prototext.Format(tt.x), prototext.Format(tt.y))
}
})
}
}
func BenchmarkEqualWithSmallEmpty(b *testing.B) {
b.ReportAllocs()
x := &testpb.ForeignMessage{}
y := &testpb.ForeignMessage{}
b.ResetTimer()
for i := 0; i < b.N; i++ {
proto.Equal(x, y)
}
}
func BenchmarkEqualWithIdenticalPtrEmpty(b *testing.B) {
b.ReportAllocs()
x := &testpb.ForeignMessage{}
b.ResetTimer()
for i := 0; i < b.N; i++ {
proto.Equal(x, x)
}
}
func BenchmarkEqualWithLargeEmpty(b *testing.B) {
b.ReportAllocs()
x := &testpb.TestManyMessageFieldsMessage{
F1: makeNested(2),
F10: makeNested(2),
F20: makeNested(2),
F30: makeNested(2),
F40: makeNested(2),
F50: makeNested(2),
F60: makeNested(2),
F70: makeNested(2),
F80: makeNested(2),
F90: makeNested(2),
}
y := &testpb.TestManyMessageFieldsMessage{
F1: makeNested(2),
F10: makeNested(2),
F20: makeNested(2),
F30: makeNested(2),
F40: makeNested(2),
F50: makeNested(2),
F60: makeNested(2),
F70: makeNested(2),
F80: makeNested(2),
F90: makeNested(2),
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
proto.Equal(x, y)
}
}
func makeNested(depth int) *testpb.TestAllTypes {
if depth <= 0 {
return nil
}
return &testpb.TestAllTypes{
OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{
Corecursive: makeNested(depth - 1),
},
}
}
func BenchmarkEqualWithDeeplyNestedEqual(b *testing.B) {
b.ReportAllocs()
x := makeNested(20)
y := makeNested(20)
b.ResetTimer()
for i := 0; i < b.N; i++ {
proto.Equal(x, y)
}
}
func BenchmarkEqualWithDeeplyNestedDifferent(b *testing.B) {
b.ReportAllocs()
x := makeNested(20)
y := makeNested(21)
b.ResetTimer()
for i := 0; i < b.N; i++ {
proto.Equal(x, y)
}
}
func BenchmarkEqualWithDeeplyNestedIdenticalPtr(b *testing.B) {
b.ReportAllocs()
x := makeNested(20)
b.ResetTimer()
for i := 0; i < b.N; i++ {
proto.Equal(x, x)
}
}