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  }