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 }