github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/storage/state/storage_state_test.go (about) 1 package state 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/require" 7 8 "github.com/onflow/flow-go/fvm/storage/snapshot" 9 "github.com/onflow/flow-go/model/flow" 10 "github.com/onflow/flow-go/utils/unittest" 11 ) 12 13 func TestStorageStateSet(t *testing.T) { 14 fooOwner := unittest.RandomAddressFixture() 15 16 registerId1 := flow.NewRegisterID(fooOwner, "1") 17 value1 := flow.RegisterValue([]byte("value1")) 18 19 registerId2 := flow.NewRegisterID(fooOwner, "2") 20 value2 := flow.RegisterValue([]byte("value2")) 21 22 state := newStorageState(nil) 23 24 err := state.Set(registerId1, []byte("old value")) 25 require.NoError(t, err) 26 27 err = state.Set(registerId2, value2) 28 require.NoError(t, err) 29 30 err = state.Set(registerId1, value1) 31 require.NoError(t, err) 32 33 snapshot := state.Finalize() 34 require.Empty(t, snapshot.ReadSet) 35 require.Equal( 36 t, 37 snapshot.WriteSet, 38 map[flow.RegisterID]flow.RegisterValue{ 39 registerId1: value1, 40 registerId2: value2, 41 }) 42 } 43 44 func TestStorageStateGetFromNilBase(t *testing.T) { 45 state := newStorageState(nil) 46 value, err := state.Get(flow.NewRegisterID(unittest.RandomAddressFixture(), "bar")) 47 require.NoError(t, err) 48 require.Nil(t, value) 49 } 50 51 func TestStorageStateGetFromBase(t *testing.T) { 52 registerId := flow.NewRegisterID(flow.EmptyAddress, "base") 53 baseValue := flow.RegisterValue([]byte("base")) 54 55 state := newStorageState( 56 snapshot.MapStorageSnapshot{ 57 registerId: baseValue, 58 }) 59 60 value, err := state.Get(registerId) 61 require.NoError(t, err) 62 require.Equal(t, value, baseValue) 63 64 // Finalize to ensure read set is updated. 65 snapshot := state.Finalize() 66 require.Equal( 67 t, 68 snapshot.ReadSet, 69 map[flow.RegisterID]struct{}{ 70 registerId: struct{}{}, 71 }) 72 require.Empty(t, snapshot.WriteSet) 73 74 // Override a previous read value won't change the read set. 75 updatedValue := flow.RegisterValue([]byte("value")) 76 err = state.Set(registerId, updatedValue) 77 require.NoError(t, err) 78 79 snapshot = state.Finalize() 80 require.Equal( 81 t, 82 snapshot.ReadSet, 83 map[flow.RegisterID]struct{}{ 84 registerId: struct{}{}, 85 }) 86 require.Equal( 87 t, 88 snapshot.WriteSet, 89 map[flow.RegisterID]flow.RegisterValue{ 90 registerId: updatedValue, 91 }) 92 } 93 94 func TestStorageStateGetFromWriteSet(t *testing.T) { 95 registerId := flow.NewRegisterID(flow.EmptyAddress, "base") 96 expectedValue := flow.RegisterValue([]byte("base")) 97 98 state := newStorageState(nil) 99 100 err := state.Set(registerId, expectedValue) 101 require.NoError(t, err) 102 103 value, err := state.Get(registerId) 104 require.NoError(t, err) 105 require.Equal(t, value, expectedValue) 106 107 snapshot := state.Finalize() 108 require.Empty(t, snapshot.ReadSet) 109 require.Equal( 110 t, 111 snapshot.WriteSet, 112 map[flow.RegisterID]flow.RegisterValue{ 113 registerId: expectedValue, 114 }) 115 } 116 117 func TestStorageStateMerge(t *testing.T) { 118 parentOwner := unittest.RandomAddressFixture() 119 childOwner := unittest.RandomAddressFixture() 120 121 baseRegisterId := flow.NewRegisterID(flow.EmptyAddress, "base") 122 baseValue := flow.RegisterValue([]byte("base")) 123 124 parentRegisterId1 := flow.NewRegisterID(parentOwner, "1") 125 parentValue := flow.RegisterValue([]byte("parent")) 126 127 parentRegisterId2 := flow.NewRegisterID(parentOwner, "2") 128 129 parentRegisterId3 := flow.NewRegisterID(parentOwner, "3") 130 originalParentValue3 := flow.RegisterValue([]byte("parent value")) 131 updatedParentValue3 := flow.RegisterValue([]byte("child value")) 132 133 childRegisterId1 := flow.NewRegisterID(childOwner, "1") 134 childValue1 := flow.RegisterValue([]byte("child")) 135 136 childRegisterId2 := flow.NewRegisterID(childOwner, "2") 137 138 parent := newStorageState( 139 snapshot.MapStorageSnapshot{ 140 baseRegisterId: baseValue, 141 }) 142 143 err := parent.Set(parentRegisterId1, parentValue) 144 require.NoError(t, err) 145 146 value, err := parent.Get(parentRegisterId2) 147 require.NoError(t, err) 148 require.Nil(t, value) 149 150 err = parent.Set(parentRegisterId3, originalParentValue3) 151 require.NoError(t, err) 152 153 child := parent.NewChild() 154 155 err = child.Set(parentRegisterId3, updatedParentValue3) 156 require.NoError(t, err) 157 158 value, err = child.Get(baseRegisterId) 159 require.NoError(t, err) 160 require.Equal(t, value, baseValue) 161 162 value, err = child.Get(parentRegisterId1) 163 require.NoError(t, err) 164 require.Equal(t, value, parentValue) 165 166 value, err = child.Get(childRegisterId2) 167 require.NoError(t, err) 168 require.Nil(t, value) 169 170 err = child.Set(childRegisterId1, childValue1) 171 require.NoError(t, err) 172 173 childSnapshot := child.Finalize() 174 require.Equal( 175 t, 176 childSnapshot.ReadSet, 177 map[flow.RegisterID]struct{}{ 178 baseRegisterId: struct{}{}, 179 parentRegisterId1: struct{}{}, 180 childRegisterId2: struct{}{}, 181 }) 182 183 require.Equal( 184 t, 185 childSnapshot.WriteSet, 186 map[flow.RegisterID]flow.RegisterValue{ 187 childRegisterId1: childValue1, 188 parentRegisterId3: updatedParentValue3, 189 }) 190 191 // Finalize parent without merging child to see if they are independent. 192 parentSnapshot := parent.Finalize() 193 require.Equal( 194 t, 195 parentSnapshot.ReadSet, 196 map[flow.RegisterID]struct{}{ 197 parentRegisterId2: struct{}{}, 198 }) 199 200 require.Equal( 201 t, 202 parentSnapshot.WriteSet, 203 map[flow.RegisterID]flow.RegisterValue{ 204 parentRegisterId1: parentValue, 205 parentRegisterId3: originalParentValue3, 206 }) 207 208 // Merge the child snapshot and check again 209 err = parent.Merge(childSnapshot) 210 require.NoError(t, err) 211 212 parentSnapshot = parent.Finalize() 213 require.Equal( 214 t, 215 parentSnapshot.ReadSet, 216 map[flow.RegisterID]struct{}{ 217 // from parent's state 218 parentRegisterId2: struct{}{}, 219 220 // from child's state (parentRegisterId1 is not included since 221 // that value is read from the write set) 222 baseRegisterId: struct{}{}, 223 childRegisterId2: struct{}{}, 224 }) 225 226 require.Equal( 227 t, 228 parentSnapshot.WriteSet, 229 map[flow.RegisterID]flow.RegisterValue{ 230 // from parent's state (parentRegisterId3 is overwritten by child) 231 parentRegisterId1: parentValue, 232 233 // from parent's state 234 childRegisterId1: childValue1, 235 parentRegisterId3: updatedParentValue3, 236 }) 237 }