github.com/ava-labs/avalanchego@v1.11.11/database/dbtest/dbtest.go (about)

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