github.com/koko1123/flow-go-1@v0.29.6/engine/execution/state/state_test.go (about) 1 package state_test 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/dgraph-io/badger/v3" 8 "github.com/golang/mock/gomock" 9 "github.com/rs/zerolog" 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 13 ledger2 "github.com/koko1123/flow-go-1/ledger" 14 "github.com/koko1123/flow-go-1/ledger/common/pathfinder" 15 16 "github.com/koko1123/flow-go-1/engine/execution/state" 17 ledger "github.com/koko1123/flow-go-1/ledger/complete" 18 "github.com/koko1123/flow-go-1/ledger/complete/wal/fixtures" 19 "github.com/koko1123/flow-go-1/model/flow" 20 "github.com/koko1123/flow-go-1/module/metrics" 21 "github.com/koko1123/flow-go-1/module/trace" 22 storage "github.com/koko1123/flow-go-1/storage/mock" 23 "github.com/koko1123/flow-go-1/storage/mocks" 24 "github.com/koko1123/flow-go-1/utils/unittest" 25 ) 26 27 func prepareTest(f func(t *testing.T, es state.ExecutionState, l *ledger.Ledger)) func(*testing.T) { 28 return func(t *testing.T) { 29 unittest.RunWithBadgerDB(t, func(badgerDB *badger.DB) { 30 metricsCollector := &metrics.NoopCollector{} 31 diskWal := &fixtures.NoopWAL{} 32 ls, err := ledger.NewLedger(diskWal, 100, metricsCollector, zerolog.Nop(), ledger.DefaultPathFinderVersion) 33 require.NoError(t, err) 34 compactor := fixtures.NewNoopCompactor(ls) 35 <-compactor.Ready() 36 defer func() { 37 <-ls.Done() 38 <-compactor.Done() 39 }() 40 41 ctrl := gomock.NewController(t) 42 43 stateCommitments := mocks.NewMockCommits(ctrl) 44 blocks := mocks.NewMockBlocks(ctrl) 45 headers := mocks.NewMockHeaders(ctrl) 46 collections := mocks.NewMockCollections(ctrl) 47 events := mocks.NewMockEvents(ctrl) 48 serviceEvents := mocks.NewMockServiceEvents(ctrl) 49 txResults := mocks.NewMockTransactionResults(ctrl) 50 51 stateCommitment := ls.InitialState() 52 53 stateCommitments.EXPECT().ByBlockID(gomock.Any()).Return(flow.StateCommitment(stateCommitment), nil) 54 55 chunkDataPacks := new(storage.ChunkDataPacks) 56 57 results := new(storage.ExecutionResults) 58 myReceipts := new(storage.MyExecutionReceipts) 59 60 es := state.NewExecutionState( 61 ls, stateCommitments, blocks, headers, collections, chunkDataPacks, results, myReceipts, events, serviceEvents, txResults, badgerDB, trace.NewNoopTracer(), 62 ) 63 64 f(t, es, ls) 65 }) 66 } 67 } 68 69 func TestExecutionStateWithTrieStorage(t *testing.T) { 70 registerID1 := "fruit" 71 72 registerID2 := "vegetable" 73 74 t.Run("commit write and read new state", prepareTest(func(t *testing.T, es state.ExecutionState, l *ledger.Ledger) { 75 // TODO: use real block ID 76 sc1, err := es.StateCommitmentByBlockID(context.Background(), flow.Identifier{}) 77 assert.NoError(t, err) 78 79 view1 := es.NewView(sc1) 80 81 err = view1.Set(registerID1, "", flow.RegisterValue("apple")) 82 assert.NoError(t, err) 83 err = view1.Set(registerID2, "", flow.RegisterValue("carrot")) 84 assert.NoError(t, err) 85 86 sc2, update, err := state.CommitDelta(l, view1.Delta(), sc1) 87 assert.NoError(t, err) 88 89 assert.Equal(t, sc1[:], update.RootHash[:]) 90 assert.Len(t, update.Paths, 2) 91 assert.Len(t, update.Payloads, 2) 92 93 key1 := ledger2.NewKey([]ledger2.KeyPart{ledger2.NewKeyPart(0, []byte(registerID1)), ledger2.NewKeyPart(2, []byte(""))}) 94 path1, err := pathfinder.KeyToPath(key1, ledger.DefaultPathFinderVersion) 95 assert.NoError(t, err) 96 97 key2 := ledger2.NewKey([]ledger2.KeyPart{ledger2.NewKeyPart(0, []byte(registerID2)), ledger2.NewKeyPart(2, []byte(""))}) 98 path2, err := pathfinder.KeyToPath(key2, ledger.DefaultPathFinderVersion) 99 assert.NoError(t, err) 100 101 assert.Equal(t, path1, update.Paths[0]) 102 assert.Equal(t, path2, update.Paths[1]) 103 104 k1, err := update.Payloads[0].Key() 105 require.NoError(t, err) 106 107 k2, err := update.Payloads[1].Key() 108 require.NoError(t, err) 109 110 assert.Equal(t, key1, k1) 111 assert.Equal(t, key2, k2) 112 113 assert.Equal(t, []byte("apple"), []byte(update.Payloads[0].Value())) 114 assert.Equal(t, []byte("carrot"), []byte(update.Payloads[1].Value())) 115 116 view2 := es.NewView(sc2) 117 118 b1, err := view2.Get(registerID1, "") 119 assert.NoError(t, err) 120 b2, err := view2.Get(registerID2, "") 121 assert.NoError(t, err) 122 123 assert.Equal(t, flow.RegisterValue("apple"), b1) 124 assert.Equal(t, flow.RegisterValue("carrot"), b2) 125 })) 126 127 t.Run("commit write and read previous state", prepareTest(func(t *testing.T, es state.ExecutionState, l *ledger.Ledger) { 128 // TODO: use real block ID 129 sc1, err := es.StateCommitmentByBlockID(context.Background(), flow.Identifier{}) 130 assert.NoError(t, err) 131 132 view1 := es.NewView(sc1) 133 134 err = view1.Set(registerID1, "", []byte("apple")) 135 assert.NoError(t, err) 136 sc2, _, err := state.CommitDelta(l, view1.Delta(), sc1) 137 assert.NoError(t, err) 138 139 // update value and get resulting state commitment 140 view2 := es.NewView(sc2) 141 err = view2.Set(registerID1, "", []byte("orange")) 142 assert.NoError(t, err) 143 144 sc3, _, err := state.CommitDelta(l, view2.Delta(), sc2) 145 assert.NoError(t, err) 146 147 // create a view for previous state version 148 view3 := es.NewView(sc2) 149 150 // create a view for new state version 151 view4 := es.NewView(sc3) 152 153 // fetch the value at both versions 154 b1, err := view3.Get(registerID1, "") 155 assert.NoError(t, err) 156 157 b2, err := view4.Get(registerID1, "") 158 assert.NoError(t, err) 159 160 assert.Equal(t, flow.RegisterValue("apple"), b1) 161 assert.Equal(t, flow.RegisterValue("orange"), b2) 162 })) 163 164 t.Run("commit delta and read new state", prepareTest(func(t *testing.T, es state.ExecutionState, l *ledger.Ledger) { 165 // TODO: use real block ID 166 sc1, err := es.StateCommitmentByBlockID(context.Background(), flow.Identifier{}) 167 assert.NoError(t, err) 168 169 // set initial value 170 view1 := es.NewView(sc1) 171 err = view1.Set(registerID1, "", []byte("apple")) 172 assert.NoError(t, err) 173 err = view1.Set(registerID2, "", []byte("apple")) 174 assert.NoError(t, err) 175 176 sc2, _, err := state.CommitDelta(l, view1.Delta(), sc1) 177 assert.NoError(t, err) 178 179 // update value and get resulting state commitment 180 view2 := es.NewView(sc2) 181 err = view2.Delete(registerID1, "") 182 assert.NoError(t, err) 183 184 sc3, _, err := state.CommitDelta(l, view2.Delta(), sc2) 185 assert.NoError(t, err) 186 187 // create a view for previous state version 188 view3 := es.NewView(sc2) 189 190 // create a view for new state version 191 view4 := es.NewView(sc3) 192 193 // fetch the value at both versions 194 b1, err := view3.Get(registerID1, "") 195 assert.NoError(t, err) 196 197 b2, err := view4.Get(registerID1, "") 198 assert.NoError(t, err) 199 200 assert.Equal(t, flow.RegisterValue("apple"), b1) 201 assert.Empty(t, b2) 202 })) 203 204 t.Run("commit delta and persist state commit for the second time should be OK", prepareTest(func(t *testing.T, es state.ExecutionState, l *ledger.Ledger) { 205 // TODO: use real block ID 206 sc1, err := es.StateCommitmentByBlockID(context.Background(), flow.Identifier{}) 207 assert.NoError(t, err) 208 209 // set initial value 210 view1 := es.NewView(sc1) 211 err = view1.Set(registerID1, "", flow.RegisterValue("apple")) 212 assert.NoError(t, err) 213 err = view1.Set(registerID2, "", flow.RegisterValue("apple")) 214 assert.NoError(t, err) 215 216 sc2, _, err := state.CommitDelta(l, view1.Delta(), sc1) 217 assert.NoError(t, err) 218 219 // committing for the second time should be OK 220 sc2Same, _, err := state.CommitDelta(l, view1.Delta(), sc1) 221 assert.NoError(t, err) 222 223 require.Equal(t, sc2, sc2Same) 224 })) 225 226 }