github.com/iotexproject/iotex-core@v1.14.1-rc1/nodeinfo/manager_test.go (about) 1 // Copyright (c) 2022 IoTeX Foundation 2 // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability 3 // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. 4 // This source code is governed by Apache License 2.0 that can be found in the LICENSE file. 5 6 package nodeinfo 7 8 import ( 9 "context" 10 "testing" 11 "time" 12 13 "github.com/golang/mock/gomock" 14 "github.com/iotexproject/go-pkgs/crypto" 15 "github.com/iotexproject/iotex-core/test/mock/mock_nodeinfo" 16 "github.com/iotexproject/iotex-proto/golang/iotextypes" 17 "github.com/libp2p/go-libp2p-core/peer" 18 dto "github.com/prometheus/client_model/go" 19 "github.com/stretchr/testify/require" 20 "google.golang.org/protobuf/proto" 21 "google.golang.org/protobuf/types/known/timestamppb" 22 ) 23 24 func getEmptyWhiteList() []string { 25 return []string{} 26 } 27 28 func TestNewDelegateManager(t *testing.T) { 29 require := require.New(t) 30 ctrl := gomock.NewController(t) 31 defer ctrl.Finish() 32 privK, err := crypto.GenerateKey() 33 require.NoError(err) 34 35 t.Run("disable_broadcast", func(t *testing.T) { 36 hMock := mock_nodeinfo.NewMockchain(ctrl) 37 tMock := mock_nodeinfo.NewMocktransmitter(ctrl) 38 cfg := Config{false, 100 * time.Millisecond, 100 * time.Millisecond, 1000} 39 dm := NewInfoManager(&cfg, tMock, hMock, privK, getEmptyWhiteList) 40 require.NotNil(dm.nodeMap) 41 require.Equal(tMock, dm.transmitter) 42 require.Equal(hMock, dm.chain) 43 require.Equal(privK, dm.privKey) 44 tMock.EXPECT().BroadcastOutbound(gomock.Any(), gomock.Any()).Times(0) 45 hMock.EXPECT().TipHeight().Return(uint64(2)).Times(0) 46 err := dm.Start(context.Background()) 47 require.NoError(err) 48 defer dm.Stop(context.Background()) 49 time.Sleep(time.Second) 50 }) 51 52 t.Run("enable_broadcast", func(t *testing.T) { 53 hMock := mock_nodeinfo.NewMockchain(ctrl) 54 tMock := mock_nodeinfo.NewMocktransmitter(ctrl) 55 cfg := Config{true, 100 * time.Millisecond, 100 * time.Millisecond, 1000} 56 dm := NewInfoManager(&cfg, tMock, hMock, privK, getEmptyWhiteList) 57 require.NotNil(dm.nodeMap) 58 require.Equal(tMock, dm.transmitter) 59 require.Equal(hMock, dm.chain) 60 require.Equal(privK, dm.privKey) 61 tMock.EXPECT().Info().Return(peer.AddrInfo{}, nil).MinTimes(1) 62 hMock.EXPECT().TipHeight().Return(uint64(10)).MinTimes(1) 63 tMock.EXPECT().BroadcastOutbound(gomock.Any(), gomock.Any()).Return(nil).MinTimes(1) 64 err := dm.Start(context.Background()) 65 require.NoError(err) 66 defer dm.Stop(context.Background()) 67 time.Sleep(time.Second) 68 }) 69 t.Run("delegate_broadcast", func(t *testing.T) { 70 hMock := mock_nodeinfo.NewMockchain(ctrl) 71 tMock := mock_nodeinfo.NewMocktransmitter(ctrl) 72 cfg := Config{false, 100 * time.Millisecond, 100 * time.Millisecond, 1000} 73 dm := NewInfoManager(&cfg, tMock, hMock, privK, func() []string { 74 return []string{privK.PublicKey().Address().String()} 75 }) 76 require.NotNil(dm.nodeMap) 77 require.Equal(tMock, dm.transmitter) 78 require.Equal(hMock, dm.chain) 79 require.Equal(privK, dm.privKey) 80 tMock.EXPECT().Info().Return(peer.AddrInfo{}, nil).MinTimes(1) 81 hMock.EXPECT().TipHeight().Return(uint64(10)).MinTimes(1) 82 tMock.EXPECT().BroadcastOutbound(gomock.Any(), gomock.Any()).Return(nil).MinTimes(1) 83 err := dm.Start(context.Background()) 84 require.NoError(err) 85 defer dm.Stop(context.Background()) 86 time.Sleep(time.Second) 87 }) 88 } 89 90 func TestDelegateManager_HandleNodeInfo(t *testing.T) { 91 ctrl := gomock.NewController(t) 92 defer ctrl.Finish() 93 94 require := require.New(t) 95 privKey, err := crypto.GenerateKey() 96 require.NoError(err) 97 98 t.Run("verify_pass", func(t *testing.T) { 99 hMock := mock_nodeinfo.NewMockchain(ctrl) 100 tMock := mock_nodeinfo.NewMocktransmitter(ctrl) 101 msg := &iotextypes.NodeInfo{ 102 Info: &iotextypes.NodeInfoCore{ 103 Version: "v1.8.0", 104 Height: 200, 105 Timestamp: timestamppb.Now(), 106 Address: privKey.PublicKey().Address().String(), 107 }, 108 } 109 hash := hashNodeInfo(msg.Info) 110 msg.Signature, _ = privKey.Sign(hash[:]) 111 dm := NewInfoManager(&DefaultConfig, tMock, hMock, privKey, getEmptyWhiteList) 112 dm.HandleNodeInfo(context.Background(), "abc", msg) 113 addr := msg.Info.Address 114 nodeGot, ok := dm.nodeMap.Get(addr) 115 require.True(ok) 116 nodeInfo := nodeGot.(Info) 117 require.Equal(msg.Info.Height, nodeInfo.Height) 118 require.Equal(msg.Info.Version, nodeInfo.Version) 119 require.Equal(msg.Info.Timestamp.AsTime().String(), nodeInfo.Timestamp.String()) 120 require.Equal("abc", nodeInfo.PeerID) 121 m := dto.Metric{} 122 _nodeInfoHeightGauge.WithLabelValues(addr, msg.Info.Version).Write(&m) 123 require.Equal(msg.Info.Height, uint64(m.Gauge.GetValue())) 124 }) 125 126 t.Run("verify_fail", func(t *testing.T) { 127 hMock := mock_nodeinfo.NewMockchain(ctrl) 128 tMock := mock_nodeinfo.NewMocktransmitter(ctrl) 129 privKey2, _ := crypto.GenerateKey() 130 msg := &iotextypes.NodeInfo{ 131 Info: &iotextypes.NodeInfoCore{ 132 Version: "v1.8.0", 133 Height: 200, 134 Timestamp: timestamppb.Now(), 135 Address: privKey2.PublicKey().Address().String(), 136 }, 137 Signature: []byte("xxxx"), 138 } 139 dm := NewInfoManager(&DefaultConfig, tMock, hMock, privKey, getEmptyWhiteList) 140 dm.HandleNodeInfo(context.Background(), "abc", msg) 141 addr := msg.Info.Address 142 _, ok := dm.nodeMap.Get(addr) 143 require.False(ok) 144 m := dto.Metric{} 145 _nodeInfoHeightGauge.WithLabelValues(addr, msg.Info.Version).Write(&m) 146 require.Equal(uint64(0), uint64(m.Gauge.GetValue())) 147 }) 148 } 149 150 func TestDelegateManager_BroadcastNodeInfo(t *testing.T) { 151 require := require.New(t) 152 ctrl := gomock.NewController(t) 153 defer ctrl.Finish() 154 privKey, err := crypto.GenerateKey() 155 require.NoError(err) 156 157 t.Run("update_self", func(t *testing.T) { 158 hMock := mock_nodeinfo.NewMockchain(ctrl) 159 tMock := mock_nodeinfo.NewMocktransmitter(ctrl) 160 dm := NewInfoManager(&DefaultConfig, tMock, hMock, privKey, getEmptyWhiteList) 161 height := uint64(200) 162 peerID, err := peer.IDFromString("12D3KooWF2fns5ZWKbPfx2U1wQDdxoTK2D6HC3ortbSAQYR4BQp4") 163 require.NoError(err) 164 hMock.EXPECT().TipHeight().Return(height).Times(1) 165 tMock.EXPECT().Info().Return(peer.AddrInfo{ID: peerID}, nil).Times(1) 166 tMock.EXPECT().BroadcastOutbound(gomock.Any(), gomock.Any()).Return(nil).Times(1) 167 err = dm.BroadcastNodeInfo(context.Background()) 168 require.NoError(err) 169 addr := privKey.PublicKey().Address().String() 170 nodeGot, ok := dm.nodeMap.Get(addr) 171 require.True(ok) 172 nodeInfo := nodeGot.(Info) 173 require.Equal(height, nodeInfo.Height) 174 require.Equal(dm.version, nodeInfo.Version) 175 require.Equal(addr, nodeInfo.Address) 176 require.Equal(peerID.Pretty(), nodeInfo.PeerID) 177 }) 178 } 179 180 func TestDelegateManager_HandleNodeInfoRequest(t *testing.T) { 181 require := require.New(t) 182 ctrl := gomock.NewController(t) 183 defer ctrl.Finish() 184 privKey, err := crypto.GenerateKey() 185 require.NoError(err) 186 187 t.Run("unicast", func(t *testing.T) { 188 hMock := mock_nodeinfo.NewMockchain(ctrl) 189 tMock := mock_nodeinfo.NewMocktransmitter(ctrl) 190 dm := NewInfoManager(&DefaultConfig, tMock, hMock, privKey, getEmptyWhiteList) 191 height := uint64(200) 192 var sig []byte 193 message := &iotextypes.NodeInfo{} 194 hMock.EXPECT().TipHeight().Return(height).Times(1) 195 tMock.EXPECT().UnicastOutbound(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(_ context.Context, peerInfo peer.AddrInfo, msg proto.Message) error { 196 message = msg.(*iotextypes.NodeInfo) 197 hash := hashNodeInfo(message.Info) 198 sig, _ = dm.privKey.Sign(hash[:]) 199 return nil 200 }).Times(1) 201 err := dm.HandleNodeInfoRequest(context.Background(), peer.AddrInfo{}) 202 require.NoError(err) 203 require.Equal(message.Info.Height, height) 204 require.Equal(message.Info.Version, dm.version) 205 require.Equal(message.Info.Address, dm.address) 206 require.Equal(message.Signature, sig) 207 }) 208 } 209 210 func TestDelegateManager_RequestSingleNodeInfoAsync(t *testing.T) { 211 require := require.New(t) 212 ctrl := gomock.NewController(t) 213 defer ctrl.Finish() 214 privKey, err := crypto.GenerateKey() 215 require.NoError(err) 216 217 t.Run("request_single", func(t *testing.T) { 218 hMock := mock_nodeinfo.NewMockchain(ctrl) 219 tMock := mock_nodeinfo.NewMocktransmitter(ctrl) 220 dm := NewInfoManager(&DefaultConfig, tMock, hMock, privKey, getEmptyWhiteList) 221 var paramPeer peer.AddrInfo 222 var paramMsg *iotextypes.NodeInfoRequest 223 peerID, err := peer.IDFromString("12D3KooWF2fns5ZWKbPfx2U1wQDdxoTK2D6HC3ortbSAQYR4BQp4") 224 require.NoError(err) 225 targetPeer := peer.AddrInfo{ID: peerID} 226 tMock.EXPECT().UnicastOutbound(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ context.Context, p peer.AddrInfo, msg proto.Message) { 227 paramPeer = p 228 paramMsg = msg.(*iotextypes.NodeInfoRequest) 229 }).Times(1) 230 dm.RequestSingleNodeInfoAsync(context.Background(), targetPeer) 231 require.Equal(targetPeer, paramPeer) 232 request := iotextypes.NodeInfoRequest{} 233 require.Equal(request.String(), paramMsg.String()) 234 }) 235 } 236 237 func TestDelegateManager_GetNodeByAddr(t *testing.T) { 238 require := require.New(t) 239 ctrl := gomock.NewController(t) 240 defer ctrl.Finish() 241 hMock := mock_nodeinfo.NewMockchain(ctrl) 242 tMock := mock_nodeinfo.NewMocktransmitter(ctrl) 243 privKey, err := crypto.GenerateKey() 244 require.NoError(err) 245 246 dm := NewInfoManager(&DefaultConfig, tMock, hMock, privKey, getEmptyWhiteList) 247 dm.updateNode(&Info{Address: "1"}) 248 dm.updateNode(&Info{Address: "2"}) 249 250 t.Run("exist", func(t *testing.T) { 251 info, ok := dm.GetNodeInfo("1") 252 require.True(ok) 253 require.Equal(Info{Address: "1"}, info) 254 info, ok = dm.GetNodeInfo("2") 255 require.True(ok) 256 require.Equal(Info{Address: "2"}, info) 257 }) 258 t.Run("not_exist", func(t *testing.T) { 259 _, ok := dm.GetNodeInfo("3") 260 require.False(ok) 261 }) 262 263 }