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  }