github.com/koko1123/flow-go-1@v0.29.6/fvm/state/state_test.go (about)

     1  package state_test
     2  
     3  import (
     4  	"testing"
     5  	"unicode/utf8"
     6  
     7  	"github.com/stretchr/testify/require"
     8  
     9  	"github.com/onflow/atree"
    10  
    11  	"github.com/koko1123/flow-go-1/fvm/meter"
    12  	"github.com/koko1123/flow-go-1/fvm/state"
    13  	"github.com/koko1123/flow-go-1/fvm/utils"
    14  )
    15  
    16  func createByteArray(size int) []byte {
    17  	bytes := make([]byte, size)
    18  	for i := range bytes {
    19  		bytes[i] = 255
    20  	}
    21  	return bytes
    22  }
    23  
    24  func TestState_ChildMergeFunctionality(t *testing.T) {
    25  	view := utils.NewSimpleView()
    26  	st := state.NewState(view, state.DefaultParameters())
    27  
    28  	t.Run("test read from parent state (backoff)", func(t *testing.T) {
    29  		key := "key1"
    30  		value := createByteArray(1)
    31  		// set key1 on parent
    32  		err := st.Set("address", key, value, true)
    33  		require.NoError(t, err)
    34  
    35  		// read key1 on child
    36  		stChild := st.NewChild()
    37  		v, err := stChild.Get("address", key, true)
    38  		require.NoError(t, err)
    39  		require.Equal(t, v, value)
    40  	})
    41  
    42  	t.Run("test write to child (no merge)", func(t *testing.T) {
    43  		key := "key2"
    44  		value := createByteArray(2)
    45  		stChild := st.NewChild()
    46  
    47  		// set key2 on child
    48  		err := stChild.Set("address", key, value, true)
    49  		require.NoError(t, err)
    50  
    51  		// read key2 on parent
    52  		v, err := st.Get("address", key, true)
    53  		require.NoError(t, err)
    54  		require.Equal(t, len(v), 0)
    55  	})
    56  
    57  	t.Run("test write to child and merge", func(t *testing.T) {
    58  		key := "key3"
    59  		value := createByteArray(3)
    60  		stChild := st.NewChild()
    61  
    62  		// set key3 on child
    63  		err := stChild.Set("address", key, value, true)
    64  		require.NoError(t, err)
    65  
    66  		// read before merge
    67  		v, err := st.Get("address", key, true)
    68  		require.NoError(t, err)
    69  		require.Equal(t, len(v), 0)
    70  
    71  		// merge to parent
    72  		err = st.MergeState(stChild)
    73  		require.NoError(t, err)
    74  
    75  		// read key3 on parent
    76  		v, err = st.Get("address", key, true)
    77  		require.NoError(t, err)
    78  		require.Equal(t, v, value)
    79  	})
    80  
    81  	t.Run("test write to ledger", func(t *testing.T) {
    82  		key := "key4"
    83  		value := createByteArray(4)
    84  		// set key4 on parent
    85  		err := st.Set("address", key, value, true)
    86  		require.NoError(t, err)
    87  
    88  		// now should be part of the ledger
    89  		v, err := view.Get("address", key)
    90  		require.NoError(t, err)
    91  		require.Equal(t, v, value)
    92  	})
    93  
    94  }
    95  
    96  func TestState_MaxValueSize(t *testing.T) {
    97  	view := utils.NewSimpleView()
    98  	st := state.NewState(view, state.DefaultParameters().WithMaxValueSizeAllowed(6))
    99  
   100  	// update should pass
   101  	value := createByteArray(5)
   102  	err := st.Set("address", "key", value, true)
   103  	require.NoError(t, err)
   104  
   105  	// update shouldn't pass
   106  	value = createByteArray(7)
   107  	err = st.Set("address", "key", value, true)
   108  	require.Error(t, err)
   109  }
   110  
   111  func TestState_MaxKeySize(t *testing.T) {
   112  	view := utils.NewSimpleView()
   113  	st := state.NewState(view, state.DefaultParameters().WithMaxKeySizeAllowed(4))
   114  
   115  	// read
   116  	_, err := st.Get("1", "2", true)
   117  	require.NoError(t, err)
   118  
   119  	// read
   120  	_, err = st.Get("123", "234", true)
   121  	require.Error(t, err)
   122  
   123  	// update
   124  	err = st.Set("1", "2", []byte{}, true)
   125  	require.NoError(t, err)
   126  
   127  	// read
   128  	err = st.Set("123", "234", []byte{}, true)
   129  	require.Error(t, err)
   130  
   131  }
   132  
   133  func TestState_MaxInteraction(t *testing.T) {
   134  	view := utils.NewSimpleView()
   135  	st := state.NewState(
   136  		view,
   137  		state.DefaultParameters().
   138  			WithMeterParameters(
   139  				meter.DefaultParameters().WithStorageInteractionLimit(12)))
   140  
   141  	// read - interaction 2
   142  	_, err := st.Get("1", "2", true)
   143  	require.Equal(t, st.InteractionUsed(), uint64(2))
   144  	require.NoError(t, err)
   145  
   146  	// read - interaction 8
   147  	_, err = st.Get("123", "234", true)
   148  	require.Equal(t, st.InteractionUsed(), uint64(8))
   149  	require.NoError(t, err)
   150  
   151  	// read - interaction 14
   152  	_, err = st.Get("234", "345", true)
   153  	require.Equal(t, st.InteractionUsed(), uint64(14))
   154  	require.Error(t, err)
   155  
   156  	st = state.NewState(
   157  		view,
   158  		state.DefaultParameters().
   159  			WithMeterParameters(
   160  				meter.DefaultParameters().WithStorageInteractionLimit(6)))
   161  	stChild := st.NewChild()
   162  
   163  	// update - 0
   164  	err = stChild.Set("1", "2", []byte{'A'}, true)
   165  	require.NoError(t, err)
   166  	require.Equal(t, st.InteractionUsed(), uint64(0))
   167  
   168  	// commit
   169  	err = st.MergeState(stChild)
   170  	require.NoError(t, err)
   171  	require.Equal(t, st.InteractionUsed(), uint64(3))
   172  
   173  	// read - interaction 3 (already in read cache)
   174  	_, err = st.Get("1", "2", true)
   175  	require.NoError(t, err)
   176  	require.Equal(t, st.InteractionUsed(), uint64(3))
   177  
   178  	// read - interaction 5
   179  	_, err = st.Get("2", "3", true)
   180  	require.NoError(t, err)
   181  	require.Equal(t, st.InteractionUsed(), uint64(5))
   182  
   183  	// read - interaction 7
   184  	_, err = st.Get("3", "4", true)
   185  	require.Error(t, err)
   186  
   187  }
   188  
   189  func TestState_IsFVMStateKey(t *testing.T) {
   190  	require.True(t, state.IsFVMStateKey("", state.UUIDKey))
   191  	require.True(t, state.IsFVMStateKey("", state.AddressStateKey))
   192  	require.False(t, state.IsFVMStateKey("", "other"))
   193  	require.False(t, state.IsFVMStateKey("Address", state.UUIDKey))
   194  	require.False(t, state.IsFVMStateKey("Address", state.AddressStateKey))
   195  	require.True(t, state.IsFVMStateKey("Address", "public_key_12"))
   196  	require.True(t, state.IsFVMStateKey("Address", state.ContractNamesKey))
   197  	require.True(t, state.IsFVMStateKey("Address", "code.MYCODE"))
   198  	require.True(t, state.IsFVMStateKey("Address", state.AccountStatusKey))
   199  	require.False(t, state.IsFVMStateKey("Address", "anything else"))
   200  }
   201  
   202  func TestAccounts_PrintableKey(t *testing.T) {
   203  	// slab with 189 should result in \\xbd
   204  	slabIndex := atree.StorageIndex([8]byte{0, 0, 0, 0, 0, 0, 0, 189})
   205  	key := string(atree.SlabIndexToLedgerKey(slabIndex))
   206  	require.False(t, utf8.ValidString(key))
   207  	printable := state.PrintableKey(key)
   208  	require.True(t, utf8.ValidString(printable))
   209  	require.Equal(t, "$189", printable)
   210  
   211  	// non slab invalid utf-8
   212  	key = "a\xc5z"
   213  	require.False(t, utf8.ValidString(key))
   214  	printable = state.PrintableKey(key)
   215  	require.True(t, utf8.ValidString(printable))
   216  	require.Equal(t, "#61c57a", printable)
   217  }