github.com/ava-labs/avalanchego@v1.11.11/vms/platformvm/network/network_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 network 5 6 import ( 7 "context" 8 "errors" 9 "testing" 10 "time" 11 12 "github.com/prometheus/client_golang/prometheus" 13 "github.com/stretchr/testify/require" 14 "go.uber.org/mock/gomock" 15 16 "github.com/ava-labs/avalanchego/ids" 17 "github.com/ava-labs/avalanchego/snow/engine/common" 18 "github.com/ava-labs/avalanchego/snow/engine/common/commonmock" 19 "github.com/ava-labs/avalanchego/snow/snowtest" 20 "github.com/ava-labs/avalanchego/vms/platformvm/txs" 21 "github.com/ava-labs/avalanchego/vms/platformvm/txs/mempool/mempoolmock" 22 "github.com/ava-labs/avalanchego/vms/txs/mempool" 23 24 pmempool "github.com/ava-labs/avalanchego/vms/platformvm/txs/mempool" 25 ) 26 27 var ( 28 errTest = errors.New("test error") 29 30 testConfig = Config{ 31 MaxValidatorSetStaleness: time.Second, 32 TargetGossipSize: 1, 33 PushGossipNumValidators: 1, 34 PushGossipNumPeers: 0, 35 PushRegossipNumValidators: 1, 36 PushRegossipNumPeers: 0, 37 PushGossipDiscardedCacheSize: 1, 38 PushGossipMaxRegossipFrequency: time.Second, 39 PushGossipFrequency: time.Second, 40 PullGossipPollSize: 1, 41 PullGossipFrequency: time.Second, 42 PullGossipThrottlingPeriod: time.Second, 43 PullGossipThrottlingLimit: 1, 44 ExpectedBloomFilterElements: 10, 45 ExpectedBloomFilterFalsePositiveProbability: .1, 46 MaxBloomFilterFalsePositiveProbability: .5, 47 } 48 ) 49 50 var _ TxVerifier = (*testTxVerifier)(nil) 51 52 type testTxVerifier struct { 53 err error 54 } 55 56 func (t testTxVerifier) VerifyTx(*txs.Tx) error { 57 return t.err 58 } 59 60 func TestNetworkIssueTxFromRPC(t *testing.T) { 61 tx := &txs.Tx{} 62 63 type test struct { 64 name string 65 mempoolFunc func(*gomock.Controller) pmempool.Mempool 66 txVerifier testTxVerifier 67 partialSyncPrimaryNetwork bool 68 appSenderFunc func(*gomock.Controller) common.AppSender 69 expectedErr error 70 } 71 72 tests := []test{ 73 { 74 name: "mempool has transaction", 75 mempoolFunc: func(ctrl *gomock.Controller) pmempool.Mempool { 76 mempool := mempoolmock.NewMempool(ctrl) 77 mempool.EXPECT().Get(gomock.Any()).Return(tx, true) 78 return mempool 79 }, 80 appSenderFunc: func(ctrl *gomock.Controller) common.AppSender { 81 return commonmock.NewSender(ctrl) 82 }, 83 expectedErr: mempool.ErrDuplicateTx, 84 }, 85 { 86 name: "transaction marked as dropped in mempool", 87 mempoolFunc: func(ctrl *gomock.Controller) pmempool.Mempool { 88 mempool := mempoolmock.NewMempool(ctrl) 89 mempool.EXPECT().Get(gomock.Any()).Return(nil, false) 90 mempool.EXPECT().GetDropReason(gomock.Any()).Return(errTest) 91 return mempool 92 }, 93 appSenderFunc: func(ctrl *gomock.Controller) common.AppSender { 94 // Shouldn't gossip the tx 95 return commonmock.NewSender(ctrl) 96 }, 97 expectedErr: errTest, 98 }, 99 { 100 name: "transaction invalid", 101 mempoolFunc: func(ctrl *gomock.Controller) pmempool.Mempool { 102 mempool := mempoolmock.NewMempool(ctrl) 103 mempool.EXPECT().Get(gomock.Any()).Return(nil, false) 104 mempool.EXPECT().GetDropReason(gomock.Any()).Return(nil) 105 mempool.EXPECT().MarkDropped(gomock.Any(), gomock.Any()) 106 return mempool 107 }, 108 txVerifier: testTxVerifier{err: errTest}, 109 appSenderFunc: func(ctrl *gomock.Controller) common.AppSender { 110 // Shouldn't gossip the tx 111 return commonmock.NewSender(ctrl) 112 }, 113 expectedErr: errTest, 114 }, 115 { 116 name: "can't add transaction to mempool", 117 mempoolFunc: func(ctrl *gomock.Controller) pmempool.Mempool { 118 mempool := mempoolmock.NewMempool(ctrl) 119 mempool.EXPECT().Get(gomock.Any()).Return(nil, false) 120 mempool.EXPECT().GetDropReason(gomock.Any()).Return(nil) 121 mempool.EXPECT().Add(gomock.Any()).Return(errTest) 122 mempool.EXPECT().MarkDropped(gomock.Any(), gomock.Any()) 123 return mempool 124 }, 125 appSenderFunc: func(ctrl *gomock.Controller) common.AppSender { 126 // Shouldn't gossip the tx 127 return commonmock.NewSender(ctrl) 128 }, 129 expectedErr: errTest, 130 }, 131 { 132 name: "mempool is disabled if primary network is not being fully synced", 133 mempoolFunc: func(ctrl *gomock.Controller) pmempool.Mempool { 134 return mempoolmock.NewMempool(ctrl) 135 }, 136 partialSyncPrimaryNetwork: true, 137 appSenderFunc: func(ctrl *gomock.Controller) common.AppSender { 138 return commonmock.NewSender(ctrl) 139 }, 140 expectedErr: errMempoolDisabledWithPartialSync, 141 }, 142 { 143 name: "happy path", 144 mempoolFunc: func(ctrl *gomock.Controller) pmempool.Mempool { 145 mempool := mempoolmock.NewMempool(ctrl) 146 mempool.EXPECT().Get(gomock.Any()).Return(nil, false) 147 mempool.EXPECT().GetDropReason(gomock.Any()).Return(nil) 148 mempool.EXPECT().Add(gomock.Any()).Return(nil) 149 mempool.EXPECT().Len().Return(0) 150 mempool.EXPECT().RequestBuildBlock(false) 151 mempool.EXPECT().Get(gomock.Any()).Return(nil, true).Times(2) 152 return mempool 153 }, 154 appSenderFunc: func(ctrl *gomock.Controller) common.AppSender { 155 appSender := commonmock.NewSender(ctrl) 156 appSender.EXPECT().SendAppGossip(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) 157 return appSender 158 }, 159 expectedErr: nil, 160 }, 161 } 162 163 for _, tt := range tests { 164 t.Run(tt.name, func(t *testing.T) { 165 require := require.New(t) 166 ctrl := gomock.NewController(t) 167 168 snowCtx := snowtest.Context(t, ids.Empty) 169 n, err := New( 170 snowCtx.Log, 171 snowCtx.NodeID, 172 snowCtx.SubnetID, 173 snowCtx.ValidatorState, 174 tt.txVerifier, 175 tt.mempoolFunc(ctrl), 176 tt.partialSyncPrimaryNetwork, 177 tt.appSenderFunc(ctrl), 178 prometheus.NewRegistry(), 179 testConfig, 180 ) 181 require.NoError(err) 182 183 err = n.IssueTxFromRPC(tx) 184 require.ErrorIs(err, tt.expectedErr) 185 186 require.NoError(n.txPushGossiper.Gossip(context.Background())) 187 }) 188 } 189 }