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