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 }