github.com/metacurrency/holochain@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  }