github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/network/simulations/overlay_test.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:43</date>
    10  //</624450115066662912>
    11  
    12  package main
    13  
    14  import (
    15  	"context"
    16  	"encoding/json"
    17  	"fmt"
    18  	"io/ioutil"
    19  	"net/http"
    20  	"net/http/httptest"
    21  	"net/url"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/ethereum/go-ethereum/p2p/enode"
    26  	"github.com/ethereum/go-ethereum/p2p/simulations"
    27  	"github.com/ethereum/go-ethereum/swarm/log"
    28  )
    29  
    30  var (
    31  	nodeCount = 16
    32  )
    33  
    34  //此测试用于测试叠加模拟。
    35  //由于模拟是通过主系统执行的,因此很容易错过更改。
    36  //自动测试将阻止
    37  //测试只是连接到模拟,启动网络,
    38  //启动mocker,获取节点数,然后再次停止它。
    39  //它还提供了前端所需步骤的文档
    40  //使用模拟
    41  func TestOverlaySim(t *testing.T) {
    42  t.Skip("Test is flaky, see: https://github.com/ethersphere/go-ethereum/issues/592“)
    43  //启动模拟
    44  	log.Info("Start simulation backend")
    45  //获取模拟网络;需要订阅up事件
    46  	net := newSimulationNetwork()
    47  //创建覆盖模拟
    48  	sim := newOverlaySim(net)
    49  //用它创建一个HTTP测试服务器
    50  	srv := httptest.NewServer(sim)
    51  	defer srv.Close()
    52  
    53  	log.Debug("Http simulation server started. Start simulation network")
    54  //启动仿真网络(仿真初始化)
    55  	resp, err := http.Post(srv.URL+"/start", "application/json", nil)
    56  	if err != nil {
    57  		t.Fatal(err)
    58  	}
    59  	defer resp.Body.Close()
    60  	if resp.StatusCode != http.StatusOK {
    61  		t.Fatalf("Expected Status Code %d, got %d", http.StatusOK, resp.StatusCode)
    62  	}
    63  
    64  	log.Debug("Start mocker")
    65  //启动mocker,需要一个节点计数和一个ID
    66  	resp, err = http.PostForm(srv.URL+"/mocker/start",
    67  		url.Values{
    68  			"node-count":  {fmt.Sprintf("%d", nodeCount)},
    69  			"mocker-type": {simulations.GetMockerList()[0]},
    70  		})
    71  	if err != nil {
    72  		t.Fatal(err)
    73  	}
    74  	defer resp.Body.Close()
    75  	if resp.StatusCode != http.StatusOK {
    76  		reason, err := ioutil.ReadAll(resp.Body)
    77  		if err != nil {
    78  			t.Fatal(err)
    79  		}
    80  		t.Fatalf("Expected Status Code %d, got %d, response body %s", http.StatusOK, resp.StatusCode, string(reason))
    81  	}
    82  
    83  //等待节点启动所需的变量
    84  	var upCount int
    85  	trigger := make(chan enode.ID)
    86  
    87  //等待所有节点启动
    88  	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    89  	defer cancel()
    90  
    91  //开始监视节点启动事件…
    92  	go watchSimEvents(net, ctx, trigger)
    93  
    94  //…并等待直到收到所有预期的向上事件(nodeCount)
    95  LOOP:
    96  	for {
    97  		select {
    98  		case <-trigger:
    99  //接收到新节点向上事件,增加计数器
   100  			upCount++
   101  //接收到所有预期的节点向上事件
   102  			if upCount == nodeCount {
   103  				break LOOP
   104  			}
   105  		case <-ctx.Done():
   106  			t.Fatalf("Timed out waiting for up events")
   107  		}
   108  
   109  	}
   110  
   111  //此时,我们可以查询服务器
   112  	log.Info("Get number of nodes")
   113  //获取节点数
   114  	resp, err = http.Get(srv.URL + "/nodes")
   115  	if err != nil {
   116  		t.Fatal(err)
   117  	}
   118  
   119  	defer resp.Body.Close()
   120  	if resp.StatusCode != http.StatusOK {
   121  		t.Fatalf("err %s", resp.Status)
   122  	}
   123  	b, err := ioutil.ReadAll(resp.Body)
   124  	if err != nil {
   125  		t.Fatal(err)
   126  	}
   127  
   128  //从JSON响应中取消标记节点数
   129  	var nodesArr []simulations.Node
   130  	err = json.Unmarshal(b, &nodesArr)
   131  	if err != nil {
   132  		t.Fatal(err)
   133  	}
   134  
   135  //检查接收的节点数是否与发送的节点数相同
   136  	if len(nodesArr) != nodeCount {
   137  		t.Fatal(fmt.Errorf("Expected %d number of nodes, got %d", nodeCount, len(nodesArr)))
   138  	}
   139  
   140  //需要让它运行一段时间,否则立即停止它会因运行节点而崩溃。
   141  //希望连接到已停止的节点
   142  	time.Sleep(1 * time.Second)
   143  
   144  	log.Info("Stop the network")
   145  //停止网络
   146  	resp, err = http.Post(srv.URL+"/stop", "application/json", nil)
   147  	if err != nil {
   148  		t.Fatal(err)
   149  	}
   150  	defer resp.Body.Close()
   151  	if resp.StatusCode != http.StatusOK {
   152  		t.Fatalf("err %s", resp.Status)
   153  	}
   154  
   155  	log.Info("Reset the network")
   156  //重置网络(删除所有节点和连接)
   157  	resp, err = http.Post(srv.URL+"/reset", "application/json", nil)
   158  	if err != nil {
   159  		t.Fatal(err)
   160  	}
   161  	defer resp.Body.Close()
   162  	if resp.StatusCode != http.StatusOK {
   163  		t.Fatalf("err %s", resp.Status)
   164  	}
   165  }
   166  
   167  //注意事件,以便我们知道所有节点何时启动
   168  func watchSimEvents(net *simulations.Network, ctx context.Context, trigger chan enode.ID) {
   169  	events := make(chan *simulations.Event)
   170  	sub := net.Events().Subscribe(events)
   171  	defer sub.Unsubscribe()
   172  
   173  	for {
   174  		select {
   175  		case ev := <-events:
   176  //仅捕获节点向上事件
   177  			if ev.Type == simulations.EventTypeNode {
   178  				if ev.Node.Up {
   179  					log.Debug("got node up event", "event", ev, "node", ev.Node.Config.ID)
   180  					select {
   181  					case trigger <- ev.Node.Config.ID:
   182  					case <-ctx.Done():
   183  						return
   184  					}
   185  				}
   186  			}
   187  		case <-ctx.Done():
   188  			return
   189  		}
   190  	}
   191  }
   192