github.com/holochain/holochain-proto@v0.1.0-alpha-26.0.20200915073418-5c83169c9b5b/node_test_util.go (about) 1 package holochain 2 3 import ( 4 "context" 5 "fmt" 6 ic "github.com/libp2p/go-libp2p-crypto" 7 peer "github.com/libp2p/go-libp2p-peer" 8 pstore "github.com/libp2p/go-libp2p-peerstore" 9 "math/rand" 10 "os" 11 "testing" 12 ) 13 14 // ------------------------------------------------------------------------------------------- 15 // node testing functions 16 17 func makePeer(id string) (pid peer.ID, key ic.PrivKey) { 18 // use a constant reader so the key will be the same each time for the test... 19 var err error 20 key, _, err = ic.GenerateEd25519Key(MakeTestSeed(id)) 21 if err != nil { 22 panic(err) 23 } 24 pid, _ = peer.IDFromPrivateKey(key) 25 return 26 } 27 28 func makeNode(port int, id string) (*Node, error) { 29 listenaddr := fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", port) 30 _, key := makePeer(id) 31 agent := LibP2PAgent{identity: AgentIdentity(id), priv: key, pub: key.GetPublic()} 32 return NewNode(listenaddr, "fakednahash", &agent, false, &debugLog) 33 } 34 35 func addTestPeers(h *Holochain, peers []peer.ID, start int, count int) []peer.ID { 36 for i := start; i < count; i++ { 37 p, _ := makePeer(fmt.Sprintf("peer_%d", i)) 38 // fmt.Printf("Peer %d: %s\n", i, peer.IDB58Encode(p)) 39 peers = append(peers, p) 40 pi := pstore.PeerInfo{ID: p} 41 err := h.addPeer(pi, false) 42 if err != nil { 43 panic(err) 44 } 45 } 46 return peers 47 } 48 49 func fullConnect(t *testing.T, ctx context.Context, nodes []*Holochain, nodesCount int) { 50 for i := 0; i < nodesCount; i++ { 51 for j := 0; j < nodesCount; j++ { 52 if j != i { 53 connect(t, ctx, nodes[i], nodes[j]) 54 } 55 } 56 } 57 } 58 59 func ringConnect(t *testing.T, ctx context.Context, nodes []*Holochain, nodesCount int) { 60 for i := 0; i < nodesCount; i++ { 61 connect(t, ctx, nodes[i], nodes[(i+1)%len(nodes)]) 62 } 63 } 64 65 func ringConnectMutual(t *testing.T, ctx context.Context, nodes []*Holochain, nodesCount int) { 66 for i := 0; i < nodesCount; i++ { 67 n2 := nodes[(i+1)%len(nodes)] 68 connect(t, ctx, nodes[i], n2) 69 connect(t, ctx, n2, nodes[i]) 70 } 71 } 72 73 func starConnect(t *testing.T, ctx context.Context, nodes []*Holochain, nodesCount int) { 74 for i := 1; i < nodesCount; i++ { 75 connect(t, ctx, nodes[0], nodes[i]) 76 } 77 } 78 79 func starConnectMutual(t *testing.T, ctx context.Context, nodes []*Holochain, nodesCount int) { 80 for i := 1; i < nodesCount; i++ { 81 connect(t, ctx, nodes[0], nodes[i]) 82 connect(t, ctx, nodes[i], nodes[0]) 83 } 84 } 85 86 func randConnect(t *testing.T, ctx context.Context, nodes []*Holochain, nodesCount, connectFromCount, connectToCount int) { 87 88 // connect nodes[1->connectFromCount] to connectToCount randomly selected nodes in 89 // nodes[(nodesCount-connectFromCount)->randConnect] 90 91 mrand := rand.New(rand.NewSource(42)) 92 guy := nodes[0] 93 others := nodes[1:] 94 for i := 0; i < connectFromCount; i++ { 95 for j := 0; j < connectToCount; j++ { // 16, high enough to probably not have any partitions 96 v := mrand.Intn(nodesCount - connectFromCount - 1) 97 connect(t, ctx, others[i], others[connectFromCount+v]) 98 } 99 } 100 101 for i := 0; i < connectFromCount; i++ { 102 connect(t, ctx, guy, others[i]) 103 } 104 } 105 106 type multiNodeTest struct { 107 ctx context.Context 108 cancel context.CancelFunc 109 s *Service 110 d string 111 nodes []*Holochain 112 count int 113 } 114 115 func setupMultiNodeTesting(n int) (mt *multiNodeTest) { 116 ctx, cancel := context.WithCancel(context.Background()) 117 d, s := SetupTestService() 118 mt = &multiNodeTest{ 119 ctx: ctx, 120 cancel: cancel, 121 s: s, 122 d: d, 123 count: n, 124 } 125 mt.nodes = makeTestNodes(mt.ctx, mt.s, n) 126 return 127 } 128 129 func (mt *multiNodeTest) cleanupMultiNodeTesting() { 130 for i := 0; i < mt.count; i++ { 131 mt.nodes[i].Close() 132 } 133 mt.cancel() 134 CleanupTestDir(mt.d) 135 } 136 137 func makeTestNodes(ctx context.Context, s *Service, n int) (nodes []*Holochain) { 138 nodes = make([]*Holochain, n) 139 for i := 0; i < n; i++ { 140 nodeName := fmt.Sprintf("node%d", i) 141 os.Setenv("HCLOG_PREFIX", nodeName+"_") 142 nodes[i] = setupTestChain(nodeName, i, s) 143 nodes[i].Config.EnableMDNS = false 144 prepareTestChain(nodes[i]) 145 } 146 for i := 0; i < n; i++ { 147 nodeName := fmt.Sprintf("node%d", i) 148 nodes[i].dht.dlog.Logf("SETUP: %s is %v", nodeName, nodes[i].nodeID) 149 } 150 os.Unsetenv("HCLOG_PREFIX") 151 return 152 } 153 154 func connectNoSync(t *testing.T, ctx context.Context, ah, bh *Holochain) { 155 a := ah.node 156 b := bh.node 157 idB := b.HashAddr 158 addrB := b.peerstore.Addrs(idB) 159 if len(addrB) == 0 { 160 t.Fatal("peers setup incorrectly: no local address") 161 } 162 163 pi := pstore.PeerInfo{ID: idB, Addrs: addrB} 164 err := ah.AddPeer(pi) 165 if err != nil { 166 t.Fatal(err) 167 } 168 169 if err = a.host.Connect(ctx, pi); err != nil { 170 t.Fatal(err) 171 } 172 } 173 174 func connect(t *testing.T, ctx context.Context, a, b *Holochain) { 175 connectNoSync(t, ctx, a, b) 176 177 // loop until connection notification has been received. 178 // under high load, this may not happen as immediately as we would like. 179 /* for a.node.routingTable.Find(b.nodeID) == "" { 180 time.Sleep(time.Millisecond * 5) 181 } 182 183 for b.node.routingTable.Find(a.nodeID) == "" { 184 time.Sleep(time.Millisecond * 5) 185 }*/ 186 // time.Sleep(100 * time.Millisecond) 187 }