| // 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) |
| } |
| } |