github.com/dashpay/godash@v0.0.0-20160726055534-e038a21e0e3d/database/internal/treap/mutable_test.go (about) 1 // Copyright (c) 2015-2016 The btcsuite developers 2 // Copyright (c) 2016 The Dash developers 3 // Use of this source code is governed by an ISC 4 // license that can be found in the LICENSE file. 5 6 package treap 7 8 import ( 9 "bytes" 10 "crypto/sha256" 11 "testing" 12 ) 13 14 // TestMutableEmpty ensures calling functions on an empty mutable treap works as 15 // expected. 16 func TestMutableEmpty(t *testing.T) { 17 t.Parallel() 18 19 // Ensure the treap length is the expected value. 20 testTreap := NewMutable() 21 if gotLen := testTreap.Len(); gotLen != 0 { 22 t.Fatalf("Len: unexpected length - got %d, want %d", gotLen, 0) 23 } 24 25 // Ensure the reported size is 0. 26 if gotSize := testTreap.Size(); gotSize != 0 { 27 t.Fatalf("Size: unexpected byte size - got %d, want 0", 28 gotSize) 29 } 30 31 // Ensure there are no errors with requesting keys from an empty treap. 32 key := serializeUint32(0) 33 if gotVal := testTreap.Has(key); gotVal != false { 34 t.Fatalf("Has: unexpected result - got %v, want false", gotVal) 35 } 36 if gotVal := testTreap.Get(key); gotVal != nil { 37 t.Fatalf("Get: unexpected result - got %x, want nil", gotVal) 38 } 39 40 // Ensure there are no panics when deleting keys from an empty treap. 41 testTreap.Delete(key) 42 43 // Ensure the number of keys iterated by ForEach on an empty treap is 44 // zero. 45 var numIterated int 46 testTreap.ForEach(func(k, v []byte) bool { 47 numIterated++ 48 return true 49 }) 50 if numIterated != 0 { 51 t.Fatalf("ForEach: unexpected iterate count - got %d, want 0", 52 numIterated) 53 } 54 } 55 56 // TestMutableReset ensures that resetting an existing mutable treap works as 57 // expected. 58 func TestMutableReset(t *testing.T) { 59 t.Parallel() 60 61 // Insert a few keys. 62 numItems := 10 63 testTreap := NewMutable() 64 for i := 0; i < numItems; i++ { 65 key := serializeUint32(uint32(i)) 66 testTreap.Put(key, key) 67 } 68 69 // Reset it. 70 testTreap.Reset() 71 72 // Ensure the treap length is now 0. 73 if gotLen := testTreap.Len(); gotLen != 0 { 74 t.Fatalf("Len: unexpected length - got %d, want %d", gotLen, 0) 75 } 76 77 // Ensure the reported size is now 0. 78 if gotSize := testTreap.Size(); gotSize != 0 { 79 t.Fatalf("Size: unexpected byte size - got %d, want 0", 80 gotSize) 81 } 82 83 // Ensure the treap no longer has any of the keys. 84 for i := 0; i < numItems; i++ { 85 key := serializeUint32(uint32(i)) 86 87 // Ensure the treap no longer has the key. 88 if testTreap.Has(key) { 89 t.Fatalf("Has #%d: key %q is in treap", i, key) 90 } 91 92 // Get the key that no longer exists from the treap and ensure 93 // it is nil. 94 if gotVal := testTreap.Get(key); gotVal != nil { 95 t.Fatalf("Get #%d: unexpected value - got %x, want nil", 96 i, gotVal) 97 } 98 } 99 100 // Ensure the number of keys iterated by ForEach is zero. 101 var numIterated int 102 testTreap.ForEach(func(k, v []byte) bool { 103 numIterated++ 104 return true 105 }) 106 if numIterated != 0 { 107 t.Fatalf("ForEach: unexpected iterate count - got %d, want 0", 108 numIterated) 109 } 110 } 111 112 // TestMutableSequential ensures that putting keys into a mutable treap in 113 // sequential order works as expected. 114 func TestMutableSequential(t *testing.T) { 115 t.Parallel() 116 117 // Insert a bunch of sequential keys while checking several of the treap 118 // functions work as expected. 119 expectedSize := uint64(0) 120 numItems := 1000 121 testTreap := NewMutable() 122 for i := 0; i < numItems; i++ { 123 key := serializeUint32(uint32(i)) 124 testTreap.Put(key, key) 125 126 // Ensure the treap length is the expected value. 127 if gotLen := testTreap.Len(); gotLen != i+1 { 128 t.Fatalf("Len #%d: unexpected length - got %d, want %d", 129 i, gotLen, i+1) 130 } 131 132 // Ensure the treap has the key. 133 if !testTreap.Has(key) { 134 t.Fatalf("Has #%d: key %q is not in treap", i, key) 135 } 136 137 // Get the key from the treap and ensure it is the expected 138 // value. 139 if gotVal := testTreap.Get(key); !bytes.Equal(gotVal, key) { 140 t.Fatalf("Get #%d: unexpected value - got %x, want %x", 141 i, gotVal, key) 142 } 143 144 // Ensure the expected size is reported. 145 expectedSize += (nodeFieldsSize + 8) 146 if gotSize := testTreap.Size(); gotSize != expectedSize { 147 t.Fatalf("Size #%d: unexpected byte size - got %d, "+ 148 "want %d", i, gotSize, expectedSize) 149 } 150 } 151 152 // Ensure the all keys are iterated by ForEach in order. 153 var numIterated int 154 testTreap.ForEach(func(k, v []byte) bool { 155 wantKey := serializeUint32(uint32(numIterated)) 156 157 // Ensure the key is as expected. 158 if !bytes.Equal(k, wantKey) { 159 t.Fatalf("ForEach #%d: unexpected key - got %x, want %x", 160 numIterated, k, wantKey) 161 } 162 163 // Ensure the value is as expected. 164 if !bytes.Equal(v, wantKey) { 165 t.Fatalf("ForEach #%d: unexpected value - got %x, want %x", 166 numIterated, v, wantKey) 167 } 168 169 numIterated++ 170 return true 171 }) 172 173 // Ensure all items were iterated. 174 if numIterated != numItems { 175 t.Fatalf("ForEach: unexpected iterate count - got %d, want %d", 176 numIterated, numItems) 177 } 178 179 // Delete the keys one-by-one while checking several of the treap 180 // functions work as expected. 181 for i := 0; i < numItems; i++ { 182 key := serializeUint32(uint32(i)) 183 testTreap.Delete(key) 184 185 // Ensure the treap length is the expected value. 186 if gotLen := testTreap.Len(); gotLen != numItems-i-1 { 187 t.Fatalf("Len #%d: unexpected length - got %d, want %d", 188 i, gotLen, numItems-i-1) 189 } 190 191 // Ensure the treap no longer has the key. 192 if testTreap.Has(key) { 193 t.Fatalf("Has #%d: key %q is in treap", i, key) 194 } 195 196 // Get the key that no longer exists from the treap and ensure 197 // it is nil. 198 if gotVal := testTreap.Get(key); gotVal != nil { 199 t.Fatalf("Get #%d: unexpected value - got %x, want nil", 200 i, gotVal) 201 } 202 203 // Ensure the expected size is reported. 204 expectedSize -= (nodeFieldsSize + 8) 205 if gotSize := testTreap.Size(); gotSize != expectedSize { 206 t.Fatalf("Size #%d: unexpected byte size - got %d, "+ 207 "want %d", i, gotSize, expectedSize) 208 } 209 } 210 } 211 212 // TestMutableReverseSequential ensures that putting keys into a mutable treap 213 // in reverse sequential order works as expected. 214 func TestMutableReverseSequential(t *testing.T) { 215 t.Parallel() 216 217 // Insert a bunch of sequential keys while checking several of the treap 218 // functions work as expected. 219 expectedSize := uint64(0) 220 numItems := 1000 221 testTreap := NewMutable() 222 for i := 0; i < numItems; i++ { 223 key := serializeUint32(uint32(numItems - i - 1)) 224 testTreap.Put(key, key) 225 226 // Ensure the treap length is the expected value. 227 if gotLen := testTreap.Len(); gotLen != i+1 { 228 t.Fatalf("Len #%d: unexpected length - got %d, want %d", 229 i, gotLen, i+1) 230 } 231 232 // Ensure the treap has the key. 233 if !testTreap.Has(key) { 234 t.Fatalf("Has #%d: key %q is not in treap", i, key) 235 } 236 237 // Get the key from the treap and ensure it is the expected 238 // value. 239 if gotVal := testTreap.Get(key); !bytes.Equal(gotVal, key) { 240 t.Fatalf("Get #%d: unexpected value - got %x, want %x", 241 i, gotVal, key) 242 } 243 244 // Ensure the expected size is reported. 245 expectedSize += (nodeFieldsSize + 8) 246 if gotSize := testTreap.Size(); gotSize != expectedSize { 247 t.Fatalf("Size #%d: unexpected byte size - got %d, "+ 248 "want %d", i, gotSize, expectedSize) 249 } 250 } 251 252 // Ensure the all keys are iterated by ForEach in order. 253 var numIterated int 254 testTreap.ForEach(func(k, v []byte) bool { 255 wantKey := serializeUint32(uint32(numIterated)) 256 257 // Ensure the key is as expected. 258 if !bytes.Equal(k, wantKey) { 259 t.Fatalf("ForEach #%d: unexpected key - got %x, want %x", 260 numIterated, k, wantKey) 261 } 262 263 // Ensure the value is as expected. 264 if !bytes.Equal(v, wantKey) { 265 t.Fatalf("ForEach #%d: unexpected value - got %x, want %x", 266 numIterated, v, wantKey) 267 } 268 269 numIterated++ 270 return true 271 }) 272 273 // Ensure all items were iterated. 274 if numIterated != numItems { 275 t.Fatalf("ForEach: unexpected iterate count - got %d, want %d", 276 numIterated, numItems) 277 } 278 279 // Delete the keys one-by-one while checking several of the treap 280 // functions work as expected. 281 for i := 0; i < numItems; i++ { 282 // Intentionally use the reverse order they were inserted here. 283 key := serializeUint32(uint32(i)) 284 testTreap.Delete(key) 285 286 // Ensure the treap length is the expected value. 287 if gotLen := testTreap.Len(); gotLen != numItems-i-1 { 288 t.Fatalf("Len #%d: unexpected length - got %d, want %d", 289 i, gotLen, numItems-i-1) 290 } 291 292 // Ensure the treap no longer has the key. 293 if testTreap.Has(key) { 294 t.Fatalf("Has #%d: key %q is in treap", i, key) 295 } 296 297 // Get the key that no longer exists from the treap and ensure 298 // it is nil. 299 if gotVal := testTreap.Get(key); gotVal != nil { 300 t.Fatalf("Get #%d: unexpected value - got %x, want nil", 301 i, gotVal) 302 } 303 304 // Ensure the expected size is reported. 305 expectedSize -= (nodeFieldsSize + 8) 306 if gotSize := testTreap.Size(); gotSize != expectedSize { 307 t.Fatalf("Size #%d: unexpected byte size - got %d, "+ 308 "want %d", i, gotSize, expectedSize) 309 } 310 } 311 } 312 313 // TestMutableUnordered ensures that putting keys into a mutable treap in no 314 // paritcular order works as expected. 315 func TestMutableUnordered(t *testing.T) { 316 t.Parallel() 317 318 // Insert a bunch of out-of-order keys while checking several of the 319 // treap functions work as expected. 320 expectedSize := uint64(0) 321 numItems := 1000 322 testTreap := NewMutable() 323 for i := 0; i < numItems; i++ { 324 // Hash the serialized int to generate out-of-order keys. 325 hash := sha256.Sum256(serializeUint32(uint32(i))) 326 key := hash[:] 327 testTreap.Put(key, key) 328 329 // Ensure the treap length is the expected value. 330 if gotLen := testTreap.Len(); gotLen != i+1 { 331 t.Fatalf("Len #%d: unexpected length - got %d, want %d", 332 i, gotLen, i+1) 333 } 334 335 // Ensure the treap has the key. 336 if !testTreap.Has(key) { 337 t.Fatalf("Has #%d: key %q is not in treap", i, key) 338 } 339 340 // Get the key from the treap and ensure it is the expected 341 // value. 342 if gotVal := testTreap.Get(key); !bytes.Equal(gotVal, key) { 343 t.Fatalf("Get #%d: unexpected value - got %x, want %x", 344 i, gotVal, key) 345 } 346 347 // Ensure the expected size is reported. 348 expectedSize += nodeFieldsSize + uint64(len(key)+len(key)) 349 if gotSize := testTreap.Size(); gotSize != expectedSize { 350 t.Fatalf("Size #%d: unexpected byte size - got %d, "+ 351 "want %d", i, gotSize, expectedSize) 352 } 353 } 354 355 // Delete the keys one-by-one while checking several of the treap 356 // functions work as expected. 357 for i := 0; i < numItems; i++ { 358 // Hash the serialized int to generate out-of-order keys. 359 hash := sha256.Sum256(serializeUint32(uint32(i))) 360 key := hash[:] 361 testTreap.Delete(key) 362 363 // Ensure the treap length is the expected value. 364 if gotLen := testTreap.Len(); gotLen != numItems-i-1 { 365 t.Fatalf("Len #%d: unexpected length - got %d, want %d", 366 i, gotLen, numItems-i-1) 367 } 368 369 // Ensure the treap no longer has the key. 370 if testTreap.Has(key) { 371 t.Fatalf("Has #%d: key %q is in treap", i, key) 372 } 373 374 // Get the key that no longer exists from the treap and ensure 375 // it is nil. 376 if gotVal := testTreap.Get(key); gotVal != nil { 377 t.Fatalf("Get #%d: unexpected value - got %x, want nil", 378 i, gotVal) 379 } 380 381 // Ensure the expected size is reported. 382 expectedSize -= (nodeFieldsSize + 64) 383 if gotSize := testTreap.Size(); gotSize != expectedSize { 384 t.Fatalf("Size #%d: unexpected byte size - got %d, "+ 385 "want %d", i, gotSize, expectedSize) 386 } 387 } 388 } 389 390 // TestMutableDuplicatePut ensures that putting a duplicate key into a mutable 391 // treap updates the existing value. 392 func TestMutableDuplicatePut(t *testing.T) { 393 t.Parallel() 394 395 key := serializeUint32(0) 396 val := []byte("testval") 397 398 // Put the key twice with the second put being the expected final value. 399 testTreap := NewMutable() 400 testTreap.Put(key, key) 401 testTreap.Put(key, val) 402 403 // Ensure the key still exists and is the new value. 404 if gotVal := testTreap.Has(key); gotVal != true { 405 t.Fatalf("Has: unexpected result - got %v, want false", gotVal) 406 } 407 if gotVal := testTreap.Get(key); !bytes.Equal(gotVal, val) { 408 t.Fatalf("Get: unexpected result - got %x, want %x", gotVal, val) 409 } 410 411 // Ensure the expected size is reported. 412 expectedSize := uint64(nodeFieldsSize + len(key) + len(val)) 413 if gotSize := testTreap.Size(); gotSize != expectedSize { 414 t.Fatalf("Size: unexpected byte size - got %d, want %d", 415 gotSize, expectedSize) 416 } 417 } 418 419 // TestMutableNilValue ensures that putting a nil value into a mutable treap 420 // results in a key being added with an empty byte slice. 421 func TestMutableNilValue(t *testing.T) { 422 t.Parallel() 423 424 key := serializeUint32(0) 425 426 // Put the key with a nil value. 427 testTreap := NewMutable() 428 testTreap.Put(key, nil) 429 430 // Ensure the key exists and is an empty byte slice. 431 if gotVal := testTreap.Has(key); gotVal != true { 432 t.Fatalf("Has: unexpected result - got %v, want false", gotVal) 433 } 434 if gotVal := testTreap.Get(key); gotVal == nil { 435 t.Fatalf("Get: unexpected result - got nil, want empty slice") 436 } 437 if gotVal := testTreap.Get(key); len(gotVal) != 0 { 438 t.Fatalf("Get: unexpected result - got %x, want empty slice", 439 gotVal) 440 } 441 } 442 443 // TestMutableForEachStopIterator ensures that returning false from the ForEach 444 // callback of a mutable treap stops iteration early. 445 func TestMutableForEachStopIterator(t *testing.T) { 446 t.Parallel() 447 448 // Insert a few keys. 449 numItems := 10 450 testTreap := NewMutable() 451 for i := 0; i < numItems; i++ { 452 key := serializeUint32(uint32(i)) 453 testTreap.Put(key, key) 454 } 455 456 // Ensure ForEach exits early on false return by caller. 457 var numIterated int 458 testTreap.ForEach(func(k, v []byte) bool { 459 numIterated++ 460 if numIterated == numItems/2 { 461 return false 462 } 463 return true 464 }) 465 if numIterated != numItems/2 { 466 t.Fatalf("ForEach: unexpected iterate count - got %d, want %d", 467 numIterated, numItems/2) 468 } 469 }