From fd777bb2104f15cb7c2f7eede7069ad436e29b57 Mon Sep 17 00:00:00 2001 From: holisticode Date: Tue, 12 Dec 2017 13:10:41 -0500 Subject: p2p/simulations: add mocker functionality (#15207) This commit adds mocker functionality to p2p/simulations. A mocker allows to starting/stopping of nodes via the HTTP API. --- p2p/simulations/mocker_test.go | 171 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 p2p/simulations/mocker_test.go (limited to 'p2p/simulations/mocker_test.go') diff --git a/p2p/simulations/mocker_test.go b/p2p/simulations/mocker_test.go new file mode 100644 index 000000000..6b866fb74 --- /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 . + +// 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 == true { + //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)) + } +} -- cgit v1.2.3 From 3654aeaa4f87452ac5bc801a18808189595e2ef8 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 13 Dec 2017 03:15:27 +0100 Subject: p2p/simulations: fix gosimple nit (#15661) --- p2p/simulations/mocker_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'p2p/simulations/mocker_test.go') diff --git a/p2p/simulations/mocker_test.go b/p2p/simulations/mocker_test.go index 6b866fb74..de8ec0b33 100644 --- a/p2p/simulations/mocker_test.go +++ b/p2p/simulations/mocker_test.go @@ -91,7 +91,7 @@ func TestMocker(t *testing.T) { select { case event := <-events: //if the event is a node Up event only - if event.Node != nil && event.Node.Up == true { + 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 -- cgit v1.2.3