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  }