github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/p2p/simulations/network_test.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2017 Go Ethereum作者 10 //此文件是Go以太坊库的一部分。 11 // 12 //Go-Ethereum库是免费软件:您可以重新分发它和/或修改 13 //根据GNU发布的较低通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊图书馆的发行目的是希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU较低的通用公共许可证,了解更多详细信息。 21 // 22 //你应该收到一份GNU较低级别的公共许可证副本 23 //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package simulations 26 27 import ( 28 "context" 29 "fmt" 30 "testing" 31 "time" 32 33 "github.com/ethereum/go-ethereum/p2p/discover" 34 "github.com/ethereum/go-ethereum/p2p/simulations/adapters" 35 ) 36 37 //TestNetworkSimulation使用每个节点创建多节点仿真网络 38 //在环形拓扑中连接,检查所有节点是否成功握手 39 //彼此之间,快照完全代表所需的拓扑 40 func TestNetworkSimulation(t *testing.T) { 41 //使用20个testservice节点创建模拟网络 42 adapter := adapters.NewSimAdapter(adapters.Services{ 43 "test": newTestService, 44 }) 45 network := NewNetwork(adapter, &NetworkConfig{ 46 DefaultService: "test", 47 }) 48 defer network.Shutdown() 49 nodeCount := 20 50 ids := make([]discover.NodeID, nodeCount) 51 for i := 0; i < nodeCount; i++ { 52 conf := adapters.RandomNodeConfig() 53 node, err := network.NewNodeWithConfig(conf) 54 if err != nil { 55 t.Fatalf("error creating node: %s", err) 56 } 57 if err := network.Start(node.ID()); err != nil { 58 t.Fatalf("error starting node: %s", err) 59 } 60 ids[i] = node.ID() 61 } 62 63 //执行连接环中节点的检查(因此每个节点 64 //然后检查所有节点 65 //通过检查他们的对等计数进行了两次握手 66 action := func(_ context.Context) error { 67 for i, id := range ids { 68 peerID := ids[(i+1)%len(ids)] 69 if err := network.Connect(id, peerID); err != nil { 70 return err 71 } 72 } 73 return nil 74 } 75 check := func(ctx context.Context, id discover.NodeID) (bool, error) { 76 //检查一下我们的时间没有用完 77 select { 78 case <-ctx.Done(): 79 return false, ctx.Err() 80 default: 81 } 82 83 //获取节点 84 node := network.GetNode(id) 85 if node == nil { 86 return false, fmt.Errorf("unknown node: %s", id) 87 } 88 89 //检查它是否有两个同龄人 90 client, err := node.Client() 91 if err != nil { 92 return false, err 93 } 94 var peerCount int64 95 if err := client.CallContext(ctx, &peerCount, "test_peerCount"); err != nil { 96 return false, err 97 } 98 switch { 99 case peerCount < 2: 100 return false, nil 101 case peerCount == 2: 102 return true, nil 103 default: 104 return false, fmt.Errorf("unexpected peerCount: %d", peerCount) 105 } 106 } 107 108 timeout := 30 * time.Second 109 ctx, cancel := context.WithTimeout(context.Background(), timeout) 110 defer cancel() 111 112 //每100毫秒触发一次检查 113 trigger := make(chan discover.NodeID) 114 go triggerChecks(ctx, ids, trigger, 100*time.Millisecond) 115 116 result := NewSimulation(network).Run(ctx, &Step{ 117 Action: action, 118 Trigger: trigger, 119 Expect: &Expectation{ 120 Nodes: ids, 121 Check: check, 122 }, 123 }) 124 if result.Error != nil { 125 t.Fatalf("simulation failed: %s", result.Error) 126 } 127 128 //获取网络快照并检查它是否包含正确的拓扑 129 snap, err := network.Snapshot() 130 if err != nil { 131 t.Fatal(err) 132 } 133 if len(snap.Nodes) != nodeCount { 134 t.Fatalf("expected snapshot to contain %d nodes, got %d", nodeCount, len(snap.Nodes)) 135 } 136 if len(snap.Conns) != nodeCount { 137 t.Fatalf("expected snapshot to contain %d connections, got %d", nodeCount, len(snap.Conns)) 138 } 139 for i, id := range ids { 140 conn := snap.Conns[i] 141 if conn.One != id { 142 t.Fatalf("expected conn[%d].One to be %s, got %s", i, id, conn.One) 143 } 144 peerID := ids[(i+1)%len(ids)] 145 if conn.Other != peerID { 146 t.Fatalf("expected conn[%d].Other to be %s, got %s", i, peerID, conn.Other) 147 } 148 } 149 } 150 151 func triggerChecks(ctx context.Context, ids []discover.NodeID, trigger chan discover.NodeID, interval time.Duration) { 152 tick := time.NewTicker(interval) 153 defer tick.Stop() 154 for { 155 select { 156 case <-tick.C: 157 for _, id := range ids { 158 select { 159 case trigger <- id: 160 case <-ctx.Done(): 161 return 162 } 163 } 164 case <-ctx.Done(): 165 return 166 } 167 } 168 }