1 // Copyright (c) 2015-2016 The btcsuite developers
2 // Use of this source code is governed by an ISC
3 // license that can be found in the LICENSE file.
13 // TestImmutableEmpty ensures calling functions on an empty immutable treap
15 func TestImmutableEmpty(t *testing.T) {
18 // Ensure the treap length is the expected value.
19 testTreap := NewImmutable()
20 if gotLen := testTreap.Len(); gotLen != 0 {
21 t.Fatalf("Len: unexpected length - got %d, want %d", gotLen, 0)
24 // Ensure the reported size is 0.
25 if gotSize := testTreap.Size(); gotSize != 0 {
26 t.Fatalf("Size: unexpected byte size - got %d, want 0",
30 // Ensure there are no errors with requesting keys from an empty treap.
31 key := serializeUint32(0)
32 if gotVal := testTreap.Has(key); gotVal {
33 t.Fatalf("Has: unexpected result - got %v, want false", gotVal)
35 if gotVal := testTreap.Get(key); gotVal != nil {
36 t.Fatalf("Get: unexpected result - got %x, want nil", gotVal)
39 // Ensure there are no panics when deleting keys from an empty treap.
42 // Ensure the number of keys iterated by ForEach on an empty treap is
45 testTreap.ForEach(func(k, v []byte) bool {
50 t.Fatalf("ForEach: unexpected iterate count - got %d, want 0",
55 // TestImmutableSequential ensures that putting keys into an immutable treap in
56 // sequential order works as expected.
57 func TestImmutableSequential(t *testing.T) {
60 // Insert a bunch of sequential keys while checking several of the treap
61 // functions work as expected.
62 expectedSize := uint64(0)
64 testTreap := NewImmutable()
65 for i := 0; i < numItems; i++ {
66 key := serializeUint32(uint32(i))
67 testTreap = testTreap.Put(key, key)
69 // Ensure the treap length is the expected value.
70 if gotLen := testTreap.Len(); gotLen != i+1 {
71 t.Fatalf("Len #%d: unexpected length - got %d, want %d",
75 // Ensure the treap has the key.
76 if !testTreap.Has(key) {
77 t.Fatalf("Has #%d: key %q is not in treap", i, key)
80 // Get the key from the treap and ensure it is the expected
82 if gotVal := testTreap.Get(key); !bytes.Equal(gotVal, key) {
83 t.Fatalf("Get #%d: unexpected value - got %x, want %x",
87 // Ensure the expected size is reported.
88 expectedSize += (nodeFieldsSize + 8)
89 if gotSize := testTreap.Size(); gotSize != expectedSize {
90 t.Fatalf("Size #%d: unexpected byte size - got %d, "+
91 "want %d", i, gotSize, expectedSize)
95 // Ensure the all keys are iterated by ForEach in order.
97 testTreap.ForEach(func(k, v []byte) bool {
98 wantKey := serializeUint32(uint32(numIterated))
100 // Ensure the key is as expected.
101 if !bytes.Equal(k, wantKey) {
102 t.Fatalf("ForEach #%d: unexpected key - got %x, want %x",
103 numIterated, k, wantKey)
106 // Ensure the value is as expected.
107 if !bytes.Equal(v, wantKey) {
108 t.Fatalf("ForEach #%d: unexpected value - got %x, want %x",
109 numIterated, v, wantKey)
116 // Ensure all items were iterated.
117 if numIterated != numItems {
118 t.Fatalf("ForEach: unexpected iterate count - got %d, want %d",
119 numIterated, numItems)
122 // Delete the keys one-by-one while checking several of the treap
123 // functions work as expected.
124 for i := 0; i < numItems; i++ {
125 key := serializeUint32(uint32(i))
126 testTreap = testTreap.Delete(key)
128 // Ensure the treap length is the expected value.
129 if gotLen := testTreap.Len(); gotLen != numItems-i-1 {
130 t.Fatalf("Len #%d: unexpected length - got %d, want %d",
131 i, gotLen, numItems-i-1)
134 // Ensure the treap no longer has the key.
135 if testTreap.Has(key) {
136 t.Fatalf("Has #%d: key %q is in treap", i, key)
139 // Get the key that no longer exists from the treap and ensure
141 if gotVal := testTreap.Get(key); gotVal != nil {
142 t.Fatalf("Get #%d: unexpected value - got %x, want nil",
146 // Ensure the expected size is reported.
147 expectedSize -= (nodeFieldsSize + 8)
148 if gotSize := testTreap.Size(); gotSize != expectedSize {
149 t.Fatalf("Size #%d: unexpected byte size - got %d, "+
150 "want %d", i, gotSize, expectedSize)
155 // TestImmutableReverseSequential ensures that putting keys into an immutable
156 // treap in reverse sequential order works as expected.
157 func TestImmutableReverseSequential(t *testing.T) {
160 // Insert a bunch of sequential keys while checking several of the treap
161 // functions work as expected.
162 expectedSize := uint64(0)
164 testTreap := NewImmutable()
165 for i := 0; i < numItems; i++ {
166 key := serializeUint32(uint32(numItems - i - 1))
167 testTreap = testTreap.Put(key, key)
169 // Ensure the treap length is the expected value.
170 if gotLen := testTreap.Len(); gotLen != i+1 {
171 t.Fatalf("Len #%d: unexpected length - got %d, want %d",
175 // Ensure the treap has the key.
176 if !testTreap.Has(key) {
177 t.Fatalf("Has #%d: key %q is not in treap", i, key)
180 // Get the key from the treap and ensure it is the expected
182 if gotVal := testTreap.Get(key); !bytes.Equal(gotVal, key) {
183 t.Fatalf("Get #%d: unexpected value - got %x, want %x",
187 // Ensure the expected size is reported.
188 expectedSize += (nodeFieldsSize + 8)
189 if gotSize := testTreap.Size(); gotSize != expectedSize {
190 t.Fatalf("Size #%d: unexpected byte size - got %d, "+
191 "want %d", i, gotSize, expectedSize)
195 // Ensure the all keys are iterated by ForEach in order.
197 testTreap.ForEach(func(k, v []byte) bool {
198 wantKey := serializeUint32(uint32(numIterated))
200 // Ensure the key is as expected.
201 if !bytes.Equal(k, wantKey) {
202 t.Fatalf("ForEach #%d: unexpected key - got %x, want %x",
203 numIterated, k, wantKey)
206 // Ensure the value is as expected.
207 if !bytes.Equal(v, wantKey) {
208 t.Fatalf("ForEach #%d: unexpected value - got %x, want %x",
209 numIterated, v, wantKey)
216 // Ensure all items were iterated.
217 if numIterated != numItems {
218 t.Fatalf("ForEach: unexpected iterate count - got %d, want %d",
219 numIterated, numItems)
222 // Delete the keys one-by-one while checking several of the treap
223 // functions work as expected.
224 for i := 0; i < numItems; i++ {
225 // Intentionally use the reverse order they were inserted here.
226 key := serializeUint32(uint32(i))
227 testTreap = testTreap.Delete(key)
229 // Ensure the treap length is the expected value.
230 if gotLen := testTreap.Len(); gotLen != numItems-i-1 {
231 t.Fatalf("Len #%d: unexpected length - got %d, want %d",
232 i, gotLen, numItems-i-1)
235 // Ensure the treap no longer has the key.
236 if testTreap.Has(key) {
237 t.Fatalf("Has #%d: key %q is in treap", i, key)
240 // Get the key that no longer exists from the treap and ensure
242 if gotVal := testTreap.Get(key); gotVal != nil {
243 t.Fatalf("Get #%d: unexpected value - got %x, want nil",
247 // Ensure the expected size is reported.
248 expectedSize -= (nodeFieldsSize + 8)
249 if gotSize := testTreap.Size(); gotSize != expectedSize {
250 t.Fatalf("Size #%d: unexpected byte size - got %d, "+
251 "want %d", i, gotSize, expectedSize)
256 // TestImmutableUnordered ensures that putting keys into an immutable treap in
257 // no paritcular order works as expected.
258 func TestImmutableUnordered(t *testing.T) {
261 // Insert a bunch of out-of-order keys while checking several of the
262 // treap functions work as expected.
263 expectedSize := uint64(0)
265 testTreap := NewImmutable()
266 for i := 0; i < numItems; i++ {
267 // Hash the serialized int to generate out-of-order keys.
268 hash := sha256.Sum256(serializeUint32(uint32(i)))
270 testTreap = testTreap.Put(key, key)
272 // Ensure the treap length is the expected value.
273 if gotLen := testTreap.Len(); gotLen != i+1 {
274 t.Fatalf("Len #%d: unexpected length - got %d, want %d",
278 // Ensure the treap has the key.
279 if !testTreap.Has(key) {
280 t.Fatalf("Has #%d: key %q is not in treap", i, key)
283 // Get the key from the treap and ensure it is the expected
285 if gotVal := testTreap.Get(key); !bytes.Equal(gotVal, key) {
286 t.Fatalf("Get #%d: unexpected value - got %x, want %x",
290 // Ensure the expected size is reported.
291 expectedSize += nodeFieldsSize + uint64(len(key)+len(key))
292 if gotSize := testTreap.Size(); gotSize != expectedSize {
293 t.Fatalf("Size #%d: unexpected byte size - got %d, "+
294 "want %d", i, gotSize, expectedSize)
298 // Delete the keys one-by-one while checking several of the treap
299 // functions work as expected.
300 for i := 0; i < numItems; i++ {
301 // Hash the serialized int to generate out-of-order keys.
302 hash := sha256.Sum256(serializeUint32(uint32(i)))
304 testTreap = testTreap.Delete(key)
306 // Ensure the treap length is the expected value.
307 if gotLen := testTreap.Len(); gotLen != numItems-i-1 {
308 t.Fatalf("Len #%d: unexpected length - got %d, want %d",
309 i, gotLen, numItems-i-1)
312 // Ensure the treap no longer has the key.
313 if testTreap.Has(key) {
314 t.Fatalf("Has #%d: key %q is in treap", i, key)
317 // Get the key that no longer exists from the treap and ensure
319 if gotVal := testTreap.Get(key); gotVal != nil {
320 t.Fatalf("Get #%d: unexpected value - got %x, want nil",
324 // Ensure the expected size is reported.
325 expectedSize -= (nodeFieldsSize + 64)
326 if gotSize := testTreap.Size(); gotSize != expectedSize {
327 t.Fatalf("Size #%d: unexpected byte size - got %d, "+
328 "want %d", i, gotSize, expectedSize)
333 // TestImmutableDuplicatePut ensures that putting a duplicate key into an
334 // immutable treap works as expected.
335 func TestImmutableDuplicatePut(t *testing.T) {
338 expectedVal := []byte("testval")
339 expectedSize := uint64(0)
341 testTreap := NewImmutable()
342 for i := 0; i < numItems; i++ {
343 key := serializeUint32(uint32(i))
344 testTreap = testTreap.Put(key, key)
345 expectedSize += nodeFieldsSize + uint64(len(key)+len(key))
347 // Put a duplicate key with the the expected final value.
348 testTreap = testTreap.Put(key, expectedVal)
350 // Ensure the key still exists and is the new value.
351 if gotVal := testTreap.Has(key); !gotVal {
352 t.Fatalf("Has: unexpected result - got %v, want true",
355 if gotVal := testTreap.Get(key); !bytes.Equal(gotVal, expectedVal) {
356 t.Fatalf("Get: unexpected result - got %x, want %x",
360 // Ensure the expected size is reported.
361 expectedSize -= uint64(len(key))
362 expectedSize += uint64(len(expectedVal))
363 if gotSize := testTreap.Size(); gotSize != expectedSize {
364 t.Fatalf("Size: unexpected byte size - got %d, want %d",
365 gotSize, expectedSize)
370 // TestImmutableNilValue ensures that putting a nil value into an immutable
371 // treap results in a key being added with an empty byte slice.
372 func TestImmutableNilValue(t *testing.T) {
375 key := serializeUint32(0)
377 // Put the key with a nil value.
378 testTreap := NewImmutable()
379 testTreap = testTreap.Put(key, nil)
381 // Ensure the key exists and is an empty byte slice.
382 if gotVal := testTreap.Has(key); !gotVal {
383 t.Fatalf("Has: unexpected result - got %v, want true", gotVal)
385 if gotVal := testTreap.Get(key); gotVal == nil {
386 t.Fatalf("Get: unexpected result - got nil, want empty slice")
388 if gotVal := testTreap.Get(key); len(gotVal) != 0 {
389 t.Fatalf("Get: unexpected result - got %x, want empty slice",
394 // TestImmutableForEachStopIterator ensures that returning false from the ForEach
395 // callback on an immutable treap stops iteration early.
396 func TestImmutableForEachStopIterator(t *testing.T) {
399 // Insert a few keys.
401 testTreap := NewImmutable()
402 for i := 0; i < numItems; i++ {
403 key := serializeUint32(uint32(i))
404 testTreap = testTreap.Put(key, key)
407 // Ensure ForEach exits early on false return by caller.
409 testTreap.ForEach(func(k, v []byte) bool {
411 return numIterated != numItems/2
413 if numIterated != numItems/2 {
414 t.Fatalf("ForEach: unexpected iterate count - got %d, want %d",
415 numIterated, numItems/2)
419 // TestImmutableSnapshot ensures that immutable treaps are actually immutable by
420 // keeping a reference to the previous treap, performing a mutation, and then
421 // ensuring the referenced treap does not have the mutation applied.
422 func TestImmutableSnapshot(t *testing.T) {
425 // Insert a bunch of sequential keys while checking several of the treap
426 // functions work as expected.
427 expectedSize := uint64(0)
429 testTreap := NewImmutable()
430 for i := 0; i < numItems; i++ {
431 treapSnap := testTreap
433 key := serializeUint32(uint32(i))
434 testTreap = testTreap.Put(key, key)
436 // Ensure the length of the treap snapshot is the expected
438 if gotLen := treapSnap.Len(); gotLen != i {
439 t.Fatalf("Len #%d: unexpected length - got %d, want %d",
443 // Ensure the treap snapshot does not have the key.
444 if treapSnap.Has(key) {
445 t.Fatalf("Has #%d: key %q is in treap", i, key)
448 // Get the key that doesn't exist in the treap snapshot and
450 if gotVal := treapSnap.Get(key); gotVal != nil {
451 t.Fatalf("Get #%d: unexpected value - got %x, want nil",
455 // Ensure the expected size is reported.
456 if gotSize := treapSnap.Size(); gotSize != expectedSize {
457 t.Fatalf("Size #%d: unexpected byte size - got %d, "+
458 "want %d", i, gotSize, expectedSize)
460 expectedSize += (nodeFieldsSize + 8)
463 // Delete the keys one-by-one while checking several of the treap
464 // functions work as expected.
465 for i := 0; i < numItems; i++ {
466 treapSnap := testTreap
468 key := serializeUint32(uint32(i))
469 testTreap = testTreap.Delete(key)
471 // Ensure the length of the treap snapshot is the expected
473 if gotLen := treapSnap.Len(); gotLen != numItems-i {
474 t.Fatalf("Len #%d: unexpected length - got %d, want %d",
475 i, gotLen, numItems-i)
478 // Ensure the treap snapshot still has the key.
479 if !treapSnap.Has(key) {
480 t.Fatalf("Has #%d: key %q is not in treap", i, key)
483 // Get the key from the treap snapshot and ensure it is still
484 // the expected value.
485 if gotVal := treapSnap.Get(key); !bytes.Equal(gotVal, key) {
486 t.Fatalf("Get #%d: unexpected value - got %x, want %x",
490 // Ensure the expected size is reported.
491 if gotSize := treapSnap.Size(); gotSize != expectedSize {
492 t.Fatalf("Size #%d: unexpected byte size - got %d, "+
493 "want %d", i, gotSize, expectedSize)
495 expectedSize -= (nodeFieldsSize + 8)