github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/p2p/testing/protocolsession.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //版权所有2017 Go Ethereum作者
    10  //此文件是Go以太坊库的一部分。
    11  //
    12  //Go-Ethereum库是免费软件:您可以重新分发它和/或修改
    13  //根据GNU发布的较低通用公共许可证的条款
    14  //自由软件基金会,或者许可证的第3版,或者
    15  //(由您选择)任何更高版本。
    16  //
    17  //Go以太坊图书馆的发行目的是希望它会有用,
    18  //但没有任何保证;甚至没有
    19  //适销性或特定用途的适用性。见
    20  //GNU较低的通用公共许可证,了解更多详细信息。
    21  //
    22  //你应该收到一份GNU较低级别的公共许可证副本
    23  //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。
    24  
    25  package testing
    26  
    27  import (
    28  	"errors"
    29  	"fmt"
    30  	"sync"
    31  	"time"
    32  
    33  	"github.com/ethereum/go-ethereum/log"
    34  	"github.com/ethereum/go-ethereum/p2p"
    35  	"github.com/ethereum/go-ethereum/p2p/discover"
    36  	"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
    37  )
    38  
    39  var errTimedOut = errors.New("timed out")
    40  
    41  //ProtocolSession是对运行的枢轴节点的准模拟。
    42  //可以发送(触发器)或
    43  //接收(预期)消息
    44  type ProtocolSession struct {
    45  	Server  *p2p.Server
    46  	IDs     []discover.NodeID
    47  	adapter *adapters.SimAdapter
    48  	events  chan *p2p.PeerEvent
    49  }
    50  
    51  //交换是协议测试的基本单元
    52  //数组中的触发器和预期将立即异步运行
    53  //因此,对于具有不同消息类型的同一对等端,不能有多个预期值
    54  //因为它是不可预测的,哪个期望会收到哪个消息
    55  //(对于Expect 1和2,可能会发送消息2和1,两个Expect都会抱怨错误的消息代码)
    56  //在会话上定义交换
    57  type Exchange struct {
    58  	Label    string
    59  	Triggers []Trigger
    60  	Expects  []Expect
    61  	Timeout  time.Duration
    62  }
    63  
    64  //触发器是交换的一部分,透视节点的传入消息
    65  //同行发送
    66  type Trigger struct {
    67  Msg     interface{}     //要发送的消息类型
    68  Code    uint64          //给出报文代码
    69  Peer    discover.NodeID //向其发送消息的对等方
    70  Timeout time.Duration   //发送超时时间
    71  }
    72  
    73  //Expect是来自透视节点的交换传出消息的一部分
    74  //由对等方接收
    75  type Expect struct {
    76  Msg     interface{}     //预期的消息类型
    77  Code    uint64          //现在给出了消息代码
    78  Peer    discover.NodeID //期望消息的对等机
    79  Timeout time.Duration   //接收超时时间
    80  }
    81  
    82  //disconnect表示一个disconnect事件,由testdisconnected使用并检查
    83  type Disconnect struct {
    84  Peer  discover.NodeID //DiscConnected对等
    85  Error error           //断开连接原因
    86  }
    87  
    88  //触发器从对等方发送消息
    89  func (s *ProtocolSession) trigger(trig Trigger) error {
    90  	simNode, ok := s.adapter.GetNode(trig.Peer)
    91  	if !ok {
    92  		return fmt.Errorf("trigger: peer %v does not exist (1- %v)", trig.Peer, len(s.IDs))
    93  	}
    94  	mockNode, ok := simNode.Services()[0].(*mockNode)
    95  	if !ok {
    96  		return fmt.Errorf("trigger: peer %v is not a mock", trig.Peer)
    97  	}
    98  
    99  	errc := make(chan error)
   100  
   101  	go func() {
   102  		log.Trace(fmt.Sprintf("trigger %v (%v)....", trig.Msg, trig.Code))
   103  		errc <- mockNode.Trigger(&trig)
   104  		log.Trace(fmt.Sprintf("triggered %v (%v)", trig.Msg, trig.Code))
   105  	}()
   106  
   107  	t := trig.Timeout
   108  	if t == time.Duration(0) {
   109  		t = 1000 * time.Millisecond
   110  	}
   111  	select {
   112  	case err := <-errc:
   113  		return err
   114  	case <-time.After(t):
   115  		return fmt.Errorf("timout expecting %v to send to peer %v", trig.Msg, trig.Peer)
   116  	}
   117  }
   118  
   119  //Expect检查透视节点发送的消息的期望值
   120  func (s *ProtocolSession) expect(exps []Expect) error {
   121  //构建每个节点的期望图
   122  	peerExpects := make(map[discover.NodeID][]Expect)
   123  	for _, exp := range exps {
   124  		if exp.Msg == nil {
   125  			return errors.New("no message to expect")
   126  		}
   127  		peerExpects[exp.Peer] = append(peerExpects[exp.Peer], exp)
   128  	}
   129  
   130  //为每个节点构造一个mocknode映射
   131  	mockNodes := make(map[discover.NodeID]*mockNode)
   132  	for nodeID := range peerExpects {
   133  		simNode, ok := s.adapter.GetNode(nodeID)
   134  		if !ok {
   135  			return fmt.Errorf("trigger: peer %v does not exist (1- %v)", nodeID, len(s.IDs))
   136  		}
   137  		mockNode, ok := simNode.Services()[0].(*mockNode)
   138  		if !ok {
   139  			return fmt.Errorf("trigger: peer %v is not a mock", nodeID)
   140  		}
   141  		mockNodes[nodeID] = mockNode
   142  	}
   143  
   144  //done chanell在函数返回时取消所有创建的goroutine
   145  	done := make(chan struct{})
   146  	defer close(done)
   147  //errc从中捕获第一个错误
   148  	errc := make(chan error)
   149  
   150  	wg := &sync.WaitGroup{}
   151  	wg.Add(len(mockNodes))
   152  	for nodeID, mockNode := range mockNodes {
   153  		nodeID := nodeID
   154  		mockNode := mockNode
   155  		go func() {
   156  			defer wg.Done()
   157  
   158  //求和所有期望超时值以给出最大值
   159  //完成所有期望的时间。
   160  //mocknode.expect检查所有接收到的消息
   161  //每个消息的预期消息和超时列表
   162  //其中不能单独检查。
   163  			var t time.Duration
   164  			for _, exp := range peerExpects[nodeID] {
   165  				if exp.Timeout == time.Duration(0) {
   166  					t += 2000 * time.Millisecond
   167  				} else {
   168  					t += exp.Timeout
   169  				}
   170  			}
   171  			alarm := time.NewTimer(t)
   172  			defer alarm.Stop()
   173  
   174  //expecterrc用于检查是否返回错误
   175  //从mocknode.expect不是nil并将其发送到
   176  //只有在这种情况下才是errc。
   177  //完成通道将在功能关闭时关闭
   178  			expectErrc := make(chan error)
   179  			go func() {
   180  				select {
   181  				case expectErrc <- mockNode.Expect(peerExpects[nodeID]...):
   182  				case <-done:
   183  				case <-alarm.C:
   184  				}
   185  			}()
   186  
   187  			select {
   188  			case err := <-expectErrc:
   189  				if err != nil {
   190  					select {
   191  					case errc <- err:
   192  					case <-done:
   193  					case <-alarm.C:
   194  						errc <- errTimedOut
   195  					}
   196  				}
   197  			case <-done:
   198  			case <-alarm.C:
   199  				errc <- errTimedOut
   200  			}
   201  
   202  		}()
   203  	}
   204  
   205  	go func() {
   206  		wg.Wait()
   207  //当所有Goroutine完成时关闭errc,从errc返回nill err
   208  		close(errc)
   209  	}()
   210  
   211  	return <-errc
   212  }
   213  
   214  //测试交换测试一系列针对会话的交换
   215  func (s *ProtocolSession) TestExchanges(exchanges ...Exchange) error {
   216  	for i, e := range exchanges {
   217  		if err := s.testExchange(e); err != nil {
   218  			return fmt.Errorf("exchange #%d %q: %v", i, e.Label, err)
   219  		}
   220  		log.Trace(fmt.Sprintf("exchange #%d %q: run successfully", i, e.Label))
   221  	}
   222  	return nil
   223  }
   224  
   225  //测试交换测试单个交换。
   226  //默认超时值为2秒。
   227  func (s *ProtocolSession) testExchange(e Exchange) error {
   228  	errc := make(chan error)
   229  	done := make(chan struct{})
   230  	defer close(done)
   231  
   232  	go func() {
   233  		for _, trig := range e.Triggers {
   234  			err := s.trigger(trig)
   235  			if err != nil {
   236  				errc <- err
   237  				return
   238  			}
   239  		}
   240  
   241  		select {
   242  		case errc <- s.expect(e.Expects):
   243  		case <-done:
   244  		}
   245  	}()
   246  
   247  //全球超时或在所有期望都满足时结束
   248  	t := e.Timeout
   249  	if t == 0 {
   250  		t = 2000 * time.Millisecond
   251  	}
   252  	alarm := time.NewTimer(t)
   253  	select {
   254  	case err := <-errc:
   255  		return err
   256  	case <-alarm.C:
   257  		return errTimedOut
   258  	}
   259  }
   260  
   261  //testDisconnected测试作为参数提供的断开
   262  //disconnect结构描述了在哪个对等机上预期出现的断开连接错误
   263  func (s *ProtocolSession) TestDisconnected(disconnects ...*Disconnect) error {
   264  	expects := make(map[discover.NodeID]error)
   265  	for _, disconnect := range disconnects {
   266  		expects[disconnect.Peer] = disconnect.Error
   267  	}
   268  
   269  	timeout := time.After(time.Second)
   270  	for len(expects) > 0 {
   271  		select {
   272  		case event := <-s.events:
   273  			if event.Type != p2p.PeerEventTypeDrop {
   274  				continue
   275  			}
   276  			expectErr, ok := expects[event.Peer]
   277  			if !ok {
   278  				continue
   279  			}
   280  
   281  			if !(expectErr == nil && event.Error == "" || expectErr != nil && expectErr.Error() == event.Error) {
   282  				return fmt.Errorf("unexpected error on peer %v. expected '%v', got '%v'", event.Peer, expectErr, event.Error)
   283  			}
   284  			delete(expects, event.Peer)
   285  		case <-timeout:
   286  			return fmt.Errorf("timed out waiting for peers to disconnect")
   287  		}
   288  	}
   289  	return nil
   290  }