github.com/Finschia/finschia-sdk@v0.48.1/store/prefix/store_test.go (about)

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