github.com/holochain/holochain-proto@v0.1.0-alpha-26.0.20200915073418-5c83169c9b5b/node_test.go (about) 1 package holochain 2 3 import ( 4 "bytes" 5 "context" 6 "errors" 7 "fmt" 8 . "github.com/holochain/holochain-proto/hash" 9 net "github.com/libp2p/go-libp2p-net" 10 peer "github.com/libp2p/go-libp2p-peer" 11 pstore "github.com/libp2p/go-libp2p-peerstore" 12 ma "github.com/multiformats/go-multiaddr" 13 . "github.com/smartystreets/goconvey/convey" 14 "io/ioutil" 15 "os" 16 "path/filepath" 17 "testing" 18 "time" 19 ) 20 21 func TestNodeConstants(t *testing.T) { 22 Convey("node constants should have the right values", t, func() { 23 So(ERROR_RESPONSE, ShouldEqual, 0) 24 So(OK_RESPONSE, ShouldEqual, 1) 25 So(PUT_REQUEST, ShouldEqual, 2) 26 So(DEL_REQUEST, ShouldEqual, 3) 27 So(MOD_REQUEST, ShouldEqual, 4) 28 So(GET_REQUEST, ShouldEqual, 5) 29 So(LINK_REQUEST, ShouldEqual, 6) 30 So(GETLINK_REQUEST, ShouldEqual, 7) 31 So(DELETELINK_REQUEST, ShouldEqual, 8) 32 So(GOSSIP_REQUEST, ShouldEqual, 9) 33 So(VALIDATE_PUT_REQUEST, ShouldEqual, 10) 34 So(VALIDATE_LINK_REQUEST, ShouldEqual, 11) 35 So(VALIDATE_DEL_REQUEST, ShouldEqual, 12) 36 So(VALIDATE_MOD_REQUEST, ShouldEqual, 13) 37 So(APP_MESSAGE, ShouldEqual, 14) 38 So(LISTADD_REQUEST, ShouldEqual, 15) 39 So(FIND_NODE_REQUEST, ShouldEqual, 16) 40 }) 41 } 42 43 func TestNodeMDNSDiscovery(t *testing.T) { 44 nodesCount := 4 45 mt := setupMultiNodeTesting(nodesCount) 46 defer mt.cleanupMultiNodeTesting() 47 nodes := mt.nodes 48 49 node0 := nodes[0].node 50 node1 := nodes[1].node 51 node2 := nodes[2].node 52 node3 := nodes[3].node 53 54 Convey("nodes should find eachother via mdns", t, func() { 55 So(len(node0.host.Peerstore().Peers()), ShouldEqual, 1) 56 So(len(node1.host.Peerstore().Peers()), ShouldEqual, 1) 57 So(len(node2.host.Peerstore().Peers()), ShouldEqual, 1) 58 59 err := node0.EnableMDNSDiscovery(nodes[0], time.Second/4) 60 So(err, ShouldBeNil) 61 err = node1.EnableMDNSDiscovery(nodes[1], time.Second/4) 62 So(err, ShouldBeNil) 63 err = node2.EnableMDNSDiscovery(nodes[2], time.Second/4) 64 So(err, ShouldBeNil) 65 66 time.Sleep(time.Millisecond * 500) 67 68 So(len(node0.host.Peerstore().Peers()), ShouldEqual, 3) 69 So(len(node1.host.Peerstore().Peers()), ShouldEqual, 3) 70 So(len(node2.host.Peerstore().Peers()), ShouldEqual, 3) 71 }) 72 73 Convey("nodes should confirm connectability before adding nodes found via mdns", t, func() { 74 So(len(node3.host.Peerstore().Peers()), ShouldEqual, 1) 75 76 // shut-down node2 so the new node can't connect to it 77 node2.Close() 78 79 err := node3.EnableMDNSDiscovery(nodes[3], time.Second/4) 80 So(err, ShouldBeNil) 81 time.Sleep(time.Millisecond * 500) 82 83 /*for _, p := range node3.host.Peerstore().Peers() { 84 fmt.Printf("PERR:%v\n", p) 85 for _, a := range node3.host.Peerstore().Addrs(p) { 86 fmt.Printf(" ADDR:%v\n", a) 87 } 88 }*/ 89 90 // mdns still reporting nodes2 91 So(len(node3.host.Peerstore().Peers()), ShouldEqual, 4) 92 // So(len(node3.host.Peerstore().Addrs(nodes[2].nodeID)), ShouldEqual, 0) 93 }) 94 } 95 96 func TestNewNode(t *testing.T) { 97 98 node, err := makeNode(1234, "") 99 defer node.Close() 100 Convey("It should create a node", t, func() { 101 So(err, ShouldBeNil) 102 So(node.NetAddr.String(), ShouldEqual, "/ip4/127.0.0.1/tcp/1234") 103 So(node.HashAddr.Pretty(), ShouldEqual, "QmNN6oDiV4GsfKDXPVmGLdBLLXCM28Jnm7pz7WD63aiwSG") 104 }) 105 106 Convey("It should send between nodes", t, func() { 107 node2, err := makeNode(4321, "node2") 108 So(err, ShouldBeNil) 109 defer node2.Close() 110 111 node.host.Peerstore().AddAddr(node2.HashAddr, node2.NetAddr, pstore.PermanentAddrTTL) 112 var payload string 113 node2.host.SetStreamHandler("/testprotocol/1.0.0", func(s net.Stream) { 114 defer s.Close() 115 116 buf := make([]byte, 1024) 117 n, err := s.Read(buf) 118 if err != nil { 119 payload = err.Error() 120 } else { 121 payload = string(buf[:n]) 122 } 123 124 _, err = s.Write([]byte("I got: " + payload)) 125 126 if err != nil { 127 panic(err) 128 } 129 }) 130 131 s, err := node.host.NewStream(node.ctx, node2.HashAddr, "/testprotocol/1.0.0") 132 So(err, ShouldBeNil) 133 _, err = s.Write([]byte("greetings")) 134 So(err, ShouldBeNil) 135 136 out, err := ioutil.ReadAll(s) 137 So(err, ShouldBeNil) 138 So(payload, ShouldEqual, "greetings") 139 So(string(out), ShouldEqual, "I got: greetings") 140 }) 141 } 142 143 func TestNewMessage(t *testing.T) { 144 node, err := makeNode(1234, "node1") 145 if err != nil { 146 panic(err) 147 } 148 defer node.Close() 149 Convey("It should create a new message", t, func() { 150 now := time.Now() 151 m := node.NewMessage(PUT_REQUEST, "fish") 152 So(now.Before(m.Time), ShouldBeTrue) // poor check, but at least makes sure the time was set to something just after the NewMessage call was made 153 So(m.Type, ShouldEqual, PUT_REQUEST) 154 So(m.Body, ShouldEqual, "fish") 155 So(m.From, ShouldEqual, node.HashAddr) 156 }) 157 } 158 159 func TestNodeSend(t *testing.T) { 160 d, _, h := PrepareTestChain("test") 161 defer CleanupTestChain(h, d) 162 163 node1, err := makeNode(1234, "node1") 164 if err != nil { 165 panic(err) 166 } 167 h.node.Close() 168 h.node = node1 169 170 d2, _, h2 := PrepareTestChain("test2") 171 defer CleanupTestChain(h2, d2) 172 h2.node.Close() 173 174 node2, err := makeNode(1235, "node2") 175 if err != nil { 176 panic(err) 177 } 178 defer node2.Close() 179 h2.node = node2 180 os.Remove(filepath.Join(h2.DBPath(), DHTStoreFileName)) 181 h2.dht = NewDHT(h2) 182 183 h.Activate() 184 185 Convey("It should start the DHT protocols", t, func() { 186 err := h2.dht.Start() 187 So(err, ShouldBeNil) 188 }) 189 Convey("It should start the Nucleus protocols", t, func() { 190 err := h2.nucleus.Start() 191 So(err, ShouldBeNil) 192 }) 193 194 node2.host.Peerstore().AddAddr(node1.HashAddr, node1.NetAddr, pstore.PermanentAddrTTL) 195 196 Convey("It should fail on messages without a source", t, func() { 197 m := Message{Type: PUT_REQUEST, Body: "fish"} 198 So(len(node1.host.Peerstore().Peers()), ShouldEqual, 1) 199 r, err := node2.Send(context.Background(), ActionProtocol, node1.HashAddr, &m) 200 So(err, ShouldBeNil) 201 So(len(node1.host.Peerstore().Peers()), ShouldEqual, 2) // node1's peerstore should now have node2 202 So(r.Type, ShouldEqual, ERROR_RESPONSE) 203 So(r.From, ShouldEqual, node1.HashAddr) // response comes from who we sent to 204 So(r.Body.(ErrorResponse).Message, ShouldEqual, "message must have a source") 205 }) 206 207 Convey("It should fail on incorrect message types", t, func() { 208 m := node1.NewMessage(PUT_REQUEST, "fish") 209 r, err := node1.Send(context.Background(), ValidateProtocol, node2.HashAddr, m) 210 So(err, ShouldBeNil) 211 So(r.Type, ShouldEqual, ERROR_RESPONSE) 212 So(r.From, ShouldEqual, node2.HashAddr) // response comes from who we sent to 213 So(r.Body.(ErrorResponse).Message, ShouldEqual, "message type 2 not in holochain-validate protocol") 214 215 m = node2.NewMessage(PUT_REQUEST, "fish") 216 r, err = node2.Send(context.Background(), GossipProtocol, node1.HashAddr, m) 217 So(err, ShouldBeNil) 218 So(r.Type, ShouldEqual, ERROR_RESPONSE) 219 So(r.From, ShouldEqual, node1.HashAddr) // response comes from who we sent to 220 So(r.Body.(ErrorResponse).Message, ShouldEqual, "message type 2 not in holochain-gossip protocol") 221 222 m = node2.NewMessage(GOSSIP_REQUEST, "fish") 223 r, err = node2.Send(context.Background(), ActionProtocol, node1.HashAddr, m) 224 So(err, ShouldBeNil) 225 So(r.Type, ShouldEqual, ERROR_RESPONSE) 226 So(r.From, ShouldEqual, node1.HashAddr) // response comes from who we sent to 227 So(r.Body.(ErrorResponse).Message, ShouldEqual, "message type 9 not in holochain-action protocol") 228 229 }) 230 231 Convey("It should respond with err on bad request on invalid PUT_REQUESTS", t, func() { 232 hash, _ := NewHash("QmY8Mzg9F69e5P9AoQPYat6x5HEhc1TVGs11tmfNSzkqh2") 233 234 m := node2.NewMessage(PUT_REQUEST, HoldReq{EntryHash: hash}) 235 r, err := node2.Send(context.Background(), ActionProtocol, node1.HashAddr, m) 236 So(err, ShouldBeNil) 237 So(r.Type, ShouldEqual, ERROR_RESPONSE) 238 So(r.From, ShouldEqual, node1.HashAddr) // response comes from who we sent to 239 So(r.Body.(ErrorResponse).Code, ShouldEqual, ErrHashNotFoundCode) 240 }) 241 242 Convey("It should respond with OK if valid request", t, func() { 243 m := node2.NewMessage(GOSSIP_REQUEST, GossipReq{}) 244 r, err := node2.Send(context.Background(), GossipProtocol, node1.HashAddr, m) 245 So(err, ShouldBeNil) 246 So(r.Type, ShouldEqual, OK_RESPONSE) 247 So(r.From, ShouldEqual, node1.HashAddr) // response comes from who we sent to 248 So(fmt.Sprintf("%T", r.Body), ShouldEqual, "holochain.Gossip") 249 }) 250 251 Convey("it should respond with err on messages from nodes on the blockedlist", t, func() { 252 node1.Block(node2.HashAddr) 253 m := node2.NewMessage(GOSSIP_REQUEST, GossipReq{}) 254 r, err := node2.Send(context.Background(), GossipProtocol, node1.HashAddr, m) 255 So(err, ShouldBeNil) 256 So(r.Type, ShouldEqual, ERROR_RESPONSE) 257 So(r.From, ShouldEqual, node1.HashAddr) // response comes from who we sent to 258 So(r.Body.(ErrorResponse).Code, ShouldEqual, ErrBlockedListedCode) 259 }) 260 261 Convey("it should respond with err on messages to nodes on the blockedlist", t, func() { 262 node1.Block(node2.HashAddr) 263 m := node1.NewMessage(GOSSIP_REQUEST, GossipReq{}) 264 _, err = node1.Send(context.Background(), GossipProtocol, node2.HashAddr, m) 265 So(err, ShouldEqual, ErrBlockedListed) 266 }) 267 268 } 269 270 func TestNodeBlockedList(t *testing.T) { 271 Convey("it should be set up from a peerlist", t, func() { 272 node, _ := makeNode(1234, "node1") 273 defer node.Close() 274 node2, _ := makeNode(1235, "node2") 275 defer node2.Close() 276 277 So(node.IsBlocked(node2.HashAddr), ShouldBeFalse) 278 node.InitBlockedList(PeerList{Records: []PeerRecord{PeerRecord{ID: node2.HashAddr}}}) 279 So(node.IsBlocked(node2.HashAddr), ShouldBeTrue) 280 node.Unblock(node2.HashAddr) 281 So(node.IsBlocked(node2.HashAddr), ShouldBeFalse) 282 node.Block(node2.HashAddr) 283 So(node.IsBlocked(node2.HashAddr), ShouldBeTrue) 284 }) 285 } 286 287 func TestMessageCoding(t *testing.T) { 288 node, err := makeNode(1234, "node1") 289 if err != nil { 290 panic(err) 291 } 292 defer node.Close() 293 294 m := node.NewMessage(PUT_REQUEST, "foo") 295 var d []byte 296 Convey("It should encode and decode put messages", t, func() { 297 d, err = m.Encode() 298 So(err, ShouldBeNil) 299 300 var m2 Message 301 r := bytes.NewReader(d) 302 err = m2.Decode(r) 303 So(err, ShouldBeNil) 304 305 So(fmt.Sprintf("%v", m), ShouldEqual, fmt.Sprintf("%v", &m2)) 306 }) 307 308 m = node.NewMessage(GET_REQUEST, "foo") 309 Convey("It should encode and decode get messages", t, func() { 310 d, err = m.Encode() 311 So(err, ShouldBeNil) 312 313 var m2 Message 314 r := bytes.NewReader(d) 315 err = m2.Decode(r) 316 So(err, ShouldBeNil) 317 318 So(fmt.Sprintf("%v", m), ShouldEqual, fmt.Sprintf("%v", &m2)) 319 }) 320 321 Convey("It should encode and decode get OK_RESPONSE", t, func() { 322 body := GetResp{} 323 body.Entry = GobEntry{C: "3"} 324 325 m = node.NewMessage(OK_RESPONSE, body) 326 d, err = m.Encode() 327 So(err, ShouldBeNil) 328 329 var m2 Message 330 r := bytes.NewReader(d) 331 err = m2.Decode(r) 332 So(err, ShouldBeNil) 333 334 So(fmt.Sprintf("%v", m), ShouldEqual, fmt.Sprintf("%v", &m2)) 335 }) 336 337 } 338 339 func TestFingerprintMessage(t *testing.T) { 340 Convey("it should create a unique fingerprint for messages", t, func() { 341 var id peer.ID 342 var mp *Message 343 344 f, err := mp.Fingerprint() 345 So(err, ShouldBeNil) 346 So(f.String(), ShouldEqual, NullHash().String()) 347 now := time.Unix(1, 1) // pick a constant time so the test will always work 348 m := Message{Type: PUT_REQUEST, Time: now, Body: "foo", From: id} 349 350 f, err = m.Fingerprint() 351 So(err, ShouldBeNil) 352 So(f.String(), ShouldEqual, "QmTZf2qqYiKbJbQVpFyidMVyAtb1S4xQNV52LcX9LDVTQn") 353 m = Message{Type: PUT_REQUEST, Time: now, Body: "foo1", From: id} 354 355 f, err = m.Fingerprint() 356 So(err, ShouldBeNil) 357 So(f.String(), ShouldEqual, "QmP2WUSMWAuZrX2nqWcEyei7GDCwVaetkynQESFDrHNkGa") 358 now = time.Unix(1, 2) // pick a constant time so the test will always work 359 m = Message{Type: PUT_REQUEST, Time: now, Body: "foo", From: id} 360 361 f, err = m.Fingerprint() 362 So(err, ShouldBeNil) 363 So(f.String(), ShouldEqual, "QmTZf2qqYiKbJbQVpFyidMVyAtb1S4xQNV52LcX9LDVTQn") 364 m = Message{Type: GET_REQUEST, Time: now, Body: "foo", From: id} 365 366 f, err = m.Fingerprint() 367 So(err, ShouldBeNil) 368 So(f.String(), ShouldEqual, "Qmd7v7bxE7xRCj3Amhx8kyj7DbUGJdbKzuiUUahx3ARPec") 369 }) 370 } 371 372 func TestErrorCoding(t *testing.T) { 373 Convey("it should encode and decode errors", t, func() { 374 er := NewErrorResponse(ErrHashNotFound) 375 So(er.DecodeResponseError(), ShouldEqual, ErrHashNotFound) 376 er = NewErrorResponse(ErrHashDeleted) 377 So(er.DecodeResponseError(), ShouldEqual, ErrHashDeleted) 378 er = NewErrorResponse(ErrHashModified) 379 So(er.DecodeResponseError(), ShouldEqual, ErrHashModified) 380 er = NewErrorResponse(ErrHashRejected) 381 So(er.DecodeResponseError(), ShouldEqual, ErrHashRejected) 382 er = NewErrorResponse(ErrLinkNotFound) 383 So(er.DecodeResponseError(), ShouldEqual, ErrLinkNotFound) 384 385 er = NewErrorResponse(errors.New("Some Error")) 386 So(er.Code, ShouldEqual, ErrUnknownCode) 387 So(er.DecodeResponseError().Error(), ShouldEqual, "Some Error") 388 }) 389 } 390 391 func TestAddPeer(t *testing.T) { 392 nodesCount := 4 393 mt := setupMultiNodeTesting(nodesCount) 394 defer mt.cleanupMultiNodeTesting() 395 nodes := mt.nodes 396 397 h := nodes[0] 398 somePeer := nodes[1].node.HashAddr 399 pi := pstore.PeerInfo{ID: somePeer, Addrs: []ma.Multiaddr{nodes[1].node.NetAddr}} 400 Convey("it should add a peer to the peer store and the gossip list with public key", t, func() { 401 So(h.node.routingTable.Size(), ShouldEqual, 0) 402 So(len(h.node.peerstore.Peers()), ShouldEqual, 1) 403 if h.Config.EnableWorldModel { 404 So(len(h.world.nodes), ShouldEqual, 0) 405 } 406 err := h.AddPeer(pi) 407 So(err, ShouldBeNil) 408 So(len(h.node.peerstore.Peers()), ShouldEqual, 2) 409 glist, err := h.dht.getGossipers() 410 So(err, ShouldBeNil) 411 So(len(glist), ShouldEqual, 1) 412 So(glist[0], ShouldEqual, somePeer) 413 So(h.node.routingTable.Size(), ShouldEqual, 1) 414 415 if h.Config.EnableWorldModel { 416 So(len(h.world.nodes), ShouldEqual, 1) 417 node1ID, _, _ := nodes[1].agent.NodeID() 418 So(h.world.nodes[node1ID].PubKey.Equals(nodes[1].agent.PubKey()), ShouldBeTrue) 419 } 420 421 }) 422 423 Convey("it should not add a blocked peer", t, func() { 424 blockedPeer := nodes[2].node.HashAddr 425 bpi := pstore.PeerInfo{ID: blockedPeer, Addrs: []ma.Multiaddr{nodes[2].node.NetAddr}} 426 h.node.Block(blockedPeer) 427 err := h.AddPeer(bpi) 428 So(err, ShouldEqual, ErrBlockedListed) 429 So(len(h.node.peerstore.Peers()), ShouldEqual, 2) 430 glist, err := h.dht.getGossipers() 431 So(err, ShouldBeNil) 432 So(len(glist), ShouldEqual, 1) 433 So(glist[0], ShouldEqual, somePeer) 434 So(h.node.routingTable.Size(), ShouldEqual, 1) 435 }) 436 437 Convey("it should clear the peer's Address list if connection fails", t, func() { 438 closedNode := nodes[nodesCount-1].node 439 pi := pstore.PeerInfo{ID: closedNode.HashAddr, Addrs: []ma.Multiaddr{closedNode.NetAddr}} 440 closedNode.Close() 441 err := h.AddPeer(pi) 442 So(err, ShouldEqual, nil) 443 So(len(h.node.peerstore.Addrs(pi.ID)), ShouldEqual, 0) 444 }) 445 } 446 447 func TestNodeRouting(t *testing.T) { 448 d, _, h := PrepareTestChain("test") 449 defer CleanupTestChain(h, d) 450 node := h.node 451 452 start := 0 453 testPeerCount := 20 454 peers := []peer.ID{} 455 456 peers = addTestPeers(h, peers, start, testPeerCount) 457 Convey("populating routing", t, func() { 458 p := node.HashAddr 459 srch := node.routingTable.NearestPeers(HashFromPeerID(p), 5) 460 nearest := fmt.Sprintf("%d %v", len(srch), srch) 461 So(nearest, ShouldEqual, "5 [<peer.ID P9vKpw> <peer.ID P9QXqa> <peer.ID PrUBh5> <peer.ID Pn94bj> <peer.ID QHFWTH>]") 462 start = testPeerCount 463 testPeerCount += 5 464 peers = addTestPeers(h, peers, start, testPeerCount) 465 srch = node.routingTable.NearestPeers(HashFromPeerID(p), 5) 466 nearest = fmt.Sprintf("%d %v", len(srch), srch) 467 468 // adding a few more yields one which is closer 469 So(nearest, ShouldEqual, "5 [<peer.ID NSQqJR> <peer.ID P9vKpw> <peer.ID P9QXqa> <peer.ID PrUBh5> <peer.ID Pn94bj>]") 470 // node.routingTable.Print() 471 }) 472 } 473 474 func TestNodeAppSendResolution(t *testing.T) { 475 // if this is too high we can face `dial backoff` errors 476 // https://github.com/holochain/holochain-proto/issues/706 477 nodesCount := 20 478 mt := setupMultiNodeTesting(nodesCount) 479 defer mt.cleanupMultiNodeTesting() 480 ringConnect(t, mt.ctx, mt.nodes, nodesCount) 481 node1 := mt.nodes[0].node 482 node2 := mt.nodes[nodesCount/2].node 483 484 Convey("sending to nodes we aren't directly connected to should resolve", t, func() { 485 m := node2.NewMessage(GOSSIP_REQUEST, GossipReq{}) 486 r, err := node2.Send(mt.ctx, GossipProtocol, node1.HashAddr, m) 487 So(err, ShouldBeNil) 488 So(r.Type, ShouldEqual, OK_RESPONSE) 489 So(r.From, ShouldEqual, node1.HashAddr) // response comes from who we sent to 490 So(fmt.Sprintf("%T", r.Body), ShouldEqual, "holochain.Gossip") 491 }) 492 } 493 494 func TestActivePeers(t *testing.T) { 495 node, _ := makeNode(1234, "") 496 defer node.Close() 497 Convey("self node should be active", t, func() { 498 So(node.isPeerActive(node.HashAddr), ShouldBeTrue) 499 }) 500 501 otherPeer, _ := makePeer("foo") 502 Convey("a peer not in the peerstore be considered inactive", t, func() { 503 So(node.isPeerActive(otherPeer), ShouldBeFalse) 504 }) 505 506 Convey("a peer without an address in the peerstore should be considered inactive", t, func() { 507 node.peerstore.AddAddrs(otherPeer, []ma.Multiaddr{}, PeerTTL) 508 So(node.isPeerActive(otherPeer), ShouldBeFalse) 509 }) 510 511 Convey("it should be able to filter out inactive peers from a list", t, func() { 512 filteredList := node.filterInactviePeers([]peer.ID{node.HashAddr, otherPeer}, 0) 513 So(len(filteredList), ShouldEqual, 1) 514 So(filteredList[0], ShouldEqual, node.HashAddr) 515 }) 516 517 Convey("it should be able to limit number returned when filtering out inactive peers", t, func() { 518 addr, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/1234") 519 if err != nil { 520 panic(err) 521 } 522 node.peerstore.AddAddrs(otherPeer, []ma.Multiaddr{addr}, PeerTTL) 523 filteredList := node.filterInactviePeers([]peer.ID{node.HashAddr, otherPeer}, 0) 524 So(len(filteredList), ShouldEqual, 2) 525 So(filteredList[0], ShouldEqual, node.HashAddr) 526 So(filteredList[1], ShouldEqual, otherPeer) 527 528 filteredList = node.filterInactviePeers([]peer.ID{node.HashAddr, otherPeer}, 1) 529 So(len(filteredList), ShouldEqual, 1) 530 }) 531 } 532 533 func TestNodeStress(t *testing.T) { 534 nodesCount := 4 535 mt := setupMultiNodeTesting(nodesCount) 536 defer mt.cleanupMultiNodeTesting() 537 nodes := mt.nodes 538 h1 := nodes[0] 539 h2 := nodes[1] 540 h3 := nodes[2] 541 h4 := nodes[3] 542 node1 := h1.node 543 node2 := h2.node 544 node3 := h3.node 545 node4 := h4.node 546 starConnectMutual(t, mt.ctx, nodes, nodesCount) 547 548 Convey("hammering a node should work", t, func() { 549 var i int 550 var err error 551 var r Message 552 //count := 1000 553 count := 10 554 s1 := make(chan bool, count) 555 s2 := make(chan bool, count) 556 for i = 0; i < count; i++ { 557 hash := commit(h1, "evenNumbers", fmt.Sprintf("%d", i*2)) 558 m := node1.NewMessage(PUT_REQUEST, HoldReq{EntryHash: hash}) 559 r, err = node1.Send(mt.ctx, ActionProtocol, node2.HashAddr, m) 560 if err != nil || r.Type != OK_RESPONSE { 561 break 562 } 563 go func() { 564 r, err = node1.Send(mt.ctx, ActionProtocol, node3.HashAddr, m) 565 if err != nil { 566 panic(err) 567 } 568 s1 <- true 569 }() 570 go func() { 571 r, err = node1.Send(mt.ctx, ActionProtocol, node4.HashAddr, m) 572 if err != nil { 573 panic(err) 574 } 575 s2 <- true 576 }() 577 } 578 for i = 0; i < count; i++ { 579 <-s1 580 <-s2 581 } 582 So(i, ShouldEqual, count) 583 So(err, ShouldBeNil) 584 So(r.Type, ShouldEqual, OK_RESPONSE) 585 }) 586 } 587 588 func TestNodeRoutingTableBootstrap(t *testing.T) { 589 nodesCount := 10 590 mt := setupMultiNodeTesting(nodesCount) 591 defer mt.cleanupMultiNodeTesting() 592 nodes := mt.nodes 593 594 rt := nodes[0].node.routingTable 595 Convey("it should should bootstrap the routing table", t, func() { 596 So(rt.Size(), ShouldEqual, 0) 597 So(rt.IsEmpty(), ShouldBeTrue) 598 599 // connect up all the nodes except 0 600 for i := 0; i < nodesCount-1; i++ { 601 connect(t, mt.ctx, nodes[i], nodes[i+1]) 602 nodes[i].node.routingTable.Update(nodes[i+1].nodeID) 603 } 604 605 //now call routing refresh to boostrap the table 606 RoutingRefreshTask(nodes[0]) 607 So(rt.Size(), ShouldEqual, 9) 608 So(rt.IsEmpty(), ShouldBeFalse) 609 }) 610 }