github.com/lbryio/lbcd@v0.22.119/database/internal/treap/mutable_test.go (about)

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