diff options
Diffstat (limited to 'p2p/simulations/mocker_test.go')
-rw-r--r-- | p2p/simulations/mocker_test.go | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/p2p/simulations/mocker_test.go b/p2p/simulations/mocker_test.go new file mode 100644 index 000000000..de8ec0b33 --- /dev/null +++ b/p2p/simulations/mocker_test.go @@ -0,0 +1,171 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. + +// Package simulations simulates p2p networks. +// A mokcer simulates starting and stopping real nodes in a network. +package simulations + +import ( + "encoding/json" + "net/http" + "net/url" + "strconv" + "sync" + "testing" + "time" + + "github.com/ethereum/go-ethereum/p2p/discover" +) + +func TestMocker(t *testing.T) { + //start the simulation HTTP server + _, s := testHTTPServer(t) + defer s.Close() + + //create a client + client := NewClient(s.URL) + + //start the network + err := client.StartNetwork() + if err != nil { + t.Fatalf("Could not start test network: %s", err) + } + //stop the network to terminate + defer func() { + err = client.StopNetwork() + if err != nil { + t.Fatalf("Could not stop test network: %s", err) + } + }() + + //get the list of available mocker types + resp, err := http.Get(s.URL + "/mocker") + if err != nil { + t.Fatalf("Could not get mocker list: %s", err) + } + defer resp.Body.Close() + + if resp.StatusCode != 200 { + t.Fatalf("Invalid Status Code received, expected 200, got %d", resp.StatusCode) + } + + //check the list is at least 1 in size + var mockerlist []string + err = json.NewDecoder(resp.Body).Decode(&mockerlist) + if err != nil { + t.Fatalf("Error decoding JSON mockerlist: %s", err) + } + + if len(mockerlist) < 1 { + t.Fatalf("No mockers available") + } + + nodeCount := 10 + var wg sync.WaitGroup + + events := make(chan *Event, 10) + var opts SubscribeOpts + sub, err := client.SubscribeNetwork(events, opts) + defer sub.Unsubscribe() + //wait until all nodes are started and connected + //store every node up event in a map (value is irrelevant, mimic Set datatype) + nodemap := make(map[discover.NodeID]bool) + wg.Add(1) + nodesComplete := false + connCount := 0 + go func() { + for { + select { + case event := <-events: + //if the event is a node Up event only + if event.Node != nil && event.Node.Up { + //add the correspondent node ID to the map + nodemap[event.Node.Config.ID] = true + //this means all nodes got a nodeUp event, so we can continue the test + if len(nodemap) == nodeCount { + nodesComplete = true + //wait for 3s as the mocker will need time to connect the nodes + //time.Sleep( 3 *time.Second) + } + } else if event.Conn != nil && nodesComplete { + connCount += 1 + if connCount == (nodeCount-1)*2 { + wg.Done() + return + } + } + case <-time.After(30 * time.Second): + wg.Done() + t.Fatalf("Timeout waiting for nodes being started up!") + } + } + }() + + //take the last element of the mockerlist as the default mocker-type to ensure one is enabled + mockertype := mockerlist[len(mockerlist)-1] + //still, use hardcoded "probabilistic" one if available ;) + for _, m := range mockerlist { + if m == "probabilistic" { + mockertype = m + break + } + } + //start the mocker with nodeCount number of nodes + resp, err = http.PostForm(s.URL+"/mocker/start", url.Values{"mocker-type": {mockertype}, "node-count": {strconv.Itoa(nodeCount)}}) + if err != nil { + t.Fatalf("Could not start mocker: %s", err) + } + if resp.StatusCode != 200 { + t.Fatalf("Invalid Status Code received for starting mocker, expected 200, got %d", resp.StatusCode) + } + + wg.Wait() + + //check there are nodeCount number of nodes in the network + nodes_info, err := client.GetNodes() + if err != nil { + t.Fatalf("Could not get nodes list: %s", err) + } + + if len(nodes_info) != nodeCount { + t.Fatalf("Expected %d number of nodes, got: %d", nodeCount, len(nodes_info)) + } + + //stop the mocker + resp, err = http.Post(s.URL+"/mocker/stop", "", nil) + if err != nil { + t.Fatalf("Could not stop mocker: %s", err) + } + if resp.StatusCode != 200 { + t.Fatalf("Invalid Status Code received for stopping mocker, expected 200, got %d", resp.StatusCode) + } + + //reset the network + _, err = http.Post(s.URL+"/reset", "", nil) + if err != nil { + t.Fatalf("Could not reset network: %s", err) + } + + //now the number of nodes in the network should be zero + nodes_info, err = client.GetNodes() + if err != nil { + t.Fatalf("Could not get nodes list: %s", err) + } + + if len(nodes_info) != 0 { + t.Fatalf("Expected empty list of nodes, got: %d", len(nodes_info)) + } +} |