github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/p2p/simulations/network_test.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:45</date> 10 //</624342661725163520> 11 12 13 package simulations 14 15 import ( 16 "context" 17 "fmt" 18 "testing" 19 "time" 20 21 "github.com/ethereum/go-ethereum/p2p/discover" 22 "github.com/ethereum/go-ethereum/p2p/simulations/adapters" 23 ) 24 25 //TestNetworkSimulation使用每个节点创建多节点仿真网络 26 //在环形拓扑中连接,检查所有节点是否成功握手 27 //彼此之间,快照完全代表所需的拓扑 28 func TestNetworkSimulation(t *testing.T) { 29 //使用20个testservice节点创建模拟网络 30 adapter := adapters.NewSimAdapter(adapters.Services{ 31 "test": newTestService, 32 }) 33 network := NewNetwork(adapter, &NetworkConfig{ 34 DefaultService: "test", 35 }) 36 defer network.Shutdown() 37 nodeCount := 20 38 ids := make([]discover.NodeID, nodeCount) 39 for i := 0; i < nodeCount; i++ { 40 conf := adapters.RandomNodeConfig() 41 node, err := network.NewNodeWithConfig(conf) 42 if err != nil { 43 t.Fatalf("error creating node: %s", err) 44 } 45 if err := network.Start(node.ID()); err != nil { 46 t.Fatalf("error starting node: %s", err) 47 } 48 ids[i] = node.ID() 49 } 50 51 //执行连接环中节点的检查(因此每个节点 52 //然后检查所有节点 53 //通过检查他们的对等计数进行了两次握手 54 action := func(_ context.Context) error { 55 for i, id := range ids { 56 peerID := ids[(i+1)%len(ids)] 57 if err := network.Connect(id, peerID); err != nil { 58 return err 59 } 60 } 61 return nil 62 } 63 check := func(ctx context.Context, id discover.NodeID) (bool, error) { 64 //检查一下我们的时间没有用完 65 select { 66 case <-ctx.Done(): 67 return false, ctx.Err() 68 default: 69 } 70 71 //获取节点 72 node := network.GetNode(id) 73 if node == nil { 74 return false, fmt.Errorf("unknown node: %s", id) 75 } 76 77 //检查它是否有两个同龄人 78 client, err := node.Client() 79 if err != nil { 80 return false, err 81 } 82 var peerCount int64 83 if err := client.CallContext(ctx, &peerCount, "test_peerCount"); err != nil { 84 return false, err 85 } 86 switch { 87 case peerCount < 2: 88 return false, nil 89 case peerCount == 2: 90 return true, nil 91 default: 92 return false, fmt.Errorf("unexpected peerCount: %d", peerCount) 93 } 94 } 95 96 timeout := 30 * time.Second 97 ctx, cancel := context.WithTimeout(context.Background(), timeout) 98 defer cancel() 99 100 //每100毫秒触发一次检查 101 trigger := make(chan discover.NodeID) 102 go triggerChecks(ctx, ids, trigger, 100*time.Millisecond) 103 104 result := NewSimulation(network).Run(ctx, &Step{ 105 Action: action, 106 Trigger: trigger, 107 Expect: &Expectation{ 108 Nodes: ids, 109 Check: check, 110 }, 111 }) 112 if result.Error != nil { 113 t.Fatalf("simulation failed: %s", result.Error) 114 } 115 116 //获取网络快照并检查它是否包含正确的拓扑 117 snap, err := network.Snapshot() 118 if err != nil { 119 t.Fatal(err) 120 } 121 if len(snap.Nodes) != nodeCount { 122 t.Fatalf("expected snapshot to contain %d nodes, got %d", nodeCount, len(snap.Nodes)) 123 } 124 if len(snap.Conns) != nodeCount { 125 t.Fatalf("expected snapshot to contain %d connections, got %d", nodeCount, len(snap.Conns)) 126 } 127 for i, id := range ids { 128 conn := snap.Conns[i] 129 if conn.One != id { 130 t.Fatalf("expected conn[%d].One to be %s, got %s", i, id, conn.One) 131 } 132 peerID := ids[(i+1)%len(ids)] 133 if conn.Other != peerID { 134 t.Fatalf("expected conn[%d].Other to be %s, got %s", i, peerID, conn.Other) 135 } 136 } 137 } 138 139 func triggerChecks(ctx context.Context, ids []discover.NodeID, trigger chan discover.NodeID, interval time.Duration) { 140 tick := time.NewTicker(interval) 141 defer tick.Stop() 142 for { 143 select { 144 case <-tick.C: 145 for _, id := range ids { 146 select { 147 case trigger <- id: 148 case <-ctx.Done(): 149 return 150 } 151 } 152 case <-ctx.Done(): 153 return 154 } 155 } 156 } 157