github.com/MetalBlockchain/metalgo@v1.11.9/vms/rpcchainvm/batched_vm_test.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package rpcchainvm 5 6 import ( 7 "context" 8 "testing" 9 "time" 10 11 "github.com/stretchr/testify/require" 12 "go.uber.org/mock/gomock" 13 14 "github.com/MetalBlockchain/metalgo/database/memdb" 15 "github.com/MetalBlockchain/metalgo/ids" 16 "github.com/MetalBlockchain/metalgo/snow/choices" 17 "github.com/MetalBlockchain/metalgo/snow/consensus/snowman/snowmantest" 18 "github.com/MetalBlockchain/metalgo/snow/engine/snowman/block" 19 "github.com/MetalBlockchain/metalgo/snow/snowtest" 20 "github.com/MetalBlockchain/metalgo/vms/components/chain" 21 ) 22 23 var ( 24 blkBytes1 = []byte{1} 25 blkBytes2 = []byte{2} 26 27 blkID0 = ids.ID{0} 28 blkID1 = ids.ID{1} 29 blkID2 = ids.ID{2} 30 31 status1 = choices.Accepted 32 status2 = choices.Processing 33 34 time1 = time.Unix(1, 0) 35 time2 = time.Unix(2, 0) 36 ) 37 38 func batchedParseBlockCachingTestPlugin(t *testing.T, loadExpectations bool) block.ChainVM { 39 // test key is "batchedParseBlockCachingTestKey" 40 41 // create mock 42 ctrl := gomock.NewController(t) 43 vm := block.NewMockChainVM(ctrl) 44 45 if loadExpectations { 46 blk1 := snowmantest.NewMockBlock(ctrl) 47 blk2 := snowmantest.NewMockBlock(ctrl) 48 gomock.InOrder( 49 // Initialize 50 vm.EXPECT().Initialize( 51 gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), 52 gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), 53 gomock.Any(), 54 ).Return(nil).Times(1), 55 vm.EXPECT().LastAccepted(gomock.Any()).Return(preSummaryBlk.ID(), nil).Times(1), 56 vm.EXPECT().GetBlock(gomock.Any(), gomock.Any()).Return(preSummaryBlk, nil).Times(1), 57 58 // Parse Block 1 59 vm.EXPECT().ParseBlock(gomock.Any(), blkBytes1).Return(blk1, nil).Times(1), 60 blk1.EXPECT().ID().Return(blkID1).Times(1), 61 blk1.EXPECT().Parent().Return(blkID0).Times(1), 62 blk1.EXPECT().Status().Return(status1).Times(1), 63 blk1.EXPECT().Height().Return(uint64(1)).Times(1), 64 blk1.EXPECT().Timestamp().Return(time1).Times(1), 65 66 // Parse Block 2 67 vm.EXPECT().ParseBlock(gomock.Any(), blkBytes2).Return(blk2, nil).Times(1), 68 blk2.EXPECT().ID().Return(blkID2).Times(1), 69 blk2.EXPECT().Parent().Return(blkID1).Times(1), 70 blk2.EXPECT().Status().Return(status2).Times(1), 71 blk2.EXPECT().Height().Return(uint64(2)).Times(1), 72 blk2.EXPECT().Timestamp().Return(time2).Times(1), 73 ) 74 } 75 76 return vm 77 } 78 79 func TestBatchedParseBlockCaching(t *testing.T) { 80 require := require.New(t) 81 testKey := batchedParseBlockCachingTestKey 82 83 // Create and start the plugin 84 vm, stopper := buildClientHelper(require, testKey) 85 defer stopper.Stop(context.Background()) 86 87 ctx := snowtest.Context(t, snowtest.CChainID) 88 89 require.NoError(vm.Initialize(context.Background(), ctx, memdb.New(), nil, nil, nil, nil, nil, nil)) 90 91 // Call should parse the first block 92 blk, err := vm.ParseBlock(context.Background(), blkBytes1) 93 require.NoError(err) 94 require.Equal(blkID1, blk.ID()) 95 96 require.IsType(&chain.BlockWrapper{}, blk) 97 98 // Call should cache the first block and parse the second block 99 blks, err := vm.BatchedParseBlock(context.Background(), [][]byte{blkBytes1, blkBytes2}) 100 require.NoError(err) 101 require.Len(blks, 2) 102 require.Equal(blkID1, blks[0].ID()) 103 require.Equal(blkID2, blks[1].ID()) 104 105 require.IsType(&chain.BlockWrapper{}, blks[0]) 106 require.IsType(&chain.BlockWrapper{}, blks[1]) 107 108 // Call should be fully cached and not result in a grpc call 109 blks, err = vm.BatchedParseBlock(context.Background(), [][]byte{blkBytes1, blkBytes2}) 110 require.NoError(err) 111 require.Len(blks, 2) 112 require.Equal(blkID1, blks[0].ID()) 113 require.Equal(blkID2, blks[1].ID()) 114 115 require.IsType(&chain.BlockWrapper{}, blks[0]) 116 require.IsType(&chain.BlockWrapper{}, blks[1]) 117 }