github.com/koko1123/flow-go-1@v0.29.6/network/p2p/p2pnode/libp2pNode_test.go (about) 1 package p2pnode_test 2 3 import ( 4 "context" 5 "fmt" 6 "testing" 7 "time" 8 9 "github.com/libp2p/go-libp2p/core/network" 10 "github.com/libp2p/go-libp2p/core/peer" 11 "github.com/libp2p/go-libp2p/core/peerstore" 12 "github.com/stretchr/testify/assert" 13 "github.com/stretchr/testify/require" 14 15 "github.com/koko1123/flow-go-1/model/flow" 16 "github.com/koko1123/flow-go-1/module/irrecoverable" 17 "github.com/koko1123/flow-go-1/module/mock" 18 "github.com/koko1123/flow-go-1/network/channels" 19 "github.com/koko1123/flow-go-1/network/internal/p2pfixtures" 20 "github.com/koko1123/flow-go-1/network/internal/p2putils" 21 "github.com/koko1123/flow-go-1/network/internal/testutils" 22 p2ptest "github.com/koko1123/flow-go-1/network/p2p/test" 23 "github.com/koko1123/flow-go-1/network/p2p/utils" 24 validator "github.com/koko1123/flow-go-1/network/validator/pubsub" 25 "github.com/koko1123/flow-go-1/utils/unittest" 26 ) 27 28 // TestMultiAddress evaluates correct translations from 29 // dns and ip4 to libp2p multi-address 30 func TestMultiAddress(t *testing.T) { 31 key := p2pfixtures.NetworkingKeyFixtures(t) 32 33 tt := []struct { 34 identity *flow.Identity 35 multiaddress string 36 }{ 37 { // ip4 test case 38 identity: unittest.IdentityFixture(unittest.WithNetworkingKey(key.PublicKey()), unittest.WithAddress("172.16.254.1:72")), 39 multiaddress: "/ip4/172.16.254.1/tcp/72", 40 }, 41 { // dns test case 42 identity: unittest.IdentityFixture(unittest.WithNetworkingKey(key.PublicKey()), unittest.WithAddress("consensus:2222")), 43 multiaddress: "/dns4/consensus/tcp/2222", 44 }, 45 { // dns test case 46 identity: unittest.IdentityFixture(unittest.WithNetworkingKey(key.PublicKey()), unittest.WithAddress("flow.com:3333")), 47 multiaddress: "/dns4/flow.com/tcp/3333", 48 }, 49 } 50 51 for _, tc := range tt { 52 ip, port, _, err := p2putils.NetworkingInfo(*tc.identity) 53 require.NoError(t, err) 54 55 actualAddress := utils.MultiAddressStr(ip, port) 56 assert.Equal(t, tc.multiaddress, actualAddress, "incorrect multi-address translation") 57 } 58 59 } 60 61 // TestSingleNodeLifeCycle evaluates correct lifecycle translation from start to stop the node 62 func TestSingleNodeLifeCycle(t *testing.T) { 63 ctx, cancel := context.WithCancel(context.Background()) 64 signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) 65 66 node, _ := p2ptest.NodeFixture( 67 t, 68 unittest.IdentifierFixture(), 69 "test_single_node_life_cycle", 70 ) 71 72 node.Start(signalerCtx) 73 unittest.RequireComponentsReadyBefore(t, 100*time.Millisecond, node) 74 75 cancel() 76 unittest.RequireComponentsDoneBefore(t, 100*time.Millisecond, node) 77 } 78 79 // TestGetPeerInfo evaluates the deterministic translation between the nodes address and 80 // their libp2p info. It generates an address, and checks whether repeated translations 81 // yields the same info or not. 82 func TestGetPeerInfo(t *testing.T) { 83 for i := 0; i < 10; i++ { 84 key := p2pfixtures.NetworkingKeyFixtures(t) 85 86 // creates node-i identity 87 identity := unittest.IdentityFixture(unittest.WithNetworkingKey(key.PublicKey()), unittest.WithAddress("1.1.1.1:0")) 88 89 // translates node-i address into info 90 info, err := utils.PeerAddressInfo(*identity) 91 require.NoError(t, err) 92 93 // repeats the translation for node-i 94 for j := 0; j < 10; j++ { 95 rinfo, err := utils.PeerAddressInfo(*identity) 96 require.NoError(t, err) 97 assert.Equal(t, rinfo.String(), info.String(), "inconsistent id generated") 98 } 99 } 100 } 101 102 // TestAddPeers checks if nodes can be added as peers to a given node 103 func TestAddPeers(t *testing.T) { 104 count := 3 105 ctx, cancel := context.WithCancel(context.Background()) 106 signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) 107 108 // create nodes 109 nodes, identities := p2ptest.NodesFixture(t, unittest.IdentifierFixture(), "test_add_peers", count) 110 p2ptest.StartNodes(t, signalerCtx, nodes, 100*time.Millisecond) 111 defer p2ptest.StopNodes(t, nodes, cancel, 100*time.Millisecond) 112 113 // add the remaining nodes to the first node as its set of peers 114 for _, identity := range identities[1:] { 115 peerInfo, err := utils.PeerAddressInfo(*identity) 116 require.NoError(t, err) 117 require.NoError(t, nodes[0].AddPeer(ctx, peerInfo)) 118 } 119 120 // Checks if both of the other nodes have been added as peers to the first node 121 assert.Len(t, nodes[0].Host().Network().Peers(), count-1) 122 } 123 124 // TestRemovePeers checks if nodes can be removed as peers from a given node 125 func TestRemovePeers(t *testing.T) { 126 count := 3 127 ctx, cancel := context.WithCancel(context.Background()) 128 signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) 129 130 // create nodes 131 nodes, identities := p2ptest.NodesFixture(t, unittest.IdentifierFixture(), "test_remove_peers", count) 132 peerInfos, errs := utils.PeerInfosFromIDs(identities) 133 assert.Len(t, errs, 0) 134 135 p2ptest.StartNodes(t, signalerCtx, nodes, 100*time.Millisecond) 136 defer p2ptest.StopNodes(t, nodes, cancel, 100*time.Millisecond) 137 138 // add nodes two and three to the first node as its peers 139 for _, pInfo := range peerInfos[1:] { 140 require.NoError(t, nodes[0].AddPeer(ctx, pInfo)) 141 } 142 143 // check if all other nodes have been added as peers to the first node 144 assert.Len(t, nodes[0].Host().Network().Peers(), count-1) 145 146 // disconnect from each peer and assert that the connection no longer exists 147 for _, pInfo := range peerInfos[1:] { 148 require.NoError(t, nodes[0].RemovePeer(pInfo.ID)) 149 assert.Equal(t, network.NotConnected, nodes[0].Host().Network().Connectedness(pInfo.ID)) 150 } 151 } 152 153 func TestConnGater(t *testing.T) { 154 ctx, cancel := context.WithCancel(context.Background()) 155 signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) 156 157 sporkID := unittest.IdentifierFixture() 158 159 node1Peers := unittest.NewProtectedMap[peer.ID, struct{}]() 160 node1, identity1 := p2ptest.NodeFixture( 161 t, 162 sporkID, 163 t.Name(), 164 p2ptest.WithConnectionGater(testutils.NewConnectionGater(func(pid peer.ID) error { 165 if !node1Peers.Has(pid) { 166 return fmt.Errorf("peer id not found: %s", pid.String()) 167 } 168 return nil 169 }))) 170 171 p2ptest.StartNode(t, signalerCtx, node1, 100*time.Millisecond) 172 defer p2ptest.StopNode(t, node1, cancel, 100*time.Millisecond) 173 174 node1Info, err := utils.PeerAddressInfo(identity1) 175 assert.NoError(t, err) 176 177 node2Peers := unittest.NewProtectedMap[peer.ID, struct{}]() 178 node2, identity2 := p2ptest.NodeFixture( 179 t, 180 sporkID, t.Name(), 181 p2ptest.WithConnectionGater(testutils.NewConnectionGater(func(pid peer.ID) error { 182 if !node2Peers.Has(pid) { 183 return fmt.Errorf("id not found: %s", pid.String()) 184 } 185 return nil 186 }))) 187 p2ptest.StartNode(t, signalerCtx, node2, 100*time.Millisecond) 188 defer p2ptest.StopNode(t, node2, cancel, 100*time.Millisecond) 189 190 node2Info, err := utils.PeerAddressInfo(identity2) 191 assert.NoError(t, err) 192 193 node1.Host().Peerstore().AddAddrs(node2Info.ID, node2Info.Addrs, peerstore.PermanentAddrTTL) 194 node2.Host().Peerstore().AddAddrs(node1Info.ID, node1Info.Addrs, peerstore.PermanentAddrTTL) 195 196 _, err = node1.CreateStream(ctx, node2Info.ID) 197 assert.Error(t, err, "connection should not be possible") 198 199 _, err = node2.CreateStream(ctx, node1Info.ID) 200 assert.Error(t, err, "connection should not be possible") 201 202 node1Peers.Add(node2Info.ID, struct{}{}) 203 _, err = node1.CreateStream(ctx, node2Info.ID) 204 assert.Error(t, err, "connection should not be possible") 205 206 node2Peers.Add(node1Info.ID, struct{}{}) 207 _, err = node1.CreateStream(ctx, node2Info.ID) 208 assert.NoError(t, err, "connection should not be blocked") 209 } 210 211 // TestNode_HasSubscription checks that when a node subscribes to a topic HasSubscription should return true. 212 func TestNode_HasSubscription(t *testing.T) { 213 ctx, cancel := context.WithCancel(context.Background()) 214 signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) 215 216 sporkID := unittest.IdentifierFixture() 217 node, _ := p2ptest.NodeFixture(t, sporkID, "test_has_subscription") 218 219 p2ptest.StartNode(t, signalerCtx, node, 100*time.Millisecond) 220 defer p2ptest.StopNode(t, node, cancel, 100*time.Millisecond) 221 222 logger := unittest.Logger() 223 met := mock.NewNetworkMetrics(t) 224 225 topicValidator := validator.TopicValidator(logger, unittest.NetworkCodec(), unittest.NetworkSlashingViolationsConsumer(logger, met), func(id peer.ID) error { 226 return nil 227 }) 228 229 // create test topic 230 topic := channels.TopicFromChannel(channels.TestNetworkChannel, unittest.IdentifierFixture()) 231 _, err := node.Subscribe(topic, topicValidator) 232 require.NoError(t, err) 233 234 require.True(t, node.HasSubscription(topic)) 235 236 // create topic with no subscription 237 topic = channels.TopicFromChannel(channels.ConsensusCommittee, unittest.IdentifierFixture()) 238 require.False(t, node.HasSubscription(topic)) 239 }