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