github.com/oskarth/go-ethereum@v1.6.8-0.20191013093314-dac24a9d3494/p2p/dial_test.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package p2p
    18  
    19  import (
    20  	"encoding/binary"
    21  	"net"
    22  	"reflect"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/davecgh/go-spew/spew"
    27  	"github.com/ethereum/go-ethereum/p2p/enode"
    28  	"github.com/ethereum/go-ethereum/p2p/enr"
    29  	"github.com/ethereum/go-ethereum/p2p/netutil"
    30  )
    31  
    32  func init() {
    33  	spew.Config.Indent = "\t"
    34  }
    35  
    36  type dialtest struct {
    37  	init   *dialstate // state before and after the test.
    38  	rounds []round
    39  }
    40  
    41  type round struct {
    42  	peers []*Peer // current peer set
    43  	done  []task  // tasks that got done this round
    44  	new   []task  // the result must match this one
    45  }
    46  
    47  func runDialTest(t *testing.T, test dialtest) {
    48  	var (
    49  		vtime   time.Time
    50  		running int
    51  	)
    52  	pm := func(ps []*Peer) map[enode.ID]*Peer {
    53  		m := make(map[enode.ID]*Peer)
    54  		for _, p := range ps {
    55  			m[p.ID()] = p
    56  		}
    57  		return m
    58  	}
    59  	for i, round := range test.rounds {
    60  		for _, task := range round.done {
    61  			running--
    62  			if running < 0 {
    63  				panic("running task counter underflow")
    64  			}
    65  			test.init.taskDone(task, vtime)
    66  		}
    67  
    68  		new := test.init.newTasks(running, pm(round.peers), vtime)
    69  		if !sametasks(new, round.new) {
    70  			t.Errorf("round %d: new tasks mismatch:\ngot %v\nwant %v\nstate: %v\nrunning: %v\n",
    71  				i, spew.Sdump(new), spew.Sdump(round.new), spew.Sdump(test.init), spew.Sdump(running))
    72  		}
    73  		t.Log("tasks:", spew.Sdump(new))
    74  
    75  		// Time advances by 16 seconds on every round.
    76  		vtime = vtime.Add(16 * time.Second)
    77  		running += len(new)
    78  	}
    79  }
    80  
    81  type fakeTable []*enode.Node
    82  
    83  func (t fakeTable) Self() *enode.Node                     { return new(enode.Node) }
    84  func (t fakeTable) Close()                                {}
    85  func (t fakeTable) LookupRandom() []*enode.Node           { return nil }
    86  func (t fakeTable) Resolve(*enode.Node) *enode.Node       { return nil }
    87  func (t fakeTable) ReadRandomNodes(buf []*enode.Node) int { return copy(buf, t) }
    88  
    89  // This test checks that dynamic dials are launched from discovery results.
    90  func TestDialStateDynDial(t *testing.T) {
    91  	runDialTest(t, dialtest{
    92  		init: newDialState(enode.ID{}, nil, nil, fakeTable{}, 5, nil),
    93  		rounds: []round{
    94  			// A discovery query is launched.
    95  			{
    96  				peers: []*Peer{
    97  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
    98  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
    99  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   100  				},
   101  				new: []task{&discoverTask{}},
   102  			},
   103  			// Dynamic dials are launched when it completes.
   104  			{
   105  				peers: []*Peer{
   106  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   107  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   108  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   109  				},
   110  				done: []task{
   111  					&discoverTask{results: []*enode.Node{
   112  						newNode(uintID(2), nil), // this one is already connected and not dialed.
   113  						newNode(uintID(3), nil),
   114  						newNode(uintID(4), nil),
   115  						newNode(uintID(5), nil),
   116  						newNode(uintID(6), nil), // these are not tried because max dyn dials is 5
   117  						newNode(uintID(7), nil), // ...
   118  					}},
   119  				},
   120  				new: []task{
   121  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
   122  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   123  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   124  				},
   125  			},
   126  			// Some of the dials complete but no new ones are launched yet because
   127  			// the sum of active dial count and dynamic peer count is == maxDynDials.
   128  			{
   129  				peers: []*Peer{
   130  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   131  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   132  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   133  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(3), nil)}},
   134  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(4), nil)}},
   135  				},
   136  				done: []task{
   137  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
   138  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   139  				},
   140  			},
   141  			// No new dial tasks are launched in the this round because
   142  			// maxDynDials has been reached.
   143  			{
   144  				peers: []*Peer{
   145  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   146  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   147  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   148  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(3), nil)}},
   149  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(4), nil)}},
   150  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
   151  				},
   152  				done: []task{
   153  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   154  				},
   155  				new: []task{
   156  					&waitExpireTask{Duration: 14 * time.Second},
   157  				},
   158  			},
   159  			// In this round, the peer with id 2 drops off. The query
   160  			// results from last discovery lookup are reused.
   161  			{
   162  				peers: []*Peer{
   163  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   164  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   165  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(3), nil)}},
   166  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(4), nil)}},
   167  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
   168  				},
   169  				new: []task{
   170  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(6), nil)},
   171  				},
   172  			},
   173  			// More peers (3,4) drop off and dial for ID 6 completes.
   174  			// The last query result from the discovery lookup is reused
   175  			// and a new one is spawned because more candidates are needed.
   176  			{
   177  				peers: []*Peer{
   178  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   179  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   180  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
   181  				},
   182  				done: []task{
   183  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(6), nil)},
   184  				},
   185  				new: []task{
   186  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(7), nil)},
   187  					&discoverTask{},
   188  				},
   189  			},
   190  			// Peer 7 is connected, but there still aren't enough dynamic peers
   191  			// (4 out of 5). However, a discovery is already running, so ensure
   192  			// no new is started.
   193  			{
   194  				peers: []*Peer{
   195  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   196  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   197  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
   198  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(7), nil)}},
   199  				},
   200  				done: []task{
   201  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(7), nil)},
   202  				},
   203  			},
   204  			// Finish the running node discovery with an empty set. A new lookup
   205  			// should be immediately requested.
   206  			{
   207  				peers: []*Peer{
   208  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   209  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   210  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
   211  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(7), nil)}},
   212  				},
   213  				done: []task{
   214  					&discoverTask{},
   215  				},
   216  				new: []task{
   217  					&discoverTask{},
   218  				},
   219  			},
   220  		},
   221  	})
   222  }
   223  
   224  // Tests that bootnodes are dialed if no peers are connectd, but not otherwise.
   225  func TestDialStateDynDialBootnode(t *testing.T) {
   226  	bootnodes := []*enode.Node{
   227  		newNode(uintID(1), nil),
   228  		newNode(uintID(2), nil),
   229  		newNode(uintID(3), nil),
   230  	}
   231  	table := fakeTable{
   232  		newNode(uintID(4), nil),
   233  		newNode(uintID(5), nil),
   234  		newNode(uintID(6), nil),
   235  		newNode(uintID(7), nil),
   236  		newNode(uintID(8), nil),
   237  	}
   238  	runDialTest(t, dialtest{
   239  		init: newDialState(enode.ID{}, nil, bootnodes, table, 5, nil),
   240  		rounds: []round{
   241  			// 2 dynamic dials attempted, bootnodes pending fallback interval
   242  			{
   243  				new: []task{
   244  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   245  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   246  					&discoverTask{},
   247  				},
   248  			},
   249  			// No dials succeed, bootnodes still pending fallback interval
   250  			{
   251  				done: []task{
   252  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   253  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   254  				},
   255  			},
   256  			// No dials succeed, bootnodes still pending fallback interval
   257  			{},
   258  			// No dials succeed, 2 dynamic dials attempted and 1 bootnode too as fallback interval was reached
   259  			{
   260  				new: []task{
   261  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
   262  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   263  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   264  				},
   265  			},
   266  			// No dials succeed, 2nd bootnode is attempted
   267  			{
   268  				done: []task{
   269  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
   270  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   271  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   272  				},
   273  				new: []task{
   274  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)},
   275  				},
   276  			},
   277  			// No dials succeed, 3rd bootnode is attempted
   278  			{
   279  				done: []task{
   280  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)},
   281  				},
   282  				new: []task{
   283  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
   284  				},
   285  			},
   286  			// No dials succeed, 1st bootnode is attempted again, expired random nodes retried
   287  			{
   288  				done: []task{
   289  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
   290  				},
   291  				new: []task{
   292  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
   293  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   294  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   295  				},
   296  			},
   297  			// Random dial succeeds, no more bootnodes are attempted
   298  			{
   299  				peers: []*Peer{
   300  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(4), nil)}},
   301  				},
   302  				done: []task{
   303  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
   304  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   305  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   306  				},
   307  			},
   308  		},
   309  	})
   310  }
   311  
   312  func TestDialStateDynDialFromTable(t *testing.T) {
   313  	// This table always returns the same random nodes
   314  	// in the order given below.
   315  	table := fakeTable{
   316  		newNode(uintID(1), nil),
   317  		newNode(uintID(2), nil),
   318  		newNode(uintID(3), nil),
   319  		newNode(uintID(4), nil),
   320  		newNode(uintID(5), nil),
   321  		newNode(uintID(6), nil),
   322  		newNode(uintID(7), nil),
   323  		newNode(uintID(8), nil),
   324  	}
   325  
   326  	runDialTest(t, dialtest{
   327  		init: newDialState(enode.ID{}, nil, nil, table, 10, nil),
   328  		rounds: []round{
   329  			// 5 out of 8 of the nodes returned by ReadRandomNodes are dialed.
   330  			{
   331  				new: []task{
   332  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
   333  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)},
   334  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
   335  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   336  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   337  					&discoverTask{},
   338  				},
   339  			},
   340  			// Dialing nodes 1,2 succeeds. Dials from the lookup are launched.
   341  			{
   342  				peers: []*Peer{
   343  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   344  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   345  				},
   346  				done: []task{
   347  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
   348  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)},
   349  					&discoverTask{results: []*enode.Node{
   350  						newNode(uintID(10), nil),
   351  						newNode(uintID(11), nil),
   352  						newNode(uintID(12), nil),
   353  					}},
   354  				},
   355  				new: []task{
   356  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(10), nil)},
   357  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(11), nil)},
   358  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(12), nil)},
   359  					&discoverTask{},
   360  				},
   361  			},
   362  			// Dialing nodes 3,4,5 fails. The dials from the lookup succeed.
   363  			{
   364  				peers: []*Peer{
   365  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   366  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   367  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(10), nil)}},
   368  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(11), nil)}},
   369  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(12), nil)}},
   370  				},
   371  				done: []task{
   372  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
   373  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   374  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   375  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(10), nil)},
   376  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(11), nil)},
   377  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(12), nil)},
   378  				},
   379  			},
   380  			// Waiting for expiry. No waitExpireTask is launched because the
   381  			// discovery query is still running.
   382  			{
   383  				peers: []*Peer{
   384  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   385  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   386  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(10), nil)}},
   387  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(11), nil)}},
   388  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(12), nil)}},
   389  				},
   390  			},
   391  			// Nodes 3,4 are not tried again because only the first two
   392  			// returned random nodes (nodes 1,2) are tried and they're
   393  			// already connected.
   394  			{
   395  				peers: []*Peer{
   396  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   397  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   398  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(10), nil)}},
   399  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(11), nil)}},
   400  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(12), nil)}},
   401  				},
   402  			},
   403  		},
   404  	})
   405  }
   406  
   407  func newNode(id enode.ID, ip net.IP) *enode.Node {
   408  	var r enr.Record
   409  	if ip != nil {
   410  		r.Set(enr.IP(ip))
   411  	}
   412  	return enode.SignNull(&r, id)
   413  }
   414  
   415  // This test checks that candidates that do not match the netrestrict list are not dialed.
   416  func TestDialStateNetRestrict(t *testing.T) {
   417  	// This table always returns the same random nodes
   418  	// in the order given below.
   419  	table := fakeTable{
   420  		newNode(uintID(1), net.ParseIP("127.0.0.1")),
   421  		newNode(uintID(2), net.ParseIP("127.0.0.2")),
   422  		newNode(uintID(3), net.ParseIP("127.0.0.3")),
   423  		newNode(uintID(4), net.ParseIP("127.0.0.4")),
   424  		newNode(uintID(5), net.ParseIP("127.0.2.5")),
   425  		newNode(uintID(6), net.ParseIP("127.0.2.6")),
   426  		newNode(uintID(7), net.ParseIP("127.0.2.7")),
   427  		newNode(uintID(8), net.ParseIP("127.0.2.8")),
   428  	}
   429  	restrict := new(netutil.Netlist)
   430  	restrict.Add("127.0.2.0/24")
   431  
   432  	runDialTest(t, dialtest{
   433  		init: newDialState(enode.ID{}, nil, nil, table, 10, restrict),
   434  		rounds: []round{
   435  			{
   436  				new: []task{
   437  					&dialTask{flags: dynDialedConn, dest: table[4]},
   438  					&discoverTask{},
   439  				},
   440  			},
   441  		},
   442  	})
   443  }
   444  
   445  // This test checks that static dials are launched.
   446  func TestDialStateStaticDial(t *testing.T) {
   447  	wantStatic := []*enode.Node{
   448  		newNode(uintID(1), nil),
   449  		newNode(uintID(2), nil),
   450  		newNode(uintID(3), nil),
   451  		newNode(uintID(4), nil),
   452  		newNode(uintID(5), nil),
   453  	}
   454  
   455  	runDialTest(t, dialtest{
   456  		init: newDialState(enode.ID{}, wantStatic, nil, fakeTable{}, 0, nil),
   457  		rounds: []round{
   458  			// Static dials are launched for the nodes that
   459  			// aren't yet connected.
   460  			{
   461  				peers: []*Peer{
   462  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   463  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   464  				},
   465  				new: []task{
   466  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)},
   467  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(4), nil)},
   468  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(5), nil)},
   469  				},
   470  			},
   471  			// No new tasks are launched in this round because all static
   472  			// nodes are either connected or still being dialed.
   473  			{
   474  				peers: []*Peer{
   475  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   476  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   477  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(3), nil)}},
   478  				},
   479  				done: []task{
   480  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)},
   481  				},
   482  			},
   483  			// No new dial tasks are launched because all static
   484  			// nodes are now connected.
   485  			{
   486  				peers: []*Peer{
   487  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   488  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   489  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(3), nil)}},
   490  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(4), nil)}},
   491  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(5), nil)}},
   492  				},
   493  				done: []task{
   494  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(4), nil)},
   495  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(5), nil)},
   496  				},
   497  				new: []task{
   498  					&waitExpireTask{Duration: 14 * time.Second},
   499  				},
   500  			},
   501  			// Wait a round for dial history to expire, no new tasks should spawn.
   502  			{
   503  				peers: []*Peer{
   504  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   505  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   506  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(3), nil)}},
   507  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(4), nil)}},
   508  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(5), nil)}},
   509  				},
   510  			},
   511  			// If a static node is dropped, it should be immediately redialed,
   512  			// irrespective whether it was originally static or dynamic.
   513  			{
   514  				peers: []*Peer{
   515  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   516  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(3), nil)}},
   517  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(5), nil)}},
   518  				},
   519  				new: []task{
   520  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)},
   521  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(4), nil)},
   522  				},
   523  			},
   524  		},
   525  	})
   526  }
   527  
   528  // This test checks that static peers will be redialed immediately if they were re-added to a static list.
   529  func TestDialStaticAfterReset(t *testing.T) {
   530  	wantStatic := []*enode.Node{
   531  		newNode(uintID(1), nil),
   532  		newNode(uintID(2), nil),
   533  	}
   534  
   535  	rounds := []round{
   536  		// Static dials are launched for the nodes that aren't yet connected.
   537  		{
   538  			peers: nil,
   539  			new: []task{
   540  				&dialTask{flags: staticDialedConn, dest: newNode(uintID(1), nil)},
   541  				&dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)},
   542  			},
   543  		},
   544  		// No new dial tasks, all peers are connected.
   545  		{
   546  			peers: []*Peer{
   547  				{rw: &conn{flags: staticDialedConn, node: newNode(uintID(1), nil)}},
   548  				{rw: &conn{flags: staticDialedConn, node: newNode(uintID(2), nil)}},
   549  			},
   550  			done: []task{
   551  				&dialTask{flags: staticDialedConn, dest: newNode(uintID(1), nil)},
   552  				&dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)},
   553  			},
   554  			new: []task{
   555  				&waitExpireTask{Duration: 30 * time.Second},
   556  			},
   557  		},
   558  	}
   559  	dTest := dialtest{
   560  		init:   newDialState(enode.ID{}, wantStatic, nil, fakeTable{}, 0, nil),
   561  		rounds: rounds,
   562  	}
   563  	runDialTest(t, dTest)
   564  	for _, n := range wantStatic {
   565  		dTest.init.removeStatic(n)
   566  		dTest.init.addStatic(n)
   567  	}
   568  	// without removing peers they will be considered recently dialed
   569  	runDialTest(t, dTest)
   570  }
   571  
   572  // This test checks that past dials are not retried for some time.
   573  func TestDialStateCache(t *testing.T) {
   574  	wantStatic := []*enode.Node{
   575  		newNode(uintID(1), nil),
   576  		newNode(uintID(2), nil),
   577  		newNode(uintID(3), nil),
   578  	}
   579  
   580  	runDialTest(t, dialtest{
   581  		init: newDialState(enode.ID{}, wantStatic, nil, fakeTable{}, 0, nil),
   582  		rounds: []round{
   583  			// Static dials are launched for the nodes that
   584  			// aren't yet connected.
   585  			{
   586  				peers: nil,
   587  				new: []task{
   588  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(1), nil)},
   589  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)},
   590  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)},
   591  				},
   592  			},
   593  			// No new tasks are launched in this round because all static
   594  			// nodes are either connected or still being dialed.
   595  			{
   596  				peers: []*Peer{
   597  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(1), nil)}},
   598  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(2), nil)}},
   599  				},
   600  				done: []task{
   601  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(1), nil)},
   602  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)},
   603  				},
   604  			},
   605  			// A salvage task is launched to wait for node 3's history
   606  			// entry to expire.
   607  			{
   608  				peers: []*Peer{
   609  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   610  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   611  				},
   612  				done: []task{
   613  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)},
   614  				},
   615  				new: []task{
   616  					&waitExpireTask{Duration: 14 * time.Second},
   617  				},
   618  			},
   619  			// Still waiting for node 3's entry to expire in the cache.
   620  			{
   621  				peers: []*Peer{
   622  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   623  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   624  				},
   625  			},
   626  			// The cache entry for node 3 has expired and is retried.
   627  			{
   628  				peers: []*Peer{
   629  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   630  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   631  				},
   632  				new: []task{
   633  					&dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)},
   634  				},
   635  			},
   636  		},
   637  	})
   638  }
   639  
   640  func TestDialResolve(t *testing.T) {
   641  	resolved := newNode(uintID(1), net.IP{127, 0, 55, 234})
   642  	table := &resolveMock{answer: resolved}
   643  	state := newDialState(enode.ID{}, nil, nil, table, 0, nil)
   644  
   645  	// Check that the task is generated with an incomplete ID.
   646  	dest := newNode(uintID(1), nil)
   647  	state.addStatic(dest)
   648  	tasks := state.newTasks(0, nil, time.Time{})
   649  	if !reflect.DeepEqual(tasks, []task{&dialTask{flags: staticDialedConn, dest: dest}}) {
   650  		t.Fatalf("expected dial task, got %#v", tasks)
   651  	}
   652  
   653  	// Now run the task, it should resolve the ID once.
   654  	config := Config{Dialer: TCPDialer{&net.Dialer{Deadline: time.Now().Add(-5 * time.Minute)}}}
   655  	srv := &Server{ntab: table, Config: config}
   656  	tasks[0].Do(srv)
   657  	if !reflect.DeepEqual(table.resolveCalls, []*enode.Node{dest}) {
   658  		t.Fatalf("wrong resolve calls, got %v", table.resolveCalls)
   659  	}
   660  
   661  	// Report it as done to the dialer, which should update the static node record.
   662  	state.taskDone(tasks[0], time.Now())
   663  	if state.static[uintID(1)].dest != resolved {
   664  		t.Fatalf("state.dest not updated")
   665  	}
   666  }
   667  
   668  // compares task lists but doesn't care about the order.
   669  func sametasks(a, b []task) bool {
   670  	if len(a) != len(b) {
   671  		return false
   672  	}
   673  next:
   674  	for _, ta := range a {
   675  		for _, tb := range b {
   676  			if reflect.DeepEqual(ta, tb) {
   677  				continue next
   678  			}
   679  		}
   680  		return false
   681  	}
   682  	return true
   683  }
   684  
   685  func uintID(i uint32) enode.ID {
   686  	var id enode.ID
   687  	binary.BigEndian.PutUint32(id[:], i)
   688  	return id
   689  }
   690  
   691  // implements discoverTable for TestDialResolve
   692  type resolveMock struct {
   693  	resolveCalls []*enode.Node
   694  	answer       *enode.Node
   695  }
   696  
   697  func (t *resolveMock) Resolve(n *enode.Node) *enode.Node {
   698  	t.resolveCalls = append(t.resolveCalls, n)
   699  	return t.answer
   700  }
   701  
   702  func (t *resolveMock) Self() *enode.Node                     { return new(enode.Node) }
   703  func (t *resolveMock) Close()                                {}
   704  func (t *resolveMock) LookupRandom() []*enode.Node           { return nil }
   705  func (t *resolveMock) ReadRandomNodes(buf []*enode.Node) int { return 0 }