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