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  }