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