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