github.com/xinfinOrg/xdposchain@v1.1.0/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(2), nil)}, 122 &dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)}, 123 &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), 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 }, 171 // More peers (3,4) drop off and dial for ID 6 completes. 172 // The last query result from the discovery lookup is reused 173 // and a new one is spawned because more candidates are needed. 174 { 175 peers: []*Peer{ 176 {rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}}, 177 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}}, 178 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}}, 179 }, 180 done: []task{ 181 &dialTask{flags: dynDialedConn, dest: newNode(uintID(6), nil)}, 182 }, 183 new: []task{ 184 &dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)}, 185 &dialTask{flags: dynDialedConn, dest: newNode(uintID(7), nil)}, 186 }, 187 }, 188 // Peer 7 is connected, but there still aren't enough dynamic peers 189 // (4 out of 5). However, a discovery is already running, so ensure 190 // no new is started. 191 { 192 peers: []*Peer{ 193 {rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}}, 194 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}}, 195 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}}, 196 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(7), nil)}}, 197 }, 198 done: []task{ 199 &dialTask{flags: dynDialedConn, dest: newNode(uintID(7), nil)}, 200 }, 201 }, 202 // Finish the running node discovery with an empty set. A new lookup 203 // should be immediately requested. 204 { 205 peers: []*Peer{ 206 {rw: &conn{flags: staticDialedConn, node: newNode(uintID(0), nil)}}, 207 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}}, 208 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(5), nil)}}, 209 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(7), nil)}}, 210 }, 211 done: []task{ 212 &discoverTask{}, 213 }, 214 new: []task{ 215 &waitExpireTask{Duration: 14 * time.Second}, 216 }, 217 }, 218 }, 219 }) 220 } 221 222 // Tests that bootnodes are dialed if no peers are connectd, but not otherwise. 223 func TestDialStateDynDialBootnode(t *testing.T) { 224 bootnodes := []*enode.Node{ 225 newNode(uintID(1), nil), 226 newNode(uintID(2), nil), 227 newNode(uintID(3), nil), 228 } 229 table := fakeTable{ 230 newNode(uintID(4), nil), 231 newNode(uintID(5), nil), 232 newNode(uintID(6), nil), 233 newNode(uintID(7), nil), 234 newNode(uintID(8), nil), 235 } 236 runDialTest(t, dialtest{ 237 init: newDialState(enode.ID{}, nil, bootnodes, table, 5, nil), 238 rounds: []round{ 239 // 2 dynamic dials attempted, bootnodes pending fallback interval 240 { 241 new: []task{ 242 &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)}, 243 &dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)}, 244 &discoverTask{}, 245 }, 246 }, 247 // No dials succeed, bootnodes still pending fallback interval 248 { 249 done: []task{ 250 &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)}, 251 &dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)}, 252 }, 253 }, 254 // No dials succeed, bootnodes still pending fallback interval 255 {}, 256 // No dials succeed, 2 dynamic dials attempted and 1 bootnode too as fallback interval was reached 257 { 258 new: []task{ 259 &dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)}, 260 &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)}, 261 &dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)}, 262 }, 263 }, 264 // No dials succeed, 2nd bootnode is attempted 265 { 266 done: []task{ 267 &dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)}, 268 &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)}, 269 &dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)}, 270 }, 271 new: []task{ 272 &dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)}, 273 }, 274 }, 275 // No dials succeed, 3rd bootnode is attempted 276 { 277 done: []task{ 278 &dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)}, 279 }, 280 new: []task{ 281 &dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)}, 282 }, 283 }, 284 // No dials succeed, 1st bootnode is attempted again, expired random nodes retried 285 { 286 done: []task{ 287 &dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)}, 288 }, 289 new: []task{ 290 &dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)}, 291 &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)}, 292 &dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)}, 293 }, 294 }, 295 // Random dial succeeds, no more bootnodes are attempted 296 { 297 peers: []*Peer{ 298 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(4), nil)}}, 299 }, 300 done: []task{ 301 &dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)}, 302 &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)}, 303 &dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)}, 304 }, 305 new: []task{ 306 &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)}, 307 }, 308 }, 309 }, 310 }) 311 } 312 313 func TestDialStateDynDialFromTable(t *testing.T) { 314 // This table always returns the same random nodes 315 // in the order given below. 316 table := fakeTable{ 317 newNode(uintID(1), nil), 318 newNode(uintID(2), nil), 319 newNode(uintID(3), nil), 320 newNode(uintID(4), nil), 321 newNode(uintID(5), nil), 322 newNode(uintID(6), nil), 323 newNode(uintID(7), nil), 324 newNode(uintID(8), nil), 325 } 326 327 runDialTest(t, dialtest{ 328 init: newDialState(enode.ID{}, nil, nil, table, 10, nil), 329 rounds: []round{ 330 // 5 out of 8 of the nodes returned by ReadRandomNodes are dialed. 331 { 332 new: []task{ 333 &dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)}, 334 &dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)}, 335 &dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)}, 336 &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)}, 337 &dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)}, 338 &discoverTask{}, 339 }, 340 }, 341 // Dialing nodes 1,2 succeeds. Dials from the lookup are launched. 342 { 343 peers: []*Peer{ 344 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}}, 345 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}}, 346 }, 347 done: []task{ 348 &dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)}, 349 &dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)}, 350 &discoverTask{results: []*enode.Node{ 351 newNode(uintID(10), nil), 352 newNode(uintID(11), nil), 353 newNode(uintID(12), nil), 354 }}, 355 }, 356 new: []task{ 357 &dialTask{flags: dynDialedConn, dest: newNode(uintID(1), nil)}, 358 &dialTask{flags: dynDialedConn, dest: newNode(uintID(2), nil)}, 359 &dialTask{flags: dynDialedConn, dest: newNode(uintID(10), nil)}, 360 &dialTask{flags: dynDialedConn, dest: newNode(uintID(11), nil)}, 361 &dialTask{flags: dynDialedConn, dest: newNode(uintID(12), nil)}, 362 }, 363 }, 364 // Dialing nodes 3,4,5 fails. The dials from the lookup succeed. 365 { 366 peers: []*Peer{ 367 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}}, 368 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}}, 369 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(10), nil)}}, 370 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(11), nil)}}, 371 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(12), nil)}}, 372 }, 373 done: []task{ 374 &dialTask{flags: dynDialedConn, dest: newNode(uintID(3), nil)}, 375 &dialTask{flags: dynDialedConn, dest: newNode(uintID(4), nil)}, 376 &dialTask{flags: dynDialedConn, dest: newNode(uintID(5), nil)}, 377 &dialTask{flags: dynDialedConn, dest: newNode(uintID(10), nil)}, 378 &dialTask{flags: dynDialedConn, dest: newNode(uintID(11), nil)}, 379 &dialTask{flags: dynDialedConn, dest: newNode(uintID(12), nil)}, 380 }, 381 new: []task{ 382 &discoverTask{}, 383 }, 384 }, 385 // Waiting for expiry. No waitExpireTask is launched because the 386 // discovery query is still running. 387 { 388 peers: []*Peer{ 389 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}}, 390 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}}, 391 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(10), nil)}}, 392 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(11), nil)}}, 393 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(12), nil)}}, 394 }, 395 }, 396 // Nodes 3,4 are not tried again because only the first two 397 // returned random nodes (nodes 1,2) are tried and they're 398 // already connected. 399 { 400 peers: []*Peer{ 401 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}}, 402 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}}, 403 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(10), nil)}}, 404 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(11), nil)}}, 405 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(12), nil)}}, 406 }, 407 }, 408 }, 409 }) 410 } 411 412 func newNode(id enode.ID, ip net.IP) *enode.Node { 413 var r enr.Record 414 if ip != nil { 415 r.Set(enr.IP(ip)) 416 } 417 return enode.SignNull(&r, id) 418 } 419 420 // This test checks that candidates that do not match the netrestrict list are not dialed. 421 func TestDialStateNetRestrict(t *testing.T) { 422 // This table always returns the same random nodes 423 // in the order given below. 424 table := fakeTable{ 425 newNode(uintID(1), net.ParseIP("127.0.0.1")), 426 newNode(uintID(2), net.ParseIP("127.0.0.2")), 427 newNode(uintID(3), net.ParseIP("127.0.0.3")), 428 newNode(uintID(4), net.ParseIP("127.0.0.4")), 429 newNode(uintID(5), net.ParseIP("127.0.2.5")), 430 newNode(uintID(6), net.ParseIP("127.0.2.6")), 431 newNode(uintID(7), net.ParseIP("127.0.2.7")), 432 newNode(uintID(8), net.ParseIP("127.0.2.8")), 433 } 434 restrict := new(netutil.Netlist) 435 restrict.Add("127.0.2.0/24") 436 437 runDialTest(t, dialtest{ 438 init: newDialState(enode.ID{}, nil, nil, table, 10, restrict), 439 rounds: []round{ 440 { 441 new: []task{ 442 &dialTask{flags: dynDialedConn, dest: table[4]}, 443 &discoverTask{}, 444 }, 445 }, 446 }, 447 }) 448 } 449 450 // This test checks that static dials are launched. 451 func TestDialStateStaticDial(t *testing.T) { 452 wantStatic := []*enode.Node{ 453 newNode(uintID(1), nil), 454 newNode(uintID(2), nil), 455 newNode(uintID(3), nil), 456 newNode(uintID(4), nil), 457 newNode(uintID(5), nil), 458 } 459 460 runDialTest(t, dialtest{ 461 init: newDialState(enode.ID{}, wantStatic, nil, fakeTable{}, 0, nil), 462 rounds: []round{ 463 // Static dials are launched for the nodes that 464 // aren't yet connected. 465 { 466 peers: []*Peer{ 467 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}}, 468 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}}, 469 }, 470 new: []task{ 471 &dialTask{flags: staticDialedConn, dest: newNode(uintID(1), nil)}, 472 &dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)}, 473 &dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)}, 474 &dialTask{flags: staticDialedConn, dest: newNode(uintID(4), nil)}, 475 &dialTask{flags: staticDialedConn, dest: newNode(uintID(5), nil)}, 476 }, 477 }, 478 // No new tasks are launched in this round because all static 479 // nodes are either connected or still being dialed. 480 { 481 peers: []*Peer{ 482 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}}, 483 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}}, 484 {rw: &conn{flags: staticDialedConn, node: newNode(uintID(3), nil)}}, 485 }, 486 new: []task{ 487 &dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)}, 488 }, 489 done: []task{ 490 &dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)}, 491 }, 492 }, 493 // No new dial tasks are launched because all static 494 // nodes are now connected. 495 { 496 peers: []*Peer{ 497 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}}, 498 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}}, 499 {rw: &conn{flags: staticDialedConn, node: newNode(uintID(3), nil)}}, 500 {rw: &conn{flags: staticDialedConn, node: newNode(uintID(4), nil)}}, 501 {rw: &conn{flags: staticDialedConn, node: newNode(uintID(5), nil)}}, 502 }, 503 done: []task{ 504 &dialTask{flags: staticDialedConn, dest: newNode(uintID(4), nil)}, 505 &dialTask{flags: staticDialedConn, dest: newNode(uintID(5), nil)}, 506 }, 507 new: []task{ 508 &dialTask{flags: staticDialedConn, dest: newNode(uintID(4), nil)}, 509 &dialTask{flags: staticDialedConn, dest: newNode(uintID(5), nil)}, 510 }, 511 }, 512 // Wait a round for dial history to expire, no new tasks should spawn. 513 { 514 peers: []*Peer{ 515 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}}, 516 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}}, 517 {rw: &conn{flags: staticDialedConn, node: newNode(uintID(3), nil)}}, 518 {rw: &conn{flags: staticDialedConn, node: newNode(uintID(4), nil)}}, 519 {rw: &conn{flags: staticDialedConn, node: newNode(uintID(5), nil)}}, 520 }, 521 }, 522 // If a static node is dropped, it should be immediately redialed, 523 // irrespective whether it was originally static or dynamic. 524 { 525 peers: []*Peer{ 526 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}}, 527 {rw: &conn{flags: staticDialedConn, node: newNode(uintID(3), nil)}}, 528 {rw: &conn{flags: staticDialedConn, node: newNode(uintID(5), nil)}}, 529 }, 530 new: []task{}, 531 }, 532 }, 533 }) 534 } 535 536 // This test checks that static peers will be redialed immediately if they were re-added to a static list. 537 func TestDialStaticAfterReset(t *testing.T) { 538 wantStatic := []*enode.Node{ 539 newNode(uintID(1), nil), 540 newNode(uintID(2), nil), 541 } 542 543 rounds := []round{ 544 // Static dials are launched for the nodes that aren't yet connected. 545 { 546 peers: nil, 547 new: []task{ 548 &dialTask{flags: staticDialedConn, dest: newNode(uintID(1), nil)}, 549 &dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)}, 550 }, 551 }, 552 // No new dial tasks, all peers are connected. 553 { 554 peers: []*Peer{ 555 {rw: &conn{flags: staticDialedConn, node: newNode(uintID(1), nil)}}, 556 {rw: &conn{flags: staticDialedConn, node: newNode(uintID(2), nil)}}, 557 }, 558 done: []task{ 559 &dialTask{flags: staticDialedConn, dest: newNode(uintID(1), nil)}, 560 &dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)}, 561 }, 562 new: []task{ 563 &dialTask{flags: staticDialedConn, dest: newNode(uintID(1), nil)}, 564 &dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)}, 565 }, 566 }, 567 } 568 dTest := dialtest{ 569 init: newDialState(enode.ID{}, wantStatic, nil, fakeTable{}, 0, nil), 570 rounds: rounds, 571 } 572 runDialTest(t, dTest) 573 for _, n := range wantStatic { 574 dTest.init.removeStatic(n) 575 dTest.init.addStatic(n) 576 delete(dTest.init.dialing, n.ID()) 577 } 578 579 // without removing peers they will be considered recently dialed 580 runDialTest(t, dTest) 581 } 582 583 // This test checks that past dials are not retried for some time. 584 func TestDialStateCache(t *testing.T) { 585 wantStatic := []*enode.Node{ 586 newNode(uintID(1), nil), 587 newNode(uintID(2), nil), 588 newNode(uintID(3), nil), 589 } 590 591 runDialTest(t, dialtest{ 592 init: newDialState(enode.ID{}, wantStatic, nil, fakeTable{}, 0, nil), 593 rounds: []round{ 594 // Static dials are launched for the nodes that 595 // aren't yet connected. 596 { 597 peers: nil, 598 new: []task{ 599 &dialTask{flags: staticDialedConn, dest: newNode(uintID(1), nil)}, 600 &dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)}, 601 &dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)}, 602 }, 603 }, 604 // No new tasks are launched in this round because all static 605 // nodes are either connected or still being dialed. 606 { 607 peers: []*Peer{ 608 {rw: &conn{flags: staticDialedConn, node: newNode(uintID(1), nil)}}, 609 {rw: &conn{flags: staticDialedConn, node: newNode(uintID(2), nil)}}, 610 }, 611 done: []task{ 612 &dialTask{flags: staticDialedConn, dest: newNode(uintID(1), nil)}, 613 &dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)}, 614 }, 615 new: []task{ 616 &dialTask{flags: staticDialedConn, dest: newNode(uintID(1), nil)}, 617 &dialTask{flags: staticDialedConn, dest: newNode(uintID(2), nil)}, 618 }, 619 }, 620 // A salvage task is launched to wait for node 3's history 621 // entry to expire. 622 { 623 peers: []*Peer{ 624 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}}, 625 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}}, 626 }, 627 done: []task{ 628 &dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)}, 629 }, 630 }, 631 // Still waiting for node 3's entry to expire in the cache. 632 { 633 peers: []*Peer{ 634 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}}, 635 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}}, 636 }, 637 }, 638 // The cache entry for node 3 has expired and is retried. 639 { 640 peers: []*Peer{ 641 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(1), nil)}}, 642 {rw: &conn{flags: dynDialedConn, node: newNode(uintID(2), nil)}}, 643 }, 644 new: []task{ 645 &dialTask{flags: staticDialedConn, dest: newNode(uintID(3), nil)}, 646 }, 647 }, 648 }, 649 }) 650 } 651 652 func TestDialResolve(t *testing.T) { 653 resolved := newNode(uintID(1), net.IP{127, 0, 55, 234}) 654 table := &resolveMock{answer: resolved} 655 state := newDialState(enode.ID{}, nil, nil, table, 0, nil) 656 657 // Check that the task is generated with an incomplete ID. 658 dest := newNode(uintID(1), nil) 659 state.addStatic(dest) 660 tasks := state.newTasks(0, nil, time.Time{}) 661 if !reflect.DeepEqual(tasks, []task{&dialTask{flags: staticDialedConn, dest: dest}}) { 662 t.Fatalf("expected dial task, got %#v", tasks) 663 } 664 665 // Now run the task, it should resolve the ID once. 666 config := Config{Dialer: TCPDialer{&net.Dialer{Deadline: time.Now().Add(-5 * time.Minute)}}} 667 srv := &Server{ntab: table, Config: config} 668 tasks[0].Do(srv) 669 if !reflect.DeepEqual(table.resolveCalls, []*enode.Node{dest}) { 670 t.Fatalf("wrong resolve calls, got %v", table.resolveCalls) 671 } 672 673 // Report it as done to the dialer, which should update the static node record. 674 state.taskDone(tasks[0], time.Now()) 675 if state.static[uintID(1)].dest != resolved { 676 t.Fatalf("state.dest not updated") 677 } 678 } 679 680 // compares task lists but doesn't care about the order. 681 func sametasks(a, b []task) bool { 682 if len(a) != len(b) { 683 return false 684 } 685 next: 686 for _, ta := range a { 687 for _, tb := range b { 688 if reflect.DeepEqual(ta, tb) { 689 continue next 690 } 691 } 692 return false 693 } 694 return true 695 } 696 697 func uintID(i uint32) enode.ID { 698 var id enode.ID 699 binary.BigEndian.PutUint32(id[:], i) 700 return id 701 } 702 703 // implements discoverTable for TestDialResolve 704 type resolveMock struct { 705 resolveCalls []*enode.Node 706 answer *enode.Node 707 } 708 709 func (t *resolveMock) Resolve(n *enode.Node) *enode.Node { 710 t.resolveCalls = append(t.resolveCalls, n) 711 return t.answer 712 } 713 714 func (t *resolveMock) Self() *enode.Node { return new(enode.Node) } 715 func (t *resolveMock) Close() {} 716 func (t *resolveMock) LookupRandom() []*enode.Node { return nil } 717 func (t *resolveMock) ReadRandomNodes(buf []*enode.Node) int { return 0 }