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