github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/p2p/peer_test.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  //版权所有2014 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 p2p
    26  
    27  import (
    28  	"errors"
    29  	"fmt"
    30  	"math/rand"
    31  	"net"
    32  	"reflect"
    33  	"testing"
    34  	"time"
    35  )
    36  
    37  var discard = Protocol{
    38  	Name:   "discard",
    39  	Length: 1,
    40  	Run: func(p *Peer, rw MsgReadWriter) error {
    41  		for {
    42  			msg, err := rw.ReadMsg()
    43  			if err != nil {
    44  				return err
    45  			}
    46  			fmt.Printf("discarding %d\n", msg.Code)
    47  			if err = msg.Discard(); err != nil {
    48  				return err
    49  			}
    50  		}
    51  	},
    52  }
    53  
    54  func testPeer(protos []Protocol) (func(), *conn, *Peer, <-chan error) {
    55  	fd1, fd2 := net.Pipe()
    56  	c1 := &conn{fd: fd1, transport: newTestTransport(randomID(), fd1)}
    57  	c2 := &conn{fd: fd2, transport: newTestTransport(randomID(), fd2)}
    58  	for _, p := range protos {
    59  		c1.caps = append(c1.caps, p.cap())
    60  		c2.caps = append(c2.caps, p.cap())
    61  	}
    62  
    63  	peer := newPeer(c1, protos)
    64  	errc := make(chan error, 1)
    65  	go func() {
    66  		_, err := peer.run()
    67  		errc <- err
    68  	}()
    69  
    70  	closer := func() { c2.close(errors.New("close func called")) }
    71  	return closer, c2, peer, errc
    72  }
    73  
    74  func TestPeerProtoReadMsg(t *testing.T) {
    75  	proto := Protocol{
    76  		Name:   "a",
    77  		Length: 5,
    78  		Run: func(peer *Peer, rw MsgReadWriter) error {
    79  			if err := ExpectMsg(rw, 2, []uint{1}); err != nil {
    80  				t.Error(err)
    81  			}
    82  			if err := ExpectMsg(rw, 3, []uint{2}); err != nil {
    83  				t.Error(err)
    84  			}
    85  			if err := ExpectMsg(rw, 4, []uint{3}); err != nil {
    86  				t.Error(err)
    87  			}
    88  			return nil
    89  		},
    90  	}
    91  
    92  	closer, rw, _, errc := testPeer([]Protocol{proto})
    93  	defer closer()
    94  
    95  	Send(rw, baseProtocolLength+2, []uint{1})
    96  	Send(rw, baseProtocolLength+3, []uint{2})
    97  	Send(rw, baseProtocolLength+4, []uint{3})
    98  
    99  	select {
   100  	case err := <-errc:
   101  		if err != errProtocolReturned {
   102  			t.Errorf("peer returned error: %v", err)
   103  		}
   104  	case <-time.After(2 * time.Second):
   105  		t.Errorf("receive timeout")
   106  	}
   107  }
   108  
   109  func TestPeerProtoEncodeMsg(t *testing.T) {
   110  	proto := Protocol{
   111  		Name:   "a",
   112  		Length: 2,
   113  		Run: func(peer *Peer, rw MsgReadWriter) error {
   114  			if err := SendItems(rw, 2); err == nil {
   115  				t.Error("expected error for out-of-range msg code, got nil")
   116  			}
   117  			if err := SendItems(rw, 1, "foo", "bar"); err != nil {
   118  				t.Errorf("write error: %v", err)
   119  			}
   120  			return nil
   121  		},
   122  	}
   123  	closer, rw, _, _ := testPeer([]Protocol{proto})
   124  	defer closer()
   125  
   126  	if err := ExpectMsg(rw, 17, []string{"foo", "bar"}); err != nil {
   127  		t.Error(err)
   128  	}
   129  }
   130  
   131  func TestPeerPing(t *testing.T) {
   132  	closer, rw, _, _ := testPeer(nil)
   133  	defer closer()
   134  	if err := SendItems(rw, pingMsg); err != nil {
   135  		t.Fatal(err)
   136  	}
   137  	if err := ExpectMsg(rw, pongMsg, nil); err != nil {
   138  		t.Error(err)
   139  	}
   140  }
   141  
   142  func TestPeerDisconnect(t *testing.T) {
   143  	closer, rw, _, disc := testPeer(nil)
   144  	defer closer()
   145  	if err := SendItems(rw, discMsg, DiscQuitting); err != nil {
   146  		t.Fatal(err)
   147  	}
   148  	select {
   149  	case reason := <-disc:
   150  		if reason != DiscQuitting {
   151  			t.Errorf("run returned wrong reason: got %v, want %v", reason, DiscQuitting)
   152  		}
   153  	case <-time.After(500 * time.Millisecond):
   154  		t.Error("peer did not return")
   155  	}
   156  }
   157  
   158  //此测试旨在验证对等端是否能够可靠地处理
   159  //同时发生多个断开原因。
   160  func TestPeerDisconnectRace(t *testing.T) {
   161  	maybe := func() bool { return rand.Intn(1) == 1 }
   162  
   163  	for i := 0; i < 1000; i++ {
   164  		protoclose := make(chan error)
   165  		protodisc := make(chan DiscReason)
   166  		closer, rw, p, disc := testPeer([]Protocol{
   167  			{
   168  				Name:   "closereq",
   169  				Run:    func(p *Peer, rw MsgReadWriter) error { return <-protoclose },
   170  				Length: 1,
   171  			},
   172  			{
   173  				Name:   "disconnect",
   174  				Run:    func(p *Peer, rw MsgReadWriter) error { p.Disconnect(<-protodisc); return nil },
   175  				Length: 1,
   176  			},
   177  		})
   178  
   179  //模拟传入消息。
   180  		go SendItems(rw, baseProtocolLength+1)
   181  		go SendItems(rw, baseProtocolLength+2)
   182  //关闭网络连接。
   183  		go closer()
   184  //使协议“closereq”返回。
   185  		protoclose <- errors.New("protocol closed")
   186  //使协议“断开”呼叫对等方。断开连接
   187  		protodisc <- DiscAlreadyConnected
   188  //在某些情况下,模拟调用peer.disconnect的其他内容。
   189  		if maybe() {
   190  			go p.Disconnect(DiscInvalidIdentity)
   191  		}
   192  //在某些情况下,模拟远程请求断开连接。
   193  		if maybe() {
   194  			go SendItems(rw, discMsg, DiscQuitting)
   195  		}
   196  
   197  		select {
   198  		case <-disc:
   199  		case <-time.After(2 * time.Second):
   200  //peer.run应该很快返回。如果不是同伴
   201  //
   202  //显示堆栈。
   203  			panic("Peer.run took to long to return.")
   204  		}
   205  	}
   206  }
   207  
   208  func TestNewPeer(t *testing.T) {
   209  	name := "nodename"
   210  	caps := []Cap{{"foo", 2}, {"bar", 3}}
   211  	id := randomID()
   212  	p := NewPeer(id, name, caps)
   213  	if p.ID() != id {
   214  		t.Errorf("ID mismatch: got %v, expected %v", p.ID(), id)
   215  	}
   216  	if p.Name() != name {
   217  		t.Errorf("Name mismatch: got %v, expected %v", p.Name(), name)
   218  	}
   219  	if !reflect.DeepEqual(p.Caps(), caps) {
   220  		t.Errorf("Caps mismatch: got %v, expected %v", p.Caps(), caps)
   221  	}
   222  
   223  p.Disconnect(DiscAlreadyConnected) //不应该挂
   224  }
   225  
   226  func TestMatchProtocols(t *testing.T) {
   227  	tests := []struct {
   228  		Remote []Cap
   229  		Local  []Protocol
   230  		Match  map[string]protoRW
   231  	}{
   232  		{
   233  //无远程功能
   234  			Local: []Protocol{{Name: "a"}},
   235  		},
   236  		{
   237  //没有本地协议
   238  			Remote: []Cap{{Name: "a"}},
   239  		},
   240  		{
   241  //没有相互协议
   242  			Remote: []Cap{{Name: "a"}},
   243  			Local:  []Protocol{{Name: "b"}},
   244  		},
   245  		{
   246  //一些匹配,一些差异
   247  			Remote: []Cap{{Name: "local"}, {Name: "match1"}, {Name: "match2"}},
   248  			Local:  []Protocol{{Name: "match1"}, {Name: "match2"}, {Name: "remote"}},
   249  			Match:  map[string]protoRW{"match1": {Protocol: Protocol{Name: "match1"}}, "match2": {Protocol: Protocol{Name: "match2"}}},
   250  		},
   251  		{
   252  //各种字母顺序
   253  			Remote: []Cap{{Name: "aa"}, {Name: "ab"}, {Name: "bb"}, {Name: "ba"}},
   254  			Local:  []Protocol{{Name: "ba"}, {Name: "bb"}, {Name: "ab"}, {Name: "aa"}},
   255  			Match:  map[string]protoRW{"aa": {Protocol: Protocol{Name: "aa"}}, "ab": {Protocol: Protocol{Name: "ab"}}, "ba": {Protocol: Protocol{Name: "ba"}}, "bb": {Protocol: Protocol{Name: "bb"}}},
   256  		},
   257  		{
   258  //没有相互的版本
   259  			Remote: []Cap{{Version: 1}},
   260  			Local:  []Protocol{{Version: 2}},
   261  		},
   262  		{
   263  //多版本,单通用
   264  			Remote: []Cap{{Version: 1}, {Version: 2}},
   265  			Local:  []Protocol{{Version: 2}, {Version: 3}},
   266  			Match:  map[string]protoRW{"": {Protocol: Protocol{Version: 2}}},
   267  		},
   268  		{
   269  //多版本,多公共
   270  			Remote: []Cap{{Version: 1}, {Version: 2}, {Version: 3}, {Version: 4}},
   271  			Local:  []Protocol{{Version: 2}, {Version: 3}},
   272  			Match:  map[string]protoRW{"": {Protocol: Protocol{Version: 3}}},
   273  		},
   274  		{
   275  //各种版本订单
   276  			Remote: []Cap{{Version: 4}, {Version: 1}, {Version: 3}, {Version: 2}},
   277  			Local:  []Protocol{{Version: 2}, {Version: 3}, {Version: 1}},
   278  			Match:  map[string]protoRW{"": {Protocol: Protocol{Version: 3}}},
   279  		},
   280  		{
   281  //覆盖子协议长度的版本
   282  			Remote: []Cap{{Version: 1}, {Version: 2}, {Version: 3}, {Name: "a"}},
   283  			Local:  []Protocol{{Version: 1, Length: 1}, {Version: 2, Length: 2}, {Version: 3, Length: 3}, {Name: "a"}},
   284  			Match:  map[string]protoRW{"": {Protocol: Protocol{Version: 3}}, "a": {Protocol: Protocol{Name: "a"}, offset: 3}},
   285  		},
   286  	}
   287  
   288  	for i, tt := range tests {
   289  		result := matchProtocols(tt.Local, tt.Remote, nil)
   290  		if len(result) != len(tt.Match) {
   291  			t.Errorf("test %d: negotiation mismatch: have %v, want %v", i, len(result), len(tt.Match))
   292  			continue
   293  		}
   294  //确保所有协商的协议都是必要的和正确的
   295  		for name, proto := range result {
   296  			match, ok := tt.Match[name]
   297  			if !ok {
   298  				t.Errorf("test %d, proto '%s': negotiated but shouldn't have", i, name)
   299  				continue
   300  			}
   301  			if proto.Name != match.Name {
   302  				t.Errorf("test %d, proto '%s': name mismatch: have %v, want %v", i, name, proto.Name, match.Name)
   303  			}
   304  			if proto.Version != match.Version {
   305  				t.Errorf("test %d, proto '%s': version mismatch: have %v, want %v", i, name, proto.Version, match.Version)
   306  			}
   307  			if proto.offset-baseProtocolLength != match.offset {
   308  				t.Errorf("test %d, proto '%s': offset mismatch: have %v, want %v", i, name, proto.offset-baseProtocolLength, match.offset)
   309  			}
   310  		}
   311  //确保没有协议错过协商
   312  		for name := range tt.Match {
   313  			if _, ok := result[name]; !ok {
   314  				t.Errorf("test %d, proto '%s': not negotiated, should have", i, name)
   315  				continue
   316  			}
   317  		}
   318  	}
   319  }