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