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

     1  // Copyright (c) 2017 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 path
     6  
     7  import (
     8  	"fmt"
     9  	"testing"
    10  
    11  	"github.com/aristanetworks/goarista/key"
    12  	"github.com/aristanetworks/goarista/value"
    13  )
    14  
    15  func TestNew(t *testing.T) {
    16  	tcases := []struct {
    17  		in  []interface{}
    18  		out key.Path
    19  	}{
    20  		{
    21  			in:  nil,
    22  			out: key.Path{},
    23  		}, {
    24  			in:  []interface{}{},
    25  			out: key.Path{},
    26  		}, {
    27  			in:  []interface{}{"foo", key.New("bar"), true},
    28  			out: key.Path{key.New("foo"), key.New("bar"), key.New(true)},
    29  		}, {
    30  			in: []interface{}{int8(5), int16(5), int32(5), int64(5)},
    31  			out: key.Path{key.New(int8(5)), key.New(int16(5)), key.New(int32(5)),
    32  				key.New(int64(5))},
    33  		}, {
    34  			in: []interface{}{uint8(5), uint16(5), uint32(5), uint64(5)},
    35  			out: key.Path{key.New(uint8(5)), key.New(uint16(5)), key.New(uint32(5)),
    36  				key.New(uint64(5))},
    37  		}, {
    38  			in:  []interface{}{float32(5), float64(5)},
    39  			out: key.Path{key.New(float32(5)), key.New(float64(5))},
    40  		}, {
    41  			in:  []interface{}{customKey{i: &a}, map[string]interface{}{}},
    42  			out: key.Path{key.New(customKey{i: &a}), key.New(map[string]interface{}{})},
    43  		}, {
    44  			in:  []interface{}{[]string{"A", "B"}, []string{"C"}, "D"},
    45  			out: key.Path{key.New("A"), key.New("B"), key.New("C"), key.New("D")},
    46  		}, {
    47  			in: []interface{}{[]string{"A", "B"}, []interface{}{"1", "2"}, "D"},
    48  			out: key.Path{key.New("A"), key.New("B"), key.New([]interface{}{"1", "2"}),
    49  				key.New("D")},
    50  		}, {
    51  			in: []interface{}{[]string{"A", "B"},
    52  				[]key.Key{key.New("C"), key.New("D")},
    53  				key.Path{key.New("E"), key.New("F")},
    54  				[]key.Path{
    55  					key.Path{key.New("G"), key.New("H")},
    56  					key.Path{key.New("I"), key.New("J")},
    57  				}},
    58  			out: key.Path{key.New("A"), key.New("B"), key.New("C"), key.New("D"),
    59  				key.New("E"), key.New("F"), key.New("G"), key.New("H"),
    60  				key.New("I"), key.New("J")},
    61  		},
    62  	}
    63  	for i, tcase := range tcases {
    64  		if p := New(tcase.in...); !Equal(p, tcase.out) {
    65  			t.Fatalf("Test %d failed: %#v != %#v", i, p, tcase.out)
    66  		}
    67  	}
    68  }
    69  
    70  func TestClone(t *testing.T) {
    71  	if !Equal(Clone(key.Path{}), key.Path{}) {
    72  		t.Error("Clone(key.Path{}) != key.Path{}")
    73  	}
    74  	a := key.Path{key.New("foo"), key.New("bar")}
    75  	b, c := Clone(a), Clone(a)
    76  	b[1] = key.New("baz")
    77  	if Equal(a, b) || !Equal(a, c) {
    78  		t.Error("Clone is not making a copied path")
    79  	}
    80  }
    81  
    82  func TestAppend(t *testing.T) {
    83  	tcases := []struct {
    84  		a      key.Path
    85  		b      []interface{}
    86  		result key.Path
    87  	}{
    88  		{
    89  			a:      key.Path{},
    90  			b:      []interface{}{},
    91  			result: key.Path{},
    92  		}, {
    93  			a:      key.Path{key.New("foo")},
    94  			b:      []interface{}{},
    95  			result: key.Path{key.New("foo")},
    96  		}, {
    97  			a:      key.Path{},
    98  			b:      []interface{}{"foo", key.New("bar")},
    99  			result: key.Path{key.New("foo"), key.New("bar")},
   100  		}, {
   101  			a:      key.Path{key.New("foo")},
   102  			b:      []interface{}{int64(0), key.New("bar")},
   103  			result: key.Path{key.New("foo"), key.New(int64(0)), key.New("bar")},
   104  		},
   105  	}
   106  	for i, tcase := range tcases {
   107  		if p := Append(tcase.a, tcase.b...); !Equal(p, tcase.result) {
   108  			t.Fatalf("Test %d failed: %#v != %#v", i, p, tcase.result)
   109  		}
   110  	}
   111  }
   112  
   113  func TestJoin(t *testing.T) {
   114  	tcases := []struct {
   115  		paths  []key.Path
   116  		result key.Path
   117  	}{
   118  		{
   119  			paths:  nil,
   120  			result: nil,
   121  		}, {
   122  			paths:  []key.Path{},
   123  			result: nil,
   124  		}, {
   125  			paths:  []key.Path{key.Path{}},
   126  			result: nil,
   127  		}, {
   128  			paths:  []key.Path{key.Path{key.New(true)}, key.Path{}},
   129  			result: key.Path{key.New(true)},
   130  		}, {
   131  			paths:  []key.Path{key.Path{}, key.Path{key.New(true)}},
   132  			result: key.Path{key.New(true)},
   133  		}, {
   134  			paths:  []key.Path{key.Path{key.New("foo")}, key.Path{key.New("bar")}},
   135  			result: key.Path{key.New("foo"), key.New("bar")},
   136  		}, {
   137  			paths:  []key.Path{key.Path{key.New("bar")}, key.Path{key.New("foo")}},
   138  			result: key.Path{key.New("bar"), key.New("foo")},
   139  		}, {
   140  			paths: []key.Path{
   141  				key.Path{key.New(uint32(0)), key.New(uint64(0))},
   142  				key.Path{key.New(int8(0))},
   143  				key.Path{key.New(int16(0)), key.New(int32(0))},
   144  				key.Path{key.New(int64(0)), key.New(uint8(0)), key.New(uint16(0))},
   145  			},
   146  			result: key.Path{
   147  				key.New(uint32(0)), key.New(uint64(0)),
   148  				key.New(int8(0)), key.New(int16(0)),
   149  				key.New(int32(0)), key.New(int64(0)),
   150  				key.New(uint8(0)), key.New(uint16(0)),
   151  			},
   152  		},
   153  	}
   154  	for i, tcase := range tcases {
   155  		if p := Join(tcase.paths...); !Equal(p, tcase.result) {
   156  			t.Fatalf("Test %d failed: %#v != %#v", i, p, tcase.result)
   157  		}
   158  	}
   159  }
   160  
   161  func TestParent(t *testing.T) {
   162  	if Parent(key.Path{}) != nil {
   163  		t.Fatal("Parent of empty key.Path should be nil")
   164  	}
   165  	tcases := []struct {
   166  		in  key.Path
   167  		out key.Path
   168  	}{
   169  		{
   170  			in:  key.Path{key.New("foo")},
   171  			out: key.Path{},
   172  		}, {
   173  			in:  key.Path{key.New("foo"), key.New("bar")},
   174  			out: key.Path{key.New("foo")},
   175  		}, {
   176  			in:  key.Path{key.New("foo"), key.New("bar"), key.New("baz")},
   177  			out: key.Path{key.New("foo"), key.New("bar")},
   178  		},
   179  	}
   180  	for _, tcase := range tcases {
   181  		if !Equal(Parent(tcase.in), tcase.out) {
   182  			t.Fatalf("Parent of %#v != %#v", tcase.in, tcase.out)
   183  		}
   184  	}
   185  }
   186  
   187  func TestBase(t *testing.T) {
   188  	if Base(key.Path{}) != nil {
   189  		t.Fatal("Base of empty key.Path should be nil")
   190  	}
   191  	tcases := []struct {
   192  		in  key.Path
   193  		out key.Key
   194  	}{
   195  		{
   196  			in:  key.Path{key.New("foo")},
   197  			out: key.New("foo"),
   198  		}, {
   199  			in:  key.Path{key.New("foo"), key.New("bar")},
   200  			out: key.New("bar"),
   201  		},
   202  	}
   203  	for _, tcase := range tcases {
   204  		if !Base(tcase.in).Equal(tcase.out) {
   205  			t.Fatalf("Base of %#v != %#v", tcase.in, tcase.out)
   206  		}
   207  	}
   208  }
   209  
   210  type customKey struct {
   211  	i *int
   212  }
   213  
   214  func (c customKey) String() string {
   215  	return fmt.Sprintf("customKey=%d", *c.i)
   216  }
   217  
   218  func (c customKey) MarshalJSON() ([]byte, error) {
   219  	return nil, nil
   220  }
   221  
   222  func (c customKey) ToBuiltin() interface{} {
   223  	return nil
   224  }
   225  
   226  func (c customKey) Equal(other interface{}) bool {
   227  	o, ok := other.(customKey)
   228  	return ok && *c.i == *o.i
   229  }
   230  
   231  var (
   232  	_ value.Value    = customKey{}
   233  	_ key.Comparable = customKey{}
   234  	a                = 1
   235  	b                = 1
   236  )
   237  
   238  func TestEqual(t *testing.T) {
   239  	tcases := []struct {
   240  		a      key.Path
   241  		b      key.Path
   242  		result bool
   243  	}{
   244  		{
   245  			a:      nil,
   246  			b:      nil,
   247  			result: true,
   248  		}, {
   249  			a:      nil,
   250  			b:      key.Path{},
   251  			result: true,
   252  		}, {
   253  			a:      key.Path{},
   254  			b:      nil,
   255  			result: true,
   256  		}, {
   257  			a:      key.Path{},
   258  			b:      key.Path{},
   259  			result: true,
   260  		}, {
   261  			a:      key.Path{},
   262  			b:      key.Path{key.New("")},
   263  			result: false,
   264  		}, {
   265  			a:      key.Path{Wildcard},
   266  			b:      key.Path{key.New("foo")},
   267  			result: false,
   268  		}, {
   269  			a:      key.Path{Wildcard},
   270  			b:      key.Path{Wildcard},
   271  			result: true,
   272  		}, {
   273  			a:      key.Path{key.New("foo")},
   274  			b:      key.Path{key.New("foo")},
   275  			result: true,
   276  		}, {
   277  			a:      key.Path{key.New(true)},
   278  			b:      key.Path{key.New(false)},
   279  			result: false,
   280  		}, {
   281  			a:      key.Path{key.New(int32(5))},
   282  			b:      key.Path{key.New(int64(5))},
   283  			result: false,
   284  		}, {
   285  			a:      key.Path{key.New("foo")},
   286  			b:      key.Path{key.New("foo"), key.New("bar")},
   287  			result: false,
   288  		}, {
   289  			a:      key.Path{key.New("foo"), key.New("bar")},
   290  			b:      key.Path{key.New("foo")},
   291  			result: false,
   292  		}, {
   293  			a:      key.Path{key.New(uint8(0)), key.New(int8(0))},
   294  			b:      key.Path{key.New(int8(0)), key.New(uint8(0))},
   295  			result: false,
   296  		},
   297  		// Ensure that we check deep equality.
   298  		{
   299  			a:      key.Path{key.New(map[string]interface{}{})},
   300  			b:      key.Path{key.New(map[string]interface{}{})},
   301  			result: true,
   302  		}, {
   303  			a:      key.Path{key.New(customKey{i: &a})},
   304  			b:      key.Path{key.New(customKey{i: &b})},
   305  			result: true,
   306  		},
   307  	}
   308  	for i, tcase := range tcases {
   309  		if result := Equal(tcase.a, tcase.b); result != tcase.result {
   310  			t.Fatalf("Test %d failed: a: %#v; b: %#v, result: %t",
   311  				i, tcase.a, tcase.b, tcase.result)
   312  		}
   313  	}
   314  }
   315  
   316  func TestMatch(t *testing.T) {
   317  	tcases := []struct {
   318  		a      key.Path
   319  		b      key.Path
   320  		result bool
   321  	}{
   322  		{
   323  			a:      nil,
   324  			b:      nil,
   325  			result: true,
   326  		}, {
   327  			a:      nil,
   328  			b:      key.Path{},
   329  			result: true,
   330  		}, {
   331  			a:      key.Path{},
   332  			b:      nil,
   333  			result: true,
   334  		}, {
   335  			a:      key.Path{},
   336  			b:      key.Path{},
   337  			result: true,
   338  		}, {
   339  			a:      key.Path{},
   340  			b:      key.Path{key.New("foo")},
   341  			result: false,
   342  		}, {
   343  			a:      key.Path{Wildcard},
   344  			b:      key.Path{key.New("foo")},
   345  			result: true,
   346  		}, {
   347  			a:      key.Path{key.New("foo")},
   348  			b:      key.Path{Wildcard},
   349  			result: false,
   350  		}, {
   351  			a:      key.Path{Wildcard},
   352  			b:      key.Path{key.New("foo"), key.New("bar")},
   353  			result: false,
   354  		}, {
   355  			a:      key.Path{Wildcard, Wildcard},
   356  			b:      key.Path{key.New(int64(0))},
   357  			result: false,
   358  		}, {
   359  			a:      key.Path{Wildcard, Wildcard},
   360  			b:      key.Path{key.New(int64(0)), key.New(int32(0))},
   361  			result: true,
   362  		}, {
   363  			a:      key.Path{Wildcard, key.New(false)},
   364  			b:      key.Path{key.New(true), Wildcard},
   365  			result: false,
   366  		},
   367  	}
   368  	for i, tcase := range tcases {
   369  		if result := Match(tcase.a, tcase.b); result != tcase.result {
   370  			t.Fatalf("Test %d failed: a: %#v; b: %#v, result: %t",
   371  				i, tcase.a, tcase.b, tcase.result)
   372  		}
   373  	}
   374  }
   375  
   376  func TestHasElement(t *testing.T) {
   377  	tcases := []struct {
   378  		a      key.Path
   379  		b      key.Key
   380  		result bool
   381  	}{
   382  		{
   383  			a:      nil,
   384  			b:      nil,
   385  			result: false,
   386  		}, {
   387  			a:      nil,
   388  			b:      key.New("foo"),
   389  			result: false,
   390  		}, {
   391  			a:      key.Path{},
   392  			b:      nil,
   393  			result: false,
   394  		}, {
   395  			a:      key.Path{key.New("foo")},
   396  			b:      nil,
   397  			result: false,
   398  		}, {
   399  			a:      key.Path{key.New("foo")},
   400  			b:      key.New("foo"),
   401  			result: true,
   402  		}, {
   403  			a:      key.Path{key.New(true)},
   404  			b:      key.New("true"),
   405  			result: false,
   406  		}, {
   407  			a:      key.Path{key.New("foo"), key.New("bar")},
   408  			b:      key.New("bar"),
   409  			result: true,
   410  		}, {
   411  			a:      key.Path{key.New(map[string]interface{}{})},
   412  			b:      key.New(map[string]interface{}{}),
   413  			result: true,
   414  		}, {
   415  			a:      key.Path{key.New(map[string]interface{}{"foo": "a"})},
   416  			b:      key.New(map[string]interface{}{"bar": "a"}),
   417  			result: false,
   418  		},
   419  	}
   420  	for i, tcase := range tcases {
   421  		if result := HasElement(tcase.a, tcase.b); result != tcase.result {
   422  			t.Errorf("Test %d failed: a: %#v; b: %#v, result: %t, expected: %t",
   423  				i, tcase.a, tcase.b, result, tcase.result)
   424  		}
   425  	}
   426  }
   427  
   428  func TestHasPrefix(t *testing.T) {
   429  	tcases := []struct {
   430  		a      key.Path
   431  		b      key.Path
   432  		result bool
   433  	}{
   434  		{
   435  			a:      nil,
   436  			b:      nil,
   437  			result: true,
   438  		}, {
   439  			a:      nil,
   440  			b:      key.Path{},
   441  			result: true,
   442  		}, {
   443  			a:      key.Path{},
   444  			b:      nil,
   445  			result: true,
   446  		}, {
   447  			a:      key.Path{},
   448  			b:      key.Path{},
   449  			result: true,
   450  		}, {
   451  			a:      key.Path{},
   452  			b:      key.Path{key.New("foo")},
   453  			result: false,
   454  		}, {
   455  			a:      key.Path{key.New("foo")},
   456  			b:      key.Path{},
   457  			result: true,
   458  		}, {
   459  			a:      key.Path{key.New(true)},
   460  			b:      key.Path{key.New(false)},
   461  			result: false,
   462  		}, {
   463  			a:      key.Path{key.New("foo"), key.New("bar")},
   464  			b:      key.Path{key.New("bar"), key.New("foo")},
   465  			result: false,
   466  		}, {
   467  			a:      key.Path{key.New(int8(0)), key.New(uint8(0))},
   468  			b:      key.Path{key.New(uint8(0)), key.New(uint8(0))},
   469  			result: false,
   470  		}, {
   471  			a:      key.Path{key.New(true), key.New(true)},
   472  			b:      key.Path{key.New(true), key.New(true), key.New(true)},
   473  			result: false,
   474  		}, {
   475  			a:      key.Path{key.New(true), key.New(true), key.New(true)},
   476  			b:      key.Path{key.New(true), key.New(true)},
   477  			result: true,
   478  		}, {
   479  			a:      key.Path{Wildcard, key.New(int32(0)), Wildcard},
   480  			b:      key.Path{key.New(int64(0)), Wildcard},
   481  			result: false,
   482  		},
   483  	}
   484  	for i, tcase := range tcases {
   485  		if result := HasPrefix(tcase.a, tcase.b); result != tcase.result {
   486  			t.Fatalf("Test %d failed: a: %#v; b: %#v, result: %t",
   487  				i, tcase.a, tcase.b, tcase.result)
   488  		}
   489  	}
   490  }
   491  
   492  func TestMatchPrefix(t *testing.T) {
   493  	tcases := []struct {
   494  		a      key.Path
   495  		b      key.Path
   496  		result bool
   497  	}{
   498  		{
   499  			a:      nil,
   500  			b:      nil,
   501  			result: true,
   502  		}, {
   503  			a:      nil,
   504  			b:      key.Path{},
   505  			result: true,
   506  		}, {
   507  			a:      key.Path{},
   508  			b:      nil,
   509  			result: true,
   510  		}, {
   511  			a:      key.Path{},
   512  			b:      key.Path{},
   513  			result: true,
   514  		}, {
   515  			a:      key.Path{},
   516  			b:      key.Path{key.New("foo")},
   517  			result: false,
   518  		}, {
   519  			a:      key.Path{key.New("foo")},
   520  			b:      key.Path{},
   521  			result: true,
   522  		}, {
   523  			a:      key.Path{key.New("foo")},
   524  			b:      key.Path{Wildcard},
   525  			result: false,
   526  		}, {
   527  			a:      key.Path{Wildcard},
   528  			b:      key.Path{key.New("foo")},
   529  			result: true,
   530  		}, {
   531  			a:      key.Path{Wildcard},
   532  			b:      key.Path{key.New("foo"), key.New("bar")},
   533  			result: false,
   534  		}, {
   535  			a:      key.Path{Wildcard, key.New(true)},
   536  			b:      key.Path{key.New(false), Wildcard},
   537  			result: false,
   538  		}, {
   539  			a:      key.Path{Wildcard, key.New(int32(0)), key.New(int16(0))},
   540  			b:      key.Path{key.New(int64(0)), key.New(int32(0))},
   541  			result: true,
   542  		},
   543  	}
   544  	for i, tcase := range tcases {
   545  		if result := MatchPrefix(tcase.a, tcase.b); result != tcase.result {
   546  			t.Fatalf("Test %d failed: a: %#v; b: %#v, result: %t",
   547  				i, tcase.a, tcase.b, tcase.result)
   548  		}
   549  	}
   550  }
   551  
   552  func TestFromString(t *testing.T) {
   553  	tcases := []struct {
   554  		in  string
   555  		out key.Path
   556  	}{
   557  		{
   558  			in:  "",
   559  			out: key.Path{},
   560  		}, {
   561  			in:  "/",
   562  			out: key.Path{},
   563  		}, {
   564  			in:  "//",
   565  			out: key.Path{key.New(""), key.New("")},
   566  		}, {
   567  			in:  "foo",
   568  			out: key.Path{key.New("foo")},
   569  		}, {
   570  			in:  "/foo",
   571  			out: key.Path{key.New("foo")},
   572  		}, {
   573  			in:  "foo/bar",
   574  			out: key.Path{key.New("foo"), key.New("bar")},
   575  		}, {
   576  			in:  "/foo/bar",
   577  			out: key.Path{key.New("foo"), key.New("bar")},
   578  		}, {
   579  			in:  "foo/bar/baz",
   580  			out: key.Path{key.New("foo"), key.New("bar"), key.New("baz")},
   581  		}, {
   582  			in:  "/foo/bar/baz",
   583  			out: key.Path{key.New("foo"), key.New("bar"), key.New("baz")},
   584  		}, {
   585  			in:  "0/123/456/789",
   586  			out: key.Path{key.New("0"), key.New("123"), key.New("456"), key.New("789")},
   587  		}, {
   588  			in:  "/0/123/456/789",
   589  			out: key.Path{key.New("0"), key.New("123"), key.New("456"), key.New("789")},
   590  		}, {
   591  			in:  "`~!@#$%^&*()_+{}\\/|[];':\"<>?,./",
   592  			out: key.Path{key.New("`~!@#$%^&*()_+{}\\"), key.New("|[];':\"<>?,."), key.New("")},
   593  		}, {
   594  			in:  "/`~!@#$%^&*()_+{}\\/|[];':\"<>?,./",
   595  			out: key.Path{key.New("`~!@#$%^&*()_+{}\\"), key.New("|[];':\"<>?,."), key.New("")},
   596  		},
   597  	}
   598  	for i, tcase := range tcases {
   599  		if p := FromString(tcase.in); !Equal(p, tcase.out) {
   600  			t.Fatalf("Test %d failed: %#v != %#v", i, p, tcase.out)
   601  		}
   602  	}
   603  }
   604  
   605  func TestString(t *testing.T) {
   606  	tcases := []struct {
   607  		in  key.Path
   608  		out string
   609  	}{
   610  		{
   611  			in:  key.Path{},
   612  			out: "/",
   613  		}, {
   614  			in:  key.Path{key.New("")},
   615  			out: "/",
   616  		}, {
   617  			in:  key.Path{key.New("foo")},
   618  			out: "/foo",
   619  		}, {
   620  			in:  key.Path{key.New("foo"), key.New("bar")},
   621  			out: "/foo/bar",
   622  		}, {
   623  			in:  key.Path{key.New("/foo"), key.New("bar")},
   624  			out: "//foo/bar",
   625  		}, {
   626  			in:  key.Path{key.New("foo"), key.New("bar/")},
   627  			out: "/foo/bar/",
   628  		}, {
   629  			in:  key.Path{key.New(""), key.New("foo"), key.New("bar")},
   630  			out: "//foo/bar",
   631  		}, {
   632  			in:  key.Path{key.New("foo"), key.New("bar"), key.New("")},
   633  			out: "/foo/bar/",
   634  		}, {
   635  			in:  key.Path{key.New("/"), key.New("foo"), key.New("bar")},
   636  			out: "///foo/bar",
   637  		}, {
   638  			in:  key.Path{key.New("foo"), key.New("bar"), key.New("/")},
   639  			out: "/foo/bar//",
   640  		},
   641  	}
   642  	for i, tcase := range tcases {
   643  		if s := tcase.in.String(); s != tcase.out {
   644  			t.Fatalf("Test %d failed: %s != %s", i, s, tcase.out)
   645  		}
   646  	}
   647  }
   648  
   649  func BenchmarkJoin(b *testing.B) {
   650  	generate := func(n int) []key.Path {
   651  		paths := make([]key.Path, 0, n)
   652  		for i := 0; i < n; i++ {
   653  			paths = append(paths, key.Path{key.New("foo")})
   654  		}
   655  		return paths
   656  	}
   657  	benchmarks := map[string][]key.Path{
   658  		"10 key.Paths":    generate(10),
   659  		"100 key.Paths":   generate(100),
   660  		"1000 key.Paths":  generate(1000),
   661  		"10000 key.Paths": generate(10000),
   662  	}
   663  	for name, benchmark := range benchmarks {
   664  		b.Run(name, func(b *testing.B) {
   665  			for i := 0; i < b.N; i++ {
   666  				Join(benchmark...)
   667  			}
   668  		})
   669  	}
   670  }
   671  
   672  func BenchmarkHasElement(b *testing.B) {
   673  	element := key.New("waldo")
   674  	generate := func(n, loc int) key.Path {
   675  		path := make(key.Path, n)
   676  		for i := 0; i < n; i++ {
   677  			if i == loc {
   678  				path[i] = element
   679  			} else {
   680  				path[i] = key.New(int8(0))
   681  			}
   682  		}
   683  		return path
   684  	}
   685  	benchmarks := map[string]key.Path{
   686  		"10 Elements Index 0":     generate(10, 0),
   687  		"10 Elements Index 4":     generate(10, 4),
   688  		"10 Elements Index 9":     generate(10, 9),
   689  		"100 Elements Index 0":    generate(100, 0),
   690  		"100 Elements Index 49":   generate(100, 49),
   691  		"100 Elements Index 99":   generate(100, 99),
   692  		"1000 Elements Index 0":   generate(1000, 0),
   693  		"1000 Elements Index 499": generate(1000, 499),
   694  		"1000 Elements Index 999": generate(1000, 999),
   695  	}
   696  	for name, benchmark := range benchmarks {
   697  		b.Run(name, func(b *testing.B) {
   698  			for i := 0; i < b.N; i++ {
   699  				HasElement(benchmark, element)
   700  			}
   701  		})
   702  	}
   703  }
   704  
   705  func TestAppendShouldCopy(t *testing.T) {
   706  	p := New("a", "b")
   707  	p = Append(p, "c")
   708  	d := Append(p, "d")
   709  	e := Append(p, "e")
   710  
   711  	if Equal(d, e) {
   712  		t.Errorf("paths d and e should not be equal: %s", e)
   713  	}
   714  }