github.com/aristanetworks/goarista@v0.0.0-20240514173732-cca2755bbd44/key/key_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 key_test
     6  
     7  import (
     8  	"encoding/json"
     9  	"fmt"
    10  	"hash/maphash"
    11  	"strconv"
    12  	"testing"
    13  
    14  	. "github.com/aristanetworks/goarista/key"
    15  	"github.com/aristanetworks/goarista/test"
    16  	"github.com/aristanetworks/goarista/value"
    17  )
    18  
    19  type compareMe struct {
    20  	i int
    21  }
    22  
    23  func (c compareMe) Equal(other interface{}) bool {
    24  	o, ok := other.(compareMe)
    25  	return ok && c == o
    26  }
    27  
    28  func (c compareMe) String() string {
    29  	return fmt.Sprintf("compareMe{%d}", c.i)
    30  }
    31  
    32  type customKey struct {
    33  	i int
    34  }
    35  
    36  var _ value.Value = customKey{}
    37  
    38  func (c customKey) String() string {
    39  	return fmt.Sprintf("customKey=%d", c.i)
    40  }
    41  
    42  func (c customKey) MarshalJSON() ([]byte, error) {
    43  	return nil, nil
    44  }
    45  
    46  func (c customKey) ToBuiltin() interface{} {
    47  	return c.i
    48  }
    49  
    50  var (
    51  	nilIntf = interface{}(nil)
    52  	nilMap  = map[string]interface{}(nil)
    53  	nilArr  = []interface{}(nil)
    54  	nilPath = Path(nil)
    55  
    56  	nilPtr Pointer
    57  	nilVal value.Value
    58  )
    59  
    60  func TestKeyEqual(t *testing.T) {
    61  	tests := []struct {
    62  		a      Key
    63  		b      Key
    64  		result bool
    65  	}{{
    66  		a:      New("foo"),
    67  		b:      New("foo"),
    68  		result: true,
    69  	}, {
    70  		a:      New("foo"),
    71  		b:      New("bar"),
    72  		result: false,
    73  	}, {
    74  		a:      New([]interface{}{}),
    75  		b:      New("bar"),
    76  		result: false,
    77  	}, {
    78  		a:      New([]interface{}{}),
    79  		b:      New([]interface{}{}),
    80  		result: true,
    81  	}, {
    82  		a:      New([]interface{}{"a", "b"}),
    83  		b:      New([]interface{}{"a"}),
    84  		result: false,
    85  	}, {
    86  		a:      New([]interface{}{"a", "b"}),
    87  		b:      New([]interface{}{"b", "a"}),
    88  		result: false,
    89  	}, {
    90  		a:      New([]interface{}{"a", "b"}),
    91  		b:      New([]interface{}{"a", "b"}),
    92  		result: true,
    93  	}, {
    94  		a:      New([]interface{}{"a", map[string]interface{}{"b": "c"}}),
    95  		b:      New([]interface{}{"a", map[string]interface{}{"c": "b"}}),
    96  		result: false,
    97  	}, {
    98  		a:      New([]interface{}{"a", map[string]interface{}{"b": "c"}}),
    99  		b:      New([]interface{}{"a", map[string]interface{}{"b": "c"}}),
   100  		result: true,
   101  	}, {
   102  		a:      New(map[string]interface{}{}),
   103  		b:      New("bar"),
   104  		result: false,
   105  	}, {
   106  		a:      New(map[string]interface{}{}),
   107  		b:      New(map[string]interface{}{}),
   108  		result: true,
   109  	}, {
   110  		a:      New(map[string]interface{}{"a": uint32(3)}),
   111  		b:      New(map[string]interface{}{}),
   112  		result: false,
   113  	}, {
   114  		a:      New(map[string]interface{}{"a": uint32(3)}),
   115  		b:      New(map[string]interface{}{"b": uint32(4)}),
   116  		result: false,
   117  	}, {
   118  		a:      New(map[string]interface{}{"a": uint32(4), "b": uint32(5)}),
   119  		b:      New(map[string]interface{}{"a": uint32(4)}),
   120  		result: false,
   121  	}, {
   122  		a:      New(map[string]interface{}{"a": uint32(3)}),
   123  		b:      New(map[string]interface{}{"a": uint32(4)}),
   124  		result: false,
   125  	}, {
   126  		a:      New(map[string]interface{}{"a": uint32(3)}),
   127  		b:      New(map[string]interface{}{"a": uint32(3)}),
   128  		result: true,
   129  	}, {
   130  		a:      New(map[string]interface{}{"a": NewMap(New("b"), uint32(3))}),
   131  		b:      New(map[string]interface{}{"a": NewMap(New("b"), uint32(4))}),
   132  		result: false,
   133  	}, {
   134  		a:      New(map[string]interface{}{"a": NewMap(New("b"), uint32(4), New("c"), uint32(5))}),
   135  		b:      New(map[string]interface{}{"a": NewMap(New("b"), uint32(4))}),
   136  		result: false,
   137  	}, {
   138  		a:      New(map[string]interface{}{"a": NewMap(New("b"), uint32(4), New("c"), uint32(5))}),
   139  		b:      New(map[string]interface{}{"a": NewMap(New("b"), uint32(4), New("c"), uint32(5))}),
   140  		result: true,
   141  	}, {
   142  		a:      New(map[string]interface{}{"a": NewMap(New("b"), uint32(4))}),
   143  		b:      New(map[string]interface{}{"a": NewMap(New("b"), uint32(4))}),
   144  		result: true,
   145  	}, {
   146  		a:      New(map[string]interface{}{"a": compareMe{i: 3}}),
   147  		b:      New(map[string]interface{}{"a": compareMe{i: 3}}),
   148  		result: true,
   149  	}, {
   150  		a:      New(map[string]interface{}{"a": compareMe{i: 3}}),
   151  		b:      New(map[string]interface{}{"a": compareMe{i: 4}}),
   152  		result: false,
   153  	}, {
   154  		a:      New(customKey{i: 42}),
   155  		b:      New(customKey{i: 42}),
   156  		result: true,
   157  	}, {
   158  		a:      New(nil),
   159  		b:      New(nil),
   160  		result: true,
   161  	}, {
   162  		a:      New(nil),
   163  		b:      New(nilIntf),
   164  		result: true,
   165  	}, {
   166  		a:      New(nil),
   167  		b:      New(nilPtr),
   168  		result: true,
   169  	}, {
   170  		a:      New(nil),
   171  		b:      New(nilVal),
   172  		result: true,
   173  	}, {
   174  		a:      New(nil),
   175  		b:      New(nilMap),
   176  		result: false,
   177  	}, {
   178  		a:      New(nilMap),
   179  		b:      New(map[string]interface{}{}),
   180  		result: true,
   181  	}, {
   182  		a:      New(nil),
   183  		b:      New(nilArr),
   184  		result: false,
   185  	}, {
   186  		a:      New(nilArr),
   187  		b:      New([]interface{}{}),
   188  		result: true,
   189  	}, {
   190  		a:      New(nil),
   191  		b:      New(nilPath),
   192  		result: false,
   193  	}, {
   194  		a:      New(nilPath),
   195  		b:      New(Path{}),
   196  		result: true,
   197  	}, {
   198  		a:      New([]byte{0x0}),
   199  		b:      New([]byte{}),
   200  		result: false,
   201  	}, {
   202  		a:      New([]byte{0x1, 0x2}),
   203  		b:      New([]byte{0x1, 0x2}),
   204  		result: true,
   205  	}, {
   206  		a:      New([]byte{0x2, 0x1}),
   207  		b:      New([]byte{0x1, 0x2}),
   208  		result: false,
   209  	}, {
   210  		a:      New(string([]byte{0x1, 0x2})),
   211  		b:      New([]byte{0x1, 0x2}),
   212  		result: false,
   213  	}, {
   214  		a:      New(map[string]interface{}{"key1": []byte{0x1}}),
   215  		b:      New(map[string]interface{}{"key1": []byte{0x1}}),
   216  		result: true,
   217  	}, {
   218  		a:      New(map[string]interface{}{"key1": []byte{0x1}}),
   219  		b:      New(map[string]interface{}{"key1": []byte{0x2}}),
   220  		result: false,
   221  	}}
   222  
   223  	for _, tcase := range tests {
   224  		t.Run(fmt.Sprintf("%s_%s", tcase.a.String(), tcase.b.String()), func(t *testing.T) {
   225  			if tcase.a.Equal(tcase.b) != tcase.result {
   226  				t.Errorf("Wrong result for case:\na: %#v\nb: %#v\nresult: %#v",
   227  					tcase.a,
   228  					tcase.b,
   229  					tcase.result)
   230  			}
   231  			seed := maphash.MakeSeed()
   232  			aHash := Hash(seed, tcase.a)
   233  			bHash := Hash(seed, tcase.b)
   234  			if tcase.result {
   235  				if aHash != bHash {
   236  					t.Errorf("Equal keys have different hash: %x vs. %x", aHash, bHash)
   237  				}
   238  			} else {
   239  				if aHash == bHash {
   240  					// This should be very unlikely
   241  					t.Logf("Unequal keys have the same hash: %x", aHash)
   242  				}
   243  			}
   244  		})
   245  	}
   246  
   247  	if New("a").Equal(32) {
   248  		t.Error("Wrong result for different types case")
   249  	}
   250  }
   251  
   252  func TestGetFromMap(t *testing.T) {
   253  	tests := []struct {
   254  		k     Key
   255  		m     *Map
   256  		v     interface{}
   257  		found bool
   258  	}{{
   259  		k:     New(nil),
   260  		m:     NewMap(New(nil), nil),
   261  		v:     nil,
   262  		found: true,
   263  	}, {
   264  		k:     New("a"),
   265  		m:     NewMap(New("a"), "b"),
   266  		v:     "b",
   267  		found: true,
   268  	}, {
   269  		k:     New(uint32(35)),
   270  		m:     NewMap(New(uint32(35)), "c"),
   271  		v:     "c",
   272  		found: true,
   273  	}, {
   274  		k:     New(uint32(37)),
   275  		m:     NewMap(New(uint32(36)), "c"),
   276  		found: false,
   277  	}, {
   278  		k:     New(uint32(37)),
   279  		m:     NewMap(),
   280  		found: false,
   281  	}, {
   282  		k: New([]interface{}{"a", "b"}),
   283  		m: NewMap(New([]interface{}{"a", "b"}), "foo"),
   284  
   285  		v:     "foo",
   286  		found: true,
   287  	}, {
   288  		k: New([]interface{}{"a", "b"}),
   289  		m: NewMap(New([]interface{}{"a", "b", "c"}), "foo"),
   290  
   291  		found: false,
   292  	}, {
   293  		k: New([]interface{}{"a", map[string]interface{}{"b": "c"}}),
   294  		m: NewMap(New([]interface{}{"a", map[string]interface{}{"b": "c"}}), "foo"),
   295  
   296  		v:     "foo",
   297  		found: true,
   298  	}, {
   299  		k: New([]interface{}{"a", map[string]interface{}{"b": "c"}}),
   300  		m: NewMap(New([]interface{}{"a", map[string]interface{}{"c": "b"}}), "foo"),
   301  
   302  		found: false,
   303  	}, {
   304  		k: New(map[string]interface{}{"a": "b", "c": uint64(4)}),
   305  		m: NewMap(New(map[string]interface{}{"a": "b", "c": uint64(4)}), "foo"),
   306  
   307  		v:     "foo",
   308  		found: true,
   309  	}, {
   310  		k: New(map[string]interface{}{"a": "b", "c": uint64(4)}),
   311  		m: NewMap(New(map[string]interface{}{"a": "b", "c": uint64(5)}), "foo"),
   312  
   313  		found: false,
   314  	}, {
   315  		k:     New(customKey{i: 42}),
   316  		m:     NewMap(New(customKey{i: 42}), "c"),
   317  		v:     "c",
   318  		found: true,
   319  	}, {
   320  		k:     New(customKey{i: 42}),
   321  		m:     NewMap(New(customKey{i: 43}), "c"),
   322  		found: false,
   323  	}, {
   324  		k: New(map[string]interface{}{
   325  			"damn": NewMap(New(map[string]interface{}{"a": uint32(42),
   326  				"b": uint32(51)}), true)}),
   327  		m: NewMap(New(map[string]interface{}{
   328  			"damn": NewMap(New(map[string]interface{}{"a": uint32(42),
   329  				"b": uint32(51)}), true)}), "foo"),
   330  
   331  		v:     "foo",
   332  		found: true,
   333  	}, {
   334  		k: New(map[string]interface{}{
   335  			"damn": NewMap(New(map[string]interface{}{"a": uint32(42),
   336  				"b": uint32(52)}), true)}),
   337  		m: NewMap(New(map[string]interface{}{
   338  			"damn": NewMap(New(map[string]interface{}{"a": uint32(42),
   339  				"b": uint32(51)}), true)}), "foo"),
   340  
   341  		found: false,
   342  	}, {
   343  		k: New(map[string]interface{}{
   344  			"nested": map[string]interface{}{
   345  				"a": uint32(42), "b": uint32(51)}}),
   346  		m: NewMap(New(map[string]interface{}{
   347  			"nested": map[string]interface{}{
   348  				"a": uint32(42), "b": uint32(51)}}), "foo"),
   349  
   350  		v:     "foo",
   351  		found: true,
   352  	}, {
   353  		k: New(map[string]interface{}{
   354  			"nested": map[string]interface{}{
   355  				"a": uint32(42), "b": uint32(52)}}),
   356  		m: NewMap(New(map[string]interface{}{
   357  			"nested": map[string]interface{}{
   358  				"a": uint32(42), "b": uint32(51)}}), "foo"),
   359  
   360  		found: false,
   361  	}, {
   362  		k: New(map[string]interface{}{
   363  			"nested": []byte{0x1, 0x2},
   364  		}),
   365  		m: NewMap(New(map[string]interface{}{
   366  			"nested": []byte{0x1, 0x2},
   367  		}), "foo"),
   368  		v:     "foo",
   369  		found: true,
   370  	}, {
   371  		k: New(map[string]interface{}{
   372  			"nested": []byte{0x1, 0x2},
   373  		}),
   374  		m: NewMap(New(map[string]interface{}{
   375  			"nested": []byte{0x1, 0x3},
   376  		}), "foo"),
   377  		found: false,
   378  	}}
   379  
   380  	for _, tcase := range tests {
   381  		v, ok := tcase.m.Get(tcase.k)
   382  		if tcase.found != ok {
   383  			t.Errorf("Wrong retrieval result for case:\nk: %#v\nm: %#v\nv: %#v",
   384  				tcase.k,
   385  				tcase.m,
   386  				tcase.v)
   387  		} else if tcase.found && !ok {
   388  			t.Errorf("Unable to retrieve value for case:\nk: %#v\nm: %#v\nv: %#v",
   389  				tcase.k,
   390  				tcase.m,
   391  				tcase.v)
   392  		} else if tcase.found && !test.DeepEqual(tcase.v, v) {
   393  			t.Errorf("Wrong result for case:\nk: %#v\nm: %#v\nv: %#v",
   394  				tcase.k,
   395  				tcase.m,
   396  				tcase.v)
   397  		}
   398  	}
   399  }
   400  
   401  func TestDeleteFromMap(t *testing.T) {
   402  	tests := []struct {
   403  		k Key
   404  		m *Map
   405  		r *Map
   406  	}{{
   407  		k: New("a"),
   408  		m: NewMap(New("a"), "b"),
   409  		r: NewMap(),
   410  	}, {
   411  		k: New("b"),
   412  		m: NewMap(New("a"), "b"),
   413  		r: NewMap(New("a"), "b"),
   414  	}, {
   415  		k: New("a"),
   416  		m: NewMap(),
   417  		r: NewMap(),
   418  	}, {
   419  		k: New(uint32(35)),
   420  		m: NewMap(New(uint32(35)), "c"),
   421  		r: NewMap(),
   422  	}, {
   423  		k: New(uint32(36)),
   424  		m: NewMap(New(uint32(35)), "c"),
   425  		r: NewMap(New(uint32(35)), "c"),
   426  	}, {
   427  		k: New(uint32(37)),
   428  		m: NewMap(),
   429  		r: NewMap(),
   430  	}, {
   431  		k: New(map[string]interface{}{"a": "b", "c": uint64(4)}),
   432  		m: NewMap(New(map[string]interface{}{"a": "b", "c": uint64(4)}), "foo"),
   433  
   434  		r: NewMap(),
   435  	}, {
   436  		k: New(customKey{i: 42}),
   437  		m: NewMap(New(customKey{i: 42}), "c"),
   438  		r: NewMap(),
   439  	}, {
   440  		k: New([]byte{0x1, 0x2}),
   441  		m: NewMap(New([]byte{0x1, 0x2}), "a", New([]byte{0x1}), "b"),
   442  		r: NewMap(New([]byte{0x1}), "b"),
   443  	}}
   444  
   445  	for _, tcase := range tests {
   446  		tcase.m.Del(tcase.k)
   447  		if !test.DeepEqual(tcase.m, tcase.r) {
   448  			t.Errorf("Wrong result for case:\nk: %#v\nm: %#v\nr: %#v",
   449  				tcase.k,
   450  				tcase.m,
   451  				tcase.r)
   452  		}
   453  	}
   454  }
   455  
   456  func TestSetToMap(t *testing.T) {
   457  	tests := []struct {
   458  		k Key
   459  		v interface{}
   460  		m *Map
   461  		r *Map
   462  	}{{
   463  		k: New("a"),
   464  		v: "c",
   465  		m: NewMap(New("a"), "b"),
   466  		r: NewMap(New("a"), "c"),
   467  	}, {
   468  		k: New("b"),
   469  		v: uint64(56),
   470  		m: NewMap(New("a"), "b"),
   471  		r: NewMap(New("a"), "b",
   472  			New("b"), uint64(56)),
   473  	}, {
   474  		k: New("a"),
   475  		v: "foo",
   476  		m: NewMap(),
   477  		r: NewMap(New("a"), "foo"),
   478  	}, {
   479  		k: New(uint32(35)),
   480  		v: "d",
   481  		m: NewMap(New(uint32(35)), "c"),
   482  		r: NewMap(New(uint32(35)), "d"),
   483  	}, {
   484  		k: New(uint32(36)),
   485  		v: true,
   486  		m: NewMap(New(uint32(35)), "c"),
   487  		r: NewMap(New(uint32(35)), "c",
   488  			New(uint32(36)), true),
   489  	}, {
   490  		k: New(uint32(37)),
   491  		v: false,
   492  		m: NewMap(New(uint32(36)), "c"),
   493  		r: NewMap(New(uint32(36)), "c",
   494  			New(uint32(37)), false),
   495  	}, {
   496  		k: New(uint32(37)),
   497  		v: "foobar",
   498  		m: NewMap(),
   499  		r: NewMap(New(uint32(37)), "foobar"),
   500  	}, {
   501  		k: New(map[string]interface{}{"a": "b", "c": uint64(4)}),
   502  		v: "foobar",
   503  		m: NewMap(New(map[string]interface{}{"a": "b", "c": uint64(4)}), "foo"),
   504  
   505  		r: NewMap(New(map[string]interface{}{"a": "b", "c": uint64(4)}), "foobar"),
   506  	}, {
   507  		k: New(map[string]interface{}{"a": "b", "c": uint64(7)}),
   508  		v: "foobar",
   509  		m: NewMap(New(map[string]interface{}{"a": "b", "c": uint64(4)}), "foo"),
   510  
   511  		r: NewMap(New(map[string]interface{}{"a": "b", "c": uint64(4)}), "foo",
   512  			New(map[string]interface{}{"a": "b", "c": uint64(7)}), "foobar"),
   513  	}, {
   514  		k: New(map[string]interface{}{"a": "b", "d": uint64(6)}),
   515  		v: "barfoo",
   516  		m: NewMap(New(map[string]interface{}{"a": "b", "c": uint64(4)}), "foo"),
   517  
   518  		r: NewMap(New(map[string]interface{}{"a": "b", "c": uint64(4)}), "foo",
   519  			New(map[string]interface{}{"a": "b", "d": uint64(6)}), "barfoo"),
   520  	}, {
   521  		k: New(customKey{i: 42}),
   522  		v: "foo",
   523  		m: NewMap(),
   524  		r: NewMap(New(customKey{i: 42}), "foo"),
   525  	}}
   526  
   527  	for i, tcase := range tests {
   528  		tcase.m.Set(tcase.k, tcase.v)
   529  		if !test.DeepEqual(tcase.m, tcase.r) {
   530  			t.Errorf("Wrong result for case %d:\nk: %#v\nm: %#v\nr: %#v",
   531  				i,
   532  				tcase.k,
   533  				tcase.m,
   534  				tcase.r)
   535  		}
   536  	}
   537  }
   538  
   539  func TestGoString(t *testing.T) {
   540  	tcases := []struct {
   541  		in  Key
   542  		out string
   543  	}{{
   544  		in:  New(nil),
   545  		out: "key.New(nil)",
   546  	}, {
   547  		in:  New(uint8(1)),
   548  		out: "key.New(uint8(1))",
   549  	}, {
   550  		in:  New(uint16(1)),
   551  		out: "key.New(uint16(1))",
   552  	}, {
   553  		in:  New(uint32(1)),
   554  		out: "key.New(uint32(1))",
   555  	}, {
   556  		in:  New(uint64(1)),
   557  		out: "key.New(uint64(1))",
   558  	}, {
   559  		in:  New(int8(1)),
   560  		out: "key.New(int8(1))",
   561  	}, {
   562  		in:  New(int16(1)),
   563  		out: "key.New(int16(1))",
   564  	}, {
   565  		in:  New(int32(1)),
   566  		out: "key.New(int32(1))",
   567  	}, {
   568  		in:  New(int64(1)),
   569  		out: "key.New(int64(1))",
   570  	}, {
   571  		in:  New(float32(1)),
   572  		out: "key.New(float32(1))",
   573  	}, {
   574  		in:  New(float64(1)),
   575  		out: "key.New(float64(1))",
   576  	}, {
   577  		in:  New(map[string]interface{}{"foo": true}),
   578  		out: `key.New(map[string]interface {}{"foo":true})`,
   579  	}}
   580  	for i, tcase := range tcases {
   581  		t.Run(strconv.Itoa(i), func(t *testing.T) {
   582  			if out := fmt.Sprintf("%#v", tcase.in); out != tcase.out {
   583  				t.Errorf("Wanted Go representation %q but got %q", tcase.out, out)
   584  			}
   585  		})
   586  	}
   587  }
   588  
   589  func TestMisc(t *testing.T) {
   590  	k := New(map[string]interface{}{"foo": true})
   591  	js, err := json.Marshal(k)
   592  	if err != nil {
   593  		t.Error("JSON encoding failed:", err)
   594  	} else if expected := `{"foo":true}`; string(js) != expected {
   595  		t.Errorf("Wanted JSON %q but got %q", expected, js)
   596  	}
   597  
   598  	test.ShouldPanic(t, func() { New(42) })
   599  
   600  	k = New(customKey{i: 42})
   601  	if expected, str := "customKey=42", k.String(); expected != str {
   602  		t.Errorf("Wanted string representation %q but got %q", expected, str)
   603  	}
   604  }
   605  
   606  func BenchmarkSetToMapWithStringKey(b *testing.B) {
   607  	m := NewMap(New("a"), true,
   608  		New("a1"), true,
   609  		New("a2"), true,
   610  		New("a3"), true,
   611  		New("a4"), true,
   612  		New("a5"), true,
   613  		New("a6"), true,
   614  		New("a7"), true,
   615  		New("a8"), true,
   616  		New("a9"), true,
   617  		New("a10"), true,
   618  		New("a11"), true,
   619  		New("a12"), true,
   620  		New("a13"), true,
   621  		New("a14"), true,
   622  		New("a15"), true,
   623  		New("a16"), true,
   624  		New("a17"), true,
   625  		New("a18"), true)
   626  
   627  	b.ReportAllocs()
   628  	b.ResetTimer()
   629  	for i := 0; i < b.N; i++ {
   630  		m.Set(New(strconv.Itoa(i)), true)
   631  	}
   632  }
   633  
   634  func BenchmarkSetToMapWithUint64Key(b *testing.B) {
   635  	m := NewMap(New(uint64(1)), true,
   636  		New(uint64(2)), true,
   637  		New(uint64(3)), true,
   638  		New(uint64(4)), true,
   639  		New(uint64(5)), true,
   640  		New(uint64(6)), true,
   641  		New(uint64(7)), true,
   642  		New(uint64(8)), true,
   643  		New(uint64(9)), true,
   644  		New(uint64(10)), true,
   645  		New(uint64(11)), true,
   646  		New(uint64(12)), true,
   647  		New(uint64(13)), true,
   648  		New(uint64(14)), true,
   649  		New(uint64(15)), true,
   650  		New(uint64(16)), true,
   651  		New(uint64(17)), true,
   652  		New(uint64(18)), true,
   653  		New(uint64(19)), true)
   654  
   655  	b.ReportAllocs()
   656  	b.ResetTimer()
   657  	for i := 0; i < b.N; i++ {
   658  		m.Set(New(uint64(i)), true)
   659  	}
   660  }
   661  
   662  func BenchmarkGetFromMapWithMapKey(b *testing.B) {
   663  	m := NewMap(New(map[string]interface{}{"a": true}), true,
   664  		New(map[string]interface{}{"b": true}), true,
   665  		New(map[string]interface{}{"c": true}), true,
   666  		New(map[string]interface{}{"d": true}), true,
   667  		New(map[string]interface{}{"e": true}), true,
   668  		New(map[string]interface{}{"f": true}), true,
   669  		New(map[string]interface{}{"g": true}), true,
   670  		New(map[string]interface{}{"h": true}), true,
   671  		New(map[string]interface{}{"i": true}), true,
   672  		New(map[string]interface{}{"j": true}), true,
   673  		New(map[string]interface{}{"k": true}), true,
   674  		New(map[string]interface{}{"l": true}), true,
   675  		New(map[string]interface{}{"m": true}), true,
   676  		New(map[string]interface{}{"n": true}), true,
   677  		New(map[string]interface{}{"o": true}), true,
   678  		New(map[string]interface{}{"p": true}), true,
   679  		New(map[string]interface{}{"q": true}), true,
   680  		New(map[string]interface{}{"r": true}), true,
   681  		New(map[string]interface{}{"s": true}), true)
   682  
   683  	b.ReportAllocs()
   684  	b.ResetTimer()
   685  	for i := 0; i < b.N; i++ {
   686  		key := New(map[string]interface{}{string(rune('a' + i%19)): true})
   687  		_, found := m.Get(key)
   688  		if !found {
   689  			b.Fatalf("WTF: %#v", key)
   690  		}
   691  	}
   692  }
   693  
   694  func mkKey(i int) Key {
   695  	return New(map[string]interface{}{
   696  		"foo": map[string]interface{}{
   697  			"aaaa1": uint32(0),
   698  			"aaaa2": uint32(0),
   699  			"aaaa3": uint32(i),
   700  		},
   701  		"bar": map[string]interface{}{
   702  			"nested": uint32(42),
   703  		},
   704  	})
   705  }
   706  
   707  func BenchmarkBigMapWithCompositeKeys(b *testing.B) {
   708  	const size = 10000
   709  	m := NewMap()
   710  	for i := 0; i < size; i++ {
   711  		m.Set(mkKey(i), true)
   712  	}
   713  	k := mkKey(0)
   714  	submap := k.Key().(map[string]interface{})["foo"].(map[string]interface{})
   715  	b.ReportAllocs()
   716  	b.ResetTimer()
   717  	for i := 0; i < b.N; i++ {
   718  		submap["aaaa3"] = uint32(i)
   719  		_, found := m.Get(k)
   720  		if found != (i < size) {
   721  			b.Fatalf("WTF: %#v", k)
   722  		}
   723  	}
   724  }
   725  
   726  func BenchmarkKeyTypes(b *testing.B) {
   727  	benches := []struct {
   728  		val interface{}
   729  	}{
   730  		{
   731  			val: "foo",
   732  		},
   733  		{
   734  			val: int8(-12),
   735  		},
   736  		{
   737  			val: int16(123),
   738  		},
   739  		{
   740  			val: int32(123),
   741  		},
   742  		{
   743  			val: int64(123456),
   744  		},
   745  		{
   746  			val: uint8(12),
   747  		},
   748  		{
   749  			val: uint16(123),
   750  		},
   751  		{
   752  			val: uint32(123),
   753  		},
   754  		{
   755  			val: uint64(123456),
   756  		},
   757  		{
   758  			val: float32(123456.12),
   759  		},
   760  		{
   761  			val: float64(123456.12),
   762  		},
   763  		{
   764  			val: true,
   765  		},
   766  		{
   767  			val: map[string]interface{}{"foo": uint32(42), "bar": uint32(42), "baz": uint32(42)},
   768  		},
   769  		{
   770  			val: []interface{}{"foo", "bar", "baz"},
   771  		},
   772  	}
   773  
   774  	for _, bench := range benches {
   775  		var k Key
   776  		b.Run(fmt.Sprintf("%T", bench.val), func(b *testing.B) {
   777  			b.ReportAllocs()
   778  			for i := 0; i < b.N; i++ {
   779  				// create the key.Key and call some function here
   780  				if k = New(bench.val); k == nil {
   781  					b.Fatalf("expect to get key.Key, but got nil")
   782  				}
   783  				if !k.Equal(New(bench.val)) {
   784  					b.Fatalf("k is not equal to itself: %v", bench.val)
   785  				}
   786  			}
   787  		})
   788  	}
   789  }