github.com/annchain/OG@v0.0.9/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  	"github.com/annchain/OG/p2p/enr"
    22  	"github.com/annchain/OG/p2p/netutil"
    23  	"github.com/annchain/OG/p2p/onode"
    24  	"github.com/davecgh/go-spew/spew"
    25  	"net"
    26  	"reflect"
    27  	"testing"
    28  	"time"
    29  )
    30  
    31  func init() {
    32  	spew.Config.Indent = "\t"
    33  }
    34  
    35  type dialtest struct {
    36  	init   *dialstate // state before and after the test.
    37  	rounds []round
    38  }
    39  
    40  type round struct {
    41  	peers []*Peer // current peer set
    42  	done  []task  // tasks that got done this round
    43  	new   []task  // the result must match this one
    44  }
    45  
    46  func runDialTest(t *testing.T, test dialtest) {
    47  	var (
    48  		vtime   time.Time
    49  		running int
    50  	)
    51  	pm := func(ps []*Peer) map[onode.ID]*Peer {
    52  		m := make(map[onode.ID]*Peer)
    53  		for _, p := range ps {
    54  			m[p.ID()] = p
    55  		}
    56  		return m
    57  	}
    58  	for i, round := range test.rounds {
    59  		for _, task := range round.done {
    60  			running--
    61  			if running < 0 {
    62  				panic("running task counter underflow")
    63  			}
    64  			test.init.taskDone(task, vtime)
    65  		}
    66  
    67  		new := test.init.newTasks(running, pm(round.peers), vtime)
    68  		if !sametasks(new, round.new) {
    69  			t.Errorf("round %d: new tasks mismatch:\ngot %v\nwant %v\nstate: %v\nrunning: %v\n",
    70  				i, spew.Sdump(new), spew.Sdump(round.new), spew.Sdump(test.init), spew.Sdump(running))
    71  		}
    72  		t.Log("tasks:", spew.Sdump(new))
    73  
    74  		// Time advances by 16 seconds on every round.
    75  		vtime = vtime.Add(16 * time.Second)
    76  		running += len(new)
    77  	}
    78  }
    79  
    80  type fakeTable []*onode.Node
    81  
    82  func (t fakeTable) Self() *onode.Node                     { return new(onode.Node) }
    83  func (t fakeTable) Close()                                {}
    84  func (t fakeTable) LookupRandom() []*onode.Node           { return nil }
    85  func (t fakeTable) Resolve(*onode.Node) *onode.Node       { return nil }
    86  func (t fakeTable) ReadRandomNodes(buf []*onode.Node) int { return copy(buf, t) }
    87  
    88  // This test checks that dynamic dials are launched from discovery results.
    89  func TestDialStateDynDial(t *testing.T) {
    90  	runDialTest(t, dialtest{
    91  		init: newDialState(onode.ID{}, nil, nil, fakeTable{}, 5, nil),
    92  		rounds: []round{
    93  			// A discovery query is launched.
    94  			{
    95  				peers: []*Peer{
    96  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
    97  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
    98  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
    99  				},
   100  				new: []task{&discoverTask{}},
   101  			},
   102  			// Dynamic dials are launched when it completes.
   103  			{
   104  				peers: []*Peer{
   105  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   106  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   107  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   108  				},
   109  				done: []task{
   110  					&discoverTask{results: []*onode.Node{
   111  						newNode(uintID(2), nil), // this one is already connected and not dialed.
   112  						newNode(uintID(3), nil),
   113  						newNode(uintID(4), nil),
   114  						newNode(uintID(5), nil),
   115  						newNode(uintID(6), nil), // these are not tried because max dyn dials is 5
   116  						newNode(uintID(7), nil), // ...
   117  					}},
   118  				},
   119  				new: []task{
   120  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
   121  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   122  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   123  				},
   124  			},
   125  			// Some of the dials complete but no new ones are launched yet because
   126  			// the sum of active dial count and dynamic peer count is == maxDynDials.
   127  			{
   128  				peers: []*Peer{
   129  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   130  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   131  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   132  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(3), nil)}},
   133  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(4), nil)}},
   134  				},
   135  				done: []task{
   136  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
   137  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   138  				},
   139  			},
   140  			// No new dial tasks are launched in the this round because
   141  			// maxDynDials has been reached.
   142  			{
   143  				peers: []*Peer{
   144  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   145  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   146  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   147  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(3), nil)}},
   148  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(4), nil)}},
   149  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
   150  				},
   151  				done: []task{
   152  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   153  				},
   154  				new: []task{
   155  					&waitExpireTask{Duration: 14 * time.Second},
   156  				},
   157  			},
   158  			// In this round, the peer with id 2 drops off. The query
   159  			// results from last discovery lookup are reused.
   160  			{
   161  				peers: []*Peer{
   162  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   163  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   164  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(3), nil)}},
   165  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(4), nil)}},
   166  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
   167  				},
   168  				new: []task{
   169  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(6), nil)},
   170  				},
   171  			},
   172  			// More peers (3,4) drop off and dial for ID 6 completes.
   173  			// The last query result from the discovery lookup is reused
   174  			// and a new one is spawned because more candidates are needed.
   175  			{
   176  				peers: []*Peer{
   177  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   178  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   179  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
   180  				},
   181  				done: []task{
   182  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(6), nil)},
   183  				},
   184  				new: []task{
   185  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(7), nil)},
   186  					&discoverTask{},
   187  				},
   188  			},
   189  			// Sender 7 is connected, but there still aren't enough dynamic peers
   190  			// (4 out of 5). However, a discovery is already running, so ensure
   191  			// no new is started.
   192  			{
   193  				peers: []*Peer{
   194  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   195  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   196  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
   197  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(7), nil)}},
   198  				},
   199  				done: []task{
   200  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(7), nil)},
   201  				},
   202  			},
   203  			// Finish the running node discovery with an empty set. A new lookup
   204  			// should be immediately requested.
   205  			{
   206  				peers: []*Peer{
   207  					{rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}},
   208  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   209  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}},
   210  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(7), nil)}},
   211  				},
   212  				done: []task{
   213  					&discoverTask{},
   214  				},
   215  				new: []task{
   216  					&discoverTask{},
   217  				},
   218  			},
   219  		},
   220  	})
   221  }
   222  
   223  // Tests that bootnodes are dialed if no peers are connectd, but not otherwise.
   224  func TestDialStateDynDialBootnode(t *testing.T) {
   225  	bootnodes := []*onode.Node{
   226  		newNode(uintID(1), nil),
   227  		newNode(uintID(2), nil),
   228  		newNode(uintID(3), nil),
   229  	}
   230  	table := fakeTable{
   231  		newNode(uintID(4), nil),
   232  		newNode(uintID(5), nil),
   233  		newNode(uintID(6), nil),
   234  		newNode(uintID(7), nil),
   235  		newNode(uintID(8), nil),
   236  	}
   237  	runDialTest(t, dialtest{
   238  		init: newDialState(onode.ID{}, nil, bootnodes, table, 5, nil),
   239  		rounds: []round{
   240  			// 2 dynamic dials attempted, bootnodes pending fallback interval
   241  			{
   242  				new: []task{
   243  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   244  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   245  					&discoverTask{},
   246  				},
   247  			},
   248  			// No dials succeed, bootnodes still pending fallback interval
   249  			{
   250  				done: []task{
   251  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   252  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   253  				},
   254  			},
   255  			// No dials succeed, bootnodes still pending fallback interval
   256  			{},
   257  			// No dials succeed, 2 dynamic dials attempted and 1 bootnode too as fallback interval was reached
   258  			{
   259  				new: []task{
   260  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
   261  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   262  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   263  				},
   264  			},
   265  			// No dials succeed, 2nd bootnode is attempted
   266  			{
   267  				done: []task{
   268  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
   269  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   270  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   271  				},
   272  				new: []task{
   273  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)},
   274  				},
   275  			},
   276  			// No dials succeed, 3rd bootnode is attempted
   277  			{
   278  				done: []task{
   279  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)},
   280  				},
   281  				new: []task{
   282  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
   283  				},
   284  			},
   285  			// No dials succeed, 1st bootnode is attempted again, expired random nodes retried
   286  			{
   287  				done: []task{
   288  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
   289  				},
   290  				new: []task{
   291  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
   292  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   293  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   294  				},
   295  			},
   296  			// Random dial succeeds, no more bootnodes are attempted
   297  			{
   298  				peers: []*Peer{
   299  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(4), nil)}},
   300  				},
   301  				done: []task{
   302  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
   303  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   304  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   305  				},
   306  			},
   307  		},
   308  	})
   309  }
   310  
   311  func TestDialStateDynDialFromTable(t *testing.T) {
   312  	// This table always returns the same random nodes
   313  	// in the order given below.
   314  	table := fakeTable{
   315  		newNode(uintID(1), nil),
   316  		newNode(uintID(2), nil),
   317  		newNode(uintID(3), nil),
   318  		newNode(uintID(4), nil),
   319  		newNode(uintID(5), nil),
   320  		newNode(uintID(6), nil),
   321  		newNode(uintID(7), nil),
   322  		newNode(uintID(8), nil),
   323  	}
   324  
   325  	runDialTest(t, dialtest{
   326  		init: newDialState(onode.ID{}, nil, nil, table, 10, nil),
   327  		rounds: []round{
   328  			// 5 out of 8 of the nodes returned by ReadRandomNodes are dialed.
   329  			{
   330  				new: []task{
   331  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
   332  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)},
   333  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
   334  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   335  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   336  					&discoverTask{},
   337  				},
   338  			},
   339  			// Dialing nodes 1,2 succeeds. Dials from the lookup are launched.
   340  			{
   341  				peers: []*Peer{
   342  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   343  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   344  				},
   345  				done: []task{
   346  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)},
   347  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)},
   348  					&discoverTask{results: []*onode.Node{
   349  						newNode(uintID(10), nil),
   350  						newNode(uintID(11), nil),
   351  						newNode(uintID(12), nil),
   352  					}},
   353  				},
   354  				new: []task{
   355  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(10), nil)},
   356  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(11), nil)},
   357  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(12), nil)},
   358  					&discoverTask{},
   359  				},
   360  			},
   361  			// Dialing nodes 3,4,5 fails. The dials from the lookup succeed.
   362  			{
   363  				peers: []*Peer{
   364  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   365  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   366  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(10), nil)}},
   367  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(11), nil)}},
   368  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(12), nil)}},
   369  				},
   370  				done: []task{
   371  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)},
   372  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)},
   373  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)},
   374  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(10), nil)},
   375  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(11), nil)},
   376  					&dialTask{flags: dynDialedConn, dest: newNode(uintID(12), nil)},
   377  				},
   378  			},
   379  			// Waiting for expiry. No waitExpireTask is launched because the
   380  			// discovery query is still running.
   381  			{
   382  				peers: []*Peer{
   383  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   384  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   385  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(10), nil)}},
   386  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(11), nil)}},
   387  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(12), nil)}},
   388  				},
   389  			},
   390  			// Nodes 3,4 are not tried again because only the first two
   391  			// returned random nodes (nodes 1,2) are tried and they're
   392  			// already connected.
   393  			{
   394  				peers: []*Peer{
   395  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}},
   396  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}},
   397  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(10), nil)}},
   398  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(11), nil)}},
   399  					{rw: &conn{flags: dynDialedConn, node: newNode(uintID(12), nil)}},
   400  				},
   401  			},
   402  		},
   403  	})
   404  }
   405  
   406  func newNode(id onode.ID, ip net.IP) *onode.Node {
   407  	var r enr.Record
   408  	if ip != nil {
   409  		eip := enr.IP(ip)
   410  		r.Set(&eip)
   411  	}
   412  	return onode.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(onode.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 := []*onode.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(onode.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 := []*onode.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(onode.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 := []*onode.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(onode.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(onode.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, []*onode.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) onode.ID {
   686  	var id onode.ID
   687  	binary.BigEndian.PutUint32(id[:], i)
   688  	return id
   689  }
   690  
   691  // implements discoverTable for TestDialResolve
   692  type resolveMock struct {
   693  	resolveCalls []*onode.Node
   694  	answer       *onode.Node
   695  }
   696  
   697  func (t *resolveMock) Resolve(n *onode.Node) *onode.Node {
   698  	t.resolveCalls = append(t.resolveCalls, n)
   699  	return t.answer
   700  }
   701  
   702  func (t *resolveMock) Self() *onode.Node                     { return new(onode.Node) }
   703  func (t *resolveMock) Close()                                {}
   704  func (t *resolveMock) LookupRandom() []*onode.Node           { return nil }
   705  func (t *resolveMock) ReadRandomNodes(buf []*onode.Node) int { return 0 }