...

Source file src/google.golang.org/protobuf/proto/equal_test.go

Documentation: google.golang.org/protobuf/proto

     1  // Copyright 2019 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package proto_test
     6  
     7  import (
     8  	"math"
     9  	"testing"
    10  
    11  	"google.golang.org/protobuf/encoding/prototext"
    12  	"google.golang.org/protobuf/internal/pragma"
    13  	"google.golang.org/protobuf/proto"
    14  	"google.golang.org/protobuf/testing/protopack"
    15  
    16  	testpb "google.golang.org/protobuf/internal/testprotos/test"
    17  	test3pb "google.golang.org/protobuf/internal/testprotos/test3"
    18  )
    19  
    20  func TestEqual(t *testing.T) {
    21  	identicalPtrPb := &testpb.TestAllTypes{MapStringString: map[string]string{"a": "b", "c": "d"}}
    22  
    23  	type incomparableMessage struct {
    24  		*testpb.TestAllTypes
    25  		pragma.DoNotCompare
    26  	}
    27  
    28  	tests := []struct {
    29  		x, y proto.Message
    30  		eq   bool
    31  	}{
    32  		{
    33  			x:  nil,
    34  			y:  nil,
    35  			eq: true,
    36  		}, {
    37  			x:  (*testpb.TestAllTypes)(nil),
    38  			y:  nil,
    39  			eq: false,
    40  		}, {
    41  			x:  (*testpb.TestAllTypes)(nil),
    42  			y:  (*testpb.TestAllTypes)(nil),
    43  			eq: true,
    44  		}, {
    45  			x:  new(testpb.TestAllTypes),
    46  			y:  (*testpb.TestAllTypes)(nil),
    47  			eq: false,
    48  		}, {
    49  			x:  new(testpb.TestAllTypes),
    50  			y:  new(testpb.TestAllTypes),
    51  			eq: true,
    52  		}, {
    53  			x:  (*testpb.TestAllTypes)(nil),
    54  			y:  (*testpb.TestAllExtensions)(nil),
    55  			eq: false,
    56  		}, {
    57  			x:  (*testpb.TestAllTypes)(nil),
    58  			y:  new(testpb.TestAllExtensions),
    59  			eq: false,
    60  		}, {
    61  			x:  new(testpb.TestAllTypes),
    62  			y:  new(testpb.TestAllExtensions),
    63  			eq: false,
    64  		},
    65  
    66  		// Identical input pointers
    67  		{
    68  			x:  identicalPtrPb,
    69  			y:  identicalPtrPb,
    70  			eq: true,
    71  		},
    72  
    73  		// Incomparable types. The top-level types are not actually directly
    74  		// compared (which would panic), but rather the comparison happens on the
    75  		// objects returned by ProtoReflect(). These tests are here just to ensure
    76  		// that any short-circuit checks do not accidentally try to compare
    77  		// incomparable top-level types.
    78  		{
    79  			x:  incomparableMessage{TestAllTypes: identicalPtrPb},
    80  			y:  incomparableMessage{TestAllTypes: identicalPtrPb},
    81  			eq: true,
    82  		},
    83  		{
    84  			x:  identicalPtrPb,
    85  			y:  incomparableMessage{TestAllTypes: identicalPtrPb},
    86  			eq: true,
    87  		},
    88  		{
    89  			x:  identicalPtrPb,
    90  			y:  &incomparableMessage{TestAllTypes: identicalPtrPb},
    91  			eq: true,
    92  		},
    93  
    94  		// Proto2 scalars.
    95  		{
    96  			x: &testpb.TestAllTypes{OptionalInt32: proto.Int32(1)},
    97  			y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(2)},
    98  		}, {
    99  			x: &testpb.TestAllTypes{OptionalInt64: proto.Int64(1)},
   100  			y: &testpb.TestAllTypes{OptionalInt64: proto.Int64(2)},
   101  		}, {
   102  			x: &testpb.TestAllTypes{OptionalUint32: proto.Uint32(1)},
   103  			y: &testpb.TestAllTypes{OptionalUint32: proto.Uint32(2)},
   104  		}, {
   105  			x: &testpb.TestAllTypes{OptionalUint64: proto.Uint64(1)},
   106  			y: &testpb.TestAllTypes{OptionalUint64: proto.Uint64(2)},
   107  		}, {
   108  			x: &testpb.TestAllTypes{OptionalSint32: proto.Int32(1)},
   109  			y: &testpb.TestAllTypes{OptionalSint32: proto.Int32(2)},
   110  		}, {
   111  			x: &testpb.TestAllTypes{OptionalSint64: proto.Int64(1)},
   112  			y: &testpb.TestAllTypes{OptionalSint64: proto.Int64(2)},
   113  		}, {
   114  			x: &testpb.TestAllTypes{OptionalFixed32: proto.Uint32(1)},
   115  			y: &testpb.TestAllTypes{OptionalFixed32: proto.Uint32(2)},
   116  		}, {
   117  			x: &testpb.TestAllTypes{OptionalFixed64: proto.Uint64(1)},
   118  			y: &testpb.TestAllTypes{OptionalFixed64: proto.Uint64(2)},
   119  		}, {
   120  			x: &testpb.TestAllTypes{OptionalSfixed32: proto.Int32(1)},
   121  			y: &testpb.TestAllTypes{OptionalSfixed32: proto.Int32(2)},
   122  		}, {
   123  			x: &testpb.TestAllTypes{OptionalSfixed64: proto.Int64(1)},
   124  			y: &testpb.TestAllTypes{OptionalSfixed64: proto.Int64(2)},
   125  		}, {
   126  			x: &testpb.TestAllTypes{OptionalFloat: proto.Float32(1)},
   127  			y: &testpb.TestAllTypes{OptionalFloat: proto.Float32(2)},
   128  		}, {
   129  			x: &testpb.TestAllTypes{OptionalDouble: proto.Float64(1)},
   130  			y: &testpb.TestAllTypes{OptionalDouble: proto.Float64(2)},
   131  		}, {
   132  			x: &testpb.TestAllTypes{OptionalFloat: proto.Float32(float32(math.NaN()))},
   133  			y: &testpb.TestAllTypes{OptionalFloat: proto.Float32(0)},
   134  		}, {
   135  			x: &testpb.TestAllTypes{OptionalDouble: proto.Float64(float64(math.NaN()))},
   136  			y: &testpb.TestAllTypes{OptionalDouble: proto.Float64(0)},
   137  		}, {
   138  			x: &testpb.TestAllTypes{OptionalBool: proto.Bool(true)},
   139  			y: &testpb.TestAllTypes{OptionalBool: proto.Bool(false)},
   140  		}, {
   141  			x: &testpb.TestAllTypes{OptionalString: proto.String("a")},
   142  			y: &testpb.TestAllTypes{OptionalString: proto.String("b")},
   143  		}, {
   144  			x: &testpb.TestAllTypes{OptionalBytes: []byte("a")},
   145  			y: &testpb.TestAllTypes{OptionalBytes: []byte("b")},
   146  		}, {
   147  			x: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
   148  			y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_BAR.Enum()},
   149  		}, {
   150  			x:  &testpb.TestAllTypes{OptionalInt32: proto.Int32(2)},
   151  			y:  &testpb.TestAllTypes{OptionalInt32: proto.Int32(2)},
   152  			eq: true,
   153  		}, {
   154  			x:  &testpb.TestAllTypes{OptionalInt64: proto.Int64(2)},
   155  			y:  &testpb.TestAllTypes{OptionalInt64: proto.Int64(2)},
   156  			eq: true,
   157  		}, {
   158  			x:  &testpb.TestAllTypes{OptionalUint32: proto.Uint32(2)},
   159  			y:  &testpb.TestAllTypes{OptionalUint32: proto.Uint32(2)},
   160  			eq: true,
   161  		}, {
   162  			x:  &testpb.TestAllTypes{OptionalUint64: proto.Uint64(2)},
   163  			y:  &testpb.TestAllTypes{OptionalUint64: proto.Uint64(2)},
   164  			eq: true,
   165  		}, {
   166  			x:  &testpb.TestAllTypes{OptionalSint32: proto.Int32(2)},
   167  			y:  &testpb.TestAllTypes{OptionalSint32: proto.Int32(2)},
   168  			eq: true,
   169  		}, {
   170  			x:  &testpb.TestAllTypes{OptionalSint64: proto.Int64(2)},
   171  			y:  &testpb.TestAllTypes{OptionalSint64: proto.Int64(2)},
   172  			eq: true,
   173  		}, {
   174  			x:  &testpb.TestAllTypes{OptionalFixed32: proto.Uint32(2)},
   175  			y:  &testpb.TestAllTypes{OptionalFixed32: proto.Uint32(2)},
   176  			eq: true,
   177  		}, {
   178  			x:  &testpb.TestAllTypes{OptionalFixed64: proto.Uint64(2)},
   179  			y:  &testpb.TestAllTypes{OptionalFixed64: proto.Uint64(2)},
   180  			eq: true,
   181  		}, {
   182  			x:  &testpb.TestAllTypes{OptionalSfixed32: proto.Int32(2)},
   183  			y:  &testpb.TestAllTypes{OptionalSfixed32: proto.Int32(2)},
   184  			eq: true,
   185  		}, {
   186  			x:  &testpb.TestAllTypes{OptionalSfixed64: proto.Int64(2)},
   187  			y:  &testpb.TestAllTypes{OptionalSfixed64: proto.Int64(2)},
   188  			eq: true,
   189  		}, {
   190  			x:  &testpb.TestAllTypes{OptionalFloat: proto.Float32(2)},
   191  			y:  &testpb.TestAllTypes{OptionalFloat: proto.Float32(2)},
   192  			eq: true,
   193  		}, {
   194  			x:  &testpb.TestAllTypes{OptionalDouble: proto.Float64(2)},
   195  			y:  &testpb.TestAllTypes{OptionalDouble: proto.Float64(2)},
   196  			eq: true,
   197  		}, {
   198  			x:  &testpb.TestAllTypes{OptionalFloat: proto.Float32(float32(math.NaN()))},
   199  			y:  &testpb.TestAllTypes{OptionalFloat: proto.Float32(float32(math.NaN()))},
   200  			eq: true,
   201  		}, {
   202  			x:  &testpb.TestAllTypes{OptionalDouble: proto.Float64(float64(math.NaN()))},
   203  			y:  &testpb.TestAllTypes{OptionalDouble: proto.Float64(float64(math.NaN()))},
   204  			eq: true,
   205  		}, {
   206  			x:  &testpb.TestAllTypes{OptionalBool: proto.Bool(true)},
   207  			y:  &testpb.TestAllTypes{OptionalBool: proto.Bool(true)},
   208  			eq: true,
   209  		}, {
   210  			x:  &testpb.TestAllTypes{OptionalString: proto.String("abc")},
   211  			y:  &testpb.TestAllTypes{OptionalString: proto.String("abc")},
   212  			eq: true,
   213  		}, {
   214  			x:  &testpb.TestAllTypes{OptionalBytes: []byte("abc")},
   215  			y:  &testpb.TestAllTypes{OptionalBytes: []byte("abc")},
   216  			eq: true,
   217  		}, {
   218  			x:  &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
   219  			y:  &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
   220  			eq: true,
   221  		},
   222  
   223  		// Proto2 presence.
   224  		{
   225  			x: &testpb.TestAllTypes{},
   226  			y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(0)},
   227  		}, {
   228  			x: &testpb.TestAllTypes{},
   229  			y: &testpb.TestAllTypes{OptionalInt64: proto.Int64(0)},
   230  		}, {
   231  			x: &testpb.TestAllTypes{},
   232  			y: &testpb.TestAllTypes{OptionalUint32: proto.Uint32(0)},
   233  		}, {
   234  			x: &testpb.TestAllTypes{},
   235  			y: &testpb.TestAllTypes{OptionalUint64: proto.Uint64(0)},
   236  		}, {
   237  			x: &testpb.TestAllTypes{},
   238  			y: &testpb.TestAllTypes{OptionalSint32: proto.Int32(0)},
   239  		}, {
   240  			x: &testpb.TestAllTypes{},
   241  			y: &testpb.TestAllTypes{OptionalSint64: proto.Int64(0)},
   242  		}, {
   243  			x: &testpb.TestAllTypes{},
   244  			y: &testpb.TestAllTypes{OptionalFixed32: proto.Uint32(0)},
   245  		}, {
   246  			x: &testpb.TestAllTypes{},
   247  			y: &testpb.TestAllTypes{OptionalFixed64: proto.Uint64(0)},
   248  		}, {
   249  			x: &testpb.TestAllTypes{},
   250  			y: &testpb.TestAllTypes{OptionalSfixed32: proto.Int32(0)},
   251  		}, {
   252  			x: &testpb.TestAllTypes{},
   253  			y: &testpb.TestAllTypes{OptionalSfixed64: proto.Int64(0)},
   254  		}, {
   255  			x: &testpb.TestAllTypes{},
   256  			y: &testpb.TestAllTypes{OptionalFloat: proto.Float32(0)},
   257  		}, {
   258  			x: &testpb.TestAllTypes{},
   259  			y: &testpb.TestAllTypes{OptionalDouble: proto.Float64(0)},
   260  		}, {
   261  			x: &testpb.TestAllTypes{},
   262  			y: &testpb.TestAllTypes{OptionalBool: proto.Bool(false)},
   263  		}, {
   264  			x: &testpb.TestAllTypes{},
   265  			y: &testpb.TestAllTypes{OptionalString: proto.String("")},
   266  		}, {
   267  			x: &testpb.TestAllTypes{},
   268  			y: &testpb.TestAllTypes{OptionalBytes: []byte{}},
   269  		}, {
   270  			x: &testpb.TestAllTypes{},
   271  			y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
   272  		},
   273  
   274  		// Proto3 presence.
   275  		{
   276  			x: &test3pb.TestAllTypes{},
   277  			y: &test3pb.TestAllTypes{OptionalInt32: proto.Int32(0)},
   278  		}, {
   279  			x: &test3pb.TestAllTypes{},
   280  			y: &test3pb.TestAllTypes{OptionalInt64: proto.Int64(0)},
   281  		}, {
   282  			x: &test3pb.TestAllTypes{},
   283  			y: &test3pb.TestAllTypes{OptionalUint32: proto.Uint32(0)},
   284  		}, {
   285  			x: &test3pb.TestAllTypes{},
   286  			y: &test3pb.TestAllTypes{OptionalUint64: proto.Uint64(0)},
   287  		}, {
   288  			x: &test3pb.TestAllTypes{},
   289  			y: &test3pb.TestAllTypes{OptionalSint32: proto.Int32(0)},
   290  		}, {
   291  			x: &test3pb.TestAllTypes{},
   292  			y: &test3pb.TestAllTypes{OptionalSint64: proto.Int64(0)},
   293  		}, {
   294  			x: &test3pb.TestAllTypes{},
   295  			y: &test3pb.TestAllTypes{OptionalFixed32: proto.Uint32(0)},
   296  		}, {
   297  			x: &test3pb.TestAllTypes{},
   298  			y: &test3pb.TestAllTypes{OptionalFixed64: proto.Uint64(0)},
   299  		}, {
   300  			x: &test3pb.TestAllTypes{},
   301  			y: &test3pb.TestAllTypes{OptionalSfixed32: proto.Int32(0)},
   302  		}, {
   303  			x: &test3pb.TestAllTypes{},
   304  			y: &test3pb.TestAllTypes{OptionalSfixed64: proto.Int64(0)},
   305  		}, {
   306  			x: &test3pb.TestAllTypes{},
   307  			y: &test3pb.TestAllTypes{OptionalFloat: proto.Float32(0)},
   308  		}, {
   309  			x: &test3pb.TestAllTypes{},
   310  			y: &test3pb.TestAllTypes{OptionalDouble: proto.Float64(0)},
   311  		}, {
   312  			x: &test3pb.TestAllTypes{},
   313  			y: &test3pb.TestAllTypes{OptionalBool: proto.Bool(false)},
   314  		}, {
   315  			x: &test3pb.TestAllTypes{},
   316  			y: &test3pb.TestAllTypes{OptionalString: proto.String("")},
   317  		}, {
   318  			x: &test3pb.TestAllTypes{},
   319  			y: &test3pb.TestAllTypes{OptionalBytes: []byte{}},
   320  		}, {
   321  			x: &test3pb.TestAllTypes{},
   322  			y: &test3pb.TestAllTypes{OptionalNestedEnum: test3pb.TestAllTypes_FOO.Enum()},
   323  		},
   324  
   325  		// Proto2 default values are not considered by Equal, so the following are still unequal.
   326  		{
   327  			x: &testpb.TestAllTypes{DefaultInt32: proto.Int32(81)},
   328  			y: &testpb.TestAllTypes{},
   329  		}, {
   330  			x: &testpb.TestAllTypes{},
   331  			y: &testpb.TestAllTypes{DefaultInt32: proto.Int32(81)},
   332  		}, {
   333  			x: &testpb.TestAllTypes{},
   334  			y: &testpb.TestAllTypes{DefaultInt64: proto.Int64(82)},
   335  		}, {
   336  			x: &testpb.TestAllTypes{},
   337  			y: &testpb.TestAllTypes{DefaultUint32: proto.Uint32(83)},
   338  		}, {
   339  			x: &testpb.TestAllTypes{},
   340  			y: &testpb.TestAllTypes{DefaultUint64: proto.Uint64(84)},
   341  		}, {
   342  			x: &testpb.TestAllTypes{},
   343  			y: &testpb.TestAllTypes{DefaultSint32: proto.Int32(-85)},
   344  		}, {
   345  			x: &testpb.TestAllTypes{},
   346  			y: &testpb.TestAllTypes{DefaultSint64: proto.Int64(86)},
   347  		}, {
   348  			x: &testpb.TestAllTypes{},
   349  			y: &testpb.TestAllTypes{DefaultFixed32: proto.Uint32(87)},
   350  		}, {
   351  			x: &testpb.TestAllTypes{},
   352  			y: &testpb.TestAllTypes{DefaultFixed64: proto.Uint64(88)},
   353  		}, {
   354  			x: &testpb.TestAllTypes{},
   355  			y: &testpb.TestAllTypes{DefaultSfixed32: proto.Int32(89)},
   356  		}, {
   357  			x: &testpb.TestAllTypes{},
   358  			y: &testpb.TestAllTypes{DefaultSfixed64: proto.Int64(-90)},
   359  		}, {
   360  			x: &testpb.TestAllTypes{},
   361  			y: &testpb.TestAllTypes{DefaultFloat: proto.Float32(91.5)},
   362  		}, {
   363  			x: &testpb.TestAllTypes{},
   364  			y: &testpb.TestAllTypes{DefaultDouble: proto.Float64(92e3)},
   365  		}, {
   366  			x: &testpb.TestAllTypes{},
   367  			y: &testpb.TestAllTypes{DefaultBool: proto.Bool(true)},
   368  		}, {
   369  			x: &testpb.TestAllTypes{},
   370  			y: &testpb.TestAllTypes{DefaultString: proto.String("hello")},
   371  		}, {
   372  			x: &testpb.TestAllTypes{},
   373  			y: &testpb.TestAllTypes{DefaultBytes: []byte("world")},
   374  		}, {
   375  			x: &testpb.TestAllTypes{},
   376  			y: &testpb.TestAllTypes{DefaultNestedEnum: testpb.TestAllTypes_BAR.Enum()},
   377  		},
   378  
   379  		// Groups.
   380  		{
   381  			x: &testpb.TestAllTypes{Optionalgroup: &testpb.TestAllTypes_OptionalGroup{
   382  				A: proto.Int32(1),
   383  			}},
   384  			y: &testpb.TestAllTypes{Optionalgroup: &testpb.TestAllTypes_OptionalGroup{
   385  				A: proto.Int32(2),
   386  			}},
   387  		}, {
   388  			x: &testpb.TestAllTypes{},
   389  			y: &testpb.TestAllTypes{Optionalgroup: &testpb.TestAllTypes_OptionalGroup{}},
   390  		},
   391  
   392  		// Messages.
   393  		{
   394  			x: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{
   395  				A: proto.Int32(1),
   396  			}},
   397  			y: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{
   398  				A: proto.Int32(2),
   399  			}},
   400  		}, {
   401  			x: &testpb.TestAllTypes{},
   402  			y: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{}},
   403  		}, {
   404  			x: &test3pb.TestAllTypes{},
   405  			y: &test3pb.TestAllTypes{OptionalNestedMessage: &test3pb.TestAllTypes_NestedMessage{}},
   406  		},
   407  
   408  		// Lists.
   409  		{
   410  			x: &testpb.TestAllTypes{RepeatedInt32: []int32{1}},
   411  			y: &testpb.TestAllTypes{RepeatedInt32: []int32{1, 2}},
   412  		}, {
   413  			x: &testpb.TestAllTypes{RepeatedInt32: []int32{1, 2}},
   414  			y: &testpb.TestAllTypes{RepeatedInt32: []int32{1, 3}},
   415  		}, {
   416  			x: &testpb.TestAllTypes{RepeatedInt64: []int64{1, 2}},
   417  			y: &testpb.TestAllTypes{RepeatedInt64: []int64{1, 3}},
   418  		}, {
   419  			x: &testpb.TestAllTypes{RepeatedUint32: []uint32{1, 2}},
   420  			y: &testpb.TestAllTypes{RepeatedUint32: []uint32{1, 3}},
   421  		}, {
   422  			x: &testpb.TestAllTypes{RepeatedUint64: []uint64{1, 2}},
   423  			y: &testpb.TestAllTypes{RepeatedUint64: []uint64{1, 3}},
   424  		}, {
   425  			x: &testpb.TestAllTypes{RepeatedSint32: []int32{1, 2}},
   426  			y: &testpb.TestAllTypes{RepeatedSint32: []int32{1, 3}},
   427  		}, {
   428  			x: &testpb.TestAllTypes{RepeatedSint64: []int64{1, 2}},
   429  			y: &testpb.TestAllTypes{RepeatedSint64: []int64{1, 3}},
   430  		}, {
   431  			x: &testpb.TestAllTypes{RepeatedFixed32: []uint32{1, 2}},
   432  			y: &testpb.TestAllTypes{RepeatedFixed32: []uint32{1, 3}},
   433  		}, {
   434  			x: &testpb.TestAllTypes{RepeatedFixed64: []uint64{1, 2}},
   435  			y: &testpb.TestAllTypes{RepeatedFixed64: []uint64{1, 3}},
   436  		}, {
   437  			x: &testpb.TestAllTypes{RepeatedSfixed32: []int32{1, 2}},
   438  			y: &testpb.TestAllTypes{RepeatedSfixed32: []int32{1, 3}},
   439  		}, {
   440  			x: &testpb.TestAllTypes{RepeatedSfixed64: []int64{1, 2}},
   441  			y: &testpb.TestAllTypes{RepeatedSfixed64: []int64{1, 3}},
   442  		}, {
   443  			x: &testpb.TestAllTypes{RepeatedFloat: []float32{1, 2}},
   444  			y: &testpb.TestAllTypes{RepeatedFloat: []float32{1, 3}},
   445  		}, {
   446  			x: &testpb.TestAllTypes{RepeatedDouble: []float64{1, 2}},
   447  			y: &testpb.TestAllTypes{RepeatedDouble: []float64{1, 3}},
   448  		}, {
   449  			x: &testpb.TestAllTypes{RepeatedBool: []bool{true, false}},
   450  			y: &testpb.TestAllTypes{RepeatedBool: []bool{true, true}},
   451  		}, {
   452  			x: &testpb.TestAllTypes{RepeatedString: []string{"a", "b"}},
   453  			y: &testpb.TestAllTypes{RepeatedString: []string{"a", "c"}},
   454  		}, {
   455  			x: &testpb.TestAllTypes{RepeatedBytes: [][]byte{[]byte("a"), []byte("b")}},
   456  			y: &testpb.TestAllTypes{RepeatedBytes: [][]byte{[]byte("a"), []byte("c")}},
   457  		}, {
   458  			x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO}},
   459  			y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}},
   460  		}, {
   461  			x: &testpb.TestAllTypes{Repeatedgroup: []*testpb.TestAllTypes_RepeatedGroup{
   462  				{A: proto.Int32(1)},
   463  				{A: proto.Int32(2)},
   464  			}},
   465  			y: &testpb.TestAllTypes{Repeatedgroup: []*testpb.TestAllTypes_RepeatedGroup{
   466  				{A: proto.Int32(1)},
   467  				{A: proto.Int32(3)},
   468  			}},
   469  		}, {
   470  			x: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{
   471  				{A: proto.Int32(1)},
   472  				{A: proto.Int32(2)},
   473  			}},
   474  			y: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{
   475  				{A: proto.Int32(1)},
   476  				{A: proto.Int32(3)},
   477  			}},
   478  		},
   479  
   480  		// Maps: various configurations.
   481  		{
   482  			x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2}},
   483  			y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{3: 4}},
   484  		}, {
   485  			x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2}},
   486  			y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 4}},
   487  		}, {
   488  			x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 4}},
   489  			y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2}},
   490  		},
   491  
   492  		// Maps: various types.
   493  		{
   494  			x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 4}},
   495  			y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 5}},
   496  		}, {
   497  			x: &testpb.TestAllTypes{MapInt64Int64: map[int64]int64{1: 2, 3: 4}},
   498  			y: &testpb.TestAllTypes{MapInt64Int64: map[int64]int64{1: 2, 3: 5}},
   499  		}, {
   500  			x: &testpb.TestAllTypes{MapUint32Uint32: map[uint32]uint32{1: 2, 3: 4}},
   501  			y: &testpb.TestAllTypes{MapUint32Uint32: map[uint32]uint32{1: 2, 3: 5}},
   502  		}, {
   503  			x: &testpb.TestAllTypes{MapUint64Uint64: map[uint64]uint64{1: 2, 3: 4}},
   504  			y: &testpb.TestAllTypes{MapUint64Uint64: map[uint64]uint64{1: 2, 3: 5}},
   505  		}, {
   506  			x: &testpb.TestAllTypes{MapSint32Sint32: map[int32]int32{1: 2, 3: 4}},
   507  			y: &testpb.TestAllTypes{MapSint32Sint32: map[int32]int32{1: 2, 3: 5}},
   508  		}, {
   509  			x: &testpb.TestAllTypes{MapSint64Sint64: map[int64]int64{1: 2, 3: 4}},
   510  			y: &testpb.TestAllTypes{MapSint64Sint64: map[int64]int64{1: 2, 3: 5}},
   511  		}, {
   512  			x: &testpb.TestAllTypes{MapFixed32Fixed32: map[uint32]uint32{1: 2, 3: 4}},
   513  			y: &testpb.TestAllTypes{MapFixed32Fixed32: map[uint32]uint32{1: 2, 3: 5}},
   514  		}, {
   515  			x: &testpb.TestAllTypes{MapFixed64Fixed64: map[uint64]uint64{1: 2, 3: 4}},
   516  			y: &testpb.TestAllTypes{MapFixed64Fixed64: map[uint64]uint64{1: 2, 3: 5}},
   517  		}, {
   518  			x: &testpb.TestAllTypes{MapSfixed32Sfixed32: map[int32]int32{1: 2, 3: 4}},
   519  			y: &testpb.TestAllTypes{MapSfixed32Sfixed32: map[int32]int32{1: 2, 3: 5}},
   520  		}, {
   521  			x: &testpb.TestAllTypes{MapSfixed64Sfixed64: map[int64]int64{1: 2, 3: 4}},
   522  			y: &testpb.TestAllTypes{MapSfixed64Sfixed64: map[int64]int64{1: 2, 3: 5}},
   523  		}, {
   524  			x: &testpb.TestAllTypes{MapInt32Float: map[int32]float32{1: 2, 3: 4}},
   525  			y: &testpb.TestAllTypes{MapInt32Float: map[int32]float32{1: 2, 3: 5}},
   526  		}, {
   527  			x: &testpb.TestAllTypes{MapInt32Double: map[int32]float64{1: 2, 3: 4}},
   528  			y: &testpb.TestAllTypes{MapInt32Double: map[int32]float64{1: 2, 3: 5}},
   529  		}, {
   530  			x: &testpb.TestAllTypes{MapBoolBool: map[bool]bool{true: false, false: true}},
   531  			y: &testpb.TestAllTypes{MapBoolBool: map[bool]bool{true: false, false: false}},
   532  		}, {
   533  			x: &testpb.TestAllTypes{MapStringString: map[string]string{"a": "b", "c": "d"}},
   534  			y: &testpb.TestAllTypes{MapStringString: map[string]string{"a": "b", "c": "e"}},
   535  		}, {
   536  			x: &testpb.TestAllTypes{MapStringBytes: map[string][]byte{"a": []byte("b"), "c": []byte("d")}},
   537  			y: &testpb.TestAllTypes{MapStringBytes: map[string][]byte{"a": []byte("b"), "c": []byte("e")}},
   538  		}, {
   539  			x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{
   540  				"a": {A: proto.Int32(1)},
   541  				"b": {A: proto.Int32(2)},
   542  			}},
   543  			y: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{
   544  				"a": {A: proto.Int32(1)},
   545  				"b": {A: proto.Int32(3)},
   546  			}},
   547  		}, {
   548  			x: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{
   549  				"a": testpb.TestAllTypes_FOO,
   550  				"b": testpb.TestAllTypes_BAR,
   551  			}},
   552  			y: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{
   553  				"a": testpb.TestAllTypes_FOO,
   554  				"b": testpb.TestAllTypes_BAZ,
   555  			}},
   556  		},
   557  
   558  		// Extensions.
   559  		{
   560  			x: build(&testpb.TestAllExtensions{},
   561  				extend(testpb.E_OptionalInt32, int32(1)),
   562  			),
   563  			y: build(&testpb.TestAllExtensions{},
   564  				extend(testpb.E_OptionalInt32, int32(2)),
   565  			),
   566  		}, {
   567  			x: &testpb.TestAllExtensions{},
   568  			y: build(&testpb.TestAllExtensions{},
   569  				extend(testpb.E_OptionalInt32, int32(2)),
   570  			),
   571  		},
   572  
   573  		// Unknown fields.
   574  		{
   575  			x: build(&testpb.TestAllTypes{}, unknown(protopack.Message{
   576  				protopack.Tag{100000, protopack.VarintType}, protopack.Varint(1),
   577  			}.Marshal())),
   578  			y: build(&testpb.TestAllTypes{}, unknown(protopack.Message{
   579  				protopack.Tag{100000, protopack.VarintType}, protopack.Varint(2),
   580  			}.Marshal())),
   581  		}, {
   582  			x: build(&testpb.TestAllTypes{}, unknown(protopack.Message{
   583  				protopack.Tag{100000, protopack.VarintType}, protopack.Varint(1),
   584  			}.Marshal())),
   585  			y: &testpb.TestAllTypes{},
   586  		},
   587  	}
   588  
   589  	for _, tt := range tests {
   590  		if !tt.eq && !proto.Equal(tt.x, tt.x) {
   591  			t.Errorf("Equal(x, x) = false, want true\n==== x ====\n%v", prototext.Format(tt.x))
   592  		}
   593  		if !tt.eq && !proto.Equal(tt.y, tt.y) {
   594  			t.Errorf("Equal(y, y) = false, want true\n==== y ====\n%v", prototext.Format(tt.y))
   595  		}
   596  		if eq := proto.Equal(tt.x, tt.y); eq != tt.eq {
   597  			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))
   598  		}
   599  	}
   600  }
   601  
   602  func BenchmarkEqualWithSmallEmpty(b *testing.B) {
   603  	x := &testpb.ForeignMessage{}
   604  	y := &testpb.ForeignMessage{}
   605  
   606  	b.ResetTimer()
   607  	for i := 0; i < b.N; i++ {
   608  		proto.Equal(x, y)
   609  	}
   610  }
   611  
   612  func BenchmarkEqualWithIdenticalPtrEmpty(b *testing.B) {
   613  	x := &testpb.ForeignMessage{}
   614  
   615  	b.ResetTimer()
   616  	for i := 0; i < b.N; i++ {
   617  		proto.Equal(x, x)
   618  	}
   619  }
   620  
   621  func BenchmarkEqualWithLargeEmpty(b *testing.B) {
   622  	x := &testpb.TestAllTypes{}
   623  	y := &testpb.TestAllTypes{}
   624  
   625  	b.ResetTimer()
   626  	for i := 0; i < b.N; i++ {
   627  		proto.Equal(x, y)
   628  	}
   629  }
   630  
   631  func makeNested(depth int) *testpb.TestAllTypes {
   632  	if depth <= 0 {
   633  		return nil
   634  	}
   635  	return &testpb.TestAllTypes{
   636  		OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{
   637  			Corecursive: makeNested(depth - 1),
   638  		},
   639  	}
   640  }
   641  
   642  func BenchmarkEqualWithDeeplyNestedEqual(b *testing.B) {
   643  	x := makeNested(20)
   644  	y := makeNested(20)
   645  
   646  	b.ResetTimer()
   647  	for i := 0; i < b.N; i++ {
   648  		proto.Equal(x, y)
   649  	}
   650  }
   651  
   652  func BenchmarkEqualWithDeeplyNestedDifferent(b *testing.B) {
   653  	x := makeNested(20)
   654  	y := makeNested(21)
   655  
   656  	b.ResetTimer()
   657  	for i := 0; i < b.N; i++ {
   658  		proto.Equal(x, y)
   659  	}
   660  }
   661  
   662  func BenchmarkEqualWithDeeplyNestedIdenticalPtr(b *testing.B) {
   663  	x := makeNested(20)
   664  
   665  	b.ResetTimer()
   666  	for i := 0; i < b.N; i++ {
   667  		proto.Equal(x, x)
   668  	}
   669  }
   670  

View as plain text