github.com/klaytn/klaytn@v1.12.1/networks/p2p/dial_test.go (about) 1 // Modifications Copyright 2018 The klaytn Authors 2 // Copyright 2015 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from p2p/dial_test.go (2018/06/04). 19 // Modified and improved for the klaytn development. 20 21 package p2p 22 23 import ( 24 "encoding/binary" 25 "net" 26 "reflect" 27 "testing" 28 "time" 29 30 "github.com/davecgh/go-spew/spew" 31 "github.com/klaytn/klaytn/common" 32 "github.com/klaytn/klaytn/common/math" 33 "github.com/klaytn/klaytn/networks/p2p/discover" 34 "github.com/klaytn/klaytn/networks/p2p/netutil" 35 ) 36 37 func init() { 38 spew.Config.Indent = "\t" 39 } 40 41 type dialtest struct { 42 init *dialstate // state before and after the test. 43 rounds []round 44 } 45 46 type failedInfo struct { 47 id discover.NodeID 48 failedTry int 49 } 50 51 type round struct { 52 peers []*Peer // current peer set 53 done []task // tasks that got done this round 54 new []task // the result must match this one 55 expired []failedInfo // task 56 } 57 58 func runDialTest(t *testing.T, test dialtest) { 59 var ( 60 vTime time.Time 61 running int 62 ) 63 pm := func(ps []*Peer) map[discover.NodeID]*Peer { 64 m := make(map[discover.NodeID]*Peer) 65 for _, p := range ps { 66 m[p.ID()] = p 67 } 68 return m 69 } 70 for i, round := range test.rounds { 71 for _, task := range round.done { 72 running-- 73 if running < 0 { 74 panic("running task counter underflow") 75 } 76 test.init.taskDone(task, vTime) 77 } 78 79 for _, info := range round.expired { 80 if dt, ok := test.init.static[info.id]; ok { 81 dt.failedTry = info.failedTry 82 } 83 } 84 85 new := test.init.newTasks(running, pm(round.peers), vTime) 86 if !sametasks(new, round.new) { 87 t.Errorf("round %d: new tasks mismatch:\ngot %v\nwant %v\nstate: %v\nrunning: %v\n", 88 i, spew.Sdump(new), spew.Sdump(round.new), spew.Sdump(test.init), spew.Sdump(running)) 89 } 90 91 // Time advances by 16 seconds on every round. 92 vTime = vTime.Add(16 * time.Second) 93 running += len(new) 94 } 95 } 96 97 type fakeTable []*discover.Node 98 99 func (t fakeTable) Name() string { return "fakeTable" } 100 func (t fakeTable) Self() *discover.Node { return new(discover.Node) } 101 func (t fakeTable) Close() {} 102 func (t fakeTable) Lookup(discover.NodeID, discover.NodeType) []*discover.Node { return nil } 103 func (t fakeTable) Resolve(discover.NodeID, discover.NodeType) *discover.Node { return nil } 104 func (t fakeTable) GetNodes(targetType discover.NodeType, max int) []*discover.Node { return nil } 105 func (t fakeTable) ReadRandomNodes(buf []*discover.Node, nType discover.NodeType) int { 106 return copy(buf, t) 107 } 108 109 func (t fakeTable) RetrieveNodes(target common.Hash, nType discover.NodeType, nresults int) []*discover.Node { 110 return nil 111 } 112 func (t fakeTable) CreateUpdateNodeOnDB(n *discover.Node) error { return nil } 113 func (t fakeTable) CreateUpdateNodeOnTable(n *discover.Node) error { return nil } 114 func (t fakeTable) GetNodeFromDB(id discover.NodeID) (*discover.Node, error) { return nil, nil } 115 func (t fakeTable) DeleteNodeFromDB(n *discover.Node) error { return nil } 116 func (t fakeTable) DeleteNodeFromTable(n *discover.Node) error { return nil } 117 func (t fakeTable) GetBucketEntries() []*discover.Node { return nil } 118 func (t fakeTable) GetReplacements() []*discover.Node { return nil } 119 func (t fakeTable) HasBond(id discover.NodeID) bool { return true } 120 func (t fakeTable) Bond(pinged bool, id discover.NodeID, addr *net.UDPAddr, tcpPort uint16, nType discover.NodeType) (*discover.Node, error) { 121 return nil, nil 122 } 123 124 func (t fakeTable) IsAuthorized(id discover.NodeID, ntype discover.NodeType) bool { 125 return true 126 } 127 128 func (t fakeTable) GetAuthorizedNodes() []*discover.Node { return nil } 129 func (t fakeTable) PutAuthorizedNodes(nodes []*discover.Node) {} 130 func (t fakeTable) DeleteAuthorizedNodes(nodes []*discover.Node) {} 131 132 // This test checks that dynamic dials are launched from discovery results. 133 func TestDialStateDynDial(t *testing.T) { 134 runDialTest(t, dialtest{ 135 init: newDialState(nil, nil, fakeTable{}, 5, nil, nil, nil), 136 rounds: []round{ 137 // A discovery query is launched. 138 { 139 peers: []*Peer{ 140 {rws: []*conn{{flags: staticDialedConn, id: uintID(0)}}}, 141 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 142 {rws: []*conn{{flags: dynDialedConn, id: uintID(2)}}}, 143 }, 144 new: []task{&discoverTask{}}, 145 }, 146 // Dynamic dials are launched when it completes. 147 { 148 peers: []*Peer{ 149 {rws: []*conn{{flags: staticDialedConn, id: uintID(0)}}}, 150 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 151 {rws: []*conn{{flags: dynDialedConn, id: uintID(2)}}}, 152 }, 153 done: []task{ 154 &discoverTask{results: []*discover.Node{ 155 {ID: uintID(2)}, // this one is already connected and not dialed. 156 {ID: uintID(3)}, 157 {ID: uintID(4)}, 158 {ID: uintID(5)}, 159 {ID: uintID(6)}, // these are not tried because max dyn dials is 5 160 {ID: uintID(7)}, // ... 161 }}, 162 }, 163 new: []task{ 164 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(3)}}, 165 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}}, 166 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}}, 167 }, 168 }, 169 // Some of the dials complete but no new ones are launched yet because 170 // the sum of active dial count and dynamic peer count is == maxDynDials. 171 { 172 peers: []*Peer{ 173 {rws: []*conn{{flags: staticDialedConn, id: uintID(0)}}}, 174 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 175 {rws: []*conn{{flags: dynDialedConn, id: uintID(2)}}}, 176 {rws: []*conn{{flags: dynDialedConn, id: uintID(3)}}}, 177 {rws: []*conn{{flags: dynDialedConn, id: uintID(4)}}}, 178 }, 179 done: []task{ 180 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(3)}}, 181 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}}, 182 }, 183 }, 184 // No new dial tasks are launched in the this round because 185 // maxDynDials has been reached. 186 { 187 peers: []*Peer{ 188 {rws: []*conn{{flags: staticDialedConn, id: uintID(0)}}}, 189 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 190 {rws: []*conn{{flags: dynDialedConn, id: uintID(2)}}}, 191 {rws: []*conn{{flags: dynDialedConn, id: uintID(3)}}}, 192 {rws: []*conn{{flags: dynDialedConn, id: uintID(4)}}}, 193 {rws: []*conn{{flags: dynDialedConn, id: uintID(5)}}}, 194 }, 195 done: []task{ 196 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}}, 197 }, 198 new: []task{ 199 &waitExpireTask{Duration: 14 * time.Second}, 200 }, 201 }, 202 // In this round, the peer with id 2 drops off. The query 203 // results from last discovery lookup are reused. 204 { 205 peers: []*Peer{ 206 {rws: []*conn{{flags: staticDialedConn, id: uintID(0)}}}, 207 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 208 {rws: []*conn{{flags: dynDialedConn, id: uintID(3)}}}, 209 {rws: []*conn{{flags: dynDialedConn, id: uintID(4)}}}, 210 {rws: []*conn{{flags: dynDialedConn, id: uintID(5)}}}, 211 }, 212 new: []task{ 213 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(6)}}, 214 }, 215 }, 216 // More peers (3,4) drop off and dial for ID 6 completes. 217 // The last query result from the discovery lookup is reused 218 // and a new one is spawned because more candidates are needed. 219 { 220 peers: []*Peer{ 221 {rws: []*conn{{flags: staticDialedConn, id: uintID(0)}}}, 222 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 223 {rws: []*conn{{flags: dynDialedConn, id: uintID(5)}}}, 224 }, 225 done: []task{ 226 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(6)}}, 227 }, 228 new: []task{ 229 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(7)}}, 230 &discoverTask{}, 231 }, 232 }, 233 // Peer 7 is connected, but there still aren't enough dynamic peers 234 // (4 out of 5). However, a discovery is already running, so ensure 235 // no new is started. 236 { 237 peers: []*Peer{ 238 {rws: []*conn{{flags: staticDialedConn, id: uintID(0)}}}, 239 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 240 {rws: []*conn{{flags: dynDialedConn, id: uintID(5)}}}, 241 {rws: []*conn{{flags: dynDialedConn, id: uintID(7)}}}, 242 }, 243 done: []task{ 244 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(7)}}, 245 }, 246 }, 247 // Finish the running node discovery with an empty set. A new lookup 248 // should be immediately requested. 249 { 250 peers: []*Peer{ 251 {rws: []*conn{{flags: staticDialedConn, id: uintID(0)}}}, 252 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 253 {rws: []*conn{{flags: dynDialedConn, id: uintID(5)}}}, 254 {rws: []*conn{{flags: dynDialedConn, id: uintID(7)}}}, 255 }, 256 done: []task{ 257 &discoverTask{}, 258 }, 259 new: []task{ 260 &discoverTask{}, 261 }, 262 }, 263 }, 264 }) 265 } 266 267 func TestDialStateDynDialFromTable(t *testing.T) { 268 // This table always returns the same random nodes 269 // in the order given below. 270 table := fakeTable{ 271 {ID: uintID(1)}, 272 {ID: uintID(2)}, 273 {ID: uintID(3)}, 274 {ID: uintID(4)}, 275 {ID: uintID(5)}, 276 {ID: uintID(6)}, 277 {ID: uintID(7)}, 278 {ID: uintID(8)}, 279 } 280 281 runDialTest(t, dialtest{ 282 init: newDialState(nil, nil, table, 10, nil, nil, nil), 283 rounds: []round{ 284 // 5 out of 8 of the nodes returned by ReadRandomNodes are dialed. 285 { 286 new: []task{ 287 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(1)}}, 288 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(2)}}, 289 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(3)}}, 290 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}}, 291 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}}, 292 &discoverTask{}, 293 }, 294 }, 295 // Dialing nodes 1,2 succeeds. Dials from the lookup are launched. 296 { 297 peers: []*Peer{ 298 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 299 {rws: []*conn{{flags: dynDialedConn, id: uintID(2)}}}, 300 }, 301 done: []task{ 302 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(1)}}, 303 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(2)}}, 304 &discoverTask{results: []*discover.Node{ 305 {ID: uintID(10)}, 306 {ID: uintID(11)}, 307 {ID: uintID(12)}, 308 }}, 309 }, 310 new: []task{ 311 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(10)}}, 312 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(11)}}, 313 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(12)}}, 314 &discoverTask{}, 315 }, 316 }, 317 // Dialing nodes 3,4,5 fails. The dials from the lookup succeed. 318 { 319 peers: []*Peer{ 320 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 321 {rws: []*conn{{flags: dynDialedConn, id: uintID(2)}}}, 322 {rws: []*conn{{flags: dynDialedConn, id: uintID(10)}}}, 323 {rws: []*conn{{flags: dynDialedConn, id: uintID(11)}}}, 324 {rws: []*conn{{flags: dynDialedConn, id: uintID(12)}}}, 325 }, 326 done: []task{ 327 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(3)}}, 328 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}}, 329 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}}, 330 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(10)}}, 331 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(11)}}, 332 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(12)}}, 333 }, 334 }, 335 // Waiting for expiry. No waitExpireTask is launched because the 336 // discovery query is still running. 337 { 338 peers: []*Peer{ 339 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 340 {rws: []*conn{{flags: dynDialedConn, id: uintID(2)}}}, 341 {rws: []*conn{{flags: dynDialedConn, id: uintID(10)}}}, 342 {rws: []*conn{{flags: dynDialedConn, id: uintID(11)}}}, 343 {rws: []*conn{{flags: dynDialedConn, id: uintID(12)}}}, 344 }, 345 }, 346 // Nodes 3,4 are not tried again because only the first two 347 // returned random nodes (nodes 1,2) are tried and they're 348 // already connected. 349 { 350 peers: []*Peer{ 351 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 352 {rws: []*conn{{flags: dynDialedConn, id: uintID(2)}}}, 353 {rws: []*conn{{flags: dynDialedConn, id: uintID(10)}}}, 354 {rws: []*conn{{flags: dynDialedConn, id: uintID(11)}}}, 355 {rws: []*conn{{flags: dynDialedConn, id: uintID(12)}}}, 356 }, 357 }, 358 }, 359 }) 360 } 361 362 // This test checks that candidates that do not match the netrestrict list are not dialed. 363 func TestDialStateNetRestrict(t *testing.T) { 364 // This table always returns the same random nodes 365 // in the order given below. 366 table := fakeTable{ 367 {ID: uintID(1), IP: net.ParseIP("127.0.0.1")}, 368 {ID: uintID(2), IP: net.ParseIP("127.0.0.2")}, 369 {ID: uintID(3), IP: net.ParseIP("127.0.0.3")}, 370 {ID: uintID(4), IP: net.ParseIP("127.0.0.4")}, 371 {ID: uintID(5), IP: net.ParseIP("127.0.2.5")}, 372 {ID: uintID(6), IP: net.ParseIP("127.0.2.6")}, 373 {ID: uintID(7), IP: net.ParseIP("127.0.2.7")}, 374 {ID: uintID(8), IP: net.ParseIP("127.0.2.8")}, 375 } 376 restrict := new(netutil.Netlist) 377 restrict.Add("127.0.2.0/24") 378 379 runDialTest(t, dialtest{ 380 init: newDialState(nil, nil, table, 10, restrict, nil, nil), 381 rounds: []round{ 382 { 383 new: []task{ 384 &dialTask{flags: dynDialedConn, dest: table[4]}, 385 &discoverTask{}, 386 }, 387 }, 388 }, 389 }) 390 } 391 392 // This test checks that static dials are launched. 393 func TestDialStateStaticDial(t *testing.T) { 394 wantStatic := []*discover.Node{ 395 {ID: uintID(1)}, 396 {ID: uintID(2)}, 397 {ID: uintID(3)}, 398 {ID: uintID(4)}, 399 {ID: uintID(5)}, 400 } 401 402 runDialTest(t, dialtest{ 403 init: newDialState(wantStatic, nil, fakeTable{}, 0, nil, nil, nil), 404 rounds: []round{ 405 // Static dials are launched for the nodes that 406 // aren't yet connected. 407 { 408 peers: []*Peer{ 409 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 410 {rws: []*conn{{flags: dynDialedConn, id: uintID(2)}}}, 411 }, 412 new: []task{ 413 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(3)}, dialType: DT_UNLIMITED}, 414 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(4)}, dialType: DT_UNLIMITED}, 415 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(5)}, dialType: DT_UNLIMITED}, 416 }, 417 }, 418 // No new tasks are launched in this round because all static 419 // nodes are either connected or still being dialed. 420 { 421 peers: []*Peer{ 422 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 423 {rws: []*conn{{flags: dynDialedConn, id: uintID(2)}}}, 424 {rws: []*conn{{flags: staticDialedConn, id: uintID(3)}}}, 425 }, 426 done: []task{ 427 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(3)}, dialType: DT_UNLIMITED}, 428 }, 429 }, 430 // No new dial tasks are launched because all static 431 // nodes are now connected. 432 { 433 peers: []*Peer{ 434 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 435 {rws: []*conn{{flags: dynDialedConn, id: uintID(2)}}}, 436 {rws: []*conn{{flags: staticDialedConn, id: uintID(3)}}}, 437 {rws: []*conn{{flags: staticDialedConn, id: uintID(4)}}}, 438 {rws: []*conn{{flags: staticDialedConn, id: uintID(5)}}}, 439 }, 440 done: []task{ 441 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(4)}, dialType: DT_UNLIMITED}, 442 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(5)}, dialType: DT_UNLIMITED}, 443 }, 444 new: []task{ 445 &waitExpireTask{Duration: 14 * time.Second}, 446 }, 447 }, 448 // Wait a round for dial history to expire, no new tasks should spawn. 449 { 450 peers: []*Peer{ 451 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 452 {rws: []*conn{{flags: dynDialedConn, id: uintID(2)}}}, 453 {rws: []*conn{{flags: staticDialedConn, id: uintID(3)}}}, 454 {rws: []*conn{{flags: staticDialedConn, id: uintID(4)}}}, 455 {rws: []*conn{{flags: staticDialedConn, id: uintID(5)}}}, 456 }, 457 }, 458 // If a static node is dropped, it should be immediately redialed, 459 // irrespective whether it was originally static or dynamic. 460 { 461 peers: []*Peer{ 462 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 463 {rws: []*conn{{flags: staticDialedConn, id: uintID(3)}}}, 464 {rws: []*conn{{flags: staticDialedConn, id: uintID(5)}}}, 465 }, 466 new: []task{ 467 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(2)}, dialType: DT_UNLIMITED}, 468 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(4)}, dialType: DT_UNLIMITED}, 469 }, 470 }, 471 }, 472 }) 473 } 474 475 // This test check expired task removed from static 476 func TestDialStateTypeStaticDialExpired(t *testing.T) { 477 tdt := dialType("test") 478 479 tsMap := make(map[dialType]typedStatic) 480 tsMap[tdt] = typedStatic{maxNodeCount: math.MaxInt64, maxTry: 3} 481 482 ds := newDialState(nil, nil, fakeTable{}, 0, nil, nil, tsMap) 483 dt := dialtest{ 484 init: ds, 485 rounds: []round{ 486 { 487 new: []task{ 488 &dialTask{flags: staticDialedConn | trustedConn, dest: &discover.Node{ID: uintID(4)}, dialType: tdt, failedTry: 2}, 489 &dialTask{flags: staticDialedConn | trustedConn, dest: &discover.Node{ID: uintID(5)}, dialType: tdt, failedTry: 3}, 490 &discoverTypedStaticTask{name: tdt, max: math.MaxInt64 - 2}, 491 }, 492 }, 493 }, 494 } 495 496 ds.addTypedStatic(&discover.Node{ID: uintID(4)}, tdt) 497 ds.static[discover.Node{ID: uintID(4)}.ID].failedTry = 2 498 ds.addTypedStatic(&discover.Node{ID: uintID(5)}, tdt) 499 ds.static[discover.Node{ID: uintID(5)}.ID].failedTry = 3 500 ds.addTypedStatic(&discover.Node{ID: uintID(6)}, tdt) // Expired DialTask, will removed from static 501 ds.static[discover.Node{ID: uintID(6)}.ID].failedTry = 4 502 503 runDialTest(t, dt) 504 } 505 506 func TestDialStateTypeStaticDialExpired2(t *testing.T) { 507 tdt := dialType("test") 508 509 tsMap := make(map[dialType]typedStatic) 510 tsMap[tdt] = typedStatic{maxNodeCount: 6, maxTry: 3} 511 512 ds := newDialState(nil, nil, fakeTable{}, 0, nil, nil, tsMap) 513 ds.addTypedStatic(&discover.Node{ID: uintID(4)}, tdt) 514 ds.addTypedStatic(&discover.Node{ID: uintID(5)}, tdt) 515 ds.addTypedStatic(&discover.Node{ID: uintID(6)}, tdt) 516 dt := dialtest{ 517 init: ds, 518 rounds: []round{ 519 { 520 peers: []*Peer{ 521 {rws: []*conn{{flags: staticDialedConn, id: uintID(1)}}}, 522 }, 523 new: []task{ 524 &dialTask{flags: staticDialedConn | trustedConn, dest: &discover.Node{ID: uintID(4)}, dialType: tdt}, 525 &dialTask{flags: staticDialedConn | trustedConn, dest: &discover.Node{ID: uintID(5)}, dialType: tdt}, 526 &dialTask{flags: staticDialedConn | trustedConn, dest: &discover.Node{ID: uintID(6)}, dialType: tdt}, 527 &discoverTypedStaticTask{name: tdt, max: 6 - 3}, 528 }, 529 }, 530 { 531 // all dialTask are failed to connect and 4, 6 dialTask is expired 532 peers: []*Peer{ 533 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 534 }, 535 done: []task{ 536 &dialTask{flags: staticDialedConn | trustedConn, dest: &discover.Node{ID: uintID(4)}, dialType: tdt}, 537 &dialTask{flags: staticDialedConn | trustedConn, dest: &discover.Node{ID: uintID(5)}, dialType: tdt}, 538 &dialTask{flags: staticDialedConn | trustedConn, dest: &discover.Node{ID: uintID(6)}, dialType: tdt}, 539 }, 540 expired: []failedInfo{ 541 {discover.Node{ID: uintID(4)}.ID, 4}, 542 {discover.Node{ID: uintID(6)}.ID, 6}, 543 }, 544 }, 545 { 546 // Wait expired task is returned to normal 547 peers: []*Peer{ 548 {rws: []*conn{{flags: staticDialedConn | trustedConn, id: uintID(1)}}}, 549 }, 550 }, 551 { 552 peers: []*Peer{ 553 {rws: []*conn{{flags: staticDialedConn | trustedConn, id: uintID(1)}}}, 554 }, 555 new: []task{ 556 &dialTask{flags: staticDialedConn | trustedConn, dest: &discover.Node{ID: uintID(5)}, dialType: tdt}, 557 }, 558 }, 559 }, 560 } 561 runDialTest(t, dt) 562 } 563 564 func TestDialStateDiscoverTypedStatic(t *testing.T) { 565 tdt := dialType("test") 566 567 tsMap := make(map[dialType]typedStatic) 568 tsMap[tdt] = typedStatic{maxNodeCount: 6, maxTry: 3} 569 570 ds := newDialState(nil, nil, fakeTable{}, 0, nil, nil, tsMap) 571 ds.addTypedStatic(&discover.Node{ID: uintID(4)}, tdt) 572 ds.addTypedStatic(&discover.Node{ID: uintID(5)}, tdt) 573 ds.addTypedStatic(&discover.Node{ID: uintID(6)}, tdt) 574 575 dt := dialtest{ 576 init: ds, 577 rounds: []round{ 578 { 579 peers: []*Peer{ 580 {rws: []*conn{{flags: staticDialedConn, id: uintID(1)}}}, 581 }, 582 new: []task{ 583 &dialTask{flags: staticDialedConn | trustedConn, dest: &discover.Node{ID: uintID(4)}, dialType: tdt}, 584 &dialTask{flags: staticDialedConn | trustedConn, dest: &discover.Node{ID: uintID(5)}, dialType: tdt}, 585 &dialTask{flags: staticDialedConn | trustedConn, dest: &discover.Node{ID: uintID(6)}, dialType: tdt}, 586 &discoverTypedStaticTask{name: tdt, max: 6 - 3}, 587 }, 588 }, 589 { 590 peers: []*Peer{ 591 {rws: []*conn{{flags: staticDialedConn, id: uintID(1)}}}, 592 }, 593 done: []task{ 594 &discoverTypedStaticTask{name: tdt, max: 6 - 3}, 595 }, 596 new: []task{ 597 &discoverTypedStaticTask{name: tdt, max: 6 - 3}, 598 }, 599 }, 600 }, 601 } 602 runDialTest(t, dt) 603 } 604 605 func TestDialStateTypedStaticMaxConn(t *testing.T) { 606 tdt := dialType("test") 607 608 tsMap := make(map[dialType]typedStatic) 609 tsMap[tdt] = typedStatic{maxNodeCount: 3, maxTry: math.MaxInt64} 610 611 ds := newDialState(nil, nil, fakeTable{}, 0, nil, nil, tsMap) 612 ds.addTypedStatic(&discover.Node{ID: uintID(1)}, tdt) 613 ds.addTypedStatic(&discover.Node{ID: uintID(2)}, tdt) 614 ds.addTypedStatic(&discover.Node{ID: uintID(3)}, tdt) // will be delete cause exceed allowed typed conntection 615 dt := dialtest{ 616 init: ds, 617 rounds: []round{ 618 { 619 new: []task{ 620 &dialTask{flags: staticDialedConn | trustedConn, dest: &discover.Node{ID: uintID(1)}, dialType: tdt}, 621 &dialTask{flags: staticDialedConn | trustedConn, dest: &discover.Node{ID: uintID(2)}, dialType: tdt}, 622 &dialTask{flags: staticDialedConn | trustedConn, dest: &discover.Node{ID: uintID(3)}, dialType: tdt}, 623 }, 624 }, 625 }, 626 } 627 runDialTest(t, dt) 628 } 629 630 func TestDialStateTypedStaticMaxConn2(t *testing.T) { 631 tdt := dialType("test") 632 633 tsMap := make(map[dialType]typedStatic) 634 tsMap[tdt] = typedStatic{maxNodeCount: 3, maxTry: math.MaxInt64} 635 636 ds := newDialState(nil, nil, fakeTable{}, 0, nil, nil, tsMap) 637 ds.addTypedStatic(&discover.Node{ID: uintID(1)}, tdt) 638 ds.addTypedStatic(&discover.Node{ID: uintID(2)}, tdt) 639 ds.addTypedStatic(&discover.Node{ID: uintID(3)}, tdt) // will be delete cause exceed allowed typed conntection 640 dt := dialtest{ 641 init: ds, 642 rounds: []round{ 643 { 644 peers: []*Peer{ 645 {rws: []*conn{{flags: staticDialedConn | trustedConn, id: uintID(1)}}}, 646 {rws: []*conn{{flags: staticDialedConn | trustedConn, id: uintID(2)}}}, 647 }, 648 new: []task{ 649 &dialTask{flags: staticDialedConn | trustedConn, dest: &discover.Node{ID: uintID(3)}, dialType: tdt}, 650 }, 651 }, 652 }, 653 } 654 runDialTest(t, dt) 655 } 656 657 func TestDialStateTypedStaticMaxConn3(t *testing.T) { 658 tdt := dialType("test") 659 660 tsMap := make(map[dialType]typedStatic) 661 tsMap[tdt] = typedStatic{maxNodeCount: 3, maxTry: math.MaxInt64} 662 663 ds := newDialState(nil, nil, fakeTable{}, 0, nil, nil, tsMap) 664 ds.addTypedStatic(&discover.Node{ID: uintID(1)}, tdt) 665 ds.addTypedStatic(&discover.Node{ID: uintID(2)}, tdt) 666 ds.addTypedStatic(&discover.Node{ID: uintID(3)}, tdt) // will be delete cause exceed allowed typed conntection 667 ds.addTypedStatic(&discover.Node{ID: uintID(4)}, tdt) 668 ds.addTypedStatic(&discover.Node{ID: uintID(5)}, tdt) 669 ds.addTypedStatic(&discover.Node{ID: uintID(6)}, tdt) 670 dt := dialtest{ 671 init: ds, 672 rounds: []round{ 673 { 674 peers: []*Peer{ 675 {rws: []*conn{{flags: staticDialedConn, id: uintID(1)}}}, 676 {rws: []*conn{{flags: staticDialedConn, id: uintID(2)}}}, 677 {rws: []*conn{{flags: staticDialedConn, id: uintID(3)}}}, 678 }, 679 new: []task{}, 680 }, 681 }, 682 } 683 runDialTest(t, dt) 684 } 685 686 // This test checks if static dials can ignore adding self ID to static node list. 687 func TestDialStateAddingSelfNode(t *testing.T) { 688 privateKey := newkey() 689 nodeID := discover.PubkeyID(&privateKey.PublicKey) 690 691 fakePrivateKey := newkey() 692 693 wantStatic := []*discover.Node{ 694 {ID: uintID(1)}, 695 {ID: uintID(2)}, 696 {ID: nodeID}, 697 {ID: uintID(3)}, 698 {ID: uintID(4)}, 699 } 700 701 dialState_nil := newDialState(wantStatic, nil, fakeTable{}, 0, nil, nil, nil) 702 dialState_func := newDialState(wantStatic, nil, fakeTable{}, 0, nil, privateKey, nil) 703 dialState_normal := newDialState(wantStatic, nil, fakeTable{}, 0, nil, fakePrivateKey, nil) 704 705 if len(dialState_nil.static) != 5 { 706 t.Errorf("newDialState() can't process nil privateKey") 707 } 708 709 for _, n := range dialState_func.static { 710 if n.dest.ID == nodeID { 711 t.Errorf("newDialState() can't ignore adding self node to the static node list") 712 } 713 } 714 715 if len(dialState_normal.static) != 5 { 716 t.Errorf("newDialState() can't deal with normal case") 717 } 718 } 719 720 // This test checks that static peers will be redialed immediately if they were re-added to a static list. 721 func TestDialStaticAfterReset(t *testing.T) { 722 wantStatic := []*discover.Node{ 723 {ID: uintID(1)}, 724 {ID: uintID(2)}, 725 } 726 727 rounds := []round{ 728 // Static dials are launched for the nodes that aren't yet connected. 729 { 730 peers: nil, 731 new: []task{ 732 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(1)}, dialType: DT_UNLIMITED}, 733 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(2)}, dialType: DT_UNLIMITED}, 734 }, 735 }, 736 // No new dial tasks, all peers are connected. 737 { 738 peers: []*Peer{ 739 {rws: []*conn{{flags: staticDialedConn, id: uintID(1)}}}, 740 {rws: []*conn{{flags: staticDialedConn, id: uintID(2)}}}, 741 }, 742 done: []task{ 743 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(1)}, dialType: DT_UNLIMITED}, 744 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(2)}, dialType: DT_UNLIMITED}, 745 }, 746 new: []task{ 747 &waitExpireTask{Duration: 30 * time.Second}, 748 }, 749 }, 750 } 751 dTest := dialtest{ 752 init: newDialState(wantStatic, nil, fakeTable{}, 0, nil, nil, nil), 753 rounds: rounds, 754 } 755 runDialTest(t, dTest) 756 for _, n := range wantStatic { 757 dTest.init.removeStatic(n) 758 dTest.init.addStatic(n) 759 } 760 // without removing peers they will be considered recently dialed 761 runDialTest(t, dTest) 762 } 763 764 // This test checks that past dials are not retried for some time. 765 func TestDialStateCache(t *testing.T) { 766 wantStatic := []*discover.Node{ 767 {ID: uintID(1)}, 768 {ID: uintID(2)}, 769 {ID: uintID(3)}, 770 } 771 772 runDialTest(t, dialtest{ 773 init: newDialState(wantStatic, nil, fakeTable{}, 0, nil, nil, nil), 774 rounds: []round{ 775 // Static dials are launched for the nodes that 776 // aren't yet connected. 777 { 778 peers: nil, 779 new: []task{ 780 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(1)}, dialType: DT_UNLIMITED}, 781 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(2)}, dialType: DT_UNLIMITED}, 782 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(3)}, dialType: DT_UNLIMITED}, 783 }, 784 }, 785 // No new tasks are launched in this round because all static 786 // nodes are either connected or still being dialed. 787 { 788 peers: []*Peer{ 789 {rws: []*conn{{flags: staticDialedConn, id: uintID(1)}}}, 790 {rws: []*conn{{flags: staticDialedConn, id: uintID(2)}}}, 791 }, 792 done: []task{ 793 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(1)}, dialType: DT_UNLIMITED}, 794 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(2)}, dialType: DT_UNLIMITED}, 795 }, 796 }, 797 // A salvage task is launched to wait for node 3's history 798 // entry to expire. 799 { 800 peers: []*Peer{ 801 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 802 {rws: []*conn{{flags: dynDialedConn, id: uintID(2)}}}, 803 }, 804 done: []task{ 805 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(3)}}, 806 }, 807 new: []task{ 808 &waitExpireTask{Duration: 14 * time.Second}, 809 }, 810 }, 811 // Still waiting for node 3's entry to expire in the cache. 812 { 813 peers: []*Peer{ 814 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 815 {rws: []*conn{{flags: dynDialedConn, id: uintID(2)}}}, 816 }, 817 }, 818 // The cache entry for node 3 has expired and is retried. 819 { 820 peers: []*Peer{ 821 {rws: []*conn{{flags: dynDialedConn, id: uintID(1)}}}, 822 {rws: []*conn{{flags: dynDialedConn, id: uintID(2)}}}, 823 }, 824 new: []task{ 825 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(3)}, dialType: DT_UNLIMITED}, 826 }, 827 }, 828 }, 829 }) 830 } 831 832 func TestDialResolve(t *testing.T) { 833 resolved := discover.NewNode(uintID(1), net.IP{127, 0, 55, 234}, 3333, 4444, nil, discover.NodeTypeUnknown) 834 table := &resolveMock{answer: resolved} 835 state := newDialState(nil, nil, table, 0, nil, nil, nil) 836 837 // Check that the task is generated with an incomplete ID. 838 dest := discover.NewNode(uintID(1), nil, 0, 0, nil, discover.NodeTypeUnknown) 839 state.addStatic(dest) 840 tasks := state.newTasks(0, nil, time.Time{}) 841 if !reflect.DeepEqual(tasks, []task{&dialTask{flags: staticDialedConn, dest: dest, dialType: DT_UNLIMITED}}) { 842 t.Fatalf("expected dial task, got %#v", tasks) 843 } 844 845 // Now run the task, it should resolve the ID once. 846 config := Config{Dialer: TCPDialer{&net.Dialer{Deadline: time.Now().Add(-5 * time.Minute)}}} 847 srv := &SingleChannelServer{&BaseServer{ntab: table, Config: config}} 848 tasks[0].Do(srv) 849 if !reflect.DeepEqual(table.resolveCalls, []discover.NodeID{dest.ID}) { 850 t.Fatalf("wrong resolve calls, got %v", table.resolveCalls) 851 } 852 853 // Report it as done to the dialer, which should update the static node record. 854 state.taskDone(tasks[0], time.Now()) 855 if state.static[uintID(1)].dest != resolved { 856 t.Fatalf("state.dest not updated") 857 } 858 } 859 860 // compares task lists but doesn't care about the order. 861 func sametasks(a, b []task) bool { 862 if len(a) != len(b) { 863 return false 864 } 865 next: 866 for _, ta := range a { 867 for _, tb := range b { 868 if reflect.DeepEqual(ta, tb) { 869 continue next 870 } 871 } 872 return false 873 } 874 return true 875 } 876 877 func uintID(i uint32) discover.NodeID { 878 var id discover.NodeID 879 binary.BigEndian.PutUint32(id[:], i) 880 return id 881 } 882 883 // implements discoverTable for TestDialResolve 884 type resolveMock struct { 885 resolveCalls []discover.NodeID 886 answer *discover.Node 887 } 888 889 func (t *resolveMock) GetNodes(targetType discover.NodeType, max int) []*discover.Node { 890 panic("implement me") 891 } 892 893 func (t *resolveMock) LookupByType(target discover.NodeID, dt discover.DiscoveryType, nType discover.NodeType) []*discover.Node { 894 panic("implement me") 895 } 896 897 func (t *resolveMock) Name() string { 898 panic("implement me") 899 } 900 901 func (t *resolveMock) RetrieveNodes(target common.Hash, nType discover.NodeType, nresults int) []*discover.Node { 902 panic("implement me") 903 } 904 905 func (t *resolveMock) HasBond(id discover.NodeID) bool { 906 panic("implement me") 907 } 908 909 func (t *resolveMock) Bond(pinged bool, id discover.NodeID, addr *net.UDPAddr, tcpPort uint16, nType discover.NodeType) (*discover.Node, error) { 910 panic("implement me") 911 } 912 913 func (t *resolveMock) CreateUpdateNodeOnDB(n *discover.Node) error { 914 panic("implement me") 915 } 916 917 func (t *resolveMock) CreateUpdateNodeOnTable(n *discover.Node) error { 918 panic("implement me") 919 } 920 921 func (t *resolveMock) GetNodeFromDB(id discover.NodeID) (*discover.Node, error) { 922 panic("implement me") 923 } 924 925 func (t *resolveMock) DeleteNodeFromDB(n *discover.Node) error { 926 panic("implement me") 927 } 928 929 func (t *resolveMock) DeleteNodeFromTable(n *discover.Node) error { 930 panic("implement me") 931 } 932 933 func (t *resolveMock) GetBucketEntries() []*discover.Node { 934 panic("implement me") 935 } 936 937 func (t *resolveMock) GetReplacements() []*discover.Node { 938 panic("implement me") 939 } 940 941 func (t *resolveMock) Resolve(target discover.NodeID, nType discover.NodeType) *discover.Node { 942 t.resolveCalls = append(t.resolveCalls, target) 943 return t.answer 944 } 945 946 func (t *resolveMock) Self() *discover.Node { return new(discover.Node) } 947 948 func (t *resolveMock) Close() {} 949 func (t *resolveMock) Bootstrap([]*discover.Node) {} 950 func (t *resolveMock) Lookup(target discover.NodeID, nType discover.NodeType) []*discover.Node { 951 return nil 952 } 953 func (t *resolveMock) ReadRandomNodes(buf []*discover.Node, nType discover.NodeType) int { return 0 } 954 func (t *resolveMock) IsAuthorized(id discover.NodeID, ntype discover.NodeType) bool { 955 panic("implement me") 956 } 957 958 func (t *resolveMock) GetAuthorizedNodes() []*discover.Node { 959 panic("implement me") 960 } 961 962 func (t *resolveMock) PutAuthorizedNodes(nodes []*discover.Node) { 963 panic("implement me") 964 } 965 966 func (t *resolveMock) DeleteAuthorizedNodes(nodes []*discover.Node) { 967 panic("implement me") 968 }