123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651 |
- // Copyright (c) 2015 Arista Networks, Inc.
- // Use of this source code is governed by the Apache License 2.0
- // that can be found in the COPYING file.
- package key_test
- import (
- "encoding/json"
- "fmt"
- "strconv"
- "testing"
- . "notabug.org/themusicgod1/goarista/key"
- "notabug.org/themusicgod1/goarista/test"
- "notabug.org/themusicgod1/goarista/value"
- )
- type compareMe struct {
- i int
- }
- func (c compareMe) Equal(other interface{}) bool {
- o, ok := other.(compareMe)
- return ok && c == o
- }
- type customKey struct {
- i int
- }
- var _ value.Value = customKey{}
- func (c customKey) String() string {
- return fmt.Sprintf("customKey=%d", c.i)
- }
- func (c customKey) MarshalJSON() ([]byte, error) {
- return nil, nil
- }
- func (c customKey) ToBuiltin() interface{} {
- return c.i
- }
- func TestKeyEqual(t *testing.T) {
- tests := []struct {
- a Key
- b Key
- result bool
- }{{
- a: New("foo"),
- b: New("foo"),
- result: true,
- }, {
- a: New("foo"),
- b: New("bar"),
- result: false,
- }, {
- a: New([]interface{}{}),
- b: New("bar"),
- result: false,
- }, {
- a: New([]interface{}{}),
- b: New([]interface{}{}),
- result: true,
- }, {
- a: New([]interface{}{"a", "b"}),
- b: New([]interface{}{"a"}),
- result: false,
- }, {
- a: New([]interface{}{"a", "b"}),
- b: New([]interface{}{"b", "a"}),
- result: false,
- }, {
- a: New([]interface{}{"a", "b"}),
- b: New([]interface{}{"a", "b"}),
- result: true,
- }, {
- a: New([]interface{}{"a", map[string]interface{}{"b": "c"}}),
- b: New([]interface{}{"a", map[string]interface{}{"c": "b"}}),
- result: false,
- }, {
- a: New([]interface{}{"a", map[string]interface{}{"b": "c"}}),
- b: New([]interface{}{"a", map[string]interface{}{"b": "c"}}),
- result: true,
- }, {
- a: New(map[string]interface{}{}),
- b: New("bar"),
- result: false,
- }, {
- a: New(map[string]interface{}{}),
- b: New(map[string]interface{}{}),
- result: true,
- }, {
- a: New(map[string]interface{}{"a": 3}),
- b: New(map[string]interface{}{}),
- result: false,
- }, {
- a: New(map[string]interface{}{"a": 3}),
- b: New(map[string]interface{}{"b": 4}),
- result: false,
- }, {
- a: New(map[string]interface{}{"a": 4, "b": 5}),
- b: New(map[string]interface{}{"a": 4}),
- result: false,
- }, {
- a: New(map[string]interface{}{"a": 3}),
- b: New(map[string]interface{}{"a": 4}),
- result: false,
- }, {
- a: New(map[string]interface{}{"a": 3}),
- b: New(map[string]interface{}{"a": 3}),
- result: true,
- }, {
- a: New(map[string]interface{}{"a": map[Key]interface{}{New("b"): 3}}),
- b: New(map[string]interface{}{"a": map[Key]interface{}{New("b"): 4}}),
- result: false,
- }, {
- a: New(map[string]interface{}{"a": map[Key]interface{}{New("b"): 4, New("c"): 5}}),
- b: New(map[string]interface{}{"a": map[Key]interface{}{New("b"): 4}}),
- result: false,
- }, {
- a: New(map[string]interface{}{"a": map[Key]interface{}{New("b"): 4, New("c"): 5}}),
- b: New(map[string]interface{}{"a": map[Key]interface{}{New("b"): 4, New("c"): 5}}),
- result: true,
- }, {
- a: New(map[string]interface{}{"a": map[Key]interface{}{New("b"): 4}}),
- b: New(map[string]interface{}{"a": map[Key]interface{}{New("b"): 4}}),
- result: true,
- }, {
- a: New(map[string]interface{}{"a": compareMe{i: 3}}),
- b: New(map[string]interface{}{"a": compareMe{i: 3}}),
- result: true,
- }, {
- a: New(map[string]interface{}{"a": compareMe{i: 3}}),
- b: New(map[string]interface{}{"a": compareMe{i: 4}}),
- result: false,
- }, {
- a: New(customKey{i: 42}),
- b: New(customKey{i: 42}),
- result: true,
- }}
- for _, tcase := range tests {
- if tcase.a.Equal(tcase.b) != tcase.result {
- t.Errorf("Wrong result for case:\na: %#v\nb: %#v\nresult: %#v",
- tcase.a,
- tcase.b,
- tcase.result)
- }
- }
- if New("a").Equal(32) {
- t.Error("Wrong result for different types case")
- }
- }
- func TestGetFromMap(t *testing.T) {
- tests := []struct {
- k Key
- m map[Key]interface{}
- v interface{}
- found bool
- }{{
- k: New("a"),
- m: map[Key]interface{}{New("a"): "b"},
- v: "b",
- found: true,
- }, {
- k: New(uint32(35)),
- m: map[Key]interface{}{New(uint32(35)): "c"},
- v: "c",
- found: true,
- }, {
- k: New(uint32(37)),
- m: map[Key]interface{}{New(uint32(36)): "c"},
- found: false,
- }, {
- k: New(uint32(37)),
- m: map[Key]interface{}{},
- found: false,
- }, {
- k: New([]interface{}{"a", "b"}),
- m: map[Key]interface{}{
- New([]interface{}{"a", "b"}): "foo",
- },
- v: "foo",
- found: true,
- }, {
- k: New([]interface{}{"a", "b"}),
- m: map[Key]interface{}{
- New([]interface{}{"a", "b", "c"}): "foo",
- },
- found: false,
- }, {
- k: New([]interface{}{"a", map[string]interface{}{"b": "c"}}),
- m: map[Key]interface{}{
- New([]interface{}{"a", map[string]interface{}{"b": "c"}}): "foo",
- },
- v: "foo",
- found: true,
- }, {
- k: New([]interface{}{"a", map[string]interface{}{"b": "c"}}),
- m: map[Key]interface{}{
- New([]interface{}{"a", map[string]interface{}{"c": "b"}}): "foo",
- },
- found: false,
- }, {
- k: New(map[string]interface{}{"a": "b", "c": uint64(4)}),
- m: map[Key]interface{}{
- New(map[string]interface{}{"a": "b", "c": uint64(4)}): "foo",
- },
- v: "foo",
- found: true,
- }, {
- k: New(map[string]interface{}{"a": "b", "c": uint64(4)}),
- m: map[Key]interface{}{
- New(map[string]interface{}{"a": "b", "c": uint64(5)}): "foo",
- },
- found: false,
- }, {
- k: New(customKey{i: 42}),
- m: map[Key]interface{}{New(customKey{i: 42}): "c"},
- v: "c",
- found: true,
- }, {
- k: New(customKey{i: 42}),
- m: map[Key]interface{}{New(customKey{i: 43}): "c"},
- found: false,
- }, {
- k: New(map[string]interface{}{
- "damn": map[Key]interface{}{
- New(map[string]interface{}{"a": uint32(42),
- "b": uint32(51)}): true}}),
- m: map[Key]interface{}{
- New(map[string]interface{}{
- "damn": map[Key]interface{}{
- New(map[string]interface{}{"a": uint32(42),
- "b": uint32(51)}): true}}): "foo",
- },
- v: "foo",
- found: true,
- }, {
- k: New(map[string]interface{}{
- "damn": map[Key]interface{}{
- New(map[string]interface{}{"a": uint32(42),
- "b": uint32(52)}): true}}),
- m: map[Key]interface{}{
- New(map[string]interface{}{
- "damn": map[Key]interface{}{
- New(map[string]interface{}{"a": uint32(42),
- "b": uint32(51)}): true}}): "foo",
- },
- found: false,
- }, {
- k: New(map[string]interface{}{
- "nested": map[string]interface{}{
- "a": uint32(42), "b": uint32(51)}}),
- m: map[Key]interface{}{
- New(map[string]interface{}{
- "nested": map[string]interface{}{
- "a": uint32(42), "b": uint32(51)}}): "foo",
- },
- v: "foo",
- found: true,
- }, {
- k: New(map[string]interface{}{
- "nested": map[string]interface{}{
- "a": uint32(42), "b": uint32(52)}}),
- m: map[Key]interface{}{
- New(map[string]interface{}{
- "nested": map[string]interface{}{
- "a": uint32(42), "b": uint32(51)}}): "foo",
- },
- found: false,
- }}
- for _, tcase := range tests {
- v, ok := tcase.m[tcase.k]
- if tcase.found != ok {
- t.Errorf("Wrong retrieval result for case:\nk: %#v\nm: %#v\nv: %#v",
- tcase.k,
- tcase.m,
- tcase.v)
- } else if tcase.found && !ok {
- t.Errorf("Unable to retrieve value for case:\nk: %#v\nm: %#v\nv: %#v",
- tcase.k,
- tcase.m,
- tcase.v)
- } else if tcase.found && !test.DeepEqual(tcase.v, v) {
- t.Errorf("Wrong result for case:\nk: %#v\nm: %#v\nv: %#v",
- tcase.k,
- tcase.m,
- tcase.v)
- }
- }
- }
- func TestDeleteFromMap(t *testing.T) {
- tests := []struct {
- k Key
- m map[Key]interface{}
- r map[Key]interface{}
- }{{
- k: New("a"),
- m: map[Key]interface{}{New("a"): "b"},
- r: map[Key]interface{}{},
- }, {
- k: New("b"),
- m: map[Key]interface{}{New("a"): "b"},
- r: map[Key]interface{}{New("a"): "b"},
- }, {
- k: New("a"),
- m: map[Key]interface{}{},
- r: map[Key]interface{}{},
- }, {
- k: New(uint32(35)),
- m: map[Key]interface{}{New(uint32(35)): "c"},
- r: map[Key]interface{}{},
- }, {
- k: New(uint32(36)),
- m: map[Key]interface{}{New(uint32(35)): "c"},
- r: map[Key]interface{}{New(uint32(35)): "c"},
- }, {
- k: New(uint32(37)),
- m: map[Key]interface{}{},
- r: map[Key]interface{}{},
- }, {
- k: New(map[string]interface{}{"a": "b", "c": uint64(4)}),
- m: map[Key]interface{}{
- New(map[string]interface{}{"a": "b", "c": uint64(4)}): "foo",
- },
- r: map[Key]interface{}{},
- }, {
- k: New(customKey{i: 42}),
- m: map[Key]interface{}{New(customKey{i: 42}): "c"},
- r: map[Key]interface{}{},
- }}
- for _, tcase := range tests {
- delete(tcase.m, tcase.k)
- if !test.DeepEqual(tcase.m, tcase.r) {
- t.Errorf("Wrong result for case:\nk: %#v\nm: %#v\nr: %#v",
- tcase.k,
- tcase.m,
- tcase.r)
- }
- }
- }
- func TestSetToMap(t *testing.T) {
- tests := []struct {
- k Key
- v interface{}
- m map[Key]interface{}
- r map[Key]interface{}
- }{{
- k: New("a"),
- v: "c",
- m: map[Key]interface{}{New("a"): "b"},
- r: map[Key]interface{}{New("a"): "c"},
- }, {
- k: New("b"),
- v: uint64(56),
- m: map[Key]interface{}{New("a"): "b"},
- r: map[Key]interface{}{
- New("a"): "b",
- New("b"): uint64(56),
- },
- }, {
- k: New("a"),
- v: "foo",
- m: map[Key]interface{}{},
- r: map[Key]interface{}{New("a"): "foo"},
- }, {
- k: New(uint32(35)),
- v: "d",
- m: map[Key]interface{}{New(uint32(35)): "c"},
- r: map[Key]interface{}{New(uint32(35)): "d"},
- }, {
- k: New(uint32(36)),
- v: true,
- m: map[Key]interface{}{New(uint32(35)): "c"},
- r: map[Key]interface{}{
- New(uint32(35)): "c",
- New(uint32(36)): true,
- },
- }, {
- k: New(uint32(37)),
- v: false,
- m: map[Key]interface{}{New(uint32(36)): "c"},
- r: map[Key]interface{}{
- New(uint32(36)): "c",
- New(uint32(37)): false,
- },
- }, {
- k: New(uint32(37)),
- v: "foobar",
- m: map[Key]interface{}{},
- r: map[Key]interface{}{New(uint32(37)): "foobar"},
- }, {
- k: New(map[string]interface{}{"a": "b", "c": uint64(4)}),
- v: "foobar",
- m: map[Key]interface{}{
- New(map[string]interface{}{"a": "b", "c": uint64(4)}): "foo",
- },
- r: map[Key]interface{}{
- New(map[string]interface{}{"a": "b", "c": uint64(4)}): "foobar",
- },
- }, {
- k: New(map[string]interface{}{"a": "b", "c": uint64(7)}),
- v: "foobar",
- m: map[Key]interface{}{
- New(map[string]interface{}{"a": "b", "c": uint64(4)}): "foo",
- },
- r: map[Key]interface{}{
- New(map[string]interface{}{"a": "b", "c": uint64(4)}): "foo",
- New(map[string]interface{}{"a": "b", "c": uint64(7)}): "foobar",
- },
- }, {
- k: New(map[string]interface{}{"a": "b", "d": uint64(6)}),
- v: "barfoo",
- m: map[Key]interface{}{
- New(map[string]interface{}{"a": "b", "c": uint64(4)}): "foo",
- },
- r: map[Key]interface{}{
- New(map[string]interface{}{"a": "b", "c": uint64(4)}): "foo",
- New(map[string]interface{}{"a": "b", "d": uint64(6)}): "barfoo",
- },
- }, {
- k: New(customKey{i: 42}),
- v: "foo",
- m: map[Key]interface{}{},
- r: map[Key]interface{}{New(customKey{i: 42}): "foo"},
- }}
- for i, tcase := range tests {
- tcase.m[tcase.k] = tcase.v
- if !test.DeepEqual(tcase.m, tcase.r) {
- t.Errorf("Wrong result for case %d:\nk: %#v\nm: %#v\nr: %#v",
- i,
- tcase.k,
- tcase.m,
- tcase.r)
- }
- }
- }
- func TestMisc(t *testing.T) {
- k := New(map[string]interface{}{"foo": true})
- js, err := json.Marshal(k)
- if err != nil {
- t.Error("JSON encoding failed:", err)
- } else if expected := `{"foo":true}`; string(js) != expected {
- t.Errorf("Wanted JSON %q but got %q", expected, js)
- }
- expected := `key.New(map[string]interface {}{"foo":true})`
- gostr := fmt.Sprintf("%#v", k)
- if expected != gostr {
- t.Errorf("Wanted Go representation %q but got %q", expected, gostr)
- }
- test.ShouldPanic(t, func() { New(42) })
- k = New(customKey{i: 42})
- if expected, str := "customKey=42", k.String(); expected != str {
- t.Errorf("Wanted string representation %q but got %q", expected, str)
- }
- }
- func BenchmarkSetToMapWithStringKey(b *testing.B) {
- m := map[Key]interface{}{
- New("a"): true,
- New("a1"): true,
- New("a2"): true,
- New("a3"): true,
- New("a4"): true,
- New("a5"): true,
- New("a6"): true,
- New("a7"): true,
- New("a8"): true,
- New("a9"): true,
- New("a10"): true,
- New("a11"): true,
- New("a12"): true,
- New("a13"): true,
- New("a14"): true,
- New("a15"): true,
- New("a16"): true,
- New("a17"): true,
- New("a18"): true,
- }
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- m[New(strconv.Itoa(i))] = true
- }
- }
- func BenchmarkSetToMapWithUint64Key(b *testing.B) {
- m := map[Key]interface{}{
- New(uint64(1)): true,
- New(uint64(2)): true,
- New(uint64(3)): true,
- New(uint64(4)): true,
- New(uint64(5)): true,
- New(uint64(6)): true,
- New(uint64(7)): true,
- New(uint64(8)): true,
- New(uint64(9)): true,
- New(uint64(10)): true,
- New(uint64(11)): true,
- New(uint64(12)): true,
- New(uint64(13)): true,
- New(uint64(14)): true,
- New(uint64(15)): true,
- New(uint64(16)): true,
- New(uint64(17)): true,
- New(uint64(18)): true,
- New(uint64(19)): true,
- }
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- m[New(uint64(i))] = true
- }
- }
- func BenchmarkGetFromMapWithMapKey(b *testing.B) {
- m := map[Key]interface{}{
- New(map[string]interface{}{"a": true}): true,
- New(map[string]interface{}{"b": true}): true,
- New(map[string]interface{}{"c": true}): true,
- New(map[string]interface{}{"d": true}): true,
- New(map[string]interface{}{"e": true}): true,
- New(map[string]interface{}{"f": true}): true,
- New(map[string]interface{}{"g": true}): true,
- New(map[string]interface{}{"h": true}): true,
- New(map[string]interface{}{"i": true}): true,
- New(map[string]interface{}{"j": true}): true,
- New(map[string]interface{}{"k": true}): true,
- New(map[string]interface{}{"l": true}): true,
- New(map[string]interface{}{"m": true}): true,
- New(map[string]interface{}{"n": true}): true,
- New(map[string]interface{}{"o": true}): true,
- New(map[string]interface{}{"p": true}): true,
- New(map[string]interface{}{"q": true}): true,
- New(map[string]interface{}{"r": true}): true,
- New(map[string]interface{}{"s": true}): true,
- }
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- key := New(map[string]interface{}{string('a' + i%19): true})
- _, found := m[key]
- if !found {
- b.Fatalf("WTF: %#v", key)
- }
- }
- }
- func mkKey(i int) Key {
- return New(map[string]interface{}{
- "foo": map[string]interface{}{
- "aaaa1": uint32(0),
- "aaaa2": uint32(0),
- "aaaa3": uint32(i),
- },
- "bar": map[string]interface{}{
- "nested": uint32(42),
- },
- })
- }
- func BenchmarkBigMapWithCompositeKeys(b *testing.B) {
- const size = 10000
- m := make(map[Key]interface{}, size)
- for i := 0; i < size; i++ {
- m[mkKey(i)] = true
- }
- k := mkKey(0)
- submap := k.Key().(map[string]interface{})["foo"].(map[string]interface{})
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- submap["aaaa3"] = uint32(i)
- _, found := m[k]
- if found != (i < size) {
- b.Fatalf("WTF: %#v", k)
- }
- }
- }
- func BenchmarkBuiltInType(b *testing.B) {
- benches := []struct {
- val interface{}
- }{
- {
- val: "foo",
- },
- {
- val: int8(-12),
- },
- {
- val: int16(123),
- },
- {
- val: int32(123),
- },
- {
- val: int64(123456),
- },
- {
- val: uint8(12),
- },
- {
- val: uint16(123),
- },
- {
- val: uint32(123),
- },
- {
- val: uint64(123456),
- },
- {
- val: float32(123456.12),
- },
- {
- val: float64(123456.12),
- },
- {
- val: true,
- },
- }
- for _, bench := range benches {
- var k Key
- b.Run(fmt.Sprintf("%T", bench.val), func(b *testing.B) {
- b.ReportAllocs()
- for i := 0; i < b.N; i++ {
- // create the key.Key and call some function here
- if k = New(bench.val); k == nil {
- b.Fatalf("expect to get key.Key, but got nil")
- }
- if !k.Equal(New(bench.val)) {
- b.Fatalf("k is not equal to itself: %v", bench.val)
- }
- }
- })
- }
- }
|