github.com/bcnmy/go-ethereum@v1.10.27/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 84 // wait until all nodes are started and connected 85 // store every node up event in a map (value is irrelevant, mimic Set datatype) 86 nodemap := make(map[enode.ID]bool) 87 nodesComplete := false 88 connCount := 0 89 wg.Add(1) 90 go func() { 91 defer wg.Done() 92 93 for connCount < (nodeCount-1)*2 { 94 select { 95 case event := <-events: 96 if isNodeUp(event) { 97 //add the correspondent node ID to the map 98 nodemap[event.Node.Config.ID] = true 99 //this means all nodes got a nodeUp event, so we can continue the test 100 if len(nodemap) == nodeCount { 101 nodesComplete = true 102 } 103 } else if event.Conn != nil && nodesComplete { 104 connCount += 1 105 } 106 case <-time.After(30 * time.Second): 107 t.Errorf("Timeout waiting for nodes being started up!") 108 return 109 } 110 } 111 }() 112 113 //take the last element of the mockerlist as the default mocker-type to ensure one is enabled 114 mockertype := mockerlist[len(mockerlist)-1] 115 //still, use hardcoded "probabilistic" one if available ;) 116 for _, m := range mockerlist { 117 if m == "probabilistic" { 118 mockertype = m 119 break 120 } 121 } 122 //start the mocker with nodeCount number of nodes 123 resp, err = http.PostForm(s.URL+"/mocker/start", url.Values{"mocker-type": {mockertype}, "node-count": {strconv.Itoa(nodeCount)}}) 124 if err != nil { 125 t.Fatalf("Could not start mocker: %s", err) 126 } 127 if resp.StatusCode != 200 { 128 t.Fatalf("Invalid Status Code received for starting mocker, expected 200, got %d", resp.StatusCode) 129 } 130 131 wg.Wait() 132 133 //check there are nodeCount number of nodes in the network 134 nodesInfo, err := client.GetNodes() 135 if err != nil { 136 t.Fatalf("Could not get nodes list: %s", err) 137 } 138 139 if len(nodesInfo) != nodeCount { 140 t.Fatalf("Expected %d number of nodes, got: %d", nodeCount, len(nodesInfo)) 141 } 142 143 //stop the mocker 144 resp, err = http.Post(s.URL+"/mocker/stop", "", nil) 145 if err != nil { 146 t.Fatalf("Could not stop mocker: %s", err) 147 } 148 if resp.StatusCode != 200 { 149 t.Fatalf("Invalid Status Code received for stopping mocker, expected 200, got %d", resp.StatusCode) 150 } 151 152 //reset the network 153 _, err = http.Post(s.URL+"/reset", "", nil) 154 if err != nil { 155 t.Fatalf("Could not reset network: %s", err) 156 } 157 158 //now the number of nodes in the network should be zero 159 nodesInfo, err = client.GetNodes() 160 if err != nil { 161 t.Fatalf("Could not get nodes list: %s", err) 162 } 163 164 if len(nodesInfo) != 0 { 165 t.Fatalf("Expected empty list of nodes, got: %d", len(nodesInfo)) 166 } 167 } 168 169 func isNodeUp(event *Event) bool { 170 return event.Node != nil && event.Node.Up() 171 }