github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/p2p/dial_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:41</date>
    10  //</624450102861238272>
    11  
    12  
    13  package p2p
    14  
    15  import (
    16  	"encoding/binary"
    17  	"net"
    18  	"reflect"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/davecgh/go-spew/spew"
    23  	"github.com/ethereum/go-ethereum/p2p/enode"
    24  	"github.com/ethereum/go-ethereum/p2p/enr"
    25  	"github.com/ethereum/go-ethereum/p2p/netutil"
    26  )
    27  
    28  func init() {
    29  	spew.Config.Indent = "\t"
    30  }
    31  
    32  type dialtest struct {
    33  init   *dialstate //测试前后的状态。
    34  	rounds []round
    35  }
    36  
    37  type round struct {
    38  peers []*Peer //当前对等集
    39  done  []task  //这一轮完成的任务
    40  new   []task  //结果必须与此匹配
    41  }
    42  
    43  func runDialTest(t *testing.T, test dialtest) {
    44  	var (
    45  		vtime   time.Time
    46  		running int
    47  	)
    48  	pm := func(ps []*Peer) map[enode.ID]*Peer {
    49  		m := make(map[enode.ID]*Peer)
    50  		for _, p := range ps {
    51  			m[p.ID()] = p
    52  		}
    53  		return m
    54  	}
    55  	for i, round := range test.rounds {
    56  		for _, task := range round.done {
    57  			running--
    58  			if running < 0 {
    59  				panic("running task counter underflow")
    60  			}
    61  			test.init.taskDone(task, vtime)
    62  		}
    63  
    64  		new := test.init.newTasks(running, pm(round.peers), vtime)
    65  		if !sametasks(new, round.new) {
    66  			t.Errorf("round %d: new tasks mismatch:\ngot %v\nwant %v\nstate: %v\nrunning: %v\n",
    67  				i, spew.Sdump(new), spew.Sdump(round.new), spew.Sdump(test.init), spew.Sdump(running))
    68  		}
    69  		t.Log("tasks:", spew.Sdump(new))
    70  
    71  //每轮时间提前16秒。
    72  		vtime = vtime.Add(16 * time.Second)
    73  		running += len(new)
    74  	}
    75  }
    76  
    77  type fakeTable []*enode.Node
    78  
    79  func (t fakeTable) Self() *enode.Node                     { return new(enode.Node) }
    80  func (t fakeTable) Close()                                {}
    81  func (t fakeTable) LookupRandom() []*enode.Node           { return nil }
    82  func (t fakeTable) Resolve(*enode.Node) *enode.Node       { return nil }
    83  func (t fakeTable) ReadRandomNodes(buf []*enode.Node) int { return copy(buf, t) }
    84  
    85  //此测试检查是否从发现结果启动动态拨号。
    86  func TestDialStateDynDial(t *testing.T) {
    87  	runDialTest(t, dialtest{
    88  		init: newDialState(enode.ID{}, nil, nil, fakeTable{}, 5, nil),
    89  		rounds: []round{
    90  //将启动发现查询。
    91  			{
    92  				peers: []*Peer{
    93  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
    94  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
    95  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
    96  				},
    97  				new: []task{&discoverTask{}},
    98  			},
    99  //动态拨号完成后启动。
   100  			{
   101  				peers: []*Peer{
   102  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   103  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   104  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   105  				},
   106  				done: []task{
   107  					&discoverTask{results: []*enode.Node{
   108  newNode(uintID(2), nil), //这个已经连接,没有拨号。
   109  						newNode(uintID(3), nil),
   110  						newNode(uintID(4), nil),
   111  						newNode(uintID(5), nil),
   112  newNode(uintID(6), nil), //因为最大动态拨号是5,所以不尝试使用。
   113  newNode(uintID(7), nil), //…
   114  					}},
   115  				},
   116  				new: []task{
   117  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
   118  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   119  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   120  				},
   121  			},
   122  //有些拨号盘已完成,但尚未启动新的拨号盘,因为
   123  //活动拨号计数和动态对等计数之和=MaxDynDials。
   124  			{
   125  				peers: []*Peer{
   126  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   127  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   128  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   129  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(3), nil)}},
   130  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(4), nil)}},
   131  				},
   132  				done: []task{
   133  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
   134  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   135  				},
   136  			},
   137  //此轮中没有启动新的拨号任务,因为
   138  //已达到MaxDynDials。
   139  			{
   140  				peers: []*Peer{
   141  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   142  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   143  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   144  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(3), nil)}},
   145  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(4), nil)}},
   146  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
   147  				},
   148  				done: []task{
   149  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   150  				},
   151  				new: []task{
   152  					&waitExpireTask{Duration: 14 * time.Second},
   153  				},
   154  			},
   155  //在这一轮中,ID为2的对等机将关闭。查询
   156  //重新使用上次发现查找的结果。
   157  			{
   158  				peers: []*Peer{
   159  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   160  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   161  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(3), nil)}},
   162  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(4), nil)}},
   163  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
   164  				},
   165  				new: []task{
   166  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(6), nil)},
   167  				},
   168  			},
   169  //更多的对等端(3,4)停止并拨出ID 6完成。
   170  //重新使用发现查找的最后一个查询结果
   171  //因为需要更多的候选人,所以产生了一个新的候选人。
   172  			{
   173  				peers: []*Peer{
   174  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   175  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   176  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
   177  				},
   178  				done: []task{
   179  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(6), nil)},
   180  				},
   181  				new: []task{
   182  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(7), nil)},
   183  					&discoverTask{},
   184  				},
   185  			},
   186  //对等7已连接,但仍然没有足够的动态对等
   187  //(5个中有4个)。但是,发现已经在运行,因此请确保
   188  //没有新的开始。
   189  			{
   190  				peers: []*Peer{
   191  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   192  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   193  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
   194  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(7), nil)}},
   195  				},
   196  				done: []task{
   197  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(7), nil)},
   198  				},
   199  			},
   200  //使用空集完成正在运行的节点发现。一种新的查找
   201  //应立即请求。
   202  			{
   203  				peers: []*Peer{
   204  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   205  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   206  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
   207  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(7), nil)}},
   208  				},
   209  				done: []task{
   210  					&discoverTask{},
   211  				},
   212  				new: []task{
   213  					&discoverTask{},
   214  				},
   215  			},
   216  		},
   217  	})
   218  }
   219  
   220  //测试在没有连接对等机的情况下是否拨号引导节点,否则不拨号。
   221  func TestDialStateDynDialBootnode(t *testing.T) {
   222  	bootnodes := []*enode.Node{
   223  		newNode(uintID(1), nil),
   224  		newNode(uintID(2), nil),
   225  		newNode(uintID(3), nil),
   226  	}
   227  	table := fakeTable{
   228  		newNode(uintID(4), nil),
   229  		newNode(uintID(5), nil),
   230  		newNode(uintID(6), nil),
   231  		newNode(uintID(7), nil),
   232  		newNode(uintID(8), nil),
   233  	}
   234  	runDialTest(t, dialtest{
   235  		init: newDialState(enode.ID{}, nil, bootnodes, table, 5, nil),
   236  		rounds: []round{
   237  //已尝试2个动态拨号,启动节点挂起回退间隔
   238  			{
   239  				new: []task{
   240  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   241  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   242  					&discoverTask{},
   243  				},
   244  			},
   245  //没有拨号成功,引导节点仍挂起回退间隔
   246  			{
   247  				done: []task{
   248  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   249  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   250  				},
   251  			},
   252  //没有拨号成功,引导节点仍挂起回退间隔
   253  			{},
   254  //没有成功的拨号,尝试了2个动态拨号,同时达到了回退间隔,还尝试了1个引导节点。
   255  			{
   256  				new: []task{
   257  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
   258  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   259  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   260  				},
   261  			},
   262  //没有拨号成功,尝试第二个bootnode
   263  			{
   264  				done: []task{
   265  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
   266  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   267  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   268  				},
   269  				new: []task{
   270  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)},
   271  				},
   272  			},
   273  //没有拨号成功,尝试第三个启动节点
   274  			{
   275  				done: []task{
   276  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)},
   277  				},
   278  				new: []task{
   279  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
   280  				},
   281  			},
   282  //没有拨号成功,再次尝试第一个bootnode,重试过期的随机节点
   283  			{
   284  				done: []task{
   285  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
   286  				},
   287  				new: []task{
   288  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
   289  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   290  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   291  				},
   292  			},
   293  //随机拨号成功,不再尝试启动节点
   294  			{
   295  				peers: []*Peer{
   296  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(4), nil)}},
   297  				},
   298  				done: []task{
   299  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
   300  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   301  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   302  				},
   303  			},
   304  		},
   305  	})
   306  }
   307  
   308  func TestDialStateDynDialFromTable(t *testing.T) {
   309  //此表始终返回相同的随机节点
   310  //按照下面给出的顺序。
   311  	table := fakeTable{
   312  		newNode(uintID(1), nil),
   313  		newNode(uintID(2), nil),
   314  		newNode(uintID(3), nil),
   315  		newNode(uintID(4), nil),
   316  		newNode(uintID(5), nil),
   317  		newNode(uintID(6), nil),
   318  		newNode(uintID(7), nil),
   319  		newNode(uintID(8), nil),
   320  	}
   321  
   322  	runDialTest(t, dialtest{
   323  		init: newDialState(enode.ID{}, nil, nil, table, 10, nil),
   324  		rounds: []round{
   325  //readrandomnodes返回的8个节点中有5个被拨号。
   326  			{
   327  				new: []task{
   328  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
   329  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)},
   330  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
   331  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   332  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   333  					&discoverTask{},
   334  				},
   335  			},
   336  //拨号节点1、2成功。启动查找中的拨号。
   337  			{
   338  				peers: []*Peer{
   339  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   340  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   341  				},
   342  				done: []task{
   343  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
   344  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)},
   345  					&discoverTask{results: []*enode.Node{
   346  						newNode(uintID(10), nil),
   347  						newNode(uintID(11), nil),
   348  						newNode(uintID(12), nil),
   349  					}},
   350  				},
   351  				new: []task{
   352  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(10), nil)},
   353  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(11), nil)},
   354  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(12), nil)},
   355  					&discoverTask{},
   356  				},
   357  			},
   358  //拨号节点3、4、5失败。查找中的拨号成功。
   359  			{
   360  				peers: []*Peer{
   361  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   362  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   363  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(10), nil)}},
   364  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(11), nil)}},
   365  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(12), nil)}},
   366  				},
   367  				done: []task{
   368  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
   369  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   370  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   371  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(10), nil)},
   372  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(11), nil)},
   373  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(12), nil)},
   374  				},
   375  			},
   376  //正在等待到期。没有启动waitexpiretask,因为
   377  //发现查询仍在运行。
   378  			{
   379  				peers: []*Peer{
   380  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   381  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   382  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(10), nil)}},
   383  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(11), nil)}},
   384  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(12), nil)}},
   385  				},
   386  			},
   387  //节点3,4不会再次尝试,因为只有前两个
   388  //返回的随机节点(节点1,2)将被尝试
   389  //已经连接。
   390  			{
   391  				peers: []*Peer{
   392  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   393  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   394  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(10), nil)}},
   395  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(11), nil)}},
   396  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(12), nil)}},
   397  				},
   398  			},
   399  		},
   400  	})
   401  }
   402  
   403  func newNode(id enode.ID, ip net.IP) *enode.Node {
   404  	var r enr.Record
   405  	if ip != nil {
   406  		r.Set(enr.IP(ip))
   407  	}
   408  	return enode.SignNull(&r, id)
   409  }
   410  
   411  //此测试检查是否未拨出与NetRestrict列表不匹配的候选人。
   412  func TestDialStateNetRestrict(t *testing.T) {
   413  //此表始终返回相同的随机节点
   414  //按照下面给出的顺序。
   415  	table := fakeTable{
   416  		newNode(uintID(1), net.ParseIP("127.0.0.1")),
   417  		newNode(uintID(2), net.ParseIP("127.0.0.2")),
   418  		newNode(uintID(3), net.ParseIP("127.0.0.3")),
   419  		newNode(uintID(4), net.ParseIP("127.0.0.4")),
   420  		newNode(uintID(5), net.ParseIP("127.0.2.5")),
   421  		newNode(uintID(6), net.ParseIP("127.0.2.6")),
   422  		newNode(uintID(7), net.ParseIP("127.0.2.7")),
   423  		newNode(uintID(8), net.ParseIP("127.0.2.8")),
   424  	}
   425  	restrict := new(netutil.Netlist)
   426  	restrict.Add("127.0.2.0/24")
   427  
   428  	runDialTest(t, dialtest{
   429  		init: newDialState(enode.ID{}, nil, nil, table, 10, restrict),
   430  		rounds: []round{
   431  			{
   432  				new: []task{
   433  					&dialTask{flags: dynDialedConn, dest: table[4]},
   434  					&discoverTask{},
   435  				},
   436  			},
   437  		},
   438  	})
   439  }
   440  
   441  //此测试检查是否启动了静态拨号。
   442  func TestDialStateStaticDial(t *testing.T) {
   443  	wantStatic := []*enode.Node{
   444  		newNode(uintID(1), nil),
   445  		newNode(uintID(2), nil),
   446  		newNode(uintID(3), nil),
   447  		newNode(uintID(4), nil),
   448  		newNode(uintID(5), nil),
   449  	}
   450  
   451  	runDialTest(t, dialtest{
   452  		init: newDialState(enode.ID{}, wantStatic, nil, fakeTable{}, 0, nil),
   453  		rounds: []round{
   454  //为以下节点启动静态拨号:
   455  //尚未连接。
   456  			{
   457  				peers: []*Peer{
   458  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   459  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   460  				},
   461  				new: []task{
   462  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)},
   463  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(4), nil)},
   464  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(5), nil)},
   465  				},
   466  			},
   467  //由于所有静态任务
   468  //节点已连接或仍在拨号。
   469  			{
   470  				peers: []*Peer{
   471  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   472  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   473  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(3), nil)}},
   474  				},
   475  				done: []task{
   476  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)},
   477  				},
   478  			},
   479  //没有启动新的拨号任务,因为所有的拨号任务都是静态的
   480  //节点现在已连接。
   481  			{
   482  				peers: []*Peer{
   483  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   484  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   485  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(3), nil)}},
   486  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(4), nil)}},
   487  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(5), nil)}},
   488  				},
   489  				done: []task{
   490  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(4), nil)},
   491  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(5), nil)},
   492  				},
   493  				new: []task{
   494  					&waitExpireTask{Duration: 14 * time.Second},
   495  				},
   496  			},
   497  //等待一轮拨号历史记录过期,不应生成新任务。
   498  			{
   499  				peers: []*Peer{
   500  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   501  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   502  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(3), nil)}},
   503  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(4), nil)}},
   504  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(5), nil)}},
   505  				},
   506  			},
   507  //如果一个静态节点被删除,它应该立即被重新拨号,
   508  //不管它最初是静态的还是动态的。
   509  			{
   510  				peers: []*Peer{
   511  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   512  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(3), nil)}},
   513  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(5), nil)}},
   514  				},
   515  				new: []task{
   516  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)},
   517  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(4), nil)},
   518  				},
   519  			},
   520  		},
   521  	})
   522  }
   523  
   524  //此测试检查静态对等点如果被重新添加到静态列表中,是否会立即重新启用。
   525  func TestDialStaticAfterReset(t *testing.T) {
   526  	wantStatic := []*enode.Node{
   527  		newNode(uintID(1), nil),
   528  		newNode(uintID(2), nil),
   529  	}
   530  
   531  	rounds := []round{
   532  //为尚未连接的节点启动静态拨号。
   533  		{
   534  			peers: nil,
   535  			new: []task{
   536  				&dialTask{flags: staticDialedConn, dest: newNode(uintID(1), nil)},
   537  				&dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)},
   538  			},
   539  		},
   540  //没有新的拨号任务,所有对等端都已连接。
   541  		{
   542  			peers: []*Peer{
   543  				{rw: &conn{flags: staticDialedConn, node: newNode(uintID(1), nil)}},
   544  				{rw: &conn{flags: staticDialedConn, node: newNode(uintID(2), nil)}},
   545  			},
   546  			done: []task{
   547  				&dialTask{flags: staticDialedConn, dest: newNode(uintID(1), nil)},
   548  				&dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)},
   549  			},
   550  			new: []task{
   551  				&waitExpireTask{Duration: 30 * time.Second},
   552  			},
   553  		},
   554  	}
   555  	dTest := dialtest{
   556  		init:   newDialState(enode.ID{}, wantStatic, nil, fakeTable{}, 0, nil),
   557  		rounds: rounds,
   558  	}
   559  	runDialTest(t, dTest)
   560  	for _, n := range wantStatic {
   561  		dTest.init.removeStatic(n)
   562  		dTest.init.addStatic(n)
   563  	}
   564  //如果不删除同龄人,他们将被视为最近拨打过电话。
   565  	runDialTest(t, dTest)
   566  }
   567  
   568  //此测试检查过去的拨号是否有一段时间没有重试。
   569  func TestDialStateCache(t *testing.T) {
   570  	wantStatic := []*enode.Node{
   571  		newNode(uintID(1), nil),
   572  		newNode(uintID(2), nil),
   573  		newNode(uintID(3), nil),
   574  	}
   575  
   576  	runDialTest(t, dialtest{
   577  		init: newDialState(enode.ID{}, wantStatic, nil, fakeTable{}, 0, nil),
   578  		rounds: []round{
   579  //为以下节点启动静态拨号:
   580  //尚未连接。
   581  			{
   582  				peers: nil,
   583  				new: []task{
   584  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(1), nil)},
   585  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)},
   586  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)},
   587  				},
   588  			},
   589  //由于所有静态任务
   590  //节点已连接或仍在拨号。
   591  			{
   592  				peers: []*Peer{
   593  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(1), nil)}},
   594  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(2), nil)}},
   595  				},
   596  				done: []task{
   597  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(1), nil)},
   598  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)},
   599  				},
   600  			},
   601  //启动补救任务以等待节点3的历史记录
   602  //条目将过期。
   603  			{
   604  				peers: []*Peer{
   605  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   606  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   607  				},
   608  				done: []task{
   609  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)},
   610  				},
   611  				new: []task{
   612  					&waitExpireTask{Duration: 14 * time.Second},
   613  				},
   614  			},
   615  //
   616  			{
   617  				peers: []*Peer{
   618  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   619  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   620  				},
   621  			},
   622  //节点3的缓存项已过期并重试。
   623  			{
   624  				peers: []*Peer{
   625  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   626  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   627  				},
   628  				new: []task{
   629  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)},
   630  				},
   631  			},
   632  		},
   633  	})
   634  }
   635  
   636  func TestDialResolve(t *testing.T) {
   637  	resolved := newNode(uintID(1), net.IP{127, 0, 55, 234})
   638  	table := &resolveMock{answer: resolved}
   639  	state := newDialState(enode.ID{}, nil, nil, table, 0, nil)
   640  
   641  //检查是否使用不完整的ID生成任务。
   642  	dest := newNode(uintID(1), nil)
   643  	state.addStatic(dest)
   644  	tasks := state.newTasks(0, nil, time.Time{})
   645  	if !reflect.DeepEqual(tasks, []task{&dialTask{flags: staticDialedConn, dest: dest}}) {
   646  		t.Fatalf("expected dial task, got %#v", tasks)
   647  	}
   648  
   649  //现在运行任务,它应该解析一次ID。
   650  	config := Config{Dialer: TCPDialer{&net.Dialer{Deadline: time.Now().Add(-5 * time.Minute)}}}
   651  	srv := &Server{ntab: table, Config: config}
   652  	tasks[0].Do(srv)
   653  	if !reflect.DeepEqual(table.resolveCalls, []*enode.Node{dest}) {
   654  		t.Fatalf("wrong resolve calls, got %v", table.resolveCalls)
   655  	}
   656  
   657  //向拨号程序报告完成情况,拨号程序应更新静态节点记录。
   658  	state.taskDone(tasks[0], time.Now())
   659  	if state.static[uintID(1)].dest != resolved {
   660  		t.Fatalf("state.dest not updated")
   661  	}
   662  }
   663  
   664  //比较任务列表,但不关心顺序。
   665  func sametasks(a, b []task) bool {
   666  	if len(a) != len(b) {
   667  		return false
   668  	}
   669  next:
   670  	for _, ta := range a {
   671  		for _, tb := range b {
   672  			if reflect.DeepEqual(ta, tb) {
   673  				continue next
   674  			}
   675  		}
   676  		return false
   677  	}
   678  	return true
   679  }
   680  
   681  func uintID(i uint32) enode.ID {
   682  	var id enode.ID
   683  	binary.BigEndian.PutUint32(id[:], i)
   684  	return id
   685  }
   686  
   687  //实现TestDialResolve的discovertable
   688  type resolveMock struct {
   689  	resolveCalls []*enode.Node
   690  	answer       *enode.Node
   691  }
   692  
   693  func (t *resolveMock) Resolve(n *enode.Node) *enode.Node {
   694  	t.resolveCalls = append(t.resolveCalls, n)
   695  	return t.answer
   696  }
   697  
   698  func (t *resolveMock) Self() *enode.Node                     { return new(enode.Node) }
   699  func (t *resolveMock) Close()                                {}
   700  func (t *resolveMock) LookupRandom() []*enode.Node           { return nil }
   701  func (t *resolveMock) ReadRandomNodes(buf []*enode.Node) int { return 0 }
   702