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

     1  // Copyright (c) 2018 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 key_test
     6  
     7  import (
     8  	"encoding/json"
     9  	"fmt"
    10  	"testing"
    11  	"unicode/utf8"
    12  
    13  	"github.com/aristanetworks/goarista/key"
    14  	"github.com/aristanetworks/goarista/path"
    15  )
    16  
    17  func TestPath(t *testing.T) {
    18  	expected := path.New("leet")
    19  	k := key.New(expected)
    20  
    21  	keyPath, ok := k.Key().(key.Path)
    22  	if !ok {
    23  		t.Fatalf("key.Key() did not return a key.Path")
    24  	}
    25  	if !path.Equal(keyPath, expected) {
    26  		t.Errorf("expected path from key is %#v, got %#v", expected, keyPath)
    27  	}
    28  
    29  	if expected, actual := "/leet", fmt.Sprint(k); actual != expected {
    30  		t.Errorf("expected string from path key %q, got %q", expected, actual)
    31  	}
    32  
    33  	if js, err := json.Marshal(k); err != nil {
    34  		t.Errorf("JSON marshalling error: %v", err)
    35  	} else if expected, actual := `{"_path":"/leet"}`, string(js); actual != expected {
    36  		t.Errorf("expected json output %q, got %q", expected, actual)
    37  	}
    38  }
    39  
    40  func newPathKey(e ...interface{}) key.Key {
    41  	return key.New(path.New(e...))
    42  }
    43  
    44  type customPath string
    45  
    46  func (p customPath) Key() interface{} {
    47  	return path.FromString(string(p))
    48  }
    49  
    50  func (p customPath) Equal(other interface{}) bool {
    51  	o, ok := other.(key.Key)
    52  	return ok && o.Equal(p)
    53  }
    54  
    55  func (p customPath) String() string               { return string(p) }
    56  func (p customPath) ToBuiltin() interface{}       { panic("not impl") }
    57  func (p customPath) MarshalJSON() ([]byte, error) { panic("not impl") }
    58  
    59  func TestPathEqual(t *testing.T) {
    60  	tests := []struct {
    61  		a      key.Key
    62  		b      key.Key
    63  		result bool
    64  	}{{
    65  		a:      newPathKey(),
    66  		b:      nil,
    67  		result: false,
    68  	}, {
    69  		a:      newPathKey(),
    70  		b:      newPathKey(),
    71  		result: true,
    72  	}, {
    73  		a:      newPathKey(),
    74  		b:      newPathKey("foo"),
    75  		result: false,
    76  	}, {
    77  		a:      newPathKey("foo"),
    78  		b:      newPathKey(),
    79  		result: false,
    80  	}, {
    81  		a:      newPathKey(int16(1337)),
    82  		b:      newPathKey(int64(1337)),
    83  		result: false,
    84  	}, {
    85  		a:      newPathKey(path.Wildcard, "bar"),
    86  		b:      newPathKey("foo", path.Wildcard),
    87  		result: false,
    88  	}, {
    89  		a:      newPathKey(map[string]interface{}{"a": "x", "b": "y"}),
    90  		b:      newPathKey(map[string]interface{}{"b": "y", "a": "x"}),
    91  		result: true,
    92  	}, {
    93  		a:      newPathKey(map[string]interface{}{"a": "x", "b": "y"}),
    94  		b:      newPathKey(map[string]interface{}{"x": "x", "y": "y"}),
    95  		result: false,
    96  	}, {
    97  		a:      newPathKey("foo", "bar"),
    98  		b:      customPath("/foo/bar"),
    99  		result: true,
   100  	}, {
   101  		a:      customPath("/foo/bar"),
   102  		b:      newPathKey("foo", "bar"),
   103  		result: true,
   104  	}, {
   105  		a:      newPathKey("foo"),
   106  		b:      key.New(customPath("/bar")),
   107  		result: false,
   108  	}, {
   109  		a:      key.New(customPath("/foo")),
   110  		b:      newPathKey("foo", "bar"),
   111  		result: false,
   112  	}}
   113  
   114  	for i, tc := range tests {
   115  		if a, b := tc.a, tc.b; a.Equal(b) != tc.result {
   116  			t.Errorf("result not as expected for test case %d", i)
   117  		}
   118  	}
   119  }
   120  
   121  func TestPathAsKey(t *testing.T) {
   122  	a := newPathKey("foo", path.Wildcard, map[string]interface{}{
   123  		"bar": key.NewMap(
   124  			// Should be able to embed a path key and value
   125  			newPathKey("path", "to", "something"), path.New("else")),
   126  	})
   127  	m := key.NewMap(a, "thats a complex key!")
   128  	if s, ok := m.Get(a); !ok {
   129  		t.Error("complex key not found in map")
   130  	} else if s != "thats a complex key!" {
   131  		t.Errorf("incorrect value in map: %s", s)
   132  	}
   133  
   134  	// preserve custom path implementations
   135  	b := key.New(customPath("/foo/bar"))
   136  	if _, ok := b.Key().(customPath); !ok {
   137  		t.Errorf("customPath implementation not preserved: %T", b.Key())
   138  	}
   139  }
   140  
   141  func TestInvalidUTF8(t *testing.T) {
   142  	bytesAsString := string([]byte{0xFF, 0xFF, 0xFF, 0xFF})
   143  	if utf8.ValidString(bytesAsString) {
   144  		t.Fatalf("expected %q to be invalid utf8", bytesAsString)
   145  	}
   146  	p := key.Path{key.New(bytesAsString)}
   147  	pathString := p.String()
   148  	if !utf8.ValidString(pathString) {
   149  		t.Errorf("expected %q to be valid utf8", pathString)
   150  	}
   151  }
   152  
   153  var pathStr string
   154  
   155  func BenchmarkPathString(b *testing.B) {
   156  	p := path.New("foo", "bar", "baz", "qux", "corge", "grault", "garply", "waldo", "fred")
   157  	b.ReportAllocs()
   158  	b.ResetTimer()
   159  	for i := 0; i < b.N; i++ {
   160  		pathStr = p.String()
   161  	}
   162  }