github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/store/prefix/store_test.go (about)

     1  package prefix
     2  
     3  import (
     4  	"crypto/rand"
     5  	"testing"
     6  
     7  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/dbadapter"
     8  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/gaskv"
     9  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/iavl"
    10  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/types"
    11  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    12  
    13  	"github.com/stretchr/testify/require"
    14  
    15  	tiavl "github.com/fibonacci-chain/fbc/libs/iavl"
    16  	dbm "github.com/fibonacci-chain/fbc/libs/tm-db"
    17  )
    18  
    19  // copied from iavl/store_test.go
    20  var cacheSize = 100
    21  
    22  func bz(s string) []byte { return []byte(s) }
    23  
    24  type kvpair struct {
    25  	key   []byte
    26  	value []byte
    27  }
    28  
    29  func genRandomKVPairs(t *testing.T) []kvpair {
    30  	kvps := make([]kvpair, 20)
    31  
    32  	for i := 0; i < 20; i++ {
    33  		kvps[i].key = make([]byte, 32)
    34  		rand.Read(kvps[i].key)
    35  		kvps[i].value = make([]byte, 32)
    36  		rand.Read(kvps[i].value)
    37  	}
    38  
    39  	return kvps
    40  }
    41  
    42  func setRandomKVPairs(t *testing.T, store types.KVStore) []kvpair {
    43  	kvps := genRandomKVPairs(t)
    44  	for _, kvp := range kvps {
    45  		store.Set(kvp.key, kvp.value)
    46  	}
    47  	return kvps
    48  }
    49  
    50  func testPrefixStore(t *testing.T, baseStore types.KVStore, prefix []byte) {
    51  	prefixStore := NewStore(baseStore, prefix)
    52  	prefixPrefixStore := NewStore(prefixStore, []byte("prefix"))
    53  
    54  	require.Panics(t, func() { prefixStore.Get(nil) })
    55  	require.Panics(t, func() { prefixStore.Set(nil, []byte{}) })
    56  
    57  	kvps := setRandomKVPairs(t, prefixPrefixStore)
    58  
    59  	for i := 0; i < 20; i++ {
    60  		key := kvps[i].key
    61  		value := kvps[i].value
    62  		require.True(t, prefixPrefixStore.Has(key))
    63  		require.Equal(t, value, prefixPrefixStore.Get(key))
    64  
    65  		key = append([]byte("prefix"), key...)
    66  		require.True(t, prefixStore.Has(key))
    67  		require.Equal(t, value, prefixStore.Get(key))
    68  		key = append(prefix, key...)
    69  		require.True(t, baseStore.Has(key))
    70  		require.Equal(t, value, baseStore.Get(key))
    71  
    72  		key = kvps[i].key
    73  		prefixPrefixStore.Delete(key)
    74  		require.False(t, prefixPrefixStore.Has(key))
    75  		require.Nil(t, prefixPrefixStore.Get(key))
    76  		key = append([]byte("prefix"), key...)
    77  		require.False(t, prefixStore.Has(key))
    78  		require.Nil(t, prefixStore.Get(key))
    79  		key = append(prefix, key...)
    80  		require.False(t, baseStore.Has(key))
    81  		require.Nil(t, baseStore.Get(key))
    82  	}
    83  }
    84  
    85  func TestIAVLStorePrefix(t *testing.T) {
    86  	db := dbm.NewMemDB()
    87  	tree, err := tiavl.NewMutableTree(db, cacheSize)
    88  	require.NoError(t, err)
    89  	iavlStore := iavl.UnsafeNewStore(tree)
    90  
    91  	testPrefixStore(t, iavlStore, []byte("test"))
    92  }
    93  
    94  func TestPrefixKVStoreNoNilSet(t *testing.T) {
    95  	meter := types.NewGasMeter(100000000)
    96  	mem := dbadapter.Store{DB: dbm.NewMemDB()}
    97  	gasStore := gaskv.NewStore(mem, meter, types.KVGasConfig())
    98  	require.Panics(t, func() { gasStore.Set([]byte("key"), nil) }, "setting a nil value should panic")
    99  }
   100  
   101  func TestPrefixStoreIterate(t *testing.T) {
   102  	db := dbm.NewMemDB()
   103  	baseStore := dbadapter.Store{DB: db}
   104  	prefix := []byte("test")
   105  	prefixStore := NewStore(baseStore, prefix)
   106  
   107  	setRandomKVPairs(t, prefixStore)
   108  
   109  	bIter := types.KVStorePrefixIterator(baseStore, prefix)
   110  	pIter := types.KVStorePrefixIterator(prefixStore, nil)
   111  
   112  	for bIter.Valid() && pIter.Valid() {
   113  		require.Equal(t, bIter.Key(), append(prefix, pIter.Key()...))
   114  		require.Equal(t, bIter.Value(), pIter.Value())
   115  
   116  		bIter.Next()
   117  		pIter.Next()
   118  	}
   119  
   120  	bIter.Close()
   121  	pIter.Close()
   122  }
   123  
   124  func incFirstByte(bz []byte) {
   125  	bz[0]++
   126  }
   127  
   128  func TestCloneAppend(t *testing.T) {
   129  	kvps := genRandomKVPairs(t)
   130  	for _, kvp := range kvps {
   131  		bz := cloneAppend(kvp.key, kvp.value)
   132  		require.Equal(t, bz, append(kvp.key, kvp.value...))
   133  
   134  		incFirstByte(bz)
   135  		require.NotEqual(t, bz, append(kvp.key, kvp.value...))
   136  
   137  		bz = cloneAppend(kvp.key, kvp.value)
   138  		incFirstByte(kvp.key)
   139  		require.NotEqual(t, bz, append(kvp.key, kvp.value...))
   140  
   141  		bz = cloneAppend(kvp.key, kvp.value)
   142  		incFirstByte(kvp.value)
   143  		require.NotEqual(t, bz, append(kvp.key, kvp.value...))
   144  	}
   145  }
   146  
   147  func TestPrefixStoreIteratorEdgeCase(t *testing.T) {
   148  	db := dbm.NewMemDB()
   149  	baseStore := dbadapter.Store{DB: db}
   150  
   151  	// overflow in cpIncr
   152  	prefix := []byte{0xAA, 0xFF, 0xFF}
   153  	prefixStore := NewStore(baseStore, prefix)
   154  
   155  	// ascending order
   156  	baseStore.Set([]byte{0xAA, 0xFF, 0xFE}, []byte{})
   157  	baseStore.Set([]byte{0xAA, 0xFF, 0xFE, 0x00}, []byte{})
   158  	baseStore.Set([]byte{0xAA, 0xFF, 0xFF}, []byte{})
   159  	baseStore.Set([]byte{0xAA, 0xFF, 0xFF, 0x00}, []byte{})
   160  	baseStore.Set([]byte{0xAB}, []byte{})
   161  	baseStore.Set([]byte{0xAB, 0x00}, []byte{})
   162  	baseStore.Set([]byte{0xAB, 0x00, 0x00}, []byte{})
   163  
   164  	iter := prefixStore.Iterator(nil, nil)
   165  
   166  	checkDomain(t, iter, nil, nil)
   167  	checkItem(t, iter, []byte{}, bz(""))
   168  	checkNext(t, iter, true)
   169  	checkItem(t, iter, []byte{0x00}, bz(""))
   170  	checkNext(t, iter, false)
   171  
   172  	checkInvalid(t, iter)
   173  
   174  	iter.Close()
   175  }
   176  
   177  func TestPrefixStoreReverseIteratorEdgeCase(t *testing.T) {
   178  	db := dbm.NewMemDB()
   179  	baseStore := dbadapter.Store{DB: db}
   180  
   181  	// overflow in cpIncr
   182  	prefix := []byte{0xAA, 0xFF, 0xFF}
   183  	prefixStore := NewStore(baseStore, prefix)
   184  
   185  	// descending order
   186  	baseStore.Set([]byte{0xAB, 0x00, 0x00}, []byte{})
   187  	baseStore.Set([]byte{0xAB, 0x00}, []byte{})
   188  	baseStore.Set([]byte{0xAB}, []byte{})
   189  	baseStore.Set([]byte{0xAA, 0xFF, 0xFF, 0x00}, []byte{})
   190  	baseStore.Set([]byte{0xAA, 0xFF, 0xFF}, []byte{})
   191  	baseStore.Set([]byte{0xAA, 0xFF, 0xFE, 0x00}, []byte{})
   192  	baseStore.Set([]byte{0xAA, 0xFF, 0xFE}, []byte{})
   193  
   194  	iter := prefixStore.ReverseIterator(nil, nil)
   195  
   196  	checkDomain(t, iter, nil, nil)
   197  	checkItem(t, iter, []byte{0x00}, bz(""))
   198  	checkNext(t, iter, true)
   199  	checkItem(t, iter, []byte{}, bz(""))
   200  	checkNext(t, iter, false)
   201  
   202  	checkInvalid(t, iter)
   203  
   204  	iter.Close()
   205  
   206  	db = dbm.NewMemDB()
   207  	baseStore = dbadapter.Store{DB: db}
   208  
   209  	// underflow in cpDecr
   210  	prefix = []byte{0xAA, 0x00, 0x00}
   211  	prefixStore = NewStore(baseStore, prefix)
   212  
   213  	baseStore.Set([]byte{0xAB, 0x00, 0x01, 0x00, 0x00}, []byte{})
   214  	baseStore.Set([]byte{0xAB, 0x00, 0x01, 0x00}, []byte{})
   215  	baseStore.Set([]byte{0xAB, 0x00, 0x01}, []byte{})
   216  	baseStore.Set([]byte{0xAA, 0x00, 0x00, 0x00}, []byte{})
   217  	baseStore.Set([]byte{0xAA, 0x00, 0x00}, []byte{})
   218  	baseStore.Set([]byte{0xA9, 0xFF, 0xFF, 0x00}, []byte{})
   219  	baseStore.Set([]byte{0xA9, 0xFF, 0xFF}, []byte{})
   220  
   221  	iter = prefixStore.ReverseIterator(nil, nil)
   222  
   223  	checkDomain(t, iter, nil, nil)
   224  	checkItem(t, iter, []byte{0x00}, bz(""))
   225  	checkNext(t, iter, true)
   226  	checkItem(t, iter, []byte{}, bz(""))
   227  	checkNext(t, iter, false)
   228  
   229  	checkInvalid(t, iter)
   230  
   231  	iter.Close()
   232  }
   233  
   234  // Tests below are ported from https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db_test.go
   235  
   236  func mockStoreWithStuff() types.KVStore {
   237  	db := dbm.NewMemDB()
   238  	store := dbadapter.Store{DB: db}
   239  	// Under "key" prefix
   240  	store.Set(bz("key"), bz("value"))
   241  	store.Set(bz("key1"), bz("value1"))
   242  	store.Set(bz("key2"), bz("value2"))
   243  	store.Set(bz("key3"), bz("value3"))
   244  	store.Set(bz("something"), bz("else"))
   245  	store.Set(bz(""), bz(""))
   246  	store.Set(bz("k"), bz(sdk.PrefixValidator))
   247  	store.Set(bz("ke"), bz("valu"))
   248  	store.Set(bz("kee"), bz("valuu"))
   249  	return store
   250  }
   251  
   252  func checkValue(t *testing.T, store types.KVStore, key []byte, expected []byte) {
   253  	bz := store.Get(key)
   254  	require.Equal(t, expected, bz)
   255  }
   256  
   257  func checkValid(t *testing.T, itr types.Iterator, expected bool) {
   258  	valid := itr.Valid()
   259  	require.Equal(t, expected, valid)
   260  }
   261  
   262  func checkNext(t *testing.T, itr types.Iterator, expected bool) {
   263  	itr.Next()
   264  	valid := itr.Valid()
   265  	require.Equal(t, expected, valid)
   266  }
   267  
   268  func checkDomain(t *testing.T, itr types.Iterator, start, end []byte) {
   269  	ds, de := itr.Domain()
   270  	require.Equal(t, start, ds)
   271  	require.Equal(t, end, de)
   272  }
   273  
   274  func checkItem(t *testing.T, itr types.Iterator, key, value []byte) {
   275  	require.Exactly(t, key, itr.Key())
   276  	require.Exactly(t, value, itr.Value())
   277  }
   278  
   279  func checkInvalid(t *testing.T, itr types.Iterator) {
   280  	checkValid(t, itr, false)
   281  	checkKeyPanics(t, itr)
   282  	checkValuePanics(t, itr)
   283  	checkNextPanics(t, itr)
   284  }
   285  
   286  func checkKeyPanics(t *testing.T, itr types.Iterator) {
   287  	require.Panics(t, func() { itr.Key() })
   288  }
   289  
   290  func checkValuePanics(t *testing.T, itr types.Iterator) {
   291  	require.Panics(t, func() { itr.Value() })
   292  }
   293  
   294  func checkNextPanics(t *testing.T, itr types.Iterator) {
   295  	require.Panics(t, func() { itr.Next() })
   296  }
   297  
   298  func TestPrefixDBSimple(t *testing.T) {
   299  	store := mockStoreWithStuff()
   300  	pstore := NewStore(store, bz("key"))
   301  
   302  	checkValue(t, pstore, bz("key"), nil)
   303  	checkValue(t, pstore, bz(""), bz("value"))
   304  	checkValue(t, pstore, bz("key1"), nil)
   305  	checkValue(t, pstore, bz("1"), bz("value1"))
   306  	checkValue(t, pstore, bz("key2"), nil)
   307  	checkValue(t, pstore, bz("2"), bz("value2"))
   308  	checkValue(t, pstore, bz("key3"), nil)
   309  	checkValue(t, pstore, bz("3"), bz("value3"))
   310  	checkValue(t, pstore, bz("something"), nil)
   311  	checkValue(t, pstore, bz("k"), nil)
   312  	checkValue(t, pstore, bz("ke"), nil)
   313  	checkValue(t, pstore, bz("kee"), nil)
   314  }
   315  
   316  func TestPrefixDBIterator1(t *testing.T) {
   317  	store := mockStoreWithStuff()
   318  	pstore := NewStore(store, bz("key"))
   319  
   320  	itr := pstore.Iterator(nil, nil)
   321  	checkDomain(t, itr, nil, nil)
   322  	checkItem(t, itr, bz(""), bz("value"))
   323  	checkNext(t, itr, true)
   324  	checkItem(t, itr, bz("1"), bz("value1"))
   325  	checkNext(t, itr, true)
   326  	checkItem(t, itr, bz("2"), bz("value2"))
   327  	checkNext(t, itr, true)
   328  	checkItem(t, itr, bz("3"), bz("value3"))
   329  	checkNext(t, itr, false)
   330  	checkInvalid(t, itr)
   331  	itr.Close()
   332  }
   333  
   334  func TestPrefixDBIterator2(t *testing.T) {
   335  	store := mockStoreWithStuff()
   336  	pstore := NewStore(store, bz("key"))
   337  
   338  	itr := pstore.Iterator(nil, bz(""))
   339  	checkDomain(t, itr, nil, bz(""))
   340  	checkInvalid(t, itr)
   341  	itr.Close()
   342  }
   343  
   344  func TestPrefixDBIterator3(t *testing.T) {
   345  	store := mockStoreWithStuff()
   346  	pstore := NewStore(store, bz("key"))
   347  
   348  	itr := pstore.Iterator(bz(""), nil)
   349  	checkDomain(t, itr, bz(""), nil)
   350  	checkItem(t, itr, bz(""), bz("value"))
   351  	checkNext(t, itr, true)
   352  	checkItem(t, itr, bz("1"), bz("value1"))
   353  	checkNext(t, itr, true)
   354  	checkItem(t, itr, bz("2"), bz("value2"))
   355  	checkNext(t, itr, true)
   356  	checkItem(t, itr, bz("3"), bz("value3"))
   357  	checkNext(t, itr, false)
   358  	checkInvalid(t, itr)
   359  	itr.Close()
   360  }
   361  
   362  func TestPrefixDBIterator4(t *testing.T) {
   363  	store := mockStoreWithStuff()
   364  	pstore := NewStore(store, bz("key"))
   365  
   366  	itr := pstore.Iterator(bz(""), bz(""))
   367  	checkDomain(t, itr, bz(""), bz(""))
   368  	checkInvalid(t, itr)
   369  	itr.Close()
   370  }
   371  
   372  func TestPrefixDBReverseIterator1(t *testing.T) {
   373  	store := mockStoreWithStuff()
   374  	pstore := NewStore(store, bz("key"))
   375  
   376  	itr := pstore.ReverseIterator(nil, nil)
   377  	checkDomain(t, itr, nil, nil)
   378  	checkItem(t, itr, bz("3"), bz("value3"))
   379  	checkNext(t, itr, true)
   380  	checkItem(t, itr, bz("2"), bz("value2"))
   381  	checkNext(t, itr, true)
   382  	checkItem(t, itr, bz("1"), bz("value1"))
   383  	checkNext(t, itr, true)
   384  	checkItem(t, itr, bz(""), bz("value"))
   385  	checkNext(t, itr, false)
   386  	checkInvalid(t, itr)
   387  	itr.Close()
   388  }
   389  
   390  func TestPrefixDBReverseIterator2(t *testing.T) {
   391  	store := mockStoreWithStuff()
   392  	pstore := NewStore(store, bz("key"))
   393  
   394  	itr := pstore.ReverseIterator(bz(""), nil)
   395  	checkDomain(t, itr, bz(""), nil)
   396  	checkItem(t, itr, bz("3"), bz("value3"))
   397  	checkNext(t, itr, true)
   398  	checkItem(t, itr, bz("2"), bz("value2"))
   399  	checkNext(t, itr, true)
   400  	checkItem(t, itr, bz("1"), bz("value1"))
   401  	checkNext(t, itr, true)
   402  	checkItem(t, itr, bz(""), bz("value"))
   403  	checkNext(t, itr, false)
   404  	checkInvalid(t, itr)
   405  	itr.Close()
   406  }
   407  
   408  func TestPrefixDBReverseIterator3(t *testing.T) {
   409  	store := mockStoreWithStuff()
   410  	pstore := NewStore(store, bz("key"))
   411  
   412  	itr := pstore.ReverseIterator(nil, bz(""))
   413  	checkDomain(t, itr, nil, bz(""))
   414  	checkInvalid(t, itr)
   415  	itr.Close()
   416  }
   417  
   418  func TestPrefixDBReverseIterator4(t *testing.T) {
   419  	store := mockStoreWithStuff()
   420  	pstore := NewStore(store, bz("key"))
   421  
   422  	itr := pstore.ReverseIterator(bz(""), bz(""))
   423  	checkInvalid(t, itr)
   424  	itr.Close()
   425  }