github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/execution/ingestion/mocks/block_store.go (about) 1 package mocks 2 3 import ( 4 "fmt" 5 "sync" 6 "testing" 7 8 "github.com/stretchr/testify/require" 9 10 "github.com/onflow/flow-go/engine/execution" 11 executionUnittest "github.com/onflow/flow-go/engine/execution/state/unittest" 12 "github.com/onflow/flow-go/model/flow" 13 "github.com/onflow/flow-go/module/mempool/entity" 14 "github.com/onflow/flow-go/utils/unittest" 15 ) 16 17 type BlockResult struct { 18 Block *entity.ExecutableBlock 19 Result *execution.ComputationResult 20 } 21 22 // MockBlockStore contains mocked block computation result 23 // it ensures that as blocks computation result are created, the block's start state 24 // is the same as its parent block's end state. 25 // it also stores which block is executed, so that the mock execution state or computer 26 // can determine what result to return 27 type MockBlockStore struct { 28 sync.Mutex 29 ResultByBlock map[flow.Identifier]*BlockResult 30 Executed map[flow.Identifier]struct{} 31 RootBlock *flow.Header 32 } 33 34 func NewMockBlockStore(t *testing.T) *MockBlockStore { 35 rootBlock := unittest.ExecutableBlockFixtureWithParent([][]flow.Identifier{{}}, 36 unittest.BlockHeaderFixture(), unittest.StateCommitmentPointerFixture()) 37 rootResult := executionUnittest.ComputationResultForBlockFixture(t, 38 unittest.IdentifierFixture(), rootBlock) 39 40 blockResult := &BlockResult{ 41 Block: rootBlock, 42 Result: rootResult, 43 } 44 45 byBlock := make(map[flow.Identifier]*BlockResult) 46 byBlock[rootResult.Block.ID()] = blockResult 47 48 executed := make(map[flow.Identifier]struct{}) 49 executed[rootResult.Block.ID()] = struct{}{} 50 return &MockBlockStore{ 51 ResultByBlock: byBlock, 52 Executed: executed, 53 RootBlock: rootBlock.Block.Header, 54 } 55 } 56 57 func (bs *MockBlockStore) MarkExecuted(computationResult *execution.ComputationResult) error { 58 bs.Lock() 59 defer bs.Unlock() 60 blockID := computationResult.ExecutableBlock.Block.Header.ID() 61 _, executed := bs.Executed[blockID] 62 if executed { 63 return fmt.Errorf("block %s already executed", blockID) 64 } 65 66 expected, exist := bs.ResultByBlock[blockID] 67 if !exist { 68 return fmt.Errorf("block %s not found", blockID) 69 } 70 71 if expected.Result != computationResult { 72 return fmt.Errorf("block %s expected %v, got %v", blockID, expected, computationResult) 73 } 74 bs.Executed[blockID] = struct{}{} 75 return nil 76 } 77 78 func (bs *MockBlockStore) CreateBlockAndMockResult(t *testing.T, block *entity.ExecutableBlock) *execution.ComputationResult { 79 bs.Lock() 80 defer bs.Unlock() 81 blockID := block.ID() 82 _, exist := bs.ResultByBlock[blockID] 83 require.False(t, exist, "block %s already exists", blockID) 84 85 parent := block.Block.Header.ParentID 86 parentResult, ok := bs.ResultByBlock[parent] 87 require.True(t, ok, "parent block %s not found", parent) 88 89 previousExecutionResultID := parentResult.Result.ExecutionReceipt.ExecutionResult.ID() 90 91 previousCommit := parentResult.Result.CurrentEndState() 92 93 block.StartState = &previousCommit 94 95 // mock computation result 96 cr := executionUnittest.ComputationResultForBlockFixture(t, 97 previousExecutionResultID, 98 block, 99 ) 100 result := &BlockResult{ 101 Block: block, 102 Result: cr, 103 } 104 bs.ResultByBlock[blockID] = result 105 return cr 106 } 107 108 func (bs *MockBlockStore) GetExecuted(blockID flow.Identifier) (*BlockResult, error) { 109 bs.Lock() 110 defer bs.Unlock() 111 _, exist := bs.Executed[blockID] 112 if !exist { 113 return nil, fmt.Errorf("block %s not executed", blockID) 114 } 115 116 result, exist := bs.ResultByBlock[blockID] 117 if !exist { 118 return nil, fmt.Errorf("block %s not found", blockID) 119 } 120 return result, nil 121 } 122 123 func (bs *MockBlockStore) AssertExecuted(t *testing.T, alias string, block flow.Identifier) { 124 bs.Lock() 125 defer bs.Unlock() 126 _, exist := bs.Executed[block] 127 require.True(t, exist, "block %s not executed", alias) 128 } 129 130 func (bs *MockBlockStore) AssertNotExecuted(t *testing.T, alias string, block flow.Identifier) { 131 bs.Lock() 132 defer bs.Unlock() 133 _, exist := bs.Executed[block] 134 require.False(t, exist, "block %s executed", alias) 135 }