github.com/aitimate-0/go-ethereum@v1.9.7/p2p/simulations/mocker_test.go (about) 1 // Copyright 2017 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 17 // Package simulations simulates p2p networks. 18 // A mocker simulates starting and stopping real nodes in a network. 19 package simulations 20 21 import ( 22 "encoding/json" 23 "net/http" 24 "net/url" 25 "strconv" 26 "sync" 27 "testing" 28 "time" 29 30 "github.com/ethereum/go-ethereum/p2p/enode" 31 ) 32 33 func TestMocker(t *testing.T) { 34 //start the simulation HTTP server 35 _, s := testHTTPServer(t) 36 defer s.Close() 37 38 //create a client 39 client := NewClient(s.URL) 40 41 //start the network 42 err := client.StartNetwork() 43 if err != nil { 44 t.Fatalf("Could not start test network: %s", err) 45 } 46 //stop the network to terminate 47 defer func() { 48 err = client.StopNetwork() 49 if err != nil { 50 t.Fatalf("Could not stop test network: %s", err) 51 } 52 }() 53 54 //get the list of available mocker types 55 resp, err := http.Get(s.URL + "/mocker") 56 if err != nil { 57 t.Fatalf("Could not get mocker list: %s", err) 58 } 59 defer resp.Body.Close() 60 61 if resp.StatusCode != 200 { 62 t.Fatalf("Invalid Status Code received, expected 200, got %d", resp.StatusCode) 63 } 64 65 //check the list is at least 1 in size 66 var mockerlist []string 67 err = json.NewDecoder(resp.Body).Decode(&mockerlist) 68 if err != nil { 69 t.Fatalf("Error decoding JSON mockerlist: %s", err) 70 } 71 72 if len(mockerlist) < 1 { 73 t.Fatalf("No mockers available") 74 } 75 76 nodeCount := 10 77 var wg sync.WaitGroup 78 79 events := make(chan *Event, 10) 80 var opts SubscribeOpts 81 sub, err := client.SubscribeNetwork(events, opts) 82 defer sub.Unsubscribe() 83 //wait until all nodes are started and connected 84 //store every node up event in a map (value is irrelevant, mimic Set datatype) 85 nodemap := make(map[enode.ID]bool) 86 wg.Add(1) 87 nodesComplete := false 88 connCount := 0 89 go func() { 90 for { 91 select { 92 case event := <-events: 93 if isNodeUp(event) { 94 //add the correspondent node ID to the map 95 nodemap[event.Node.Config.ID] = true 96 //this means all nodes got a nodeUp event, so we can continue the test 97 if len(nodemap) == nodeCount { 98 nodesComplete = true 99 } 100 } else if event.Conn != nil && nodesComplete { 101 connCount += 1 102 if connCount == (nodeCount-1)*2 { 103 wg.Done() 104 return 105 } 106 } 107 case <-time.After(30 * time.Second): 108 wg.Done() 109 t.Fatalf("Timeout waiting for nodes being started up!") 110 } 111 } 112 }() 113 114 //take the last element of the mockerlist as the default mocker-type to ensure one is enabled 115 mockertype := mockerlist[len(mockerlist)-1] 116 //still, use hardcoded "probabilistic" one if available ;) 117 for _, m := range mockerlist { 118 if m == "probabilistic" { 119 mockertype = m 120 break 121 } 122 } 123 //start the mocker with nodeCount number of nodes 124 resp, err = http.PostForm(s.URL+"/mocker/start", url.Values{"mocker-type": {mockertype}, "node-count": {strconv.Itoa(nodeCount)}}) 125 if err != nil { 126 t.Fatalf("Could not start mocker: %s", err) 127 } 128 if resp.StatusCode != 200 { 129 t.Fatalf("Invalid Status Code received for starting mocker, expected 200, got %d", resp.StatusCode) 130 } 131 132 wg.Wait() 133 134 //check there are nodeCount number of nodes in the network 135 nodesInfo, err := client.GetNodes() 136 if err != nil { 137 t.Fatalf("Could not get nodes list: %s", err) 138 } 139 140 if len(nodesInfo) != nodeCount { 141 t.Fatalf("Expected %d number of nodes, got: %d", nodeCount, len(nodesInfo)) 142 } 143 144 //stop the mocker 145 resp, err = http.Post(s.URL+"/mocker/stop", "", nil) 146 if err != nil { 147 t.Fatalf("Could not stop mocker: %s", err) 148 } 149 if resp.StatusCode != 200 { 150 t.Fatalf("Invalid Status Code received for stopping mocker, expected 200, got %d", resp.StatusCode) 151 } 152 153 //reset the network 154 _, err = http.Post(s.URL+"/reset", "", nil) 155 if err != nil { 156 t.Fatalf("Could not reset network: %s", err) 157 } 158 159 //now the number of nodes in the network should be zero 160 nodesInfo, err = client.GetNodes() 161 if err != nil { 162 t.Fatalf("Could not get nodes list: %s", err) 163 } 164 165 if len(nodesInfo) != 0 { 166 t.Fatalf("Expected empty list of nodes, got: %d", len(nodesInfo)) 167 } 168 } 169 170 func isNodeUp(event *Event) bool { 171 return event.Node != nil && event.Node.Up() 172 }