github.com/BlockABC/godash@v0.0.0-20191112120524-f4aa3a32c566/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  }