github.com/MetalBlockchain/metalgo@v1.11.9/database/test_database.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package database
     5  
     6  import (
     7  	"bytes"
     8  	"io"
     9  	"math"
    10  	"math/rand"
    11  	"slices"
    12  	"testing"
    13  
    14  	"github.com/stretchr/testify/require"
    15  	"go.uber.org/mock/gomock"
    16  	"golang.org/x/exp/maps"
    17  	"golang.org/x/sync/errgroup"
    18  
    19  	"github.com/MetalBlockchain/metalgo/utils"
    20  	"github.com/MetalBlockchain/metalgo/utils/units"
    21  )
    22  
    23  // Tests is a list of all database tests
    24  var Tests = map[string]func(t *testing.T, db Database){
    25  	"SimpleKeyValue":                   TestSimpleKeyValue,
    26  	"OverwriteKeyValue":                TestOverwriteKeyValue,
    27  	"EmptyKey":                         TestEmptyKey,
    28  	"KeyEmptyValue":                    TestKeyEmptyValue,
    29  	"SimpleKeyValueClosed":             TestSimpleKeyValueClosed,
    30  	"NewBatchClosed":                   TestNewBatchClosed,
    31  	"BatchPut":                         TestBatchPut,
    32  	"BatchDelete":                      TestBatchDelete,
    33  	"BatchReset":                       TestBatchReset,
    34  	"BatchReuse":                       TestBatchReuse,
    35  	"BatchRewrite":                     TestBatchRewrite,
    36  	"BatchReplay":                      TestBatchReplay,
    37  	"BatchReplayPropagateError":        TestBatchReplayPropagateError,
    38  	"BatchInner":                       TestBatchInner,
    39  	"BatchLargeSize":                   TestBatchLargeSize,
    40  	"IteratorSnapshot":                 TestIteratorSnapshot,
    41  	"Iterator":                         TestIterator,
    42  	"IteratorStart":                    TestIteratorStart,
    43  	"IteratorPrefix":                   TestIteratorPrefix,
    44  	"IteratorStartPrefix":              TestIteratorStartPrefix,
    45  	"IteratorMemorySafety":             TestIteratorMemorySafety,
    46  	"IteratorClosed":                   TestIteratorClosed,
    47  	"IteratorError":                    TestIteratorError,
    48  	"IteratorErrorAfterRelease":        TestIteratorErrorAfterRelease,
    49  	"CompactNoPanic":                   TestCompactNoPanic,
    50  	"MemorySafetyDatabase":             TestMemorySafetyDatabase,
    51  	"MemorySafetyBatch":                TestMemorySafetyBatch,
    52  	"AtomicClear":                      TestAtomicClear,
    53  	"Clear":                            TestClear,
    54  	"AtomicClearPrefix":                TestAtomicClearPrefix,
    55  	"ClearPrefix":                      TestClearPrefix,
    56  	"ModifyValueAfterPut":              TestModifyValueAfterPut,
    57  	"ModifyValueAfterBatchPut":         TestModifyValueAfterBatchPut,
    58  	"ModifyValueAfterBatchPutReplay":   TestModifyValueAfterBatchPutReplay,
    59  	"ConcurrentBatches":                TestConcurrentBatches,
    60  	"ManySmallConcurrentKVPairBatches": TestManySmallConcurrentKVPairBatches,
    61  	"PutGetEmpty":                      TestPutGetEmpty,
    62  }
    63  
    64  // TestSimpleKeyValue tests to make sure that simple Put + Get + Delete + Has
    65  // calls return the expected values.
    66  func TestSimpleKeyValue(t *testing.T, db Database) {
    67  	require := require.New(t)
    68  
    69  	key := []byte("hello")
    70  	value := []byte("world")
    71  
    72  	has, err := db.Has(key)
    73  	require.NoError(err)
    74  	require.False(has)
    75  
    76  	_, err = db.Get(key)
    77  	require.Equal(ErrNotFound, err)
    78  
    79  	require.NoError(db.Delete(key))
    80  	require.NoError(db.Put(key, value))
    81  
    82  	has, err = db.Has(key)
    83  	require.NoError(err)
    84  	require.True(has)
    85  
    86  	v, err := db.Get(key)
    87  	require.NoError(err)
    88  	require.Equal(value, v)
    89  
    90  	require.NoError(db.Delete(key))
    91  
    92  	has, err = db.Has(key)
    93  	require.NoError(err)
    94  	require.False(has)
    95  
    96  	_, err = db.Get(key)
    97  	require.Equal(ErrNotFound, err)
    98  
    99  	require.NoError(db.Delete(key))
   100  }
   101  
   102  func TestOverwriteKeyValue(t *testing.T, db Database) {
   103  	require := require.New(t)
   104  
   105  	key := []byte("hello")
   106  	value1 := []byte("world1")
   107  	value2 := []byte("world2")
   108  
   109  	require.NoError(db.Put(key, value1))
   110  
   111  	require.NoError(db.Put(key, value2))
   112  
   113  	gotValue, err := db.Get(key)
   114  	require.NoError(err)
   115  	require.Equal(value2, gotValue)
   116  }
   117  
   118  func TestKeyEmptyValue(t *testing.T, db Database) {
   119  	require := require.New(t)
   120  
   121  	key := []byte("hello")
   122  	val := []byte(nil)
   123  
   124  	_, err := db.Get(key)
   125  	require.Equal(ErrNotFound, err)
   126  
   127  	require.NoError(db.Put(key, val))
   128  
   129  	value, err := db.Get(key)
   130  	require.NoError(err)
   131  	require.Empty(value)
   132  }
   133  
   134  func TestEmptyKey(t *testing.T, db Database) {
   135  	require := require.New(t)
   136  
   137  	var (
   138  		nilKey   = []byte(nil)
   139  		emptyKey = []byte{}
   140  		val1     = []byte("hi")
   141  		val2     = []byte("hello")
   142  	)
   143  
   144  	// Test that nil key can be retrieved by empty key
   145  	_, err := db.Get(nilKey)
   146  	require.Equal(ErrNotFound, err)
   147  
   148  	require.NoError(db.Put(nilKey, val1))
   149  
   150  	value, err := db.Get(emptyKey)
   151  	require.NoError(err)
   152  	require.Equal(value, val1)
   153  
   154  	// Test that empty key can be retrieved by nil key
   155  	require.NoError(db.Put(emptyKey, val2))
   156  
   157  	value, err = db.Get(nilKey)
   158  	require.NoError(err)
   159  	require.Equal(value, val2)
   160  }
   161  
   162  // TestSimpleKeyValueClosed tests to make sure that Put + Get + Delete + Has
   163  // calls return the correct error when the database has been closed.
   164  func TestSimpleKeyValueClosed(t *testing.T, db Database) {
   165  	require := require.New(t)
   166  
   167  	key := []byte("hello")
   168  	value := []byte("world")
   169  
   170  	has, err := db.Has(key)
   171  	require.NoError(err)
   172  	require.False(has)
   173  
   174  	_, err = db.Get(key)
   175  	require.Equal(ErrNotFound, err)
   176  
   177  	require.NoError(db.Delete(key))
   178  	require.NoError(db.Put(key, value))
   179  
   180  	has, err = db.Has(key)
   181  	require.NoError(err)
   182  	require.True(has)
   183  
   184  	v, err := db.Get(key)
   185  	require.NoError(err)
   186  	require.Equal(value, v)
   187  
   188  	require.NoError(db.Close())
   189  
   190  	_, err = db.Has(key)
   191  	require.Equal(ErrClosed, err)
   192  
   193  	_, err = db.Get(key)
   194  	require.Equal(ErrClosed, err)
   195  
   196  	require.Equal(ErrClosed, db.Put(key, value))
   197  	require.Equal(ErrClosed, db.Delete(key))
   198  	require.Equal(ErrClosed, db.Close())
   199  }
   200  
   201  // TestMemorySafetyDatabase ensures it is safe to modify a key after passing it
   202  // to Database.Put and Database.Get.
   203  func TestMemorySafetyDatabase(t *testing.T, db Database) {
   204  	require := require.New(t)
   205  
   206  	key := []byte("1key")
   207  	keyCopy := slices.Clone(key)
   208  	value := []byte("value")
   209  	key2 := []byte("2key")
   210  	value2 := []byte("value2")
   211  
   212  	// Put both K/V pairs in the database
   213  	require.NoError(db.Put(key, value))
   214  	require.NoError(db.Put(key2, value2))
   215  
   216  	// Get the value for [key]
   217  	gotVal, err := db.Get(key)
   218  	require.NoError(err)
   219  	require.Equal(value, gotVal)
   220  
   221  	// Modify [key]; make sure the value we got before hasn't changed
   222  	key[0] = key2[0]
   223  	gotVal2, err := db.Get(key)
   224  	require.NoError(err)
   225  	require.Equal(value2, gotVal2)
   226  	require.Equal(value, gotVal)
   227  
   228  	// Reset [key] to its original value and make sure it's correct
   229  	key[0] = keyCopy[0]
   230  	gotVal, err = db.Get(key)
   231  	require.NoError(err)
   232  	require.Equal(value, gotVal)
   233  }
   234  
   235  // TestNewBatchClosed tests to make sure that calling NewBatch on a closed
   236  // database returns a batch that errors correctly.
   237  func TestNewBatchClosed(t *testing.T, db Database) {
   238  	require := require.New(t)
   239  
   240  	require.NoError(db.Close())
   241  
   242  	batch := db.NewBatch()
   243  	require.NotNil(batch)
   244  
   245  	key := []byte("hello")
   246  	value := []byte("world")
   247  
   248  	require.NoError(batch.Put(key, value))
   249  	require.Positive(batch.Size())
   250  	require.Equal(ErrClosed, batch.Write())
   251  }
   252  
   253  // TestBatchPut tests to make sure that batched writes work as expected.
   254  func TestBatchPut(t *testing.T, db Database) {
   255  	require := require.New(t)
   256  
   257  	key := []byte("hello")
   258  	value := []byte("world")
   259  
   260  	batch := db.NewBatch()
   261  	require.NotNil(batch)
   262  
   263  	require.NoError(batch.Put(key, value))
   264  	require.Positive(batch.Size())
   265  	require.NoError(batch.Write())
   266  
   267  	has, err := db.Has(key)
   268  	require.NoError(err)
   269  	require.True(has)
   270  
   271  	v, err := db.Get(key)
   272  	require.NoError(err)
   273  	require.Equal(value, v)
   274  
   275  	require.NoError(db.Delete(key))
   276  
   277  	batch = db.NewBatch()
   278  	require.NotNil(batch)
   279  
   280  	require.NoError(batch.Put(key, value))
   281  	require.NoError(db.Close())
   282  	require.Equal(ErrClosed, batch.Write())
   283  }
   284  
   285  // TestBatchDelete tests to make sure that batched deletes work as expected.
   286  func TestBatchDelete(t *testing.T, db Database) {
   287  	require := require.New(t)
   288  
   289  	key := []byte("hello")
   290  	value := []byte("world")
   291  
   292  	require.NoError(db.Put(key, value))
   293  
   294  	batch := db.NewBatch()
   295  	require.NotNil(batch)
   296  
   297  	require.NoError(batch.Delete(key))
   298  	require.NoError(batch.Write())
   299  
   300  	has, err := db.Has(key)
   301  	require.NoError(err)
   302  	require.False(has)
   303  
   304  	_, err = db.Get(key)
   305  	require.Equal(ErrNotFound, err)
   306  
   307  	require.NoError(db.Delete(key))
   308  }
   309  
   310  // TestMemorySafetyBatch ensures it is safe to modify a key after passing it
   311  // to Batch.Put.
   312  func TestMemorySafetyBatch(t *testing.T, db Database) {
   313  	require := require.New(t)
   314  
   315  	key := []byte("hello")
   316  	keyCopy := slices.Clone(key)
   317  	value := []byte("world")
   318  	valueCopy := slices.Clone(value)
   319  
   320  	batch := db.NewBatch()
   321  	require.NotNil(batch)
   322  
   323  	// Put a key in the batch
   324  	require.NoError(batch.Put(key, value))
   325  	require.Positive(batch.Size())
   326  
   327  	// Modify the key
   328  	key[0] = 'j'
   329  	require.NoError(batch.Write())
   330  
   331  	// Make sure the original key was written to the database
   332  	has, err := db.Has(keyCopy)
   333  	require.NoError(err)
   334  	require.True(has)
   335  
   336  	v, err := db.Get(keyCopy)
   337  	require.NoError(err)
   338  	require.Equal(valueCopy, v)
   339  
   340  	// Make sure the new key wasn't written to the database
   341  	has, err = db.Has(key)
   342  	require.NoError(err)
   343  	require.False(has)
   344  }
   345  
   346  // TestBatchReset tests to make sure that a batch drops un-written operations
   347  // when it is reset.
   348  func TestBatchReset(t *testing.T, db Database) {
   349  	require := require.New(t)
   350  
   351  	key := []byte("hello")
   352  	value := []byte("world")
   353  
   354  	require.NoError(db.Put(key, value))
   355  
   356  	batch := db.NewBatch()
   357  	require.NotNil(batch)
   358  
   359  	require.NoError(batch.Delete(key))
   360  
   361  	batch.Reset()
   362  
   363  	require.Zero(batch.Size())
   364  	require.NoError(batch.Write())
   365  
   366  	has, err := db.Has(key)
   367  	require.NoError(err)
   368  	require.True(has)
   369  
   370  	v, err := db.Get(key)
   371  	require.NoError(err)
   372  	require.Equal(value, v)
   373  }
   374  
   375  // TestBatchReuse tests to make sure that a batch can be reused once it is
   376  // reset.
   377  func TestBatchReuse(t *testing.T, db Database) {
   378  	require := require.New(t)
   379  
   380  	key1 := []byte("hello1")
   381  	value1 := []byte("world1")
   382  
   383  	key2 := []byte("hello2")
   384  	value2 := []byte("world2")
   385  
   386  	batch := db.NewBatch()
   387  	require.NotNil(batch)
   388  
   389  	require.NoError(batch.Put(key1, value1))
   390  	require.NoError(batch.Write())
   391  	require.NoError(db.Delete(key1))
   392  
   393  	has, err := db.Has(key1)
   394  	require.NoError(err)
   395  	require.False(has)
   396  
   397  	batch.Reset()
   398  
   399  	require.Zero(batch.Size())
   400  	require.NoError(batch.Put(key2, value2))
   401  	require.NoError(batch.Write())
   402  
   403  	has, err = db.Has(key1)
   404  	require.NoError(err)
   405  	require.False(has)
   406  
   407  	has, err = db.Has(key2)
   408  	require.NoError(err)
   409  	require.True(has)
   410  
   411  	v, err := db.Get(key2)
   412  	require.NoError(err)
   413  	require.Equal(value2, v)
   414  }
   415  
   416  // TestBatchRewrite tests to make sure that write can be called multiple times
   417  // on a batch and the values will be updated correctly.
   418  func TestBatchRewrite(t *testing.T, db Database) {
   419  	require := require.New(t)
   420  
   421  	key := []byte("hello1")
   422  	value := []byte("world1")
   423  
   424  	batch := db.NewBatch()
   425  	require.NotNil(batch)
   426  
   427  	require.NoError(batch.Put(key, value))
   428  	require.NoError(batch.Write())
   429  	require.NoError(db.Delete(key))
   430  
   431  	has, err := db.Has(key)
   432  	require.NoError(err)
   433  	require.False(has)
   434  
   435  	require.NoError(batch.Write())
   436  
   437  	has, err = db.Has(key)
   438  	require.NoError(err)
   439  	require.True(has)
   440  
   441  	v, err := db.Get(key)
   442  	require.NoError(err)
   443  	require.Equal(value, v)
   444  }
   445  
   446  // TestBatchReplay tests to make sure that batches will correctly replay their
   447  // contents.
   448  func TestBatchReplay(t *testing.T, db Database) {
   449  	ctrl := gomock.NewController(t)
   450  	require := require.New(t)
   451  
   452  	key1 := []byte("hello1")
   453  	value1 := []byte("world1")
   454  
   455  	key2 := []byte("hello2")
   456  	value2 := []byte("world2")
   457  
   458  	batch := db.NewBatch()
   459  	require.NotNil(batch)
   460  
   461  	require.NoError(batch.Put(key1, value1))
   462  	require.NoError(batch.Put(key2, value2))
   463  	require.NoError(batch.Delete(key1))
   464  	require.NoError(batch.Delete(key2))
   465  	require.NoError(batch.Put(key1, value2))
   466  
   467  	for i := 0; i < 2; i++ {
   468  		mockBatch := NewMockBatch(ctrl)
   469  		gomock.InOrder(
   470  			mockBatch.EXPECT().Put(key1, value1).Times(1),
   471  			mockBatch.EXPECT().Put(key2, value2).Times(1),
   472  			mockBatch.EXPECT().Delete(key1).Times(1),
   473  			mockBatch.EXPECT().Delete(key2).Times(1),
   474  			mockBatch.EXPECT().Put(key1, value2).Times(1),
   475  		)
   476  
   477  		require.NoError(batch.Replay(mockBatch))
   478  	}
   479  }
   480  
   481  // TestBatchReplayPropagateError tests to make sure that batches will correctly
   482  // propagate any returned error during Replay.
   483  func TestBatchReplayPropagateError(t *testing.T, db Database) {
   484  	ctrl := gomock.NewController(t)
   485  	require := require.New(t)
   486  
   487  	key1 := []byte("hello1")
   488  	value1 := []byte("world1")
   489  
   490  	key2 := []byte("hello2")
   491  	value2 := []byte("world2")
   492  
   493  	batch := db.NewBatch()
   494  	require.NotNil(batch)
   495  
   496  	require.NoError(batch.Put(key1, value1))
   497  	require.NoError(batch.Put(key2, value2))
   498  
   499  	mockBatch := NewMockBatch(ctrl)
   500  	gomock.InOrder(
   501  		mockBatch.EXPECT().Put(key1, value1).Return(ErrClosed).Times(1),
   502  	)
   503  	require.Equal(ErrClosed, batch.Replay(mockBatch))
   504  
   505  	mockBatch = NewMockBatch(ctrl)
   506  	gomock.InOrder(
   507  		mockBatch.EXPECT().Put(key1, value1).Return(io.ErrClosedPipe).Times(1),
   508  	)
   509  	require.Equal(io.ErrClosedPipe, batch.Replay(mockBatch))
   510  }
   511  
   512  // TestBatchInner tests to make sure that inner can be used to write to the
   513  // database.
   514  func TestBatchInner(t *testing.T, db Database) {
   515  	require := require.New(t)
   516  
   517  	key1 := []byte("hello1")
   518  	value1 := []byte("world1")
   519  
   520  	key2 := []byte("hello2")
   521  	value2 := []byte("world2")
   522  
   523  	firstBatch := db.NewBatch()
   524  	require.NotNil(firstBatch)
   525  
   526  	require.NoError(firstBatch.Put(key1, value1))
   527  
   528  	secondBatch := db.NewBatch()
   529  	require.NotNil(firstBatch)
   530  
   531  	require.NoError(secondBatch.Put(key2, value2))
   532  
   533  	innerFirstBatch := firstBatch.Inner()
   534  	require.NotNil(innerFirstBatch)
   535  
   536  	innerSecondBatch := secondBatch.Inner()
   537  	require.NotNil(innerSecondBatch)
   538  
   539  	require.NoError(innerFirstBatch.Replay(innerSecondBatch))
   540  	require.NoError(innerSecondBatch.Write())
   541  
   542  	has, err := db.Has(key1)
   543  	require.NoError(err)
   544  	require.True(has)
   545  
   546  	v, err := db.Get(key1)
   547  	require.NoError(err)
   548  	require.Equal(value1, v)
   549  
   550  	has, err = db.Has(key2)
   551  	require.NoError(err)
   552  	require.True(has)
   553  
   554  	v, err = db.Get(key2)
   555  	require.NoError(err)
   556  	require.Equal(value2, v)
   557  }
   558  
   559  // TestBatchLargeSize tests to make sure that the batch can support a large
   560  // amount of entries.
   561  func TestBatchLargeSize(t *testing.T, db Database) {
   562  	require := require.New(t)
   563  
   564  	totalSize := 8 * units.MiB
   565  	elementSize := 4 * units.KiB
   566  	pairSize := 2 * elementSize // 8 KiB
   567  
   568  	bytes := utils.RandomBytes(totalSize)
   569  
   570  	batch := db.NewBatch()
   571  	require.NotNil(batch)
   572  
   573  	for len(bytes) > pairSize {
   574  		key := bytes[:elementSize]
   575  		bytes = bytes[elementSize:]
   576  
   577  		value := bytes[:elementSize]
   578  		bytes = bytes[elementSize:]
   579  
   580  		require.NoError(batch.Put(key, value))
   581  	}
   582  
   583  	require.NoError(batch.Write())
   584  }
   585  
   586  // TestIteratorSnapshot tests to make sure the database iterates over a snapshot
   587  // of the database at the time of the iterator creation.
   588  func TestIteratorSnapshot(t *testing.T, db Database) {
   589  	require := require.New(t)
   590  
   591  	key1 := []byte("hello1")
   592  	value1 := []byte("world1")
   593  
   594  	key2 := []byte("hello2")
   595  	value2 := []byte("world2")
   596  
   597  	require.NoError(db.Put(key1, value1))
   598  
   599  	iterator := db.NewIterator()
   600  	require.NotNil(iterator)
   601  
   602  	defer iterator.Release()
   603  
   604  	require.NoError(db.Put(key2, value2))
   605  	require.True(iterator.Next())
   606  	require.Equal(key1, iterator.Key())
   607  	require.Equal(value1, iterator.Value())
   608  
   609  	require.False(iterator.Next())
   610  	require.Nil(iterator.Key())
   611  	require.Nil(iterator.Value())
   612  	require.NoError(iterator.Error())
   613  }
   614  
   615  // TestIterator tests to make sure the database iterates over the database
   616  // contents lexicographically.
   617  func TestIterator(t *testing.T, db Database) {
   618  	require := require.New(t)
   619  
   620  	key1 := []byte("hello1")
   621  	value1 := []byte("world1")
   622  
   623  	key2 := []byte("hello2")
   624  	value2 := []byte("world2")
   625  
   626  	require.NoError(db.Put(key1, value1))
   627  	require.NoError(db.Put(key2, value2))
   628  
   629  	iterator := db.NewIterator()
   630  	require.NotNil(iterator)
   631  
   632  	defer iterator.Release()
   633  
   634  	require.True(iterator.Next())
   635  	require.Equal(key1, iterator.Key())
   636  	require.Equal(value1, iterator.Value())
   637  
   638  	require.True(iterator.Next())
   639  	require.Equal(key2, iterator.Key())
   640  	require.Equal(value2, iterator.Value())
   641  
   642  	require.False(iterator.Next())
   643  	require.Nil(iterator.Key())
   644  	require.Nil(iterator.Value())
   645  	require.NoError(iterator.Error())
   646  }
   647  
   648  // TestIteratorStart tests to make sure the iterator can be configured to
   649  // start mid way through the database.
   650  func TestIteratorStart(t *testing.T, db Database) {
   651  	require := require.New(t)
   652  
   653  	key1 := []byte("hello1")
   654  	value1 := []byte("world1")
   655  
   656  	key2 := []byte("hello2")
   657  	value2 := []byte("world2")
   658  
   659  	require.NoError(db.Put(key1, value1))
   660  	require.NoError(db.Put(key2, value2))
   661  
   662  	iterator := db.NewIteratorWithStart(key2)
   663  	require.NotNil(iterator)
   664  
   665  	defer iterator.Release()
   666  
   667  	require.True(iterator.Next())
   668  	require.Equal(key2, iterator.Key())
   669  	require.Equal(value2, iterator.Value())
   670  
   671  	require.False(iterator.Next())
   672  	require.Nil(iterator.Key())
   673  	require.Nil(iterator.Value())
   674  	require.NoError(iterator.Error())
   675  }
   676  
   677  // TestIteratorPrefix tests to make sure the iterator can be configured to skip
   678  // keys missing the provided prefix.
   679  func TestIteratorPrefix(t *testing.T, db Database) {
   680  	require := require.New(t)
   681  
   682  	key1 := []byte("hello")
   683  	value1 := []byte("world1")
   684  
   685  	key2 := []byte("goodbye")
   686  	value2 := []byte("world2")
   687  
   688  	key3 := []byte("joy")
   689  	value3 := []byte("world3")
   690  
   691  	require.NoError(db.Put(key1, value1))
   692  	require.NoError(db.Put(key2, value2))
   693  	require.NoError(db.Put(key3, value3))
   694  
   695  	iterator := db.NewIteratorWithPrefix([]byte("h"))
   696  	require.NotNil(iterator)
   697  
   698  	defer iterator.Release()
   699  
   700  	require.True(iterator.Next())
   701  	require.Equal(key1, iterator.Key())
   702  	require.Equal(value1, iterator.Value())
   703  
   704  	require.False(iterator.Next())
   705  	require.Nil(iterator.Key())
   706  	require.Nil(iterator.Value())
   707  	require.NoError(iterator.Error())
   708  }
   709  
   710  // TestIteratorStartPrefix tests to make sure that the iterator can start mid
   711  // way through the database while skipping a prefix.
   712  func TestIteratorStartPrefix(t *testing.T, db Database) {
   713  	require := require.New(t)
   714  
   715  	key1 := []byte("hello1")
   716  	value1 := []byte("world1")
   717  
   718  	key2 := []byte("z")
   719  	value2 := []byte("world2")
   720  
   721  	key3 := []byte("hello3")
   722  	value3 := []byte("world3")
   723  
   724  	require.NoError(db.Put(key1, value1))
   725  	require.NoError(db.Put(key2, value2))
   726  	require.NoError(db.Put(key3, value3))
   727  
   728  	iterator := db.NewIteratorWithStartAndPrefix(key1, []byte("h"))
   729  	require.NotNil(iterator)
   730  
   731  	defer iterator.Release()
   732  
   733  	require.True(iterator.Next())
   734  	require.Equal(key1, iterator.Key())
   735  	require.Equal(value1, iterator.Value())
   736  
   737  	require.True(iterator.Next())
   738  	require.Equal(key3, iterator.Key())
   739  	require.Equal(value3, iterator.Value())
   740  
   741  	require.False(iterator.Next())
   742  	require.Nil(iterator.Key())
   743  	require.Nil(iterator.Value())
   744  	require.NoError(iterator.Error())
   745  }
   746  
   747  // TestIteratorMemorySafety tests to make sure that keys can values are able to
   748  // be modified from the returned iterator.
   749  func TestIteratorMemorySafety(t *testing.T, db Database) {
   750  	require := require.New(t)
   751  
   752  	key1 := []byte("hello1")
   753  	value1 := []byte("world1")
   754  
   755  	key2 := []byte("z")
   756  	value2 := []byte("world2")
   757  
   758  	key3 := []byte("hello3")
   759  	value3 := []byte("world3")
   760  
   761  	require.NoError(db.Put(key1, value1))
   762  	require.NoError(db.Put(key2, value2))
   763  	require.NoError(db.Put(key3, value3))
   764  
   765  	iterator := db.NewIterator()
   766  	require.NotNil(iterator)
   767  
   768  	defer iterator.Release()
   769  
   770  	keys := [][]byte{}
   771  	values := [][]byte{}
   772  	for iterator.Next() {
   773  		keys = append(keys, iterator.Key())
   774  		values = append(values, iterator.Value())
   775  	}
   776  
   777  	expectedKeys := [][]byte{
   778  		key1,
   779  		key3,
   780  		key2,
   781  	}
   782  	expectedValues := [][]byte{
   783  		value1,
   784  		value3,
   785  		value2,
   786  	}
   787  
   788  	for i, key := range keys {
   789  		value := values[i]
   790  		expectedKey := expectedKeys[i]
   791  		expectedValue := expectedValues[i]
   792  
   793  		require.Equal(expectedKey, key)
   794  		require.Equal(expectedValue, value)
   795  	}
   796  }
   797  
   798  // TestIteratorClosed tests to make sure that an iterator that was created with
   799  // a closed database will report a closed error correctly.
   800  func TestIteratorClosed(t *testing.T, db Database) {
   801  	require := require.New(t)
   802  
   803  	key1 := []byte("hello1")
   804  	value1 := []byte("world1")
   805  
   806  	require.NoError(db.Put(key1, value1))
   807  	require.NoError(db.Close())
   808  
   809  	{
   810  		iterator := db.NewIterator()
   811  		require.NotNil(iterator)
   812  
   813  		defer iterator.Release()
   814  
   815  		require.False(iterator.Next())
   816  		require.Nil(iterator.Key())
   817  		require.Nil(iterator.Value())
   818  		require.Equal(ErrClosed, iterator.Error())
   819  	}
   820  
   821  	{
   822  		iterator := db.NewIteratorWithPrefix(nil)
   823  		require.NotNil(iterator)
   824  
   825  		defer iterator.Release()
   826  
   827  		require.False(iterator.Next())
   828  		require.Nil(iterator.Key())
   829  		require.Nil(iterator.Value())
   830  		require.Equal(ErrClosed, iterator.Error())
   831  	}
   832  
   833  	{
   834  		iterator := db.NewIteratorWithStart(nil)
   835  		require.NotNil(iterator)
   836  
   837  		defer iterator.Release()
   838  
   839  		require.False(iterator.Next())
   840  		require.Nil(iterator.Key())
   841  		require.Nil(iterator.Value())
   842  		require.Equal(ErrClosed, iterator.Error())
   843  	}
   844  
   845  	{
   846  		iterator := db.NewIteratorWithStartAndPrefix(nil, nil)
   847  		require.NotNil(iterator)
   848  
   849  		defer iterator.Release()
   850  
   851  		require.False(iterator.Next())
   852  		require.Nil(iterator.Key())
   853  		require.Nil(iterator.Value())
   854  		require.Equal(ErrClosed, iterator.Error())
   855  	}
   856  }
   857  
   858  // TestIteratorError tests to make sure that an iterator on a database will report
   859  // itself as being exhausted and return [ErrClosed] to indicate that the iteration
   860  // was not successful.
   861  // Additionally tests that an iterator that has already called Next() can still serve
   862  // its current value after the underlying DB was closed.
   863  func TestIteratorError(t *testing.T, db Database) {
   864  	require := require.New(t)
   865  
   866  	key1 := []byte("hello1")
   867  	value1 := []byte("world1")
   868  
   869  	key2 := []byte("hello2")
   870  	value2 := []byte("world2")
   871  
   872  	require.NoError(db.Put(key1, value1))
   873  	require.NoError(db.Put(key2, value2))
   874  
   875  	iterator := db.NewIterator()
   876  	require.NotNil(iterator)
   877  
   878  	defer iterator.Release()
   879  
   880  	// Call Next() and ensure that if the database is closed, the iterator
   881  	// can still report the current contents.
   882  	require.True(iterator.Next())
   883  	require.NoError(db.Close())
   884  	require.Equal(key1, iterator.Key())
   885  	require.Equal(value1, iterator.Value())
   886  
   887  	// Subsequent calls to the iterator should return false and report an error
   888  	require.False(iterator.Next())
   889  	require.Nil(iterator.Key())
   890  	require.Nil(iterator.Value())
   891  	require.Equal(ErrClosed, iterator.Error())
   892  }
   893  
   894  // TestIteratorErrorAfterRelease tests to make sure that an iterator that was
   895  // released still reports the error correctly.
   896  func TestIteratorErrorAfterRelease(t *testing.T, db Database) {
   897  	require := require.New(t)
   898  
   899  	key := []byte("hello1")
   900  	value := []byte("world1")
   901  
   902  	require.NoError(db.Put(key, value))
   903  	require.NoError(db.Close())
   904  
   905  	iterator := db.NewIterator()
   906  	require.NotNil(iterator)
   907  
   908  	iterator.Release()
   909  
   910  	require.False(iterator.Next())
   911  	require.Nil(iterator.Key())
   912  	require.Nil(iterator.Value())
   913  	require.Equal(ErrClosed, iterator.Error())
   914  }
   915  
   916  // TestCompactNoPanic tests to make sure compact never panics.
   917  func TestCompactNoPanic(t *testing.T, db Database) {
   918  	require := require.New(t)
   919  
   920  	key1 := []byte("hello1")
   921  	value1 := []byte("world1")
   922  
   923  	key2 := []byte("z")
   924  	value2 := []byte("world2")
   925  
   926  	key3 := []byte("hello3")
   927  	value3 := []byte("world3")
   928  
   929  	require.NoError(db.Put(key1, value1))
   930  	require.NoError(db.Put(key2, value2))
   931  	require.NoError(db.Put(key3, value3))
   932  
   933  	// Test compacting with nil bounds
   934  	require.NoError(db.Compact(nil, nil))
   935  
   936  	// Test compacting when start > end
   937  	require.NoError(db.Compact([]byte{2}, []byte{1}))
   938  
   939  	// Test compacting when start > largest key
   940  	require.NoError(db.Compact([]byte{255}, nil))
   941  
   942  	require.NoError(db.Close())
   943  	err := db.Compact(nil, nil)
   944  	require.ErrorIs(err, ErrClosed)
   945  }
   946  
   947  func TestAtomicClear(t *testing.T, db Database) {
   948  	testClear(t, db, func(db Database) error {
   949  		return AtomicClear(db, db)
   950  	})
   951  }
   952  
   953  func TestClear(t *testing.T, db Database) {
   954  	testClear(t, db, func(db Database) error {
   955  		return Clear(db, math.MaxInt)
   956  	})
   957  }
   958  
   959  // testClear tests to make sure the deletion helper works as expected.
   960  func testClear(t *testing.T, db Database, clearF func(Database) error) {
   961  	require := require.New(t)
   962  
   963  	key1 := []byte("hello1")
   964  	value1 := []byte("world1")
   965  
   966  	key2 := []byte("z")
   967  	value2 := []byte("world2")
   968  
   969  	key3 := []byte("hello3")
   970  	value3 := []byte("world3")
   971  
   972  	require.NoError(db.Put(key1, value1))
   973  	require.NoError(db.Put(key2, value2))
   974  	require.NoError(db.Put(key3, value3))
   975  
   976  	count, err := Count(db)
   977  	require.NoError(err)
   978  	require.Equal(3, count)
   979  
   980  	require.NoError(clearF(db))
   981  
   982  	count, err = Count(db)
   983  	require.NoError(err)
   984  	require.Zero(count)
   985  
   986  	require.NoError(db.Close())
   987  }
   988  
   989  func TestAtomicClearPrefix(t *testing.T, db Database) {
   990  	testClearPrefix(t, db, func(db Database, prefix []byte) error {
   991  		return AtomicClearPrefix(db, db, prefix)
   992  	})
   993  }
   994  
   995  func TestClearPrefix(t *testing.T, db Database) {
   996  	testClearPrefix(t, db, func(db Database, prefix []byte) error {
   997  		return ClearPrefix(db, prefix, math.MaxInt)
   998  	})
   999  }
  1000  
  1001  // testClearPrefix tests to make sure prefix deletion works as expected.
  1002  func testClearPrefix(t *testing.T, db Database, clearF func(Database, []byte) error) {
  1003  	require := require.New(t)
  1004  
  1005  	key1 := []byte("hello1")
  1006  	value1 := []byte("world1")
  1007  
  1008  	key2 := []byte("z")
  1009  	value2 := []byte("world2")
  1010  
  1011  	key3 := []byte("hello3")
  1012  	value3 := []byte("world3")
  1013  
  1014  	require.NoError(db.Put(key1, value1))
  1015  	require.NoError(db.Put(key2, value2))
  1016  	require.NoError(db.Put(key3, value3))
  1017  
  1018  	count, err := Count(db)
  1019  	require.NoError(err)
  1020  	require.Equal(3, count)
  1021  
  1022  	require.NoError(clearF(db, []byte("hello")))
  1023  
  1024  	count, err = Count(db)
  1025  	require.NoError(err)
  1026  	require.Equal(1, count)
  1027  
  1028  	has, err := db.Has(key1)
  1029  	require.NoError(err)
  1030  	require.False(has)
  1031  
  1032  	has, err = db.Has(key2)
  1033  	require.NoError(err)
  1034  	require.True(has)
  1035  
  1036  	has, err = db.Has(key3)
  1037  	require.NoError(err)
  1038  	require.False(has)
  1039  
  1040  	require.NoError(db.Close())
  1041  }
  1042  
  1043  func TestModifyValueAfterPut(t *testing.T, db Database) {
  1044  	require := require.New(t)
  1045  
  1046  	key := []byte{1}
  1047  	value := []byte{1, 2}
  1048  	originalValue := slices.Clone(value)
  1049  
  1050  	require.NoError(db.Put(key, value))
  1051  
  1052  	// Modify the value that was Put into the database
  1053  	// to see if the database copied the value correctly.
  1054  	value[0] = 2
  1055  	retrievedValue, err := db.Get(key)
  1056  	require.NoError(err)
  1057  	require.Equal(originalValue, retrievedValue)
  1058  }
  1059  
  1060  func TestModifyValueAfterBatchPut(t *testing.T, db Database) {
  1061  	require := require.New(t)
  1062  
  1063  	key := []byte{1}
  1064  	value := []byte{1, 2}
  1065  	originalValue := slices.Clone(value)
  1066  
  1067  	batch := db.NewBatch()
  1068  	require.NoError(batch.Put(key, value))
  1069  
  1070  	// Modify the value that was Put into the Batch and then Write the
  1071  	// batch to the database.
  1072  	value[0] = 2
  1073  	require.NoError(batch.Write())
  1074  
  1075  	// Verify that the value written to the database contains matches the original
  1076  	// value of the byte slice when Put was called.
  1077  	retrievedValue, err := db.Get(key)
  1078  	require.NoError(err)
  1079  	require.Equal(originalValue, retrievedValue)
  1080  }
  1081  
  1082  func TestModifyValueAfterBatchPutReplay(t *testing.T, db Database) {
  1083  	require := require.New(t)
  1084  
  1085  	key := []byte{1}
  1086  	value := []byte{1, 2}
  1087  	originalValue := slices.Clone(value)
  1088  
  1089  	batch := db.NewBatch()
  1090  	require.NoError(batch.Put(key, value))
  1091  
  1092  	// Modify the value that was Put into the Batch and then Write the
  1093  	// batch to the database.
  1094  	value[0] = 2
  1095  
  1096  	// Create a new batch and replay the batch onto this one before writing it to the DB.
  1097  	replayBatch := db.NewBatch()
  1098  	require.NoError(batch.Replay(replayBatch))
  1099  	require.NoError(replayBatch.Write())
  1100  
  1101  	// Verify that the value written to the database contains matches the original
  1102  	// value of the byte slice when Put was called.
  1103  	retrievedValue, err := db.Get(key)
  1104  	require.NoError(err)
  1105  	require.Equal(originalValue, retrievedValue)
  1106  }
  1107  
  1108  func TestConcurrentBatches(t *testing.T, db Database) {
  1109  	numBatches := 10
  1110  	keysPerBatch := 50
  1111  	keySize := 32
  1112  	valueSize := units.KiB
  1113  
  1114  	require.NoError(t, runConcurrentBatches(
  1115  		db,
  1116  		numBatches,
  1117  		keysPerBatch,
  1118  		keySize,
  1119  		valueSize,
  1120  	))
  1121  }
  1122  
  1123  func TestManySmallConcurrentKVPairBatches(t *testing.T, db Database) {
  1124  	numBatches := 100
  1125  	keysPerBatch := 10
  1126  	keySize := 10
  1127  	valueSize := 10
  1128  
  1129  	require.NoError(t, runConcurrentBatches(
  1130  		db,
  1131  		numBatches,
  1132  		keysPerBatch,
  1133  		keySize,
  1134  		valueSize,
  1135  	))
  1136  }
  1137  
  1138  func runConcurrentBatches(
  1139  	db Database,
  1140  	numBatches,
  1141  	keysPerBatch,
  1142  	keySize,
  1143  	valueSize int,
  1144  ) error {
  1145  	batches := make([]Batch, 0, numBatches)
  1146  	for i := 0; i < numBatches; i++ {
  1147  		batches = append(batches, db.NewBatch())
  1148  	}
  1149  
  1150  	for _, batch := range batches {
  1151  		for i := 0; i < keysPerBatch; i++ {
  1152  			key := utils.RandomBytes(keySize)
  1153  			value := utils.RandomBytes(valueSize)
  1154  			if err := batch.Put(key, value); err != nil {
  1155  				return err
  1156  			}
  1157  		}
  1158  	}
  1159  
  1160  	var eg errgroup.Group
  1161  	for _, batch := range batches {
  1162  		eg.Go(batch.Write)
  1163  	}
  1164  	return eg.Wait()
  1165  }
  1166  
  1167  func TestPutGetEmpty(t *testing.T, db Database) {
  1168  	require := require.New(t)
  1169  
  1170  	key := []byte("hello")
  1171  
  1172  	require.NoError(db.Put(key, nil))
  1173  
  1174  	value, err := db.Get(key)
  1175  	require.NoError(err)
  1176  	require.Empty(value) // May be nil or empty byte slice.
  1177  
  1178  	require.NoError(db.Put(key, []byte{}))
  1179  
  1180  	value, err = db.Get(key)
  1181  	require.NoError(err)
  1182  	require.Empty(value) // May be nil or empty byte slice.
  1183  }
  1184  
  1185  func FuzzKeyValue(f *testing.F, db Database) {
  1186  	f.Fuzz(func(t *testing.T, key []byte, value []byte) {
  1187  		require := require.New(t)
  1188  
  1189  		require.NoError(db.Put(key, value))
  1190  
  1191  		exists, err := db.Has(key)
  1192  		require.NoError(err)
  1193  		require.True(exists)
  1194  
  1195  		gotVal, err := db.Get(key)
  1196  		require.NoError(err)
  1197  		require.True(bytes.Equal(value, gotVal))
  1198  
  1199  		require.NoError(db.Delete(key))
  1200  
  1201  		exists, err = db.Has(key)
  1202  		require.NoError(err)
  1203  		require.False(exists)
  1204  
  1205  		_, err = db.Get(key)
  1206  		require.Equal(ErrNotFound, err)
  1207  	})
  1208  }
  1209  
  1210  func FuzzNewIteratorWithPrefix(f *testing.F, db Database) {
  1211  	const (
  1212  		maxKeyLen   = 32
  1213  		maxValueLen = 32
  1214  	)
  1215  
  1216  	f.Fuzz(func(
  1217  		t *testing.T,
  1218  		randSeed int64,
  1219  		prefix []byte,
  1220  		numKeyValues uint,
  1221  	) {
  1222  		require := require.New(t)
  1223  		r := rand.New(rand.NewSource(randSeed)) // #nosec G404
  1224  
  1225  		// Put a bunch of key-values
  1226  		expected := map[string][]byte{}
  1227  		for i := 0; i < int(numKeyValues); i++ {
  1228  			key := make([]byte, r.Intn(maxKeyLen))
  1229  			_, _ = r.Read(key) // #nosec G404
  1230  
  1231  			value := make([]byte, r.Intn(maxValueLen))
  1232  			_, _ = r.Read(value) // #nosec G404
  1233  
  1234  			if len(value) == 0 {
  1235  				// Consistently treat zero length values as nil
  1236  				// so that we can compare [expected] and [got] with
  1237  				// require.Equal, which treats nil and empty byte
  1238  				// as being unequal, whereas the database treats
  1239  				// them as being equal.
  1240  				value = nil
  1241  			}
  1242  
  1243  			if bytes.HasPrefix(key, prefix) {
  1244  				expected[string(key)] = value
  1245  			}
  1246  
  1247  			require.NoError(db.Put(key, value))
  1248  		}
  1249  		expectedList := maps.Keys(expected)
  1250  		slices.Sort(expectedList)
  1251  
  1252  		iter := db.NewIteratorWithPrefix(prefix)
  1253  		defer iter.Release()
  1254  
  1255  		// Assert the iterator returns the expected key-values.
  1256  		numIterElts := 0
  1257  		for iter.Next() {
  1258  			val := iter.Value()
  1259  			if len(val) == 0 {
  1260  				val = nil
  1261  			}
  1262  			require.Equal(expectedList[numIterElts], string(iter.Key()))
  1263  			require.Equal(expected[string(iter.Key())], val)
  1264  			numIterElts++
  1265  		}
  1266  		require.Len(expectedList, numIterElts)
  1267  
  1268  		// Clear the database for the next fuzz iteration.
  1269  		require.NoError(AtomicClear(db, db))
  1270  	})
  1271  }
  1272  
  1273  func FuzzNewIteratorWithStartAndPrefix(f *testing.F, db Database) {
  1274  	const (
  1275  		maxKeyLen   = 32
  1276  		maxValueLen = 32
  1277  	)
  1278  
  1279  	f.Fuzz(func(
  1280  		t *testing.T,
  1281  		randSeed int64,
  1282  		start []byte,
  1283  		prefix []byte,
  1284  		numKeyValues uint,
  1285  	) {
  1286  		require := require.New(t)
  1287  		r := rand.New(rand.NewSource(randSeed)) // #nosec G404
  1288  
  1289  		expected := map[string][]byte{}
  1290  
  1291  		// Put a bunch of key-values
  1292  		for i := 0; i < int(numKeyValues); i++ {
  1293  			key := make([]byte, r.Intn(maxKeyLen))
  1294  			_, _ = r.Read(key) // #nosec G404
  1295  
  1296  			value := make([]byte, r.Intn(maxValueLen))
  1297  			_, _ = r.Read(value) // #nosec G404
  1298  
  1299  			if len(value) == 0 {
  1300  				// Consistently treat zero length values as nil
  1301  				// so that we can compare [expected] and [got] with
  1302  				// require.Equal, which treats nil and empty byte
  1303  				// as being unequal, whereas the database treats
  1304  				// them as being equal.
  1305  				value = nil
  1306  			}
  1307  
  1308  			if bytes.HasPrefix(key, prefix) && bytes.Compare(key, start) >= 0 {
  1309  				expected[string(key)] = value
  1310  			}
  1311  
  1312  			require.NoError(db.Put(key, value))
  1313  		}
  1314  
  1315  		expectedList := maps.Keys(expected)
  1316  		slices.Sort(expectedList)
  1317  
  1318  		iter := db.NewIteratorWithStartAndPrefix(start, prefix)
  1319  		defer iter.Release()
  1320  
  1321  		// Assert the iterator returns the expected key-values.
  1322  		numIterElts := 0
  1323  		for iter.Next() {
  1324  			val := iter.Value()
  1325  			if len(val) == 0 {
  1326  				val = nil
  1327  			}
  1328  			keyStr := string(iter.Key())
  1329  			require.Equal(expectedList[numIterElts], keyStr)
  1330  			require.Equal(expected[keyStr], val)
  1331  			numIterElts++
  1332  		}
  1333  		require.Len(expectedList, numIterElts)
  1334  
  1335  		// Clear the database for the next fuzz iteration.
  1336  		require.NoError(AtomicClear(db, db))
  1337  	})
  1338  }