github.com/sunvim/utils@v0.1.0/patricia/patricia_dense_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 "math/rand" 10 "runtime" 11 "strconv" 12 "testing" 13 ) 14 15 // Tests ----------------------------------------------------------------------- 16 17 // overhead is allowed tolerance for Go's runtime/GC to increase the allocated memory 18 // (to avoid failing tests on insignificant growth amounts) 19 const overhead = 4000 20 21 func TestTrie_InsertDense(t *testing.T) { 22 trie := NewTrie() 23 24 data := []testData{ 25 {"aba", 0, success}, 26 {"abb", 1, success}, 27 {"abc", 2, success}, 28 {"abd", 3, success}, 29 {"abe", 4, success}, 30 {"abf", 5, success}, 31 {"abg", 6, success}, 32 {"abh", 7, success}, 33 {"abi", 8, success}, 34 {"abj", 9, success}, 35 {"abk", 0, success}, 36 {"abl", 1, success}, 37 {"abm", 2, success}, 38 {"abn", 3, success}, 39 {"abo", 4, success}, 40 {"abp", 5, success}, 41 {"abq", 6, success}, 42 {"abr", 7, success}, 43 {"abs", 8, success}, 44 {"abt", 9, success}, 45 {"abu", 0, success}, 46 {"abv", 1, success}, 47 {"abw", 2, success}, 48 {"abx", 3, success}, 49 {"aby", 4, success}, 50 {"abz", 5, success}, 51 } 52 53 for _, v := range data { 54 t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal) 55 if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal { 56 t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok) 57 } 58 } 59 } 60 61 func TestTrie_InsertDensePreceeding(t *testing.T) { 62 trie := NewTrie() 63 start := byte(70) 64 // create a dense node 65 for i := byte(0); i <= DefaultMaxChildrenPerSparseNode; i++ { 66 if !trie.Insert(Prefix([]byte{start + i}), true) { 67 t.Errorf("insert failed, prefix=%v", start+i) 68 } 69 } 70 // insert some preceding keys 71 for i := byte(1); i < start; i *= i + 1 { 72 if !trie.Insert(Prefix([]byte{start - i}), true) { 73 t.Errorf("insert failed, prefix=%v", start-i) 74 } 75 } 76 } 77 78 func TestTrie_InsertDenseDuplicatePrefixes(t *testing.T) { 79 trie := NewTrie() 80 81 data := []testData{ 82 {"aba", 0, success}, 83 {"abb", 1, success}, 84 {"abc", 2, success}, 85 {"abd", 3, success}, 86 {"abe", 4, success}, 87 {"abf", 5, success}, 88 {"abg", 6, success}, 89 {"abh", 7, success}, 90 {"abi", 8, success}, 91 {"abj", 9, success}, 92 {"abk", 0, success}, 93 {"abl", 1, success}, 94 {"abm", 2, success}, 95 {"abn", 3, success}, 96 {"abo", 4, success}, 97 {"abp", 5, success}, 98 {"abq", 6, success}, 99 {"abr", 7, success}, 100 {"abs", 8, success}, 101 {"abt", 9, success}, 102 {"abu", 0, success}, 103 {"abv", 1, success}, 104 {"abw", 2, success}, 105 {"abx", 3, success}, 106 {"aby", 4, success}, 107 {"abz", 5, success}, 108 {"aba", 0, failure}, 109 {"abb", 1, failure}, 110 {"abc", 2, failure}, 111 {"abd", 3, failure}, 112 {"abe", 4, failure}, 113 } 114 115 for _, v := range data { 116 t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal) 117 if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal { 118 t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok) 119 } 120 } 121 } 122 123 func TestTrie_CloneDense(t *testing.T) { 124 trie := NewTrie() 125 126 data := []testData{ 127 {"aba", 0, success}, 128 {"abb", 1, success}, 129 {"abc", 2, success}, 130 {"abd", 3, success}, 131 {"abe", 4, success}, 132 {"abf", 5, success}, 133 {"abg", 6, success}, 134 {"abh", 7, success}, 135 {"abi", 8, success}, 136 {"abj", 9, success}, 137 {"abk", 0, success}, 138 {"abl", 1, success}, 139 {"abm", 2, success}, 140 {"abn", 3, success}, 141 {"abo", 4, success}, 142 {"abp", 5, success}, 143 {"abq", 6, success}, 144 {"abr", 7, success}, 145 {"abs", 8, success}, 146 {"abt", 9, success}, 147 {"abu", 0, success}, 148 {"abv", 1, success}, 149 {"abw", 2, success}, 150 {"abx", 3, success}, 151 {"aby", 4, success}, 152 {"abz", 5, success}, 153 } 154 155 for _, v := range data { 156 t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal) 157 if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal { 158 t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok) 159 } 160 } 161 162 t.Log("CLONE") 163 clone := trie.Clone() 164 165 for _, v := range data { 166 t.Logf("GET prefix=%v, item=%v", v.key, v.value) 167 if item := clone.Get(Prefix(v.key)); item != v.value { 168 t.Errorf("Unexpected return value, expected=%v, got=%v", v.value, item) 169 } 170 } 171 172 prefix := "xxx" 173 item := 666 174 t.Logf("INSERT prefix=%v, item=%v", prefix, item) 175 if ok := trie.Insert(Prefix(prefix), item); !ok { 176 t.Errorf("Unexpected return value, expected=true, got=%v", ok) 177 } 178 t.Logf("GET cloned prefix=%v", prefix) 179 if item := clone.Get(Prefix(prefix)); item != nil { 180 t.Errorf("Unexpected return value, expected=nil, got=%v", item) 181 } 182 } 183 184 func TestTrie_DeleteDense(t *testing.T) { 185 trie := NewTrie() 186 187 data := []testData{ 188 {"aba", 0, success}, 189 {"abb", 1, success}, 190 {"abc", 2, success}, 191 {"abd", 3, success}, 192 {"abe", 4, success}, 193 {"abf", 5, success}, 194 {"abg", 6, success}, 195 {"abh", 7, success}, 196 {"abi", 8, success}, 197 {"abj", 9, success}, 198 {"abk", 0, success}, 199 {"abl", 1, success}, 200 {"abm", 2, success}, 201 {"abn", 3, success}, 202 {"abo", 4, success}, 203 {"abp", 5, success}, 204 {"abq", 6, success}, 205 {"abr", 7, success}, 206 {"abs", 8, success}, 207 {"abt", 9, success}, 208 {"abu", 0, success}, 209 {"abv", 1, success}, 210 {"abw", 2, success}, 211 {"abx", 3, success}, 212 {"aby", 4, success}, 213 {"abz", 5, success}, 214 } 215 216 for _, v := range data { 217 t.Logf("INSERT prefix=%v, item=%v, success=%v", v.key, v.value, v.retVal) 218 if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal { 219 t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok) 220 } 221 } 222 223 for _, v := range data { 224 t.Logf("DELETE word=%v, success=%v", v.key, v.retVal) 225 if ok := trie.Delete([]byte(v.key)); ok != v.retVal { 226 t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok) 227 } 228 } 229 } 230 231 func TestTrie_DeleteLeakageDense(t *testing.T) { 232 trie := NewTrie() 233 234 genTestData := func() *testData { 235 // Generate a random integer as a key. 236 key := strconv.FormatUint(rand.Uint64(), 10) 237 return &testData{key: key, value: "v", retVal: success} 238 } 239 240 testSize := 100 241 data := make([]*testData, 0, testSize) 242 for i := 0; i < testSize; i++ { 243 data = append(data, genTestData()) 244 } 245 246 oldBytes := heapAllocatedBytes() 247 248 // repeat insertion/deletion for 10K times to catch possible memory issues 249 for i := 0; i < 10000; i++ { 250 for _, v := range data { 251 if ok := trie.Insert(Prefix(v.key), v.value); ok != v.retVal { 252 t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok) 253 } 254 } 255 256 for _, v := range data { 257 if ok := trie.Delete([]byte(v.key)); ok != v.retVal { 258 t.Errorf("Unexpected return value, expected=%v, got=%v", v.retVal, ok) 259 } 260 } 261 } 262 263 if newBytes := heapAllocatedBytes(); newBytes > oldBytes+overhead { 264 t.Logf("Size=%d, Total=%d, Trie state:\n%s\n", trie.size(), trie.total(), trie.dump()) 265 t.Errorf("Heap space leak, grew %d bytes (%d to %d)\n", newBytes-oldBytes, oldBytes, newBytes) 266 } 267 268 if numChildren := trie.children.length(); numChildren != 0 { 269 t.Errorf("Trie is not empty: %v children found", numChildren) 270 } 271 } 272 273 func heapAllocatedBytes() uint64 { 274 runtime.GC() 275 276 ms := runtime.MemStats{} 277 runtime.ReadMemStats(&ms) 278 return ms.Alloc 279 }