github.com/sunvim/utils@v0.1.0/patricia/patricia_test.go (about)

     1  // Copyright (c) 2014 The go-patricia AUTHORS
     2  //
     3  // Use of this source code is governed by The MIT License
     4  // that can be found in the LICENSE file.
     5  
     6  package patricia
     7  
     8  import (
     9  	"crypto/rand"
    10  	"reflect"
    11  	"testing"
    12  )
    13  
    14  // Tests -----------------------------------------------------------------------
    15  
    16  func TestTrie_ConstructorOptions(t *testing.T) {
    17  	trie := NewTrie(MaxPrefixPerNode(16), MaxChildrenPerSparseNode(10))
    18  
    19  	if trie.maxPrefixPerNode != 16 {
    20  		t.Errorf("Unexpected trie.maxPrefixPerNode value, expected=%v, got=%v",
    21  			16, trie.maxPrefixPerNode)
    22  	}
    23  
    24  	if trie.maxChildrenPerSparseNode != 10 {
    25  		t.Errorf("Unexpected trie.maxChildrenPerSparseNode value, expected=%v, got=%v",
    26  			10, trie.maxChildrenPerSparseNode)
    27  	}
    28  }
    29  
    30  func TestTrie_GetNonexistentPrefix(t *testing.T) {
    31  	trie := NewTrie()
    32  
    33  	data := []testData{
    34  		{"aba", 0, success},
    35  	}
    36  
    37  	for _, v := range data {
    38  		t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
    39  		if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal {
    40  			t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
    41  		}
    42  	}
    43  
    44  	t.Logf("GET prefix=baa, expect item=nil")
    45  	if item := trie.Get(Prefix("baa")); item != nil {
    46  		t.Errorf("Unexpected return value, expected=<nil>, got=%v", item)
    47  	}
    48  }
    49  
    50  func TestTrie_RandomKitchenSink(t *testing.T) {
    51  	if testing.Short() {
    52  		t.Skip()
    53  	}
    54  	const count, size = 750000, 16
    55  	b := make([]byte, count+size+1)
    56  	if _, err := rand.Read(b); err != nil {
    57  		t.Fatal("error generating random bytes", err)
    58  	}
    59  	m := make(map[string]string)
    60  	for i := 0; i < count; i++ {
    61  		m[string(b[i:i+size])] = string(b[i+1 : i+size+1])
    62  	}
    63  	trie := NewTrie()
    64  	getAndDelete := func(k, v string) {
    65  		i := trie.Get(Prefix(k))
    66  		if i == nil {
    67  			t.Fatalf("item not found, prefix=%v", []byte(k))
    68  		} else if s, ok := i.(string); !ok {
    69  			t.Fatalf("unexpected item type, expecting=%v, got=%v", reflect.TypeOf(k), reflect.TypeOf(i))
    70  		} else if s != v {
    71  			t.Fatalf("unexpected item, expecting=%v, got=%v", []byte(k), []byte(s))
    72  		} else if !trie.Delete(Prefix(k)) {
    73  			t.Fatalf("delete failed, prefix=%v", []byte(k))
    74  		} else if i = trie.Get(Prefix(k)); i != nil {
    75  			t.Fatalf("unexpected item, expecting=<nil>, got=%v", i)
    76  		} else if trie.Delete(Prefix(k)) {
    77  			t.Fatalf("extra delete succeeded, prefix=%v", []byte(k))
    78  		}
    79  	}
    80  	for k, v := range m {
    81  		if !trie.Insert(Prefix(k), v) {
    82  			t.Fatalf("insert failed, prefix=%v", []byte(k))
    83  		}
    84  		if byte(k[size/2]) < 128 {
    85  			getAndDelete(k, v)
    86  			delete(m, k)
    87  		}
    88  	}
    89  	for k, v := range m {
    90  		getAndDelete(k, v)
    91  	}
    92  }
    93  
    94  // Make sure Delete that affects the root node works.
    95  // This was panicking when Delete was broken.
    96  func TestTrie_DeleteRoot(t *testing.T) {
    97  	trie := NewTrie()
    98  
    99  	v := testData{"aba", 0, success}
   100  
   101  	t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
   102  	if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal {
   103  		t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   104  	}
   105  
   106  	t.Logf("DELETE prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
   107  	if ok := trie.Delete(Prefix(v.key)); ok != v.retVal {
   108  		t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   109  	}
   110  }
   111  
   112  func TestTrie_DeleteAbsentPrefix(t *testing.T) {
   113  	trie := NewTrie()
   114  
   115  	v := testData{"a", 0, success}
   116  
   117  	t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
   118  	if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal {
   119  		t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok)
   120  	}
   121  
   122  	d := "ab"
   123  	t.Logf("DELETE prefix=%v, success=%v", d, failure)
   124  	if ok := trie.Delete(Prefix(d)); ok != failure {
   125  		t.Errorf("Unexpected return value, expected=%v, got=%v", failure, ok)
   126  	}
   127  	t.Logf("GET prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal)
   128  	if i := trie.Get(Prefix(v.key)); i != v.value {
   129  		t.Errorf("Unexpected item, expected=%v, got=%v", v.value, i)
   130  	}
   131  }