123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686 |
- // Copyright (c) 2017 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 path
- import (
- "fmt"
- "testing"
- "notabug.org/themusicgod1/goarista/key"
- "notabug.org/themusicgod1/goarista/value"
- )
- func TestNew(t *testing.T) {
- tcases := []struct {
- in []interface{}
- out key.Path
- }{
- {
- in: nil,
- out: key.Path{},
- }, {
- in: []interface{}{},
- out: key.Path{},
- }, {
- in: []interface{}{"foo", key.New("bar"), true},
- out: key.Path{key.New("foo"), key.New("bar"), key.New(true)},
- }, {
- in: []interface{}{int8(5), int16(5), int32(5), int64(5)},
- out: key.Path{key.New(int8(5)), key.New(int16(5)), key.New(int32(5)),
- key.New(int64(5))},
- }, {
- in: []interface{}{uint8(5), uint16(5), uint32(5), uint64(5)},
- out: key.Path{key.New(uint8(5)), key.New(uint16(5)), key.New(uint32(5)),
- key.New(uint64(5))},
- }, {
- in: []interface{}{float32(5), float64(5)},
- out: key.Path{key.New(float32(5)), key.New(float64(5))},
- }, {
- in: []interface{}{customKey{i: &a}, map[string]interface{}{}},
- out: key.Path{key.New(customKey{i: &a}), key.New(map[string]interface{}{})},
- },
- }
- for i, tcase := range tcases {
- if p := New(tcase.in...); !Equal(p, tcase.out) {
- t.Fatalf("Test %d failed: %#v != %#v", i, p, tcase.out)
- }
- }
- }
- func TestClone(t *testing.T) {
- if !Equal(Clone(key.Path{}), key.Path{}) {
- t.Error("Clone(key.Path{}) != key.Path{}")
- }
- a := key.Path{key.New("foo"), key.New("bar")}
- b, c := Clone(a), Clone(a)
- b[1] = key.New("baz")
- if Equal(a, b) || !Equal(a, c) {
- t.Error("Clone is not making a copied path")
- }
- }
- func TestAppend(t *testing.T) {
- tcases := []struct {
- a key.Path
- b []interface{}
- result key.Path
- }{
- {
- a: key.Path{},
- b: []interface{}{},
- result: key.Path{},
- }, {
- a: key.Path{key.New("foo")},
- b: []interface{}{},
- result: key.Path{key.New("foo")},
- }, {
- a: key.Path{},
- b: []interface{}{"foo", key.New("bar")},
- result: key.Path{key.New("foo"), key.New("bar")},
- }, {
- a: key.Path{key.New("foo")},
- b: []interface{}{int64(0), key.New("bar")},
- result: key.Path{key.New("foo"), key.New(int64(0)), key.New("bar")},
- },
- }
- for i, tcase := range tcases {
- if p := Append(tcase.a, tcase.b...); !Equal(p, tcase.result) {
- t.Fatalf("Test %d failed: %#v != %#v", i, p, tcase.result)
- }
- }
- }
- func TestJoin(t *testing.T) {
- tcases := []struct {
- paths []key.Path
- result key.Path
- }{
- {
- paths: nil,
- result: nil,
- }, {
- paths: []key.Path{},
- result: nil,
- }, {
- paths: []key.Path{key.Path{}},
- result: nil,
- }, {
- paths: []key.Path{key.Path{key.New(true)}, key.Path{}},
- result: key.Path{key.New(true)},
- }, {
- paths: []key.Path{key.Path{}, key.Path{key.New(true)}},
- result: key.Path{key.New(true)},
- }, {
- paths: []key.Path{key.Path{key.New("foo")}, key.Path{key.New("bar")}},
- result: key.Path{key.New("foo"), key.New("bar")},
- }, {
- paths: []key.Path{key.Path{key.New("bar")}, key.Path{key.New("foo")}},
- result: key.Path{key.New("bar"), key.New("foo")},
- }, {
- paths: []key.Path{
- key.Path{key.New(uint32(0)), key.New(uint64(0))},
- key.Path{key.New(int8(0))},
- key.Path{key.New(int16(0)), key.New(int32(0))},
- key.Path{key.New(int64(0)), key.New(uint8(0)), key.New(uint16(0))},
- },
- result: key.Path{
- key.New(uint32(0)), key.New(uint64(0)),
- key.New(int8(0)), key.New(int16(0)),
- key.New(int32(0)), key.New(int64(0)),
- key.New(uint8(0)), key.New(uint16(0)),
- },
- },
- }
- for i, tcase := range tcases {
- if p := Join(tcase.paths...); !Equal(p, tcase.result) {
- t.Fatalf("Test %d failed: %#v != %#v", i, p, tcase.result)
- }
- }
- }
- func TestParent(t *testing.T) {
- if Parent(key.Path{}) != nil {
- t.Fatal("Parent of empty key.Path should be nil")
- }
- tcases := []struct {
- in key.Path
- out key.Path
- }{
- {
- in: key.Path{key.New("foo")},
- out: key.Path{},
- }, {
- in: key.Path{key.New("foo"), key.New("bar")},
- out: key.Path{key.New("foo")},
- }, {
- in: key.Path{key.New("foo"), key.New("bar"), key.New("baz")},
- out: key.Path{key.New("foo"), key.New("bar")},
- },
- }
- for _, tcase := range tcases {
- if !Equal(Parent(tcase.in), tcase.out) {
- t.Fatalf("Parent of %#v != %#v", tcase.in, tcase.out)
- }
- }
- }
- func TestBase(t *testing.T) {
- if Base(key.Path{}) != nil {
- t.Fatal("Base of empty key.Path should be nil")
- }
- tcases := []struct {
- in key.Path
- out key.Key
- }{
- {
- in: key.Path{key.New("foo")},
- out: key.New("foo"),
- }, {
- in: key.Path{key.New("foo"), key.New("bar")},
- out: key.New("bar"),
- },
- }
- for _, tcase := range tcases {
- if !Base(tcase.in).Equal(tcase.out) {
- t.Fatalf("Base of %#v != %#v", tcase.in, tcase.out)
- }
- }
- }
- type customKey struct {
- i *int
- }
- 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 nil
- }
- func (c customKey) Equal(other interface{}) bool {
- o, ok := other.(customKey)
- return ok && *c.i == *o.i
- }
- var (
- _ value.Value = customKey{}
- _ key.Comparable = customKey{}
- a = 1
- b = 1
- )
- func TestEqual(t *testing.T) {
- tcases := []struct {
- a key.Path
- b key.Path
- result bool
- }{
- {
- a: nil,
- b: nil,
- result: true,
- }, {
- a: nil,
- b: key.Path{},
- result: true,
- }, {
- a: key.Path{},
- b: nil,
- result: true,
- }, {
- a: key.Path{},
- b: key.Path{},
- result: true,
- }, {
- a: key.Path{},
- b: key.Path{key.New("")},
- result: false,
- }, {
- a: key.Path{Wildcard},
- b: key.Path{key.New("foo")},
- result: false,
- }, {
- a: key.Path{Wildcard},
- b: key.Path{Wildcard},
- result: true,
- }, {
- a: key.Path{key.New("foo")},
- b: key.Path{key.New("foo")},
- result: true,
- }, {
- a: key.Path{key.New(true)},
- b: key.Path{key.New(false)},
- result: false,
- }, {
- a: key.Path{key.New(int32(5))},
- b: key.Path{key.New(int64(5))},
- result: false,
- }, {
- a: key.Path{key.New("foo")},
- b: key.Path{key.New("foo"), key.New("bar")},
- result: false,
- }, {
- a: key.Path{key.New("foo"), key.New("bar")},
- b: key.Path{key.New("foo")},
- result: false,
- }, {
- a: key.Path{key.New(uint8(0)), key.New(int8(0))},
- b: key.Path{key.New(int8(0)), key.New(uint8(0))},
- result: false,
- },
- // Ensure that we check deep equality.
- {
- a: key.Path{key.New(map[string]interface{}{})},
- b: key.Path{key.New(map[string]interface{}{})},
- result: true,
- }, {
- a: key.Path{key.New(customKey{i: &a})},
- b: key.Path{key.New(customKey{i: &b})},
- result: true,
- },
- }
- for i, tcase := range tcases {
- if result := Equal(tcase.a, tcase.b); result != tcase.result {
- t.Fatalf("Test %d failed: a: %#v; b: %#v, result: %t",
- i, tcase.a, tcase.b, tcase.result)
- }
- }
- }
- func TestMatch(t *testing.T) {
- tcases := []struct {
- a key.Path
- b key.Path
- result bool
- }{
- {
- a: nil,
- b: nil,
- result: true,
- }, {
- a: nil,
- b: key.Path{},
- result: true,
- }, {
- a: key.Path{},
- b: nil,
- result: true,
- }, {
- a: key.Path{},
- b: key.Path{},
- result: true,
- }, {
- a: key.Path{},
- b: key.Path{key.New("foo")},
- result: false,
- }, {
- a: key.Path{Wildcard},
- b: key.Path{key.New("foo")},
- result: true,
- }, {
- a: key.Path{key.New("foo")},
- b: key.Path{Wildcard},
- result: false,
- }, {
- a: key.Path{Wildcard},
- b: key.Path{key.New("foo"), key.New("bar")},
- result: false,
- }, {
- a: key.Path{Wildcard, Wildcard},
- b: key.Path{key.New(int64(0))},
- result: false,
- }, {
- a: key.Path{Wildcard, Wildcard},
- b: key.Path{key.New(int64(0)), key.New(int32(0))},
- result: true,
- }, {
- a: key.Path{Wildcard, key.New(false)},
- b: key.Path{key.New(true), Wildcard},
- result: false,
- },
- }
- for i, tcase := range tcases {
- if result := Match(tcase.a, tcase.b); result != tcase.result {
- t.Fatalf("Test %d failed: a: %#v; b: %#v, result: %t",
- i, tcase.a, tcase.b, tcase.result)
- }
- }
- }
- func TestHasElement(t *testing.T) {
- tcases := []struct {
- a key.Path
- b key.Key
- result bool
- }{
- {
- a: nil,
- b: nil,
- result: false,
- }, {
- a: nil,
- b: key.New("foo"),
- result: false,
- }, {
- a: key.Path{},
- b: nil,
- result: false,
- }, {
- a: key.Path{key.New("foo")},
- b: nil,
- result: false,
- }, {
- a: key.Path{key.New("foo")},
- b: key.New("foo"),
- result: true,
- }, {
- a: key.Path{key.New(true)},
- b: key.New("true"),
- result: false,
- }, {
- a: key.Path{key.New("foo"), key.New("bar")},
- b: key.New("bar"),
- result: true,
- }, {
- a: key.Path{key.New(map[string]interface{}{})},
- b: key.New(map[string]interface{}{}),
- result: true,
- }, {
- a: key.Path{key.New(map[string]interface{}{"foo": "a"})},
- b: key.New(map[string]interface{}{"bar": "a"}),
- result: false,
- },
- }
- for i, tcase := range tcases {
- if result := HasElement(tcase.a, tcase.b); result != tcase.result {
- t.Errorf("Test %d failed: a: %#v; b: %#v, result: %t, expected: %t",
- i, tcase.a, tcase.b, result, tcase.result)
- }
- }
- }
- func TestHasPrefix(t *testing.T) {
- tcases := []struct {
- a key.Path
- b key.Path
- result bool
- }{
- {
- a: nil,
- b: nil,
- result: true,
- }, {
- a: nil,
- b: key.Path{},
- result: true,
- }, {
- a: key.Path{},
- b: nil,
- result: true,
- }, {
- a: key.Path{},
- b: key.Path{},
- result: true,
- }, {
- a: key.Path{},
- b: key.Path{key.New("foo")},
- result: false,
- }, {
- a: key.Path{key.New("foo")},
- b: key.Path{},
- result: true,
- }, {
- a: key.Path{key.New(true)},
- b: key.Path{key.New(false)},
- result: false,
- }, {
- a: key.Path{key.New("foo"), key.New("bar")},
- b: key.Path{key.New("bar"), key.New("foo")},
- result: false,
- }, {
- a: key.Path{key.New(int8(0)), key.New(uint8(0))},
- b: key.Path{key.New(uint8(0)), key.New(uint8(0))},
- result: false,
- }, {
- a: key.Path{key.New(true), key.New(true)},
- b: key.Path{key.New(true), key.New(true), key.New(true)},
- result: false,
- }, {
- a: key.Path{key.New(true), key.New(true), key.New(true)},
- b: key.Path{key.New(true), key.New(true)},
- result: true,
- }, {
- a: key.Path{Wildcard, key.New(int32(0)), Wildcard},
- b: key.Path{key.New(int64(0)), Wildcard},
- result: false,
- },
- }
- for i, tcase := range tcases {
- if result := HasPrefix(tcase.a, tcase.b); result != tcase.result {
- t.Fatalf("Test %d failed: a: %#v; b: %#v, result: %t",
- i, tcase.a, tcase.b, tcase.result)
- }
- }
- }
- func TestMatchPrefix(t *testing.T) {
- tcases := []struct {
- a key.Path
- b key.Path
- result bool
- }{
- {
- a: nil,
- b: nil,
- result: true,
- }, {
- a: nil,
- b: key.Path{},
- result: true,
- }, {
- a: key.Path{},
- b: nil,
- result: true,
- }, {
- a: key.Path{},
- b: key.Path{},
- result: true,
- }, {
- a: key.Path{},
- b: key.Path{key.New("foo")},
- result: false,
- }, {
- a: key.Path{key.New("foo")},
- b: key.Path{},
- result: true,
- }, {
- a: key.Path{key.New("foo")},
- b: key.Path{Wildcard},
- result: false,
- }, {
- a: key.Path{Wildcard},
- b: key.Path{key.New("foo")},
- result: true,
- }, {
- a: key.Path{Wildcard},
- b: key.Path{key.New("foo"), key.New("bar")},
- result: false,
- }, {
- a: key.Path{Wildcard, key.New(true)},
- b: key.Path{key.New(false), Wildcard},
- result: false,
- }, {
- a: key.Path{Wildcard, key.New(int32(0)), key.New(int16(0))},
- b: key.Path{key.New(int64(0)), key.New(int32(0))},
- result: true,
- },
- }
- for i, tcase := range tcases {
- if result := MatchPrefix(tcase.a, tcase.b); result != tcase.result {
- t.Fatalf("Test %d failed: a: %#v; b: %#v, result: %t",
- i, tcase.a, tcase.b, tcase.result)
- }
- }
- }
- func TestFromString(t *testing.T) {
- tcases := []struct {
- in string
- out key.Path
- }{
- {
- in: "",
- out: key.Path{},
- }, {
- in: "/",
- out: key.Path{},
- }, {
- in: "//",
- out: key.Path{key.New(""), key.New("")},
- }, {
- in: "foo",
- out: key.Path{key.New("foo")},
- }, {
- in: "/foo",
- out: key.Path{key.New("foo")},
- }, {
- in: "foo/bar",
- out: key.Path{key.New("foo"), key.New("bar")},
- }, {
- in: "/foo/bar",
- out: key.Path{key.New("foo"), key.New("bar")},
- }, {
- in: "foo/bar/baz",
- out: key.Path{key.New("foo"), key.New("bar"), key.New("baz")},
- }, {
- in: "/foo/bar/baz",
- out: key.Path{key.New("foo"), key.New("bar"), key.New("baz")},
- }, {
- in: "0/123/456/789",
- out: key.Path{key.New("0"), key.New("123"), key.New("456"), key.New("789")},
- }, {
- in: "/0/123/456/789",
- out: key.Path{key.New("0"), key.New("123"), key.New("456"), key.New("789")},
- }, {
- in: "`~!@#$%^&*()_+{}\\/|[];':\"<>?,./",
- out: key.Path{key.New("`~!@#$%^&*()_+{}\\"), key.New("|[];':\"<>?,."), key.New("")},
- }, {
- in: "/`~!@#$%^&*()_+{}\\/|[];':\"<>?,./",
- out: key.Path{key.New("`~!@#$%^&*()_+{}\\"), key.New("|[];':\"<>?,."), key.New("")},
- },
- }
- for i, tcase := range tcases {
- if p := FromString(tcase.in); !Equal(p, tcase.out) {
- t.Fatalf("Test %d failed: %#v != %#v", i, p, tcase.out)
- }
- }
- }
- func TestString(t *testing.T) {
- tcases := []struct {
- in key.Path
- out string
- }{
- {
- in: key.Path{},
- out: "/",
- }, {
- in: key.Path{key.New("")},
- out: "/",
- }, {
- in: key.Path{key.New("foo")},
- out: "/foo",
- }, {
- in: key.Path{key.New("foo"), key.New("bar")},
- out: "/foo/bar",
- }, {
- in: key.Path{key.New("/foo"), key.New("bar")},
- out: "//foo/bar",
- }, {
- in: key.Path{key.New("foo"), key.New("bar/")},
- out: "/foo/bar/",
- }, {
- in: key.Path{key.New(""), key.New("foo"), key.New("bar")},
- out: "//foo/bar",
- }, {
- in: key.Path{key.New("foo"), key.New("bar"), key.New("")},
- out: "/foo/bar/",
- }, {
- in: key.Path{key.New("/"), key.New("foo"), key.New("bar")},
- out: "///foo/bar",
- }, {
- in: key.Path{key.New("foo"), key.New("bar"), key.New("/")},
- out: "/foo/bar//",
- },
- }
- for i, tcase := range tcases {
- if s := tcase.in.String(); s != tcase.out {
- t.Fatalf("Test %d failed: %s != %s", i, s, tcase.out)
- }
- }
- }
- func BenchmarkJoin(b *testing.B) {
- generate := func(n int) []key.Path {
- paths := make([]key.Path, 0, n)
- for i := 0; i < n; i++ {
- paths = append(paths, key.Path{key.New("foo")})
- }
- return paths
- }
- benchmarks := map[string][]key.Path{
- "10 key.Paths": generate(10),
- "100 key.Paths": generate(100),
- "1000 key.Paths": generate(1000),
- "10000 key.Paths": generate(10000),
- }
- for name, benchmark := range benchmarks {
- b.Run(name, func(b *testing.B) {
- for i := 0; i < b.N; i++ {
- Join(benchmark...)
- }
- })
- }
- }
- func BenchmarkHasElement(b *testing.B) {
- element := key.New("waldo")
- generate := func(n, loc int) key.Path {
- path := make(key.Path, n)
- for i := 0; i < n; i++ {
- if i == loc {
- path[i] = element
- } else {
- path[i] = key.New(int8(0))
- }
- }
- return path
- }
- benchmarks := map[string]key.Path{
- "10 Elements Index 0": generate(10, 0),
- "10 Elements Index 4": generate(10, 4),
- "10 Elements Index 9": generate(10, 9),
- "100 Elements Index 0": generate(100, 0),
- "100 Elements Index 49": generate(100, 49),
- "100 Elements Index 99": generate(100, 99),
- "1000 Elements Index 0": generate(1000, 0),
- "1000 Elements Index 499": generate(1000, 499),
- "1000 Elements Index 999": generate(1000, 999),
- }
- for name, benchmark := range benchmarks {
- b.Run(name, func(b *testing.B) {
- for i := 0; i < b.N; i++ {
- HasElement(benchmark, element)
- }
- })
- }
- }
|