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