github.com/searKing/golang/go@v1.2.117/container/hashring/hashring_test.go (about)

     1  // Copyright 2020 The searKing Author. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package hashring
     6  
     7  import (
     8  	"runtime"
     9  	"sort"
    10  	"strconv"
    11  	"testing"
    12  	"testing/quick"
    13  )
    14  
    15  func TestNew(t *testing.T) {
    16  	numReps := 160
    17  	x := New(WithNumberNodeRepetitions(numReps))
    18  	if x == nil {
    19  		t.Errorf("expected obj")
    20  		return
    21  	}
    22  
    23  	if x.numReps != numReps {
    24  		t.Errorf("got %d, want %d", x.numReps, numReps)
    25  	}
    26  }
    27  
    28  func TestAdd(t *testing.T) {
    29  	numReps := 160
    30  	x := New(WithNumberNodeRepetitions(numReps))
    31  	x.AddNodes(StringNode("abcdefg"))
    32  
    33  	if len(x.nodeByKey) != numReps {
    34  		t.Errorf("got %d, want %d", len(x.nodeByKey), numReps)
    35  	}
    36  	if len(x.sortedKeys) != numReps {
    37  		t.Errorf("got %d, want %d", len(x.sortedKeys), numReps)
    38  	}
    39  	if sort.IsSorted(x.sortedKeys) == false {
    40  		t.Errorf("expected sorted hashes to be sorted")
    41  	}
    42  	x.AddNodes(StringNode("qwer"))
    43  
    44  	if len(x.nodeByKey) != 2*numReps {
    45  		t.Errorf("got %d, want %d", len(x.nodeByKey), 2*numReps)
    46  	}
    47  	if len(x.sortedKeys) != 2*numReps {
    48  		t.Errorf("got %d, want %d", len(x.nodeByKey), 2*numReps)
    49  	}
    50  	if sort.IsSorted(x.sortedKeys) == false {
    51  		t.Errorf("expected sorted hashes to be sorted")
    52  	}
    53  }
    54  
    55  func TestRemove(t *testing.T) {
    56  	numReps := 160
    57  	x := New(WithNumberNodeRepetitions(numReps))
    58  	x.AddNodes(StringNode("abcdefg"))
    59  	x.RemoveNodes(StringNode("abcdefg"))
    60  	if len(x.nodeByKey) != 0 {
    61  		t.Errorf("got %d, want %d", len(x.nodeByKey), 0)
    62  	}
    63  	if len(x.sortedKeys) != 0 {
    64  		t.Errorf("got %d, want %d", len(x.nodeByKey), 0)
    65  	}
    66  }
    67  
    68  func TestRemoveNonExisting(t *testing.T) {
    69  	numReps := 160
    70  	x := New(WithNumberNodeRepetitions(numReps))
    71  	x.AddNodes(StringNode("abcdefg"))
    72  	x.RemoveNodes(StringNode("abcdefghijk"))
    73  	if len(x.nodeByKey) != numReps {
    74  		t.Errorf("got %d, want %d", len(x.nodeByKey), numReps)
    75  	}
    76  }
    77  
    78  func TestGetEmpty(t *testing.T) {
    79  	numReps := 160
    80  	x := New(WithNumberNodeRepetitions(numReps))
    81  	_, has := x.Get("asdfsadfsadf")
    82  	if has {
    83  		t.Errorf("expected error")
    84  	}
    85  }
    86  
    87  func TestGetSingle(t *testing.T) {
    88  	numReps := 160
    89  	x := New(WithNumberNodeRepetitions(numReps))
    90  	x.AddNodes(StringNode("abcdefg"))
    91  	f := func(s string) bool {
    92  		y, has := x.Get(s)
    93  		if !has {
    94  			return false
    95  		}
    96  		// t.Logf("s = %q, y = %q", s, y)
    97  		return y.String() == "abcdefg"
    98  	}
    99  	if err := quick.Check(f, nil); err != nil {
   100  		t.Logf("missing nodes")
   101  	}
   102  }
   103  
   104  type gtest struct {
   105  	in  string
   106  	out string
   107  }
   108  
   109  var gmtests = []gtest{
   110  	{"ggg", "abcdefg"},
   111  	{"hhh", "opqrstu"},
   112  	{"iii", "hijklmn"},
   113  }
   114  
   115  func TestGetMultiple(t *testing.T) {
   116  	x := New()
   117  	x.AddNodes(StringNode("abcdefg"))
   118  	x.AddNodes(StringNode("hijklmn"))
   119  	x.AddNodes(StringNode("opqrstu"))
   120  	for i, v := range gmtests {
   121  		result, has := x.Get(v.in)
   122  		if !has {
   123  			t.Fatal()
   124  		}
   125  		if result.String() != v.out {
   126  			t.Errorf("%d. got %q, expected %q", i, result, v.out)
   127  		}
   128  	}
   129  }
   130  
   131  func TestGetMultipleQuick(t *testing.T) {
   132  	x := New()
   133  	x.AddNodes(StringNode("abcdefg"))
   134  	x.AddNodes(StringNode("hijklmn"))
   135  	x.AddNodes(StringNode("opqrstu"))
   136  	f := func(s string) bool {
   137  		y, has := x.Get(s)
   138  		if !has {
   139  			return false
   140  		}
   141  		// t.Logf("s = %q, y = %q", s, y)
   142  		return y.String() == "abcdefg" ||
   143  			y.String() == "hijklmn" ||
   144  			y.String() == "opqrstu"
   145  	}
   146  	if err := quick.Check(f, nil); err != nil {
   147  		t.Logf("missing nodes")
   148  	}
   149  }
   150  
   151  var rtestsBefore = []gtest{
   152  	{"ggg", "abcdefg"},
   153  	{"hhh", "opqrstu"},
   154  	{"iii", "hijklmn"},
   155  }
   156  
   157  var rtestsAfter = []gtest{
   158  	{"ggg", "abcdefg"},
   159  	{"hhh", "opqrstu"},
   160  	{"iii", "abcdefg"},
   161  }
   162  
   163  func TestGetMultipleRemove(t *testing.T) {
   164  	x := New()
   165  	x.AddNodes(StringNode("abcdefg"))
   166  	x.AddNodes(StringNode("hijklmn"))
   167  	x.AddNodes(StringNode("opqrstu"))
   168  	for i, v := range rtestsBefore {
   169  		result, has := x.Get(v.in)
   170  		if !has {
   171  			t.Fatal()
   172  		}
   173  		if result.String() != v.out {
   174  			t.Errorf("%d. got %q, expected %q before rm", i, result, v.out)
   175  		}
   176  	}
   177  	x.RemoveNodes(StringNode("hijklmn"))
   178  	for i, v := range rtestsAfter {
   179  		result, has := x.Get(v.in)
   180  		if !has {
   181  			t.Fatal()
   182  		}
   183  		if result.String() != v.out {
   184  			t.Errorf("%d. got %q, expected %q after rm", i, result, v.out)
   185  		}
   186  	}
   187  }
   188  
   189  func TestGetMultipleRemoveQuick(t *testing.T) {
   190  	x := New()
   191  	x.AddNodes(StringNode("abcdefg"))
   192  	x.AddNodes(StringNode("hijklmn"))
   193  	x.AddNodes(StringNode("opqrstu"))
   194  	x.RemoveNodes(StringNode("opqrstu"))
   195  	f := func(s string) bool {
   196  		y, has := x.Get(s)
   197  		if !has {
   198  			t.Logf("missing node")
   199  			return false
   200  		}
   201  		//t.Logf("s = %q, y = %q", s, y)
   202  		return y.String() == "abcdefg" || y.String() == "hijklmn"
   203  	}
   204  	if err := quick.Check(f, nil); err != nil {
   205  		t.Logf("missing nodes")
   206  	}
   207  }
   208  
   209  func TestGetTwo(t *testing.T) {
   210  	x := New()
   211  	x.AddNodes(StringNode("abcdefg"))
   212  	x.AddNodes(StringNode("hijklmn"))
   213  	x.AddNodes(StringNode("opqrstu"))
   214  	a, b, has := x.GetTwo("99999999")
   215  	if !has {
   216  		t.Fatal("missing nodes")
   217  	}
   218  	if a == b {
   219  		t.Errorf("a shouldn't equal b")
   220  	}
   221  	if a.String() != "opqrstu" {
   222  		t.Errorf("wrong a: %q", a)
   223  	}
   224  	if b.String() != "hijklmn" {
   225  		t.Errorf("wrong b: %q", b)
   226  	}
   227  }
   228  
   229  func TestGetTwoQuick(t *testing.T) {
   230  	x := New()
   231  	x.AddNodes(StringNode("abcdefg"))
   232  	x.AddNodes(StringNode("hijklmn"))
   233  	x.AddNodes(StringNode("opqrstu"))
   234  	f := func(s string) bool {
   235  		a, b, has := x.GetTwo(s)
   236  		if !has {
   237  			t.Logf("missing nodes")
   238  			return false
   239  		}
   240  		if a == b {
   241  			t.Logf("a == b")
   242  			return false
   243  		}
   244  		if a.String() != "abcdefg" &&
   245  			a.String() != "hijklmn" &&
   246  			a.String() != "opqrstu" {
   247  			t.Logf("invalid a: %q", a)
   248  			return false
   249  		}
   250  
   251  		if b.String() != "abcdefg" &&
   252  			b.String() != "hijklmn" &&
   253  			b.String() != "opqrstu" {
   254  			t.Logf("invalid b: %q", b)
   255  			return false
   256  		}
   257  		return true
   258  	}
   259  	if err := quick.Check(f, nil); err != nil {
   260  		t.Logf("missing nodes")
   261  	}
   262  }
   263  
   264  func TestGetTwoOnlyTwoQuick(t *testing.T) {
   265  	x := New()
   266  	x.AddNodes(StringNode("abcdefg"))
   267  	x.AddNodes(StringNode("hijklmn"))
   268  	f := func(s string) bool {
   269  		a, b, has := x.GetTwo(s)
   270  		if !has {
   271  			t.Logf("missing nodes")
   272  			return false
   273  		}
   274  		if a == b {
   275  			t.Logf("a == b")
   276  			return false
   277  		}
   278  		if a.String() != "abcdefg" && a.String() != "hijklmn" {
   279  			t.Logf("invalid a: %q", a)
   280  			return false
   281  		}
   282  
   283  		if b.String() != "abcdefg" && b.String() != "hijklmn" {
   284  			t.Logf("invalid b: %q", b)
   285  			return false
   286  		}
   287  		return true
   288  	}
   289  	if err := quick.Check(f, nil); err != nil {
   290  		t.Logf("missing nodes")
   291  	}
   292  }
   293  
   294  func TestGetTwoOnlyOneInCircle(t *testing.T) {
   295  	x := New()
   296  
   297  	x.AddNodes(StringNode("abcdefg"))
   298  	a, b, has := x.GetTwo("99999999")
   299  	if !has {
   300  		t.Logf("missing nodes")
   301  	}
   302  	if a == b {
   303  		t.Errorf("a shouldn't equal b")
   304  	}
   305  	if a.String() != "abcdefg" {
   306  		t.Errorf("wrong a: %q", a)
   307  	}
   308  	if b != nil {
   309  		t.Errorf("wrong b: %q", b)
   310  	}
   311  }
   312  
   313  func TestGetN(t *testing.T) {
   314  	x := New()
   315  	x.AddNodes(StringNode("abcdefg"))
   316  	x.AddNodes(StringNode("hijklmn"))
   317  	x.AddNodes(StringNode("opqrstu"))
   318  	members, has := x.GetN("9999999", 3)
   319  	if !has {
   320  		t.Logf("missing nodes")
   321  	}
   322  	if len(members) != 3 {
   323  		t.Errorf("expected 3 allNodes instead of %d", len(members))
   324  	}
   325  	if members[0].String() != "abcdefg" {
   326  		t.Errorf("wrong allNodes[0]: %q", members[0])
   327  	}
   328  	if members[1].String() != "opqrstu" {
   329  		t.Errorf("wrong allNodes[1]: %q", members[1])
   330  	}
   331  	if members[2].String() != "hijklmn" {
   332  		t.Errorf("wrong allNodes[2]: %q", members[2])
   333  	}
   334  }
   335  
   336  func TestGetNLess(t *testing.T) {
   337  	x := New()
   338  	x.AddNodes(StringNode("abcdefg"))
   339  	x.AddNodes(StringNode("hijklmn"))
   340  	x.AddNodes(StringNode("opqrstu"))
   341  	members, has := x.GetN("99999999", 2)
   342  	if !has {
   343  		t.Logf("missing nodes")
   344  	}
   345  	if len(members) != 2 {
   346  		t.Errorf("expected 2 allNodes instead of %d", len(members))
   347  	}
   348  	if members[0].String() != "opqrstu" {
   349  		t.Errorf("wrong allNodes[0]: %q", members[0])
   350  	}
   351  	if members[1].String() != "hijklmn" {
   352  		t.Errorf("wrong allNodes[1]: %q", members[1])
   353  	}
   354  }
   355  
   356  func TestGetNMore(t *testing.T) {
   357  	x := New()
   358  	x.AddNodes(StringNode("abcdefg"))
   359  	x.AddNodes(StringNode("hijklmn"))
   360  	x.AddNodes(StringNode("opqrstu"))
   361  	members, has := x.GetN("9999999", 5)
   362  	if !has {
   363  		t.Logf("missing nodes")
   364  	}
   365  	if len(members) != 3 {
   366  		t.Errorf("expected 3 allNodes instead of %d", len(members))
   367  	}
   368  	if members[0].String() != "abcdefg" {
   369  		t.Errorf("wrong allNodes[0]: %q", members[0])
   370  	}
   371  	if members[1].String() != "opqrstu" {
   372  		t.Errorf("wrong allNodes[1]: %q", members[1])
   373  	}
   374  	if members[2].String() != "hijklmn" {
   375  		t.Errorf("wrong allNodes[2]: %q", members[2])
   376  	}
   377  }
   378  
   379  func TestGetNQuick(t *testing.T) {
   380  	x := New()
   381  	x.AddNodes(StringNode("abcdefg"))
   382  	x.AddNodes(StringNode("hijklmn"))
   383  	x.AddNodes(StringNode("opqrstu"))
   384  	f := func(s string) bool {
   385  		members, has := x.GetN(s, 3)
   386  		if !has {
   387  			t.Logf("missing nodes")
   388  			return false
   389  		}
   390  		if len(members) != 3 {
   391  			t.Logf("expected 3 allNodes instead of %d", len(members))
   392  			return false
   393  		}
   394  		set := make(map[string]bool, 4)
   395  		for _, member := range members {
   396  			if set[member.String()] {
   397  				t.Logf("duplicate error")
   398  				return false
   399  			}
   400  			set[member.String()] = true
   401  			if member.String() != "abcdefg" &&
   402  				member.String() != "hijklmn" &&
   403  				member.String() != "opqrstu" {
   404  				t.Logf("invalid member: %q", member)
   405  				return false
   406  			}
   407  		}
   408  		return true
   409  	}
   410  	if err := quick.Check(f, nil); err != nil {
   411  		t.Logf("missing nodes")
   412  	}
   413  }
   414  
   415  func TestGetNLessQuick(t *testing.T) {
   416  	x := New()
   417  	x.AddNodes(StringNode("abcdefg"))
   418  	x.AddNodes(StringNode("hijklmn"))
   419  	x.AddNodes(StringNode("opqrstu"))
   420  	f := func(s string) bool {
   421  		members, has := x.GetN(s, 2)
   422  		if !has {
   423  			t.Logf("missing nodes")
   424  			return false
   425  		}
   426  		if len(members) != 2 {
   427  			t.Logf("expected 2 allNodes instead of %d", len(members))
   428  			return false
   429  		}
   430  		set := make(map[string]bool, 4)
   431  		for _, member := range members {
   432  			if set[member.String()] {
   433  				t.Logf("duplicate error")
   434  				return false
   435  			}
   436  			set[member.String()] = true
   437  			if member.String() != "abcdefg" &&
   438  				member.String() != "hijklmn" &&
   439  				member.String() != "opqrstu" {
   440  				t.Logf("invalid member: %q", member)
   441  				return false
   442  			}
   443  		}
   444  		return true
   445  	}
   446  	if err := quick.Check(f, nil); err != nil {
   447  		t.Logf("missing nodes")
   448  	}
   449  }
   450  
   451  func TestGetNMoreQuick(t *testing.T) {
   452  	x := New()
   453  	x.AddNodes(StringNode("abcdefg"))
   454  	x.AddNodes(StringNode("hijklmn"))
   455  	x.AddNodes(StringNode("opqrstu"))
   456  	f := func(s string) bool {
   457  		// t.Log("check", s)
   458  		members, has := x.GetN(s, 5)
   459  		if !has {
   460  			t.Logf("missing nodes")
   461  			return false
   462  		}
   463  		if len(members) != 3 {
   464  			t.Logf("expected 3 allNodes instead of %d", len(members))
   465  			return false
   466  		}
   467  		set := make(map[string]bool, 4)
   468  		for _, member := range members {
   469  			if set[member.String()] {
   470  				t.Logf("duplicate error")
   471  				return false
   472  			}
   473  			set[member.String()] = true
   474  			if member.String() != "abcdefg" && member.String() != "hijklmn" && member.String() != "opqrstu" {
   475  				t.Logf("invalid member: %q", member)
   476  				return false
   477  			}
   478  		}
   479  		return true
   480  	}
   481  	if err := quick.Check(f, nil); err != nil {
   482  		t.Logf("missing nodes")
   483  	}
   484  }
   485  
   486  func TestSet(t *testing.T) {
   487  	x := New()
   488  	x.AddNodes(StringNode("abc"))
   489  	x.AddNodes(StringNode("def"))
   490  	x.AddNodes(StringNode("ghi"))
   491  	x.SetNodes(StringNode("jkl"), StringNode("mno"))
   492  	if len(x.allNodes) != 2 {
   493  		t.Errorf("expected 2 elts, got %d", len(x.allNodes))
   494  	}
   495  	a, b, has := x.GetTwo("qwerqwerwqer")
   496  	if !has {
   497  		t.Fatal()
   498  	}
   499  	if a.String() != "jkl" && a.String() != "mno" {
   500  		t.Errorf("expected jkl or mno, got %s", a)
   501  	}
   502  	if b.String() != "jkl" && b.String() != "mno" {
   503  		t.Errorf("expected jkl or mno, got %s", b)
   504  	}
   505  	if a == b {
   506  		t.Errorf("expected a != b, they were both %s", a)
   507  	}
   508  	x.SetNodes(StringNode("jkl"), StringNode("mno"))
   509  	if len(x.allNodes) != 2 {
   510  		t.Errorf("expected 2 elts, got %d", len(x.allNodes))
   511  	}
   512  	a, b, has = x.GetTwo("qwerqwerwqer")
   513  	if !has {
   514  		t.Fatal()
   515  	}
   516  	if a.String() != "jkl" && a.String() != "mno" {
   517  		t.Errorf("expected jkl or mno, got %s", a)
   518  	}
   519  	if b.String() != "jkl" && b.String() != "mno" {
   520  		t.Errorf("expected jkl or mno, got %s", b)
   521  	}
   522  	if a == b {
   523  		t.Errorf("expected a != b, they were both %s", a)
   524  	}
   525  	x.SetNodes(StringNode("pqr"), StringNode("mno"))
   526  	if len(x.allNodes) != 2 {
   527  		t.Errorf("expected 2 elts, got %d", len(x.allNodes))
   528  	}
   529  	a, b, has = x.GetTwo("qwerqwerwqer")
   530  	if !has {
   531  		t.Fatal()
   532  	}
   533  	if a.String() != "pqr" && a.String() != "mno" {
   534  		t.Errorf("expected jkl or mno, got %s", a)
   535  	}
   536  	if b.String() != "pqr" && b.String() != "mno" {
   537  		t.Errorf("expected jkl or mno, got %s", b)
   538  	}
   539  	if a == b {
   540  		t.Errorf("expected a != b, they were both %s", a)
   541  	}
   542  }
   543  
   544  // allocBytes returns the number of bytes allocated by invoking f.
   545  func allocBytes(f func()) uint64 {
   546  	var stats runtime.MemStats
   547  	runtime.ReadMemStats(&stats)
   548  	t := stats.TotalAlloc
   549  	f()
   550  	runtime.ReadMemStats(&stats)
   551  	return stats.TotalAlloc - t
   552  }
   553  
   554  func mallocNum(f func()) uint64 {
   555  	var stats runtime.MemStats
   556  	runtime.ReadMemStats(&stats)
   557  	t := stats.Mallocs
   558  	f()
   559  	runtime.ReadMemStats(&stats)
   560  	return stats.Mallocs - t
   561  }
   562  
   563  func BenchmarkAllocations(b *testing.B) {
   564  	x := New()
   565  	x.AddNodes(StringNode("stays"))
   566  	b.ResetTimer()
   567  	allocSize := allocBytes(func() {
   568  		for i := 0; i < b.N; i++ {
   569  			x.AddNodes(StringNode("Foo"))
   570  			x.RemoveNodes(StringNode("Foo"))
   571  		}
   572  	})
   573  	b.Logf("%d: Allocated %d bytes (%.2fx)", b.N, allocSize, float64(allocSize)/float64(b.N))
   574  }
   575  
   576  func BenchmarkMalloc(b *testing.B) {
   577  	x := New()
   578  	x.AddNodes(StringNode("stays"))
   579  	b.ResetTimer()
   580  	mallocs := mallocNum(func() {
   581  		for i := 0; i < b.N; i++ {
   582  			x.AddNodes(StringNode("Foo"))
   583  			x.RemoveNodes(StringNode("Foo"))
   584  		}
   585  	})
   586  	b.Logf("%d: Mallocd %d times (%.2fx)", b.N, mallocs, float64(mallocs)/float64(b.N))
   587  }
   588  
   589  func BenchmarkCycle(b *testing.B) {
   590  	x := New()
   591  	x.AddNodes(StringNode("nothing"))
   592  	b.ResetTimer()
   593  	for i := 0; i < b.N; i++ {
   594  		x.AddNodes(StringNode("foo" + strconv.Itoa(i)))
   595  		x.RemoveNodes(StringNode("foo" + strconv.Itoa(i)))
   596  	}
   597  }
   598  
   599  func BenchmarkCycleLarge(b *testing.B) {
   600  	x := New()
   601  	for i := 0; i < 10; i++ {
   602  		x.AddNodes(StringNode("start" + strconv.Itoa(i)))
   603  	}
   604  	b.ResetTimer()
   605  	for i := 0; i < b.N; i++ {
   606  		x.AddNodes(StringNode("foo" + strconv.Itoa(i)))
   607  		x.RemoveNodes(StringNode("foo" + strconv.Itoa(i)))
   608  	}
   609  }
   610  
   611  func BenchmarkGet(b *testing.B) {
   612  	x := New()
   613  	x.AddNodes(StringNode("nothing"))
   614  	b.ResetTimer()
   615  	for i := 0; i < b.N; i++ {
   616  		x.Get("nothing")
   617  	}
   618  }
   619  
   620  func BenchmarkGetLarge(b *testing.B) {
   621  	x := New()
   622  	for i := 0; i < 10; i++ {
   623  		x.AddNodes(StringNode("start" + strconv.Itoa(i)))
   624  	}
   625  	b.ResetTimer()
   626  	for i := 0; i < b.N; i++ {
   627  		x.Get("nothing")
   628  	}
   629  }
   630  
   631  func BenchmarkGetN(b *testing.B) {
   632  	x := New()
   633  	x.AddNodes(StringNode("nothing"))
   634  	b.ResetTimer()
   635  	for i := 0; i < b.N; i++ {
   636  		x.GetN("nothing", 3)
   637  	}
   638  }
   639  
   640  func BenchmarkGetNLarge(b *testing.B) {
   641  	x := New()
   642  	for i := 0; i < 10; i++ {
   643  		x.AddNodes(StringNode("start" + strconv.Itoa(i)))
   644  	}
   645  	b.ResetTimer()
   646  	for i := 0; i < b.N; i++ {
   647  		x.GetN("nothing", 3)
   648  	}
   649  }
   650  
   651  func BenchmarkGetTwo(b *testing.B) {
   652  	x := New()
   653  	x.AddNodes(StringNode("nothing"))
   654  	b.ResetTimer()
   655  	for i := 0; i < b.N; i++ {
   656  		x.GetTwo("nothing")
   657  	}
   658  }
   659  
   660  func BenchmarkGetTwoLarge(b *testing.B) {
   661  	x := New()
   662  	for i := 0; i < 10; i++ {
   663  		x.AddNodes(StringNode("start" + strconv.Itoa(i)))
   664  	}
   665  	b.ResetTimer()
   666  	for i := 0; i < b.N; i++ {
   667  		x.GetTwo("nothing")
   668  	}
   669  }
   670  
   671  // from @edsrzf on github:
   672  func TestAddCollision(t *testing.T) {
   673  	// These two strings produce several crc32 collisions after "|i" is
   674  	// appended added by NodeLocator.virtualNode.
   675  	const s1 = "abear"
   676  	const s2 = "solidiform"
   677  	x := New()
   678  	x.AddNodes(StringNode(s1))
   679  	x.AddNodes(StringNode(s2))
   680  	elt1, has := x.Get("abear")
   681  	if !has {
   682  		t.Fatal("missing node")
   683  	}
   684  
   685  	y := New()
   686  	// add elements in opposite order
   687  	y.AddNodes(StringNode(s2))
   688  	y.AddNodes(StringNode(s1))
   689  	elt2, has := y.Get(s1)
   690  	if !has {
   691  		t.Fatal("missing node")
   692  	}
   693  
   694  	if elt1 != elt2 {
   695  		t.Error(elt1, "and", elt2, "should be equal")
   696  	}
   697  }