github.com/codingfuture/orig-energi3@v0.8.4/swarm/network/simulations/overlay_test.go (about) 1 // Copyright 2018 The Energi Core Authors 2 // Copyright 2018 The go-ethereum Authors 3 // This file is part of the Energi Core library. 4 // 5 // The Energi Core library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The Energi Core library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the Energi Core library. If not, see <http://www.gnu.org/licenses/>. 17 18 package main 19 20 import ( 21 "context" 22 "encoding/json" 23 "fmt" 24 "io/ioutil" 25 "net/http" 26 "net/http/httptest" 27 "net/url" 28 "testing" 29 "time" 30 31 "github.com/ethereum/go-ethereum/p2p/enode" 32 "github.com/ethereum/go-ethereum/p2p/simulations" 33 "github.com/ethereum/go-ethereum/swarm/log" 34 ) 35 36 var ( 37 nodeCount = 10 38 ) 39 40 //This test is used to test the overlay simulation. 41 //As the simulation is executed via a main, it is easily missed on changes 42 //An automated test will prevent that 43 //The test just connects to the simulations, starts the network, 44 //starts the mocker, gets the number of nodes, and stops it again. 45 //It also provides a documentation on the steps needed by frontends 46 //to use the simulations 47 func TestOverlaySim(t *testing.T) { 48 t.Skip("Test is flaky, see: https://github.com/ethersphere/go-ethereum/issues/592") 49 //start the simulation 50 log.Info("Start simulation backend") 51 //get the simulation networ; needed to subscribe for up events 52 net := newSimulationNetwork() 53 //create the overlay simulation 54 sim := newOverlaySim(net) 55 //create a http test server with it 56 srv := httptest.NewServer(sim) 57 defer srv.Close() 58 59 log.Debug("Http simulation server started. Start simulation network") 60 //start the simulation network (initialization of simulation) 61 resp, err := http.Post(srv.URL+"/start", "application/json", nil) 62 if err != nil { 63 t.Fatal(err) 64 } 65 defer resp.Body.Close() 66 if resp.StatusCode != http.StatusOK { 67 t.Fatalf("Expected Status Code %d, got %d", http.StatusOK, resp.StatusCode) 68 } 69 70 log.Debug("Start mocker") 71 //start the mocker, needs a node count and an ID 72 resp, err = http.PostForm(srv.URL+"/mocker/start", 73 url.Values{ 74 "node-count": {fmt.Sprintf("%d", nodeCount)}, 75 "mocker-type": {simulations.GetMockerList()[0]}, 76 }) 77 if err != nil { 78 t.Fatal(err) 79 } 80 defer resp.Body.Close() 81 if resp.StatusCode != http.StatusOK { 82 reason, err := ioutil.ReadAll(resp.Body) 83 if err != nil { 84 t.Fatal(err) 85 } 86 t.Fatalf("Expected Status Code %d, got %d, response body %s", http.StatusOK, resp.StatusCode, string(reason)) 87 } 88 89 //variables needed to wait for nodes being up 90 var upCount int 91 trigger := make(chan enode.ID) 92 93 //wait for all nodes to be up 94 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 95 defer cancel() 96 97 //start watching node up events... 98 go watchSimEvents(net, ctx, trigger) 99 100 //...and wait until all expected up events (nodeCount) have been received 101 LOOP: 102 for { 103 select { 104 case <-trigger: 105 //new node up event received, increase counter 106 upCount++ 107 //all expected node up events received 108 if upCount == nodeCount { 109 break LOOP 110 } 111 case <-ctx.Done(): 112 t.Fatalf("Timed out waiting for up events") 113 } 114 115 } 116 117 //at this point we can query the server 118 log.Info("Get number of nodes") 119 //get the number of nodes 120 resp, err = http.Get(srv.URL + "/nodes") 121 if err != nil { 122 t.Fatal(err) 123 } 124 125 defer resp.Body.Close() 126 if resp.StatusCode != http.StatusOK { 127 t.Fatalf("err %s", resp.Status) 128 } 129 b, err := ioutil.ReadAll(resp.Body) 130 if err != nil { 131 t.Fatal(err) 132 } 133 134 //unmarshal number of nodes from JSON response 135 var nodesArr []simulations.Node 136 err = json.Unmarshal(b, &nodesArr) 137 if err != nil { 138 t.Fatal(err) 139 } 140 141 //check if number of nodes received is same as sent 142 if len(nodesArr) != nodeCount { 143 t.Fatal(fmt.Errorf("Expected %d number of nodes, got %d", nodeCount, len(nodesArr))) 144 } 145 146 //need to let it run for a little while, otherwise stopping it immediately can crash due running nodes 147 //wanting to connect to already stopped nodes 148 time.Sleep(1 * time.Second) 149 150 log.Info("Stop the network") 151 //stop the network 152 resp, err = http.Post(srv.URL+"/stop", "application/json", nil) 153 if err != nil { 154 t.Fatal(err) 155 } 156 defer resp.Body.Close() 157 if resp.StatusCode != http.StatusOK { 158 t.Fatalf("err %s", resp.Status) 159 } 160 161 log.Info("Reset the network") 162 //reset the network (removes all nodes and connections) 163 resp, err = http.Post(srv.URL+"/reset", "application/json", nil) 164 if err != nil { 165 t.Fatal(err) 166 } 167 defer resp.Body.Close() 168 if resp.StatusCode != http.StatusOK { 169 t.Fatalf("err %s", resp.Status) 170 } 171 } 172 173 //watch for events so we know when all nodes are up 174 func watchSimEvents(net *simulations.Network, ctx context.Context, trigger chan enode.ID) { 175 events := make(chan *simulations.Event) 176 sub := net.Events().Subscribe(events) 177 defer sub.Unsubscribe() 178 179 for { 180 select { 181 case ev := <-events: 182 //only catch node up events 183 if ev.Type == simulations.EventTypeNode { 184 if ev.Node.Up() { 185 log.Debug("got node up event", "event", ev, "node", ev.Node.Config.ID) 186 select { 187 case trigger <- ev.Node.Config.ID: 188 case <-ctx.Done(): 189 return 190 } 191 } 192 } 193 case <-ctx.Done(): 194 return 195 } 196 } 197 }