github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/p2p/dial_test.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2015 Go Ethereum作者 10 //此文件是Go以太坊库的一部分。 11 // 12 //Go-Ethereum库是免费软件:您可以重新分发它和/或修改 13 //根据GNU发布的较低通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊图书馆的发行目的是希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU较低的通用公共许可证,了解更多详细信息。 21 // 22 //你应该收到一份GNU较低级别的公共许可证副本 23 //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package p2p 26 27 import ( 28 "encoding/binary" 29 "net" 30 "reflect" 31 "testing" 32 "time" 33 34 "github.com/davecgh/go-spew/spew" 35 "github.com/ethereum/go-ethereum/p2p/discover" 36 "github.com/ethereum/go-ethereum/p2p/netutil" 37 ) 38 39 func init() { 40 spew.Config.Indent = "\t" 41 } 42 43 type dialtest struct { 44 init *dialstate //测试前后的状态。 45 rounds []round 46 } 47 48 type round struct { 49 peers []*Peer //当前对等集 50 done []task //这一轮完成的任务 51 new []task //结果必须与此匹配 52 } 53 54 func runDialTest(t *testing.T, test dialtest) { 55 var ( 56 vtime time.Time 57 running int 58 ) 59 pm := func(ps []*Peer) map[discover.NodeID]*Peer { 60 m := make(map[discover.NodeID]*Peer) 61 for _, p := range ps { 62 m[p.rw.id] = p 63 } 64 return m 65 } 66 for i, round := range test.rounds { 67 for _, task := range round.done { 68 running-- 69 if running < 0 { 70 panic("running task counter underflow") 71 } 72 test.init.taskDone(task, vtime) 73 } 74 75 new := test.init.newTasks(running, pm(round.peers), vtime) 76 if !sametasks(new, round.new) { 77 t.Errorf("round %d: new tasks mismatch:\ngot %v\nwant %v\nstate: %v\nrunning: %v\n", 78 i, spew.Sdump(new), spew.Sdump(round.new), spew.Sdump(test.init), spew.Sdump(running)) 79 } 80 81 //每轮时间提前16秒。 82 vtime = vtime.Add(16 * time.Second) 83 running += len(new) 84 } 85 } 86 87 type fakeTable []*discover.Node 88 89 func (t fakeTable) Self() *discover.Node { return new(discover.Node) } 90 func (t fakeTable) Close() {} 91 func (t fakeTable) Lookup(discover.NodeID) []*discover.Node { return nil } 92 func (t fakeTable) Resolve(discover.NodeID) *discover.Node { return nil } 93 func (t fakeTable) ReadRandomNodes(buf []*discover.Node) int { return copy(buf, t) } 94 95 //此测试检查是否从发现结果启动动态拨号。 96 func TestDialStateDynDial(t *testing.T) { 97 runDialTest(t, dialtest{ 98 init: newDialState(nil, nil, fakeTable{}, 5, nil), 99 rounds: []round{ 100 //将启动发现查询。 101 { 102 peers: []*Peer{ 103 {rw: &conn{flags: staticDialedConn, id: uintID(0)}}, 104 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 105 {rw: &conn{flags: dynDialedConn, id: uintID(2)}}, 106 }, 107 new: []task{&discoverTask{}}, 108 }, 109 //动态拨号完成后启动。 110 { 111 peers: []*Peer{ 112 {rw: &conn{flags: staticDialedConn, id: uintID(0)}}, 113 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 114 {rw: &conn{flags: dynDialedConn, id: uintID(2)}}, 115 }, 116 done: []task{ 117 &discoverTask{results: []*discover.Node{ 118 {ID: uintID(2)}, //这个已经连接,没有拨号。 119 {ID: uintID(3)}, 120 {ID: uintID(4)}, 121 {ID: uintID(5)}, 122 {ID: uintID(6)}, //因为最大动态拨号是5,所以不尝试使用。 123 {ID: uintID(7)}, //… 124 }}, 125 }, 126 new: []task{ 127 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(3)}}, 128 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}}, 129 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}}, 130 }, 131 }, 132 //有些拨号盘已完成,但尚未启动新的拨号盘,因为 133 //活动拨号计数和动态对等计数之和=MaxDynDials。 134 { 135 peers: []*Peer{ 136 {rw: &conn{flags: staticDialedConn, id: uintID(0)}}, 137 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 138 {rw: &conn{flags: dynDialedConn, id: uintID(2)}}, 139 {rw: &conn{flags: dynDialedConn, id: uintID(3)}}, 140 {rw: &conn{flags: dynDialedConn, id: uintID(4)}}, 141 }, 142 done: []task{ 143 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(3)}}, 144 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}}, 145 }, 146 }, 147 //此轮中没有启动新的拨号任务,因为 148 //已达到MaxDynDials。 149 { 150 peers: []*Peer{ 151 {rw: &conn{flags: staticDialedConn, id: uintID(0)}}, 152 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 153 {rw: &conn{flags: dynDialedConn, id: uintID(2)}}, 154 {rw: &conn{flags: dynDialedConn, id: uintID(3)}}, 155 {rw: &conn{flags: dynDialedConn, id: uintID(4)}}, 156 {rw: &conn{flags: dynDialedConn, id: uintID(5)}}, 157 }, 158 done: []task{ 159 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}}, 160 }, 161 new: []task{ 162 &waitExpireTask{Duration: 14 * time.Second}, 163 }, 164 }, 165 //在这一轮中,ID为2的对等机将关闭。查询 166 //重新使用上次发现查找的结果。 167 { 168 peers: []*Peer{ 169 {rw: &conn{flags: staticDialedConn, id: uintID(0)}}, 170 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 171 {rw: &conn{flags: dynDialedConn, id: uintID(3)}}, 172 {rw: &conn{flags: dynDialedConn, id: uintID(4)}}, 173 {rw: &conn{flags: dynDialedConn, id: uintID(5)}}, 174 }, 175 new: []task{ 176 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(6)}}, 177 }, 178 }, 179 //更多的对等端(3,4)停止并拨出ID 6完成。 180 //重新使用发现查找的最后一个查询结果 181 //因为需要更多的候选人,所以产生了一个新的候选人。 182 { 183 peers: []*Peer{ 184 {rw: &conn{flags: staticDialedConn, id: uintID(0)}}, 185 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 186 {rw: &conn{flags: dynDialedConn, id: uintID(5)}}, 187 }, 188 done: []task{ 189 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(6)}}, 190 }, 191 new: []task{ 192 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(7)}}, 193 &discoverTask{}, 194 }, 195 }, 196 //对等7已连接,但仍然没有足够的动态对等 197 //(5个中有4个)。但是,发现已经在运行,因此请确保 198 //没有新的开始。 199 { 200 peers: []*Peer{ 201 {rw: &conn{flags: staticDialedConn, id: uintID(0)}}, 202 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 203 {rw: &conn{flags: dynDialedConn, id: uintID(5)}}, 204 {rw: &conn{flags: dynDialedConn, id: uintID(7)}}, 205 }, 206 done: []task{ 207 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(7)}}, 208 }, 209 }, 210 //使用空集完成正在运行的节点发现。一种新的查找 211 //应立即请求。 212 { 213 peers: []*Peer{ 214 {rw: &conn{flags: staticDialedConn, id: uintID(0)}}, 215 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 216 {rw: &conn{flags: dynDialedConn, id: uintID(5)}}, 217 {rw: &conn{flags: dynDialedConn, id: uintID(7)}}, 218 }, 219 done: []task{ 220 &discoverTask{}, 221 }, 222 new: []task{ 223 &discoverTask{}, 224 }, 225 }, 226 }, 227 }) 228 } 229 230 //测试在没有连接对等机的情况下是否拨号引导节点,否则不拨号。 231 func TestDialStateDynDialBootnode(t *testing.T) { 232 bootnodes := []*discover.Node{ 233 {ID: uintID(1)}, 234 {ID: uintID(2)}, 235 {ID: uintID(3)}, 236 } 237 table := fakeTable{ 238 {ID: uintID(4)}, 239 {ID: uintID(5)}, 240 {ID: uintID(6)}, 241 {ID: uintID(7)}, 242 {ID: uintID(8)}, 243 } 244 runDialTest(t, dialtest{ 245 init: newDialState(nil, bootnodes, table, 5, nil), 246 rounds: []round{ 247 //已尝试2个动态拨号,启动节点挂起回退间隔 248 { 249 new: []task{ 250 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}}, 251 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}}, 252 &discoverTask{}, 253 }, 254 }, 255 //没有拨号成功,引导节点仍挂起回退间隔 256 { 257 done: []task{ 258 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}}, 259 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}}, 260 }, 261 }, 262 //没有拨号成功,引导节点仍挂起回退间隔 263 {}, 264 //没有成功的拨号,尝试了2个动态拨号,同时达到了回退间隔,还尝试了1个引导节点。 265 { 266 new: []task{ 267 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(1)}}, 268 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}}, 269 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}}, 270 }, 271 }, 272 //没有拨号成功,尝试第二个bootnode 273 { 274 done: []task{ 275 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(1)}}, 276 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}}, 277 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}}, 278 }, 279 new: []task{ 280 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(2)}}, 281 }, 282 }, 283 //没有拨号成功,尝试第三个启动节点 284 { 285 done: []task{ 286 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(2)}}, 287 }, 288 new: []task{ 289 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(3)}}, 290 }, 291 }, 292 //没有拨号成功,再次尝试第一个bootnode,重试过期的随机节点 293 { 294 done: []task{ 295 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(3)}}, 296 }, 297 new: []task{ 298 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(1)}}, 299 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}}, 300 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}}, 301 }, 302 }, 303 //随机拨号成功,不再尝试启动节点 304 { 305 peers: []*Peer{ 306 {rw: &conn{flags: dynDialedConn, id: uintID(4)}}, 307 }, 308 done: []task{ 309 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(1)}}, 310 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}}, 311 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}}, 312 }, 313 }, 314 }, 315 }) 316 } 317 318 func TestDialStateDynDialFromTable(t *testing.T) { 319 //此表始终返回相同的随机节点 320 //按照下面给出的顺序。 321 table := fakeTable{ 322 {ID: uintID(1)}, 323 {ID: uintID(2)}, 324 {ID: uintID(3)}, 325 {ID: uintID(4)}, 326 {ID: uintID(5)}, 327 {ID: uintID(6)}, 328 {ID: uintID(7)}, 329 {ID: uintID(8)}, 330 } 331 332 runDialTest(t, dialtest{ 333 init: newDialState(nil, nil, table, 10, nil), 334 rounds: []round{ 335 //readrandomnodes返回的8个节点中有5个被拨号。 336 { 337 new: []task{ 338 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(1)}}, 339 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(2)}}, 340 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(3)}}, 341 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}}, 342 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}}, 343 &discoverTask{}, 344 }, 345 }, 346 //拨号节点1、2成功。启动查找中的拨号。 347 { 348 peers: []*Peer{ 349 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 350 {rw: &conn{flags: dynDialedConn, id: uintID(2)}}, 351 }, 352 done: []task{ 353 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(1)}}, 354 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(2)}}, 355 &discoverTask{results: []*discover.Node{ 356 {ID: uintID(10)}, 357 {ID: uintID(11)}, 358 {ID: uintID(12)}, 359 }}, 360 }, 361 new: []task{ 362 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(10)}}, 363 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(11)}}, 364 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(12)}}, 365 &discoverTask{}, 366 }, 367 }, 368 //拨号节点3、4、5失败。查找中的拨号成功。 369 { 370 peers: []*Peer{ 371 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 372 {rw: &conn{flags: dynDialedConn, id: uintID(2)}}, 373 {rw: &conn{flags: dynDialedConn, id: uintID(10)}}, 374 {rw: &conn{flags: dynDialedConn, id: uintID(11)}}, 375 {rw: &conn{flags: dynDialedConn, id: uintID(12)}}, 376 }, 377 done: []task{ 378 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(3)}}, 379 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(4)}}, 380 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(5)}}, 381 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(10)}}, 382 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(11)}}, 383 &dialTask{flags: dynDialedConn, dest: &discover.Node{ID: uintID(12)}}, 384 }, 385 }, 386 //正在等待到期。没有启动waitexpiretask,因为 387 //发现查询仍在运行。 388 { 389 peers: []*Peer{ 390 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 391 {rw: &conn{flags: dynDialedConn, id: uintID(2)}}, 392 {rw: &conn{flags: dynDialedConn, id: uintID(10)}}, 393 {rw: &conn{flags: dynDialedConn, id: uintID(11)}}, 394 {rw: &conn{flags: dynDialedConn, id: uintID(12)}}, 395 }, 396 }, 397 //节点3,4不会再次尝试,因为只有前两个 398 //返回的随机节点(节点1,2)将被尝试 399 //已经连接。 400 { 401 peers: []*Peer{ 402 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 403 {rw: &conn{flags: dynDialedConn, id: uintID(2)}}, 404 {rw: &conn{flags: dynDialedConn, id: uintID(10)}}, 405 {rw: &conn{flags: dynDialedConn, id: uintID(11)}}, 406 {rw: &conn{flags: dynDialedConn, id: uintID(12)}}, 407 }, 408 }, 409 }, 410 }) 411 } 412 413 //此测试检查是否未拨出与NetRestrict列表不匹配的候选人。 414 func TestDialStateNetRestrict(t *testing.T) { 415 //此表始终返回相同的随机节点 416 //按照下面给出的顺序。 417 table := fakeTable{ 418 {ID: uintID(1), IP: net.ParseIP("127.0.0.1")}, 419 {ID: uintID(2), IP: net.ParseIP("127.0.0.2")}, 420 {ID: uintID(3), IP: net.ParseIP("127.0.0.3")}, 421 {ID: uintID(4), IP: net.ParseIP("127.0.0.4")}, 422 {ID: uintID(5), IP: net.ParseIP("127.0.2.5")}, 423 {ID: uintID(6), IP: net.ParseIP("127.0.2.6")}, 424 {ID: uintID(7), IP: net.ParseIP("127.0.2.7")}, 425 {ID: uintID(8), IP: net.ParseIP("127.0.2.8")}, 426 } 427 restrict := new(netutil.Netlist) 428 restrict.Add("127.0.2.0/24") 429 430 runDialTest(t, dialtest{ 431 init: newDialState(nil, nil, table, 10, restrict), 432 rounds: []round{ 433 { 434 new: []task{ 435 &dialTask{flags: dynDialedConn, dest: table[4]}, 436 &discoverTask{}, 437 }, 438 }, 439 }, 440 }) 441 } 442 443 //此测试检查是否启动了静态拨号。 444 func TestDialStateStaticDial(t *testing.T) { 445 wantStatic := []*discover.Node{ 446 {ID: uintID(1)}, 447 {ID: uintID(2)}, 448 {ID: uintID(3)}, 449 {ID: uintID(4)}, 450 {ID: uintID(5)}, 451 } 452 453 runDialTest(t, dialtest{ 454 init: newDialState(wantStatic, nil, fakeTable{}, 0, nil), 455 rounds: []round{ 456 //为以下节点启动静态拨号: 457 //尚未连接。 458 { 459 peers: []*Peer{ 460 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 461 {rw: &conn{flags: dynDialedConn, id: uintID(2)}}, 462 }, 463 new: []task{ 464 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(3)}}, 465 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(4)}}, 466 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(5)}}, 467 }, 468 }, 469 //由于所有静态任务 470 //节点已连接或仍在拨号。 471 { 472 peers: []*Peer{ 473 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 474 {rw: &conn{flags: dynDialedConn, id: uintID(2)}}, 475 {rw: &conn{flags: staticDialedConn, id: uintID(3)}}, 476 }, 477 done: []task{ 478 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(3)}}, 479 }, 480 }, 481 //没有启动新的拨号任务,因为所有的拨号任务都是静态的 482 //节点现在已连接。 483 { 484 peers: []*Peer{ 485 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 486 {rw: &conn{flags: dynDialedConn, id: uintID(2)}}, 487 {rw: &conn{flags: staticDialedConn, id: uintID(3)}}, 488 {rw: &conn{flags: staticDialedConn, id: uintID(4)}}, 489 {rw: &conn{flags: staticDialedConn, id: uintID(5)}}, 490 }, 491 done: []task{ 492 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(4)}}, 493 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(5)}}, 494 }, 495 new: []task{ 496 &waitExpireTask{Duration: 14 * time.Second}, 497 }, 498 }, 499 //等待一轮拨号历史记录过期,不应生成新任务。 500 { 501 peers: []*Peer{ 502 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 503 {rw: &conn{flags: dynDialedConn, id: uintID(2)}}, 504 {rw: &conn{flags: staticDialedConn, id: uintID(3)}}, 505 {rw: &conn{flags: staticDialedConn, id: uintID(4)}}, 506 {rw: &conn{flags: staticDialedConn, id: uintID(5)}}, 507 }, 508 }, 509 //如果一个静态节点被删除,它应该立即被重新拨号, 510 //不管它最初是静态的还是动态的。 511 { 512 peers: []*Peer{ 513 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 514 {rw: &conn{flags: staticDialedConn, id: uintID(3)}}, 515 {rw: &conn{flags: staticDialedConn, id: uintID(5)}}, 516 }, 517 new: []task{ 518 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(2)}}, 519 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(4)}}, 520 }, 521 }, 522 }, 523 }) 524 } 525 526 //此测试检查静态对等点如果被重新添加到静态列表中,是否会立即重新启用。 527 func TestDialStaticAfterReset(t *testing.T) { 528 wantStatic := []*discover.Node{ 529 {ID: uintID(1)}, 530 {ID: uintID(2)}, 531 } 532 533 rounds := []round{ 534 //为尚未连接的节点启动静态拨号。 535 { 536 peers: nil, 537 new: []task{ 538 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(1)}}, 539 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(2)}}, 540 }, 541 }, 542 //没有新的拨号任务,所有对等端都已连接。 543 { 544 peers: []*Peer{ 545 {rw: &conn{flags: staticDialedConn, id: uintID(1)}}, 546 {rw: &conn{flags: staticDialedConn, id: uintID(2)}}, 547 }, 548 done: []task{ 549 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(1)}}, 550 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(2)}}, 551 }, 552 new: []task{ 553 &waitExpireTask{Duration: 30 * time.Second}, 554 }, 555 }, 556 } 557 dTest := dialtest{ 558 init: newDialState(wantStatic, nil, fakeTable{}, 0, nil), 559 rounds: rounds, 560 } 561 runDialTest(t, dTest) 562 for _, n := range wantStatic { 563 dTest.init.removeStatic(n) 564 dTest.init.addStatic(n) 565 } 566 //如果不删除同龄人,他们将被视为最近拨打过电话。 567 runDialTest(t, dTest) 568 } 569 570 //此测试检查过去的拨号是否有一段时间没有重试。 571 func TestDialStateCache(t *testing.T) { 572 wantStatic := []*discover.Node{ 573 {ID: uintID(1)}, 574 {ID: uintID(2)}, 575 {ID: uintID(3)}, 576 } 577 578 runDialTest(t, dialtest{ 579 init: newDialState(wantStatic, nil, fakeTable{}, 0, nil), 580 rounds: []round{ 581 //为以下节点启动静态拨号: 582 //尚未连接。 583 { 584 peers: nil, 585 new: []task{ 586 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(1)}}, 587 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(2)}}, 588 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(3)}}, 589 }, 590 }, 591 //由于所有静态任务 592 //节点已连接或仍在拨号。 593 { 594 peers: []*Peer{ 595 {rw: &conn{flags: staticDialedConn, id: uintID(1)}}, 596 {rw: &conn{flags: staticDialedConn, id: uintID(2)}}, 597 }, 598 done: []task{ 599 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(1)}}, 600 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(2)}}, 601 }, 602 }, 603 //启动补救任务以等待节点3的历史记录 604 //条目将过期。 605 { 606 peers: []*Peer{ 607 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 608 {rw: &conn{flags: dynDialedConn, id: uintID(2)}}, 609 }, 610 done: []task{ 611 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(3)}}, 612 }, 613 new: []task{ 614 &waitExpireTask{Duration: 14 * time.Second}, 615 }, 616 }, 617 //仍在等待节点3的条目在缓存中过期。 618 { 619 peers: []*Peer{ 620 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 621 {rw: &conn{flags: dynDialedConn, id: uintID(2)}}, 622 }, 623 }, 624 //节点3的缓存项已过期并重试。 625 { 626 peers: []*Peer{ 627 {rw: &conn{flags: dynDialedConn, id: uintID(1)}}, 628 {rw: &conn{flags: dynDialedConn, id: uintID(2)}}, 629 }, 630 new: []task{ 631 &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(3)}}, 632 }, 633 }, 634 }, 635 }) 636 } 637 638 func TestDialResolve(t *testing.T) { 639 resolved := discover.NewNode(uintID(1), net.IP{127, 0, 55, 234}, 3333, 4444) 640 table := &resolveMock{answer: resolved} 641 state := newDialState(nil, nil, table, 0, nil) 642 643 //检查是否使用不完整的ID生成任务。 644 dest := discover.NewNode(uintID(1), nil, 0, 0) 645 state.addStatic(dest) 646 tasks := state.newTasks(0, nil, time.Time{}) 647 if !reflect.DeepEqual(tasks, []task{&dialTask{flags: staticDialedConn, dest: dest}}) { 648 t.Fatalf("expected dial task, got %#v", tasks) 649 } 650 651 //现在运行任务,它应该解析一次ID。 652 config := Config{Dialer: TCPDialer{&net.Dialer{Deadline: time.Now().Add(-5 * time.Minute)}}} 653 srv := &Server{ntab: table, Config: config} 654 tasks[0].Do(srv) 655 if !reflect.DeepEqual(table.resolveCalls, []discover.NodeID{dest.ID}) { 656 t.Fatalf("wrong resolve calls, got %v", table.resolveCalls) 657 } 658 659 //向拨号程序报告完成情况,拨号程序应更新静态节点记录。 660 state.taskDone(tasks[0], time.Now()) 661 if state.static[uintID(1)].dest != resolved { 662 t.Fatalf("state.dest not updated") 663 } 664 } 665 666 //比较任务列表,但不关心顺序。 667 func sametasks(a, b []task) bool { 668 if len(a) != len(b) { 669 return false 670 } 671 next: 672 for _, ta := range a { 673 for _, tb := range b { 674 if reflect.DeepEqual(ta, tb) { 675 continue next 676 } 677 } 678 return false 679 } 680 return true 681 } 682 683 func uintID(i uint32) discover.NodeID { 684 var id discover.NodeID 685 binary.BigEndian.PutUint32(id[:], i) 686 return id 687 } 688 689 //实现TestDialResolve的discovertable 690 type resolveMock struct { 691 resolveCalls []discover.NodeID 692 answer *discover.Node 693 } 694 695 func (t *resolveMock) Resolve(id discover.NodeID) *discover.Node { 696 t.resolveCalls = append(t.resolveCalls, id) 697 return t.answer 698 } 699 700 func (t *resolveMock) Self() *discover.Node { return new(discover.Node) } 701 func (t *resolveMock) Close() {} 702 func (t *resolveMock) Bootstrap([]*discover.Node) {} 703 func (t *resolveMock) Lookup(discover.NodeID) []*discover.Node { return nil } 704 func (t *resolveMock) ReadRandomNodes(buf []*discover.Node) int { return 0 }