github.com/aristanetworks/goarista@v0.0.0-20240514173732-cca2755bbd44/test/data_test.go (about)

     1  // Copyright (c) 2015 Arista Networks, Inc.
     2  // Use of this source code is governed by the Apache License 2.0
     3  // that can be found in the COPYING file.
     4  
     5  package test
     6  
     7  import (
     8  	"errors"
     9  	"fmt"
    10  	"reflect"
    11  	"runtime"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/aristanetworks/goarista/key"
    16  	pb "google.golang.org/protobuf/types/known/durationpb"
    17  )
    18  
    19  type builtinCompare struct {
    20  	a uint32
    21  	b string
    22  }
    23  
    24  type complexCompare struct {
    25  	m map[builtinCompare]int8
    26  	p *complexCompare
    27  }
    28  
    29  type embedder struct {
    30  	builtinCompare
    31  }
    32  
    33  type partialCompare struct {
    34  	a uint32
    35  	b string `deepequal:"ignore"`
    36  }
    37  
    38  type deepEqualTestCase struct {
    39  	a, b interface{}
    40  	diff string
    41  }
    42  
    43  type code int32
    44  
    45  type message string
    46  
    47  type myError struct {
    48  	e string
    49  }
    50  
    51  type myEmbeddedErrorPtr struct {
    52  	e *myError
    53  }
    54  
    55  func (e *myError) Error() string {
    56  	return e.e
    57  }
    58  
    59  type myStringError string
    60  
    61  func (e myStringError) Error() string {
    62  	return string(e)
    63  }
    64  
    65  type hasFunc struct {
    66  	f func()
    67  }
    68  
    69  func someFunction()      {}
    70  func someOtherFunction() {}
    71  
    72  func generateFunc() func() {
    73  	return func() {}
    74  }
    75  
    76  // both of these functions are generated, but will both will be assigned distinct anonymous names,
    77  // for example:
    78  // generatedFuncA would be github.com/aristanetworks/goarista/test.init.func1
    79  // generatedFuncB would be github.com/aristanetworks/goarista/test.init.func2
    80  var generatedFuncA = generateFunc()
    81  var generatedFuncB = generateFunc()
    82  
    83  func getDeepEqualTests(t *testing.T) []deepEqualTestCase {
    84  	var deepEqualNullMapString map[string]interface{}
    85  	recursive := &complexCompare{}
    86  	recursive.p = recursive
    87  	time1 := time.Now()
    88  	time2 := time1.Add(time.Second)
    89  	time1a := time.Unix(0, time1.UnixNano())
    90  	return []deepEqualTestCase{{
    91  		a: nil,
    92  		b: nil,
    93  	}, {
    94  		a: uint8(5),
    95  		b: uint8(5),
    96  	}, {
    97  		a:    nil,
    98  		b:    uint8(5),
    99  		diff: "expected nil but got a uint8: 0x5",
   100  	}, {
   101  		a:    uint8(5),
   102  		b:    nil,
   103  		diff: "expected a uint8 (0x5) but got nil",
   104  	}, {
   105  		a:    uint16(1),
   106  		b:    uint16(2),
   107  		diff: "uint16(1) != uint16(2)",
   108  	}, {
   109  		a:    int8(1),
   110  		b:    int16(1),
   111  		diff: "expected a int8 but got a int16",
   112  	}, {
   113  		a: true,
   114  		b: true,
   115  	}, {
   116  		a: float32(3.1415),
   117  		b: float32(3.1415),
   118  	}, {
   119  		a:    float32(3.1415),
   120  		b:    float32(3.1416),
   121  		diff: "float32(3.1415) != float32(3.1416)",
   122  	}, {
   123  		a: float64(3.14159265),
   124  		b: float64(3.14159265),
   125  	}, {
   126  		a:    float64(3.14159265),
   127  		b:    float64(3.14159266),
   128  		diff: "float64(3.14159265) != float64(3.14159266)",
   129  	}, {
   130  		a: deepEqualNullMapString,
   131  		b: deepEqualNullMapString,
   132  	}, {
   133  		a: &deepEqualNullMapString,
   134  		b: &deepEqualNullMapString,
   135  	}, {
   136  		a:    deepEqualNullMapString,
   137  		b:    &deepEqualNullMapString,
   138  		diff: "expected a map[string]interface {} but got a *map[string]interface {}",
   139  	}, {
   140  		a:    &deepEqualNullMapString,
   141  		b:    deepEqualNullMapString,
   142  		diff: "expected a *map[string]interface {} but got a map[string]interface {}",
   143  	}, {
   144  		a: map[string]interface{}{"a": uint32(42)},
   145  		b: map[string]interface{}{"a": uint32(42)},
   146  	}, {
   147  		a:    map[string]interface{}{"a": int32(42)},
   148  		b:    map[string]interface{}{"a": int32(51)},
   149  		diff: `for key "a" in map, values are different: int32(42) != int32(51)`,
   150  	}, {
   151  		a:    map[string]interface{}{"a": uint32(42)},
   152  		b:    map[string]interface{}{},
   153  		diff: `Maps have different size: 1 != 0 (missing key: "a")`,
   154  	}, {
   155  		a:    map[string]interface{}{},
   156  		b:    map[string]interface{}{"a": uint32(42)},
   157  		diff: `Maps have different size: 0 != 1 (extra key: "a")`,
   158  	}, {
   159  		a:    map[string]interface{}{"a": uint64(42), "b": "extra"},
   160  		b:    map[string]interface{}{"a": uint64(42)},
   161  		diff: `Maps have different size: 2 != 1 (missing key: "b")`,
   162  	}, {
   163  		a:    map[string]interface{}{"a": uint64(42)},
   164  		b:    map[string]interface{}{"a": uint64(42), "b": "extra"},
   165  		diff: `Maps have different size: 1 != 2 (extra key: "b")`,
   166  	}, {
   167  		a: map[uint64]interface{}{uint64(42): "foo"},
   168  		b: map[uint64]interface{}{uint64(42): "foo"},
   169  	}, {
   170  		a:    map[uint64]interface{}{uint64(42): "foo"},
   171  		b:    map[uint64]interface{}{uint64(51): "foo"},
   172  		diff: "key uint64(42) in map is missing in the actual map",
   173  	}, {
   174  		a:    map[uint64]interface{}{uint64(42): "foo"},
   175  		b:    map[uint64]interface{}{uint64(42): "foo", uint64(51): "bar"},
   176  		diff: `Maps have different size: 1 != 2 (extra key: uint64(51))`,
   177  	}, {
   178  		a:    map[uint64]interface{}{uint64(42): "foo"},
   179  		b:    map[interface{}]interface{}{uint32(42): "foo"},
   180  		diff: "expected a map[uint64]interface {} but got a map[interface {}]interface {}",
   181  	}, {
   182  		a:    map[interface{}]interface{}{"a": uint32(42)},
   183  		b:    map[string]interface{}{"a": uint32(42)},
   184  		diff: "expected a map[interface {}]interface {} but got a map[string]interface {}",
   185  	}, {
   186  		a: map[interface{}]interface{}{},
   187  		b: map[interface{}]interface{}{},
   188  	}, {
   189  		a: &map[interface{}]interface{}{},
   190  		b: &map[interface{}]interface{}{},
   191  	}, {
   192  		a: map[interface{}]interface{}{
   193  			&map[string]interface{}{"a": "foo", "b": int16(8)}: "foo"},
   194  		b: map[interface{}]interface{}{
   195  			&map[string]interface{}{"a": "foo", "b": int16(8)}: "foo"},
   196  	}, {
   197  		a: map[interface{}]interface{}{
   198  			&map[string]interface{}{"a": "foo", "b": uint32(8)}: "foo"},
   199  		b: map[interface{}]interface{}{
   200  			&map[string]interface{}{"a": "foo", "b": uint32(8)}: "fox"},
   201  		diff: `for complex key *map[string]interface {}{"a":"foo", "b":uint32(8)}` +
   202  			` in map, values are different: string(foo) != string(fox)`,
   203  	}, {
   204  		a: map[interface{}]interface{}{
   205  			&map[string]interface{}{"a": "foo", "b": uint32(8)}: "foo"},
   206  		b: map[interface{}]interface{}{
   207  			&map[string]interface{}{"a": "foo", "b": uint32(5)}: "foo"},
   208  		diff: `complex key *map[string]interface {}{"a":"foo", "b":uint32(8)}` +
   209  			` in map is missing in the actual map`,
   210  	}, {
   211  		a: map[interface{}]interface{}{
   212  			&map[string]interface{}{"a": "foo", "b": uint32(8)}: "foo"},
   213  		b: map[interface{}]interface{}{
   214  			&map[string]interface{}{"a": "foo"}: "foo"},
   215  		diff: `complex key *map[string]interface {}{"a":"foo", "b":uint32(8)}` +
   216  			` in map is missing in the actual map`,
   217  	}, {
   218  		a: map[interface{}]interface{}{
   219  			&map[string]interface{}{"a": "foo", "b": int16(8)}: "foo",
   220  			&map[string]interface{}{"a": "foo", "b": int8(8)}:  "foo",
   221  		},
   222  		b: map[interface{}]interface{}{
   223  			&map[string]interface{}{"a": "foo", "b": int16(8)}: "foo",
   224  			&map[string]interface{}{"a": "foo", "b": int8(8)}:  "foo",
   225  		},
   226  	}, {
   227  		a: map[interface{}]interface{}{
   228  			&map[string]interface{}{"a": "foo", "b": int16(8)}: "foo",
   229  			&map[string]interface{}{"a": "foo", "b": int8(8)}:  "foo",
   230  		},
   231  		b: map[interface{}]interface{}{
   232  			&map[string]interface{}{"a": "foo", "b": int16(8)}: "foo",
   233  			&map[string]interface{}{"a": "foo", "b": int8(5)}:  "foo",
   234  		},
   235  		diff: `complex key *map[string]interface {}{"a":"foo", "b":int8(8)}` +
   236  			` in map is missing in the actual map`,
   237  	}, {
   238  		a: map[interface{}]interface{}{
   239  			&map[string]interface{}{"a": "foo", "b": int16(8)}: "foo",
   240  			&map[string]interface{}{"a": "foo", "b": int8(8)}:  "foo",
   241  		},
   242  		b: map[interface{}]interface{}{
   243  			&map[string]interface{}{"a": "foo", "b": int16(8)}: "foo",
   244  			&map[string]interface{}{"a": "foo", "b": int32(8)}: "foo",
   245  		},
   246  		diff: `complex key *map[string]interface {}{"a":"foo", "b":int8(8)}` +
   247  			` in map is missing in the actual map`,
   248  	}, {
   249  		a: map[interface{}]interface{}{
   250  			&map[string]interface{}{"a": "foo", "b": int16(8)}: "foo",
   251  			&map[string]interface{}{"a": "foo", "b": int8(8)}:  "foo",
   252  		},
   253  		b: map[interface{}]interface{}{
   254  			&map[string]interface{}{"a": "foo", "b": int16(8)}: "foo",
   255  		},
   256  		diff: `Maps have different size: 2 != 1` +
   257  			` (extra key: *map[string]interface {}{"a":"foo", "b":int16(8)},` +
   258  			` missing key: *map[string]interface {}{"a":"foo", "b":int16(8)},` +
   259  			` missing key: *map[string]interface {}{"a":"foo", "b":int8(8)})`,
   260  	}, {
   261  		a: map[interface{}]interface{}{
   262  			&map[string]interface{}{"a": "foo", "b": int16(8)}: "foo",
   263  		},
   264  		b: map[interface{}]interface{}{
   265  			&map[string]interface{}{"a": "foo", "b": int16(8)}: "foo",
   266  			&map[string]interface{}{"a": "foo", "b": int8(8)}:  "foo",
   267  		},
   268  		diff: `Maps have different size: 1 != 2` +
   269  			` (extra key: *map[string]interface {}{"a":"foo", "b":int16(8)},` +
   270  			` extra key: *map[string]interface {}{"a":"foo", "b":int8(8)},` +
   271  			` missing key: *map[string]interface {}{"a":"foo", "b":int16(8)})`,
   272  	}, {
   273  		a: []string{},
   274  		b: []string{},
   275  	}, {
   276  		a: []string{"foo", "bar"},
   277  		b: []string{"foo", "bar"},
   278  	}, {
   279  		a:    []string{"foo", "bar"},
   280  		b:    []string{"foo"},
   281  		diff: "Expected an array of size 2 but got 1",
   282  	}, {
   283  		a:    []string{"foo"},
   284  		b:    []string{"foo", "bar"},
   285  		diff: "Expected an array of size 1 but got 2",
   286  	}, {
   287  		a: []string{"foo", "bar"},
   288  		b: []string{"bar", "foo"},
   289  		diff: `In arrays, values are different at index 0:` +
   290  			` string(foo) != string(bar)`,
   291  	}, {
   292  		a:    &[]string{},
   293  		b:    []string{},
   294  		diff: "expected a *[]string but got a []string",
   295  	}, {
   296  		a: &[]string{},
   297  		b: &[]string{},
   298  	}, {
   299  		a: &[]string{"foo", "bar"},
   300  		b: &[]string{"foo", "bar"},
   301  	}, {
   302  		a:    &[]string{"foo", "bar"},
   303  		b:    &[]string{"foo"},
   304  		diff: "Expected an array of size 2 but got 1",
   305  	}, {
   306  		a:    &[]string{"foo"},
   307  		b:    &[]string{"foo", "bar"},
   308  		diff: "Expected an array of size 1 but got 2",
   309  	}, {
   310  		a: &[]string{"foo", "bar"},
   311  		b: &[]string{"bar", "foo"},
   312  		diff: `In arrays, values are different at index 0:` +
   313  			` string(foo) != string(bar)`,
   314  	}, {
   315  		a: []uint32{42, 51},
   316  		b: []uint32{42, 51},
   317  	}, {
   318  		a:    []uint32{42, 51},
   319  		b:    []uint32{42, 88},
   320  		diff: "In arrays, values are different at index 1: uint32(51) != uint32(88)",
   321  	}, {
   322  		a:    []uint32{42, 51},
   323  		b:    []uint32{42},
   324  		diff: "Expected an array of size 2 but got 1",
   325  	}, {
   326  		a:    []uint32{42, 51},
   327  		b:    []uint64{42, 51},
   328  		diff: "expected a []uint32 but got a []uint64",
   329  	}, {
   330  		a:    []uint64{42, 51},
   331  		b:    []uint32{42, 51},
   332  		diff: "expected a []uint64 but got a []uint32",
   333  	}, {
   334  		a: []uint64{42, 51},
   335  		b: []uint64{42, 51},
   336  	}, {
   337  		a:    []uint64{42, 51},
   338  		b:    []uint64{42},
   339  		diff: "Expected an array of size 2 but got 1",
   340  	}, {
   341  		a:    []uint64{42, 51},
   342  		b:    []uint64{42, 88},
   343  		diff: "In arrays, values are different at index 1: uint64(51) != uint64(88)",
   344  	}, {
   345  		a: []interface{}{"foo", uint32(42)},
   346  		b: []interface{}{"foo", uint32(42)},
   347  	}, {
   348  		a:    []interface{}{"foo", uint32(42)},
   349  		b:    []interface{}{"foo"},
   350  		diff: "Expected an array of size 2 but got 1",
   351  	}, {
   352  		a:    []interface{}{"foo"},
   353  		b:    []interface{}{"foo", uint32(42)},
   354  		diff: "Expected an array of size 1 but got 2",
   355  	}, {
   356  		a: []interface{}{"foo", uint32(42)},
   357  		b: []interface{}{"foo", uint8(42)},
   358  		diff: "In arrays, values are different at index 1:" +
   359  			" expected a uint32 but got a uint8",
   360  	}, {
   361  		a:    []interface{}{"foo", "bar"},
   362  		b:    []string{"foo", "bar"},
   363  		diff: "expected a []interface {} but got a []string",
   364  	}, {
   365  		a: &[]interface{}{"foo", uint32(42)},
   366  		b: &[]interface{}{"foo", uint32(42)},
   367  	}, {
   368  		a:    &[]interface{}{"foo", uint32(42)},
   369  		b:    []interface{}{"foo", uint32(42)},
   370  		diff: "expected a *[]interface {} but got a []interface {}",
   371  	}, {
   372  		a: comparableStruct{a: 42},
   373  		b: comparableStruct{a: 42},
   374  	}, {
   375  		a: comparableStruct{a: 42, t: t},
   376  		b: comparableStruct{a: 42},
   377  	}, {
   378  		a: comparableStruct{a: 42},
   379  		b: comparableStruct{a: 42, t: t},
   380  	}, {
   381  		a: comparableStruct{a: 42},
   382  		b: comparableStruct{a: 51},
   383  		diff: "Comparable types are different: test.comparableStruct{a:" +
   384  			"uint32(42), t:*nil} vs test.comparableStruct{a:uint32(51), t:*nil}",
   385  	}, {
   386  		a: builtinCompare{a: 42, b: "foo"},
   387  		b: builtinCompare{a: 42, b: "foo"},
   388  	}, {
   389  		a:    builtinCompare{a: 42, b: "foo"},
   390  		b:    builtinCompare{a: 42, b: "bar"},
   391  		diff: `attributes "b" are different: string(foo) != string(bar)`,
   392  	}, {
   393  		a: map[int8]int8{2: 3, 3: 4},
   394  		b: map[int8]int8{2: 3, 3: 4},
   395  	}, {
   396  		a:    map[int8]int8{2: 3, 3: 4},
   397  		b:    map[int8]int8{2: 3, 3: 5},
   398  		diff: "for key int8(3) in map, values are different: int8(4) != int8(5)",
   399  	}, {
   400  		a: complexCompare{},
   401  		b: complexCompare{},
   402  	}, {
   403  		a: complexCompare{
   404  			m: map[builtinCompare]int8{{1, "foo"}: 42}},
   405  		b: complexCompare{
   406  			m: map[builtinCompare]int8{{1, "foo"}: 42}},
   407  	}, {
   408  		a: complexCompare{
   409  			m: map[builtinCompare]int8{{1, "foo"}: 42}},
   410  		b: complexCompare{
   411  			m: map[builtinCompare]int8{{1, "foo"}: 51}},
   412  		diff: `attributes "m" are different: for key test.builtinCompare{a:uint32(1),` +
   413  			` b:"foo"} in map, values are different: int8(42) != int8(51)`,
   414  	}, {
   415  		a: complexCompare{
   416  			m: map[builtinCompare]int8{{1, "foo"}: 42}},
   417  		b: complexCompare{
   418  			m: map[builtinCompare]int8{{1, "bar"}: 42}},
   419  		diff: `attributes "m" are different: key test.builtinCompare{a:uint32(1),` +
   420  			` b:"foo"} in map is missing in the actual map`,
   421  	}, {
   422  		a: recursive,
   423  		b: recursive,
   424  	}, {
   425  		a: complexCompare{p: recursive},
   426  		b: complexCompare{p: recursive},
   427  	}, {
   428  		a: complexCompare{p: &complexCompare{p: recursive}},
   429  		b: complexCompare{p: &complexCompare{p: recursive}},
   430  	}, {
   431  		a: []complexCompare{{p: &complexCompare{p: recursive}}},
   432  		b: []complexCompare{{p: &complexCompare{p: recursive}}},
   433  	}, {
   434  		a: []complexCompare{{p: &complexCompare{p: recursive}}},
   435  		b: []complexCompare{{p: &complexCompare{p: nil}}},
   436  		diff: `In arrays, values are different at index 0: attributes "p" are` +
   437  			` different: attributes "p" are different: got nil instead of ` +
   438  			`*test.complexCompare{m:map[test.builtinCompare]int8{},` +
   439  			` p:*test.complexCompare{<circular dependency>}}`,
   440  	}, {
   441  		a: partialCompare{a: 42},
   442  		b: partialCompare{a: 42},
   443  	}, {
   444  		a:    partialCompare{a: 42},
   445  		b:    partialCompare{a: 51},
   446  		diff: `attributes "a" are different: uint32(42) != uint32(51)`,
   447  	}, {
   448  		a: partialCompare{a: 42, b: "foo"},
   449  		b: partialCompare{a: 42, b: "bar"},
   450  	}, {
   451  		a: map[*builtinCompare]uint32{{1, "foo"}: 42},
   452  		b: map[*builtinCompare]uint32{{1, "foo"}: 42},
   453  	}, {
   454  		a: map[*builtinCompare]uint32{{1, "foo"}: 42},
   455  		b: map[*builtinCompare]uint32{{2, "foo"}: 42},
   456  		diff: `complex key *test.builtinCompare{a:uint32(1), b:"foo"}` +
   457  			` in map is missing in the actual map`,
   458  	}, {
   459  		a: map[*builtinCompare]uint32{{1, "foo"}: 42},
   460  		b: map[*builtinCompare]uint32{{1, "foo"}: 51},
   461  		diff: `for complex key *test.builtinCompare{a:uint32(1), b:"foo"}` +
   462  			` in map, values are different: uint32(42) != uint32(51)`,
   463  	}, {
   464  		a: key.New("a"),
   465  		b: key.New("a"),
   466  	}, {
   467  		a: key.NewMap(key.New("a"), "b"),
   468  		b: key.NewMap(key.New("a"), "b"),
   469  	}, {
   470  		a: key.NewMap(key.New(map[string]interface{}{"a": true}), "b"),
   471  		b: key.NewMap(key.New(map[string]interface{}{"a": true}), "b"),
   472  	}, {
   473  		a: key.New(map[string]interface{}{
   474  			"a": key.NewMap(key.New(map[string]interface{}{"k": 42}), true)}),
   475  		b: key.New(map[string]interface{}{
   476  			"a": key.NewMap(key.New(map[string]interface{}{"k": 42}), true)}),
   477  	}, {
   478  		a: key.New(map[string]interface{}{
   479  			"a": key.NewMap(key.New(map[string]interface{}{"k": 42}), true)}),
   480  		b: key.New(map[string]interface{}{
   481  			"a": key.NewMap(key.New(map[string]interface{}{"k": 51}), true)}),
   482  		diff: `Comparable types are different: ` +
   483  			`key.mapKey{"a":*key.Map{normal:map[interface {}]interface {}{}, ` +
   484  			`custom:map[uint64]key.entry{<max_depth>:<max_depth>}, length:int(1)}} vs ` +
   485  			`key.mapKey{"a":*key.Map{normal:map[interface {}]interface {}{}, ` +
   486  			`custom:map[uint64]key.entry{<max_depth>:<max_depth>}, length:int(1)}}`,
   487  	}, {
   488  		a: fmt.Errorf("This is a %d error", 42),
   489  		b: errors.New("This is a 42 error"),
   490  	}, {
   491  		a: fmt.Errorf("This is a %d error", 42),
   492  		b: &myError{e: "This is a 42 error"},
   493  	}, {
   494  		a:    &myError{e: "This is a 42 error"},
   495  		diff: `expected a *test.myError (&test.myError{e:"This is a 42 error"}) but got nil`,
   496  	}, {
   497  		a: myStringError("This is a 42 error"),
   498  		b: fmt.Errorf("This is a %d error", 42),
   499  	}, {
   500  		a: &myEmbeddedErrorPtr{},
   501  		b: &myEmbeddedErrorPtr{},
   502  	}, {
   503  		a: code(42),
   504  		b: code(42),
   505  	}, {
   506  		a:    code(42),
   507  		b:    code(51),
   508  		diff: "code(42) != code(51)",
   509  	}, {
   510  		a: message("foo"),
   511  		b: message("foo"),
   512  	}, {
   513  		a:    message("foo"),
   514  		b:    message("bar"),
   515  		diff: `message("foo") != message("bar")`,
   516  	}, {
   517  		a: []byte("foo"),
   518  		b: []byte("foo"),
   519  	}, {
   520  		a:    []byte("foo"),
   521  		b:    []byte("bar"),
   522  		diff: `[]byte("foo") != []byte("bar")`,
   523  	}, {
   524  		a: time1,
   525  		b: time1a,
   526  	}, {
   527  		a: time1,
   528  		b: time1.UTC(),
   529  	}, {
   530  		a:    time1,
   531  		b:    time2,
   532  		diff: fmt.Sprintf("time.Time values are different: %s vs %s", time1, time2),
   533  	}, {
   534  		a: embedder{builtinCompare: builtinCompare{}},
   535  		b: embedder{builtinCompare: builtinCompare{}},
   536  	}, {
   537  		a: pb.Duration{Seconds: 1},
   538  		b: pb.Duration{Seconds: 1},
   539  	}, {
   540  		a:    pb.Duration{Seconds: 1},
   541  		b:    pb.Duration{Seconds: 2},
   542  		diff: "attributes \"Seconds\" are different: int64(1) != int64(2)",
   543  	}, {
   544  		a:    []interface{}{"foo", uint32(42)},
   545  		b:    pb.Duration{Seconds: 1},
   546  		diff: "expected a []interface {} but got a durationpb.Duration",
   547  	}, {
   548  		a:    pb.Duration{Seconds: 1},
   549  		b:    []interface{}{"foo", uint32(42)},
   550  		diff: "expected a durationpb.Duration but got a []interface {}",
   551  	}, {
   552  		a: &hasFunc{},
   553  		b: &hasFunc{},
   554  	}, {
   555  		a: &hasFunc{f: someFunction},
   556  		b: &hasFunc{f: someFunction},
   557  	}, {
   558  		a: &hasFunc{},
   559  		b: &hasFunc{f: someFunction},
   560  		diff: fmt.Sprintf("attributes \"f\" are different: type func():"+
   561  			" (func())(nil) with name \"\" cannot be compared to %#v with name %q,"+
   562  			" functions must be exactly equal or nil",
   563  			reflect.ValueOf(someFunction),
   564  			runtime.FuncForPC(reflect.ValueOf(someFunction).Pointer()).Name()),
   565  	}, {
   566  		a: &hasFunc{f: someFunction},
   567  		b: &hasFunc{f: someOtherFunction},
   568  		diff: fmt.Sprintf("attributes \"f\" are different: type func(): %#v with name %q"+
   569  			" cannot be compared to %#v with name %q, functions must be exactly equal or nil",
   570  			reflect.ValueOf(someFunction),
   571  			runtime.FuncForPC(reflect.ValueOf(someFunction).Pointer()).Name(),
   572  			reflect.ValueOf(someOtherFunction),
   573  			runtime.FuncForPC(reflect.ValueOf(someOtherFunction).Pointer()).Name()),
   574  	}, {
   575  		a: &hasFunc{f: generatedFuncA},
   576  		b: &hasFunc{f: generatedFuncB},
   577  		diff: fmt.Sprintf("attributes \"f\" are different: type func(): %#v with name %q"+
   578  			" cannot be compared to %#v with name %q, functions must be exactly equal or nil",
   579  			reflect.ValueOf(generatedFuncA),
   580  			runtime.FuncForPC(reflect.ValueOf(generatedFuncA).Pointer()).Name(),
   581  			reflect.ValueOf(generatedFuncB),
   582  			runtime.FuncForPC(reflect.ValueOf(generatedFuncB).Pointer()).Name()),
   583  	}}
   584  }