github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/network/simulations/overlay_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 19:16:43</date> 10 //</624450115066662912> 11 12 package main 13 14 import ( 15 "context" 16 "encoding/json" 17 "fmt" 18 "io/ioutil" 19 "net/http" 20 "net/http/httptest" 21 "net/url" 22 "testing" 23 "time" 24 25 "github.com/ethereum/go-ethereum/p2p/enode" 26 "github.com/ethereum/go-ethereum/p2p/simulations" 27 "github.com/ethereum/go-ethereum/swarm/log" 28 ) 29 30 var ( 31 nodeCount = 16 32 ) 33 34 //此测试用于测试叠加模拟。 35 //由于模拟是通过主系统执行的,因此很容易错过更改。 36 //自动测试将阻止 37 //测试只是连接到模拟,启动网络, 38 //启动mocker,获取节点数,然后再次停止它。 39 //它还提供了前端所需步骤的文档 40 //使用模拟 41 func TestOverlaySim(t *testing.T) { 42 t.Skip("Test is flaky, see: https://github.com/ethersphere/go-ethereum/issues/592“) 43 //启动模拟 44 log.Info("Start simulation backend") 45 //获取模拟网络;需要订阅up事件 46 net := newSimulationNetwork() 47 //创建覆盖模拟 48 sim := newOverlaySim(net) 49 //用它创建一个HTTP测试服务器 50 srv := httptest.NewServer(sim) 51 defer srv.Close() 52 53 log.Debug("Http simulation server started. Start simulation network") 54 //启动仿真网络(仿真初始化) 55 resp, err := http.Post(srv.URL+"/start", "application/json", nil) 56 if err != nil { 57 t.Fatal(err) 58 } 59 defer resp.Body.Close() 60 if resp.StatusCode != http.StatusOK { 61 t.Fatalf("Expected Status Code %d, got %d", http.StatusOK, resp.StatusCode) 62 } 63 64 log.Debug("Start mocker") 65 //启动mocker,需要一个节点计数和一个ID 66 resp, err = http.PostForm(srv.URL+"/mocker/start", 67 url.Values{ 68 "node-count": {fmt.Sprintf("%d", nodeCount)}, 69 "mocker-type": {simulations.GetMockerList()[0]}, 70 }) 71 if err != nil { 72 t.Fatal(err) 73 } 74 defer resp.Body.Close() 75 if resp.StatusCode != http.StatusOK { 76 reason, err := ioutil.ReadAll(resp.Body) 77 if err != nil { 78 t.Fatal(err) 79 } 80 t.Fatalf("Expected Status Code %d, got %d, response body %s", http.StatusOK, resp.StatusCode, string(reason)) 81 } 82 83 //等待节点启动所需的变量 84 var upCount int 85 trigger := make(chan enode.ID) 86 87 //等待所有节点启动 88 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 89 defer cancel() 90 91 //开始监视节点启动事件… 92 go watchSimEvents(net, ctx, trigger) 93 94 //…并等待直到收到所有预期的向上事件(nodeCount) 95 LOOP: 96 for { 97 select { 98 case <-trigger: 99 //接收到新节点向上事件,增加计数器 100 upCount++ 101 //接收到所有预期的节点向上事件 102 if upCount == nodeCount { 103 break LOOP 104 } 105 case <-ctx.Done(): 106 t.Fatalf("Timed out waiting for up events") 107 } 108 109 } 110 111 //此时,我们可以查询服务器 112 log.Info("Get number of nodes") 113 //获取节点数 114 resp, err = http.Get(srv.URL + "/nodes") 115 if err != nil { 116 t.Fatal(err) 117 } 118 119 defer resp.Body.Close() 120 if resp.StatusCode != http.StatusOK { 121 t.Fatalf("err %s", resp.Status) 122 } 123 b, err := ioutil.ReadAll(resp.Body) 124 if err != nil { 125 t.Fatal(err) 126 } 127 128 //从JSON响应中取消标记节点数 129 var nodesArr []simulations.Node 130 err = json.Unmarshal(b, &nodesArr) 131 if err != nil { 132 t.Fatal(err) 133 } 134 135 //检查接收的节点数是否与发送的节点数相同 136 if len(nodesArr) != nodeCount { 137 t.Fatal(fmt.Errorf("Expected %d number of nodes, got %d", nodeCount, len(nodesArr))) 138 } 139 140 //需要让它运行一段时间,否则立即停止它会因运行节点而崩溃。 141 //希望连接到已停止的节点 142 time.Sleep(1 * time.Second) 143 144 log.Info("Stop the network") 145 //停止网络 146 resp, err = http.Post(srv.URL+"/stop", "application/json", nil) 147 if err != nil { 148 t.Fatal(err) 149 } 150 defer resp.Body.Close() 151 if resp.StatusCode != http.StatusOK { 152 t.Fatalf("err %s", resp.Status) 153 } 154 155 log.Info("Reset the network") 156 //重置网络(删除所有节点和连接) 157 resp, err = http.Post(srv.URL+"/reset", "application/json", nil) 158 if err != nil { 159 t.Fatal(err) 160 } 161 defer resp.Body.Close() 162 if resp.StatusCode != http.StatusOK { 163 t.Fatalf("err %s", resp.Status) 164 } 165 } 166 167 //注意事件,以便我们知道所有节点何时启动 168 func watchSimEvents(net *simulations.Network, ctx context.Context, trigger chan enode.ID) { 169 events := make(chan *simulations.Event) 170 sub := net.Events().Subscribe(events) 171 defer sub.Unsubscribe() 172 173 for { 174 select { 175 case ev := <-events: 176 //仅捕获节点向上事件 177 if ev.Type == simulations.EventTypeNode { 178 if ev.Node.Up { 179 log.Debug("got node up event", "event", ev, "node", ev.Node.Config.ID) 180 select { 181 case trigger <- ev.Node.Config.ID: 182 case <-ctx.Done(): 183 return 184 } 185 } 186 } 187 case <-ctx.Done(): 188 return 189 } 190 } 191 } 192