github.com/core-coin/go-core/v2@v2.1.9/p2p/dial_test.go (about)

     1  // Copyright 2015 by the Authors
     2  // This file is part of the go-core library.
     3  //
     4  // The go-core 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-core 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-core library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package p2p
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"fmt"
    23  	"math/rand"
    24  	"net"
    25  	"reflect"
    26  	"sync"
    27  	"testing"
    28  	"time"
    29  
    30  	"github.com/core-coin/go-core/v2/common/mclock"
    31  	"github.com/core-coin/go-core/v2/internal/testlog"
    32  	"github.com/core-coin/go-core/v2/log"
    33  	"github.com/core-coin/go-core/v2/p2p/enode"
    34  	"github.com/core-coin/go-core/v2/p2p/netutil"
    35  )
    36  
    37  // This test checks that dynamic dials are launched from discovery results.
    38  func TestDialSchedDynDial(t *testing.T) {
    39  	t.Parallel()
    40  
    41  	config := dialConfig{
    42  		maxActiveDials: 5,
    43  		maxDialPeers:   4,
    44  	}
    45  	runDialTest(t, config, []dialTestRound{
    46  		// 3 out of 4 peers are connected, leaving 2 dial slots.
    47  		// 9 nodes are discovered, but only 2 are dialed.
    48  		{
    49  			peersAdded: []*conn{
    50  				{flags: staticDialedConn, node: newNode(uintID(0x00), "")},
    51  				{flags: dynDialedConn, node: newNode(uintID(0x01), "")},
    52  				{flags: dynDialedConn, node: newNode(uintID(0x02), "")},
    53  			},
    54  			discovered: []*enode.Node{
    55  				newNode(uintID(0x00), "127.0.0.1:30300"), // not dialed because already connected as static peer
    56  				newNode(uintID(0x02), "127.0.0.1:30300"), // ...
    57  				newNode(uintID(0x03), "127.0.0.1:30300"),
    58  				newNode(uintID(0x04), "127.0.0.1:30300"),
    59  				newNode(uintID(0x05), "127.0.0.1:30300"), // not dialed because there are only two slots
    60  				newNode(uintID(0x06), "127.0.0.1:30300"), // ...
    61  				newNode(uintID(0x07), "127.0.0.1:30300"), // ...
    62  				newNode(uintID(0x08), "127.0.0.1:30300"), // ...
    63  			},
    64  			wantNewDials: []*enode.Node{
    65  				newNode(uintID(0x03), "127.0.0.1:30300"),
    66  				newNode(uintID(0x04), "127.0.0.1:30300"),
    67  			},
    68  		},
    69  
    70  		// One dial completes, freeing one dial slot.
    71  		{
    72  			failed: []enode.ID{
    73  				uintID(0x04),
    74  			},
    75  			wantNewDials: []*enode.Node{
    76  				newNode(uintID(0x05), "127.0.0.1:30300"),
    77  			},
    78  		},
    79  
    80  		// Dial to 0x03 completes, filling the last remaining peer slot.
    81  		{
    82  			succeeded: []enode.ID{
    83  				uintID(0x03),
    84  			},
    85  			failed: []enode.ID{
    86  				uintID(0x05),
    87  			},
    88  			discovered: []*enode.Node{
    89  				newNode(uintID(0x09), "127.0.0.1:30300"), // not dialed because there are no free slots
    90  			},
    91  		},
    92  
    93  		// 3 peers drop off, creating 6 dial slots. Check that 5 of those slots
    94  		// (i.e. up to maxActiveDialTasks) are used.
    95  		{
    96  			peersRemoved: []enode.ID{
    97  				uintID(0x00),
    98  				uintID(0x01),
    99  				uintID(0x02),
   100  			},
   101  			discovered: []*enode.Node{
   102  				newNode(uintID(0x0a), "127.0.0.1:30300"),
   103  				newNode(uintID(0x0b), "127.0.0.1:30300"),
   104  				newNode(uintID(0x0c), "127.0.0.1:30300"),
   105  				newNode(uintID(0x0d), "127.0.0.1:30300"),
   106  				newNode(uintID(0x0f), "127.0.0.1:30300"),
   107  			},
   108  			wantNewDials: []*enode.Node{
   109  				newNode(uintID(0x06), "127.0.0.1:30300"),
   110  				newNode(uintID(0x07), "127.0.0.1:30300"),
   111  				newNode(uintID(0x08), "127.0.0.1:30300"),
   112  				newNode(uintID(0x09), "127.0.0.1:30300"),
   113  				newNode(uintID(0x0a), "127.0.0.1:30300"),
   114  			},
   115  		},
   116  	})
   117  }
   118  
   119  // This test checks that candidates that do not match the netrestrict list are not dialed.
   120  func TestDialSchedNetRestrict(t *testing.T) {
   121  	t.Parallel()
   122  
   123  	nodes := []*enode.Node{
   124  		newNode(uintID(0x01), "127.0.0.1:30300"),
   125  		newNode(uintID(0x02), "127.0.0.2:30300"),
   126  		newNode(uintID(0x03), "127.0.0.3:30300"),
   127  		newNode(uintID(0x04), "127.0.0.4:30300"),
   128  		newNode(uintID(0x05), "127.0.2.5:30300"),
   129  		newNode(uintID(0x06), "127.0.2.6:30300"),
   130  		newNode(uintID(0x07), "127.0.2.7:30300"),
   131  		newNode(uintID(0x08), "127.0.2.8:30300"),
   132  	}
   133  	config := dialConfig{
   134  		netRestrict:    new(netutil.Netlist),
   135  		maxActiveDials: 10,
   136  		maxDialPeers:   10,
   137  	}
   138  	config.netRestrict.Add("127.0.2.0/24")
   139  	runDialTest(t, config, []dialTestRound{
   140  		{
   141  			discovered:   nodes,
   142  			wantNewDials: nodes[4:8],
   143  		},
   144  		{
   145  			succeeded: []enode.ID{
   146  				nodes[4].ID(),
   147  				nodes[5].ID(),
   148  				nodes[6].ID(),
   149  				nodes[7].ID(),
   150  			},
   151  		},
   152  	})
   153  }
   154  
   155  // This test checks that static dials work and obey the limits.
   156  func TestDialSchedStaticDial(t *testing.T) {
   157  	t.Parallel()
   158  
   159  	config := dialConfig{
   160  		maxActiveDials: 5,
   161  		maxDialPeers:   4,
   162  	}
   163  	runDialTest(t, config, []dialTestRound{
   164  		// Static dials are launched for the nodes that
   165  		// aren't yet connected.
   166  		{
   167  			peersAdded: []*conn{
   168  				{flags: dynDialedConn, node: newNode(uintID(0x01), "127.0.0.1:30300")},
   169  				{flags: dynDialedConn, node: newNode(uintID(0x02), "127.0.0.2:30300")},
   170  			},
   171  			update: func(d *dialScheduler) {
   172  				// These two are not dialed because they're already connected
   173  				// as dynamic peers.
   174  				d.addStatic(newNode(uintID(0x01), "127.0.0.1:30300"))
   175  				d.addStatic(newNode(uintID(0x02), "127.0.0.2:30300"))
   176  				// These nodes will be dialed:
   177  				d.addStatic(newNode(uintID(0x03), "127.0.0.3:30300"))
   178  				d.addStatic(newNode(uintID(0x04), "127.0.0.4:30300"))
   179  				d.addStatic(newNode(uintID(0x05), "127.0.0.5:30300"))
   180  				d.addStatic(newNode(uintID(0x06), "127.0.0.6:30300"))
   181  				d.addStatic(newNode(uintID(0x07), "127.0.0.7:30300"))
   182  				d.addStatic(newNode(uintID(0x08), "127.0.0.8:30300"))
   183  				d.addStatic(newNode(uintID(0x09), "127.0.0.9:30300"))
   184  			},
   185  			wantNewDials: []*enode.Node{
   186  				newNode(uintID(0x03), "127.0.0.3:30300"),
   187  				newNode(uintID(0x04), "127.0.0.4:30300"),
   188  				newNode(uintID(0x05), "127.0.0.5:30300"),
   189  				newNode(uintID(0x06), "127.0.0.6:30300"),
   190  			},
   191  		},
   192  		// Dial to 0x03 completes, filling a peer slot. One slot remains,
   193  		// two dials are launched to attempt to fill it.
   194  		{
   195  			succeeded: []enode.ID{
   196  				uintID(0x03),
   197  			},
   198  			failed: []enode.ID{
   199  				uintID(0x04),
   200  				uintID(0x05),
   201  				uintID(0x06),
   202  			},
   203  			wantResolves: map[enode.ID]*enode.Node{
   204  				uintID(0x04): nil,
   205  				uintID(0x05): nil,
   206  				uintID(0x06): nil,
   207  			},
   208  			wantNewDials: []*enode.Node{
   209  				newNode(uintID(0x08), "127.0.0.8:30300"),
   210  				newNode(uintID(0x09), "127.0.0.9:30300"),
   211  			},
   212  		},
   213  		// Peer 0x01 drops and 0x07 connects as inbound peer.
   214  		// Only 0x01 is dialed.
   215  		{
   216  			peersAdded: []*conn{
   217  				{flags: inboundConn, node: newNode(uintID(0x07), "127.0.0.7:30300")},
   218  			},
   219  			peersRemoved: []enode.ID{
   220  				uintID(0x01),
   221  			},
   222  			wantNewDials: []*enode.Node{
   223  				newNode(uintID(0x01), "127.0.0.1:30300"),
   224  			},
   225  		},
   226  	})
   227  }
   228  
   229  // This test checks that removing static nodes stops connecting to them.
   230  func TestDialSchedRemoveStatic(t *testing.T) {
   231  	t.Parallel()
   232  
   233  	config := dialConfig{
   234  		maxActiveDials: 1,
   235  		maxDialPeers:   1,
   236  	}
   237  	runDialTest(t, config, []dialTestRound{
   238  		// Add static nodes.
   239  		{
   240  			update: func(d *dialScheduler) {
   241  				d.addStatic(newNode(uintID(0x01), "127.0.0.1:30300"))
   242  				d.addStatic(newNode(uintID(0x02), "127.0.0.2:30300"))
   243  				d.addStatic(newNode(uintID(0x03), "127.0.0.3:30300"))
   244  			},
   245  			wantNewDials: []*enode.Node{
   246  				newNode(uintID(0x01), "127.0.0.1:30300"),
   247  			},
   248  		},
   249  		// Dial to 0x01 fails.
   250  		{
   251  			failed: []enode.ID{
   252  				uintID(0x01),
   253  			},
   254  			wantResolves: map[enode.ID]*enode.Node{
   255  				uintID(0x01): nil,
   256  			},
   257  			wantNewDials: []*enode.Node{
   258  				newNode(uintID(0x02), "127.0.0.2:30300"),
   259  			},
   260  		},
   261  		// All static nodes are removed. 0x01 is in history, 0x02 is being
   262  		// dialed, 0x03 is in staticPool.
   263  		{
   264  			update: func(d *dialScheduler) {
   265  				d.removeStatic(newNode(uintID(0x01), "127.0.0.1:30300"))
   266  				d.removeStatic(newNode(uintID(0x02), "127.0.0.2:30300"))
   267  				d.removeStatic(newNode(uintID(0x03), "127.0.0.3:30300"))
   268  			},
   269  			failed: []enode.ID{
   270  				uintID(0x02),
   271  			},
   272  			wantResolves: map[enode.ID]*enode.Node{
   273  				uintID(0x02): nil,
   274  			},
   275  		},
   276  		// Since all static nodes are removed, they should not be dialed again.
   277  		{}, {}, {},
   278  	})
   279  }
   280  
   281  // This test checks that static dials are selected at random.
   282  func TestDialSchedManyStaticNodes(t *testing.T) {
   283  	t.Parallel()
   284  
   285  	config := dialConfig{maxDialPeers: 2}
   286  	runDialTest(t, config, []dialTestRound{
   287  		{
   288  			peersAdded: []*conn{
   289  				{flags: dynDialedConn, node: newNode(uintID(0xFFFE), "")},
   290  				{flags: dynDialedConn, node: newNode(uintID(0xFFFF), "")},
   291  			},
   292  			update: func(d *dialScheduler) {
   293  				for id := uint16(0); id < 2000; id++ {
   294  					n := newNode(uintID(id), "127.0.0.1:30300")
   295  					d.addStatic(n)
   296  				}
   297  			},
   298  		},
   299  		{
   300  			peersRemoved: []enode.ID{
   301  				uintID(0xFFFE),
   302  				uintID(0xFFFF),
   303  			},
   304  			wantNewDials: []*enode.Node{
   305  				newNode(uintID(0x0085), "127.0.0.1:30300"),
   306  				newNode(uintID(0x02dc), "127.0.0.1:30300"),
   307  				newNode(uintID(0x0285), "127.0.0.1:30300"),
   308  				newNode(uintID(0x00cb), "127.0.0.1:30300"),
   309  			},
   310  		},
   311  	})
   312  }
   313  
   314  // This test checks that past dials are not retried for some time.
   315  func TestDialSchedHistory(t *testing.T) {
   316  	t.Parallel()
   317  
   318  	config := dialConfig{
   319  		maxActiveDials: 3,
   320  		maxDialPeers:   3,
   321  	}
   322  	runDialTest(t, config, []dialTestRound{
   323  		{
   324  			update: func(d *dialScheduler) {
   325  				d.addStatic(newNode(uintID(0x01), "127.0.0.1:30300"))
   326  				d.addStatic(newNode(uintID(0x02), "127.0.0.2:30300"))
   327  				d.addStatic(newNode(uintID(0x03), "127.0.0.3:30300"))
   328  			},
   329  			wantNewDials: []*enode.Node{
   330  				newNode(uintID(0x01), "127.0.0.1:30300"),
   331  				newNode(uintID(0x02), "127.0.0.2:30300"),
   332  				newNode(uintID(0x03), "127.0.0.3:30300"),
   333  			},
   334  		},
   335  		// No new tasks are launched in this round because all static
   336  		// nodes are either connected or still being dialed.
   337  		{
   338  			succeeded: []enode.ID{
   339  				uintID(0x01),
   340  				uintID(0x02),
   341  			},
   342  			failed: []enode.ID{
   343  				uintID(0x03),
   344  			},
   345  			wantResolves: map[enode.ID]*enode.Node{
   346  				uintID(0x03): nil,
   347  			},
   348  		},
   349  		// Nothing happens in this round because we're waiting for
   350  		// node 0x3's history entry to expire.
   351  		{},
   352  		// The cache entry for node 0x03 has expired and is retried.
   353  		{
   354  			wantNewDials: []*enode.Node{
   355  				newNode(uintID(0x03), "127.0.0.3:30300"),
   356  			},
   357  		},
   358  	})
   359  }
   360  
   361  func TestDialSchedResolve(t *testing.T) {
   362  	t.Parallel()
   363  
   364  	config := dialConfig{
   365  		maxActiveDials: 1,
   366  		maxDialPeers:   1,
   367  	}
   368  	node := newNode(uintID(0x01), "")
   369  	resolved := newNode(uintID(0x01), "127.0.0.1:30300")
   370  	resolved2 := newNode(uintID(0x01), "127.0.0.55:30300")
   371  	runDialTest(t, config, []dialTestRound{
   372  		{
   373  			update: func(d *dialScheduler) {
   374  				d.addStatic(node)
   375  			},
   376  			wantResolves: map[enode.ID]*enode.Node{
   377  				uintID(0x01): resolved,
   378  			},
   379  			wantNewDials: []*enode.Node{
   380  				resolved,
   381  			},
   382  		},
   383  		{
   384  			failed: []enode.ID{
   385  				uintID(0x01),
   386  			},
   387  			wantResolves: map[enode.ID]*enode.Node{
   388  				uintID(0x01): resolved2,
   389  			},
   390  			wantNewDials: []*enode.Node{
   391  				resolved2,
   392  			},
   393  		},
   394  	})
   395  }
   396  
   397  // -------
   398  // Code below here is the framework for the tests above.
   399  
   400  type dialTestRound struct {
   401  	peersAdded   []*conn
   402  	peersRemoved []enode.ID
   403  	update       func(*dialScheduler) // called at beginning of round
   404  	discovered   []*enode.Node        // newly discovered nodes
   405  	succeeded    []enode.ID           // dials which succeed this round
   406  	failed       []enode.ID           // dials which fail this round
   407  	wantResolves map[enode.ID]*enode.Node
   408  	wantNewDials []*enode.Node // dials that should be launched in this round
   409  }
   410  
   411  func runDialTest(t *testing.T, config dialConfig, rounds []dialTestRound) {
   412  	var (
   413  		clock    = new(mclock.Simulated)
   414  		iterator = newDialTestIterator()
   415  		dialer   = newDialTestDialer()
   416  		resolver = new(dialTestResolver)
   417  		peers    = make(map[enode.ID]*conn)
   418  		setupCh  = make(chan *conn)
   419  	)
   420  
   421  	// Override config.
   422  	config.clock = clock
   423  	config.dialer = dialer
   424  	config.resolver = resolver
   425  	config.log = testlog.Logger(t, log.LvlTrace)
   426  	config.rand = rand.New(rand.NewSource(0x1111))
   427  
   428  	// Set up the dialer. The setup function below runs on the dialTask
   429  	// goroutine and adds the peer.
   430  	var dialsched *dialScheduler
   431  	setup := func(fd net.Conn, f connFlag, node *enode.Node) error {
   432  		conn := &conn{flags: f, node: node}
   433  		dialsched.peerAdded(conn)
   434  		setupCh <- conn
   435  		return nil
   436  	}
   437  	dialsched = newDialScheduler(config, iterator, setup)
   438  	defer dialsched.stop()
   439  
   440  	for i, round := range rounds {
   441  		// Apply peer set updates.
   442  		for _, c := range round.peersAdded {
   443  			if peers[c.node.ID()] != nil {
   444  				t.Fatalf("round %d: peer %v already connected", i, c.node.ID())
   445  			}
   446  			dialsched.peerAdded(c)
   447  			peers[c.node.ID()] = c
   448  		}
   449  		for _, id := range round.peersRemoved {
   450  			c := peers[id]
   451  			if c == nil {
   452  				t.Fatalf("round %d: can't remove non-existent peer %v", i, id)
   453  			}
   454  			dialsched.peerRemoved(c)
   455  		}
   456  
   457  		// Init round.
   458  		t.Logf("round %d (%d peers)", i, len(peers))
   459  		resolver.setAnswers(round.wantResolves)
   460  		if round.update != nil {
   461  			round.update(dialsched)
   462  		}
   463  		iterator.addNodes(round.discovered)
   464  
   465  		// Unblock dialTask goroutines.
   466  		if err := dialer.completeDials(round.succeeded, nil); err != nil {
   467  			t.Fatalf("round %d: %v", i, err)
   468  		}
   469  		for range round.succeeded {
   470  			conn := <-setupCh
   471  			peers[conn.node.ID()] = conn
   472  		}
   473  		if err := dialer.completeDials(round.failed, errors.New("oops")); err != nil {
   474  			t.Fatalf("round %d: %v", i, err)
   475  		}
   476  
   477  		// Wait for new tasks.
   478  		if err := dialer.waitForDials(round.wantNewDials); err != nil {
   479  			t.Fatalf("round %d: %v", i, err)
   480  		}
   481  		if !resolver.checkCalls() {
   482  			t.Fatalf("unexpected calls to Resolve: %v", resolver.calls)
   483  		}
   484  
   485  		clock.Run(16 * time.Second)
   486  	}
   487  }
   488  
   489  // dialTestIterator is the input iterator for dialer tests. This works a bit like a channel
   490  // with infinite buffer: nodes are added to the buffer with addNodes, which unblocks Next
   491  // and returns them from the iterator.
   492  type dialTestIterator struct {
   493  	cur *enode.Node
   494  
   495  	mu     sync.Mutex
   496  	buf    []*enode.Node
   497  	cond   *sync.Cond
   498  	closed bool
   499  }
   500  
   501  func newDialTestIterator() *dialTestIterator {
   502  	it := &dialTestIterator{}
   503  	it.cond = sync.NewCond(&it.mu)
   504  	return it
   505  }
   506  
   507  // addNodes adds nodes to the iterator buffer and unblocks Next.
   508  func (it *dialTestIterator) addNodes(nodes []*enode.Node) {
   509  	it.mu.Lock()
   510  	defer it.mu.Unlock()
   511  
   512  	it.buf = append(it.buf, nodes...)
   513  	it.cond.Signal()
   514  }
   515  
   516  // Node returns the current node.
   517  func (it *dialTestIterator) Node() *enode.Node {
   518  	return it.cur
   519  }
   520  
   521  // Next moves to the next node.
   522  func (it *dialTestIterator) Next() bool {
   523  	it.mu.Lock()
   524  	defer it.mu.Unlock()
   525  
   526  	it.cur = nil
   527  	for len(it.buf) == 0 && !it.closed {
   528  		it.cond.Wait()
   529  	}
   530  	if it.closed {
   531  		return false
   532  	}
   533  	it.cur = it.buf[0]
   534  	copy(it.buf[:], it.buf[1:])
   535  	it.buf = it.buf[:len(it.buf)-1]
   536  	return true
   537  }
   538  
   539  // Close ends the iterator, unblocking Next.
   540  func (it *dialTestIterator) Close() {
   541  	it.mu.Lock()
   542  	defer it.mu.Unlock()
   543  
   544  	it.closed = true
   545  	it.buf = nil
   546  	it.cond.Signal()
   547  }
   548  
   549  // dialTestDialer is the NodeDialer used by runDialTest.
   550  type dialTestDialer struct {
   551  	init    chan *dialTestReq
   552  	blocked map[enode.ID]*dialTestReq
   553  }
   554  
   555  type dialTestReq struct {
   556  	n       *enode.Node
   557  	unblock chan error
   558  }
   559  
   560  func newDialTestDialer() *dialTestDialer {
   561  	return &dialTestDialer{
   562  		init:    make(chan *dialTestReq),
   563  		blocked: make(map[enode.ID]*dialTestReq),
   564  	}
   565  }
   566  
   567  // Dial implements NodeDialer.
   568  func (d *dialTestDialer) Dial(ctx context.Context, n *enode.Node) (net.Conn, error) {
   569  	req := &dialTestReq{n: n, unblock: make(chan error, 1)}
   570  	select {
   571  	case d.init <- req:
   572  		select {
   573  		case err := <-req.unblock:
   574  			pipe, _ := net.Pipe()
   575  			return pipe, err
   576  		case <-ctx.Done():
   577  			return nil, ctx.Err()
   578  		}
   579  	case <-ctx.Done():
   580  		return nil, ctx.Err()
   581  	}
   582  }
   583  
   584  // waitForDials waits for calls to Dial with the given nodes as argument.
   585  // Those calls will be held blocking until completeDials is called with the same nodes.
   586  func (d *dialTestDialer) waitForDials(nodes []*enode.Node) error {
   587  	waitset := make(map[enode.ID]*enode.Node)
   588  	for _, n := range nodes {
   589  		waitset[n.ID()] = n
   590  	}
   591  	timeout := time.NewTimer(1 * time.Second)
   592  	defer timeout.Stop()
   593  
   594  	for len(waitset) > 0 {
   595  		select {
   596  		case req := <-d.init:
   597  			want, ok := waitset[req.n.ID()]
   598  			if !ok {
   599  				return fmt.Errorf("attempt to dial unexpected node %v", req.n.ID())
   600  			}
   601  			if !reflect.DeepEqual(req.n, want) {
   602  				return fmt.Errorf("ENR of dialed node %v does not match test", req.n.ID())
   603  			}
   604  			delete(waitset, req.n.ID())
   605  			d.blocked[req.n.ID()] = req
   606  		case <-timeout.C:
   607  			var waitlist []enode.ID
   608  			for id := range waitset {
   609  				waitlist = append(waitlist, id)
   610  			}
   611  			return fmt.Errorf("timed out waiting for dials to %v", waitlist)
   612  		}
   613  	}
   614  
   615  	return d.checkUnexpectedDial()
   616  }
   617  
   618  func (d *dialTestDialer) checkUnexpectedDial() error {
   619  	select {
   620  	case req := <-d.init:
   621  		return fmt.Errorf("attempt to dial unexpected node %v", req.n.ID())
   622  	case <-time.After(150 * time.Millisecond):
   623  		return nil
   624  	}
   625  }
   626  
   627  // completeDials unblocks calls to Dial for the given nodes.
   628  func (d *dialTestDialer) completeDials(ids []enode.ID, err error) error {
   629  	for _, id := range ids {
   630  		req := d.blocked[id]
   631  		if req == nil {
   632  			return fmt.Errorf("can't complete dial to %v", id)
   633  		}
   634  		req.unblock <- err
   635  	}
   636  	return nil
   637  }
   638  
   639  // dialTestResolver tracks calls to resolve.
   640  type dialTestResolver struct {
   641  	mu      sync.Mutex
   642  	calls   []enode.ID
   643  	answers map[enode.ID]*enode.Node
   644  }
   645  
   646  func (t *dialTestResolver) setAnswers(m map[enode.ID]*enode.Node) {
   647  	t.mu.Lock()
   648  	defer t.mu.Unlock()
   649  
   650  	t.answers = m
   651  	t.calls = nil
   652  }
   653  
   654  func (t *dialTestResolver) checkCalls() bool {
   655  	t.mu.Lock()
   656  	defer t.mu.Unlock()
   657  
   658  	for _, id := range t.calls {
   659  		if _, ok := t.answers[id]; !ok {
   660  			return false
   661  		}
   662  	}
   663  	return true
   664  }
   665  
   666  func (t *dialTestResolver) Resolve(n *enode.Node) *enode.Node {
   667  	t.mu.Lock()
   668  	defer t.mu.Unlock()
   669  
   670  	t.calls = append(t.calls, n.ID())
   671  	return t.answers[n.ID()]
   672  }