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