github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/node/node_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:40</date> 10 //</624450102576025600> 11 12 13 package node 14 15 import ( 16 "errors" 17 "io/ioutil" 18 "os" 19 "reflect" 20 "testing" 21 "time" 22 23 "github.com/ethereum/go-ethereum/crypto" 24 "github.com/ethereum/go-ethereum/p2p" 25 "github.com/ethereum/go-ethereum/rpc" 26 ) 27 28 var ( 29 testNodeKey, _ = crypto.GenerateKey() 30 ) 31 32 func testNodeConfig() *Config { 33 return &Config{ 34 Name: "test node", 35 P2P: p2p.Config{PrivateKey: testNodeKey}, 36 } 37 } 38 39 //测试是否可以启动、重新启动和停止空协议堆栈。 40 func TestNodeLifeCycle(t *testing.T) { 41 stack, err := New(testNodeConfig()) 42 if err != nil { 43 t.Fatalf("failed to create protocol stack: %v", err) 44 } 45 //确保停止的节点可以再次停止 46 for i := 0; i < 3; i++ { 47 if err := stack.Stop(); err != ErrNodeStopped { 48 t.Fatalf("iter %d: stop failure mismatch: have %v, want %v", i, err, ErrNodeStopped) 49 } 50 } 51 //确保节点可以成功启动,但只能启动一次 52 if err := stack.Start(); err != nil { 53 t.Fatalf("failed to start node: %v", err) 54 } 55 if err := stack.Start(); err != ErrNodeRunning { 56 t.Fatalf("start failure mismatch: have %v, want %v ", err, ErrNodeRunning) 57 } 58 //确保节点可以任意多次重新启动 59 for i := 0; i < 3; i++ { 60 if err := stack.Restart(); err != nil { 61 t.Fatalf("iter %d: failed to restart node: %v", i, err) 62 } 63 } 64 //确保节点可以停止,但只能停止一次 65 if err := stack.Stop(); err != nil { 66 t.Fatalf("failed to stop node: %v", err) 67 } 68 if err := stack.Stop(); err != ErrNodeStopped { 69 t.Fatalf("stop failure mismatch: have %v, want %v ", err, ErrNodeStopped) 70 } 71 } 72 73 //测试如果data dir已在使用中,则返回适当的错误。 74 func TestNodeUsedDataDir(t *testing.T) { 75 //创建用作数据目录的临时文件夹 76 dir, err := ioutil.TempDir("", "") 77 if err != nil { 78 t.Fatalf("failed to create temporary data directory: %v", err) 79 } 80 defer os.RemoveAll(dir) 81 82 //基于数据目录创建新节点 83 original, err := New(&Config{DataDir: dir}) 84 if err != nil { 85 t.Fatalf("failed to create original protocol stack: %v", err) 86 } 87 if err := original.Start(); err != nil { 88 t.Fatalf("failed to start original protocol stack: %v", err) 89 } 90 defer original.Stop() 91 92 //基于相同的数据目录创建第二个节点并确保失败 93 duplicate, err := New(&Config{DataDir: dir}) 94 if err != nil { 95 t.Fatalf("failed to create duplicate protocol stack: %v", err) 96 } 97 if err := duplicate.Start(); err != ErrDatadirUsed { 98 t.Fatalf("duplicate datadir failure mismatch: have %v, want %v", err, ErrDatadirUsed) 99 } 100 } 101 102 //测试是否可以注册服务并捕获重复项。 103 func TestServiceRegistry(t *testing.T) { 104 stack, err := New(testNodeConfig()) 105 if err != nil { 106 t.Fatalf("failed to create protocol stack: %v", err) 107 } 108 //注册一批唯一的服务并确保它们成功启动 109 services := []ServiceConstructor{NewNoopServiceA, NewNoopServiceB, NewNoopServiceC} 110 for i, constructor := range services { 111 if err := stack.Register(constructor); err != nil { 112 t.Fatalf("service #%d: registration failed: %v", i, err) 113 } 114 } 115 if err := stack.Start(); err != nil { 116 t.Fatalf("failed to start original service stack: %v", err) 117 } 118 if err := stack.Stop(); err != nil { 119 t.Fatalf("failed to stop original service stack: %v", err) 120 } 121 //复制一个服务,然后重试启动节点 122 if err := stack.Register(NewNoopServiceB); err != nil { 123 t.Fatalf("duplicate registration failed: %v", err) 124 } 125 if err := stack.Start(); err == nil { 126 t.Fatalf("duplicate service started") 127 } else { 128 if _, ok := err.(*DuplicateServiceError); !ok { 129 t.Fatalf("duplicate error mismatch: have %v, want %v", err, DuplicateServiceError{}) 130 } 131 } 132 } 133 134 //已注册服务的测试将正确启动和停止。 135 func TestServiceLifeCycle(t *testing.T) { 136 stack, err := New(testNodeConfig()) 137 if err != nil { 138 t.Fatalf("failed to create protocol stack: %v", err) 139 } 140 //注册一批生命周期仪表化服务 141 services := map[string]InstrumentingWrapper{ 142 "A": InstrumentedServiceMakerA, 143 "B": InstrumentedServiceMakerB, 144 "C": InstrumentedServiceMakerC, 145 } 146 started := make(map[string]bool) 147 stopped := make(map[string]bool) 148 149 for id, maker := range services { 150 id := id //施工单位关闭 151 constructor := func(*ServiceContext) (Service, error) { 152 return &InstrumentedService{ 153 startHook: func(*p2p.Server) { started[id] = true }, 154 stopHook: func() { stopped[id] = true }, 155 }, nil 156 } 157 if err := stack.Register(maker(constructor)); err != nil { 158 t.Fatalf("service %s: registration failed: %v", id, err) 159 } 160 } 161 //启动节点并检查所有服务是否都在运行 162 if err := stack.Start(); err != nil { 163 t.Fatalf("failed to start protocol stack: %v", err) 164 } 165 for id := range services { 166 if !started[id] { 167 t.Fatalf("service %s: freshly started service not running", id) 168 } 169 if stopped[id] { 170 t.Fatalf("service %s: freshly started service already stopped", id) 171 } 172 } 173 //停止节点并检查所有服务是否已停止 174 if err := stack.Stop(); err != nil { 175 t.Fatalf("failed to stop protocol stack: %v", err) 176 } 177 for id := range services { 178 if !stopped[id] { 179 t.Fatalf("service %s: freshly terminated service still running", id) 180 } 181 } 182 } 183 184 //测试服务是否作为新实例干净地重新启动。 185 func TestServiceRestarts(t *testing.T) { 186 stack, err := New(testNodeConfig()) 187 if err != nil { 188 t.Fatalf("failed to create protocol stack: %v", err) 189 } 190 //定义不支持重新启动的服务 191 var ( 192 running bool 193 started int 194 ) 195 constructor := func(*ServiceContext) (Service, error) { 196 running = false 197 198 return &InstrumentedService{ 199 startHook: func(*p2p.Server) { 200 if running { 201 panic("already running") 202 } 203 running = true 204 started++ 205 }, 206 }, nil 207 } 208 //注册服务并启动协议栈 209 if err := stack.Register(constructor); err != nil { 210 t.Fatalf("failed to register the service: %v", err) 211 } 212 if err := stack.Start(); err != nil { 213 t.Fatalf("failed to start protocol stack: %v", err) 214 } 215 defer stack.Stop() 216 217 if !running || started != 1 { 218 t.Fatalf("running/started mismatch: have %v/%d, want true/1", running, started) 219 } 220 //重新启动堆栈几次,并检查成功的服务重新启动 221 for i := 0; i < 3; i++ { 222 if err := stack.Restart(); err != nil { 223 t.Fatalf("iter %d: failed to restart stack: %v", i, err) 224 } 225 } 226 if !running || started != 4 { 227 t.Fatalf("running/started mismatch: have %v/%d, want true/4", running, started) 228 } 229 } 230 231 //测试如果一个服务未能初始化自身,则没有其他服务 232 //甚至可以启动。 233 func TestServiceConstructionAbortion(t *testing.T) { 234 stack, err := New(testNodeConfig()) 235 if err != nil { 236 t.Fatalf("failed to create protocol stack: %v", err) 237 } 238 //定义一批好服务 239 services := map[string]InstrumentingWrapper{ 240 "A": InstrumentedServiceMakerA, 241 "B": InstrumentedServiceMakerB, 242 "C": InstrumentedServiceMakerC, 243 } 244 started := make(map[string]bool) 245 for id, maker := range services { 246 id := id //施工单位关闭 247 constructor := func(*ServiceContext) (Service, error) { 248 return &InstrumentedService{ 249 startHook: func(*p2p.Server) { started[id] = true }, 250 }, nil 251 } 252 if err := stack.Register(maker(constructor)); err != nil { 253 t.Fatalf("service %s: registration failed: %v", id, err) 254 } 255 } 256 //注册无法构造自身的服务 257 failure := errors.New("fail") 258 failer := func(*ServiceContext) (Service, error) { 259 return nil, failure 260 } 261 if err := stack.Register(failer); err != nil { 262 t.Fatalf("failer registration failed: %v", err) 263 } 264 //启动协议栈并确保没有任何服务启动 265 for i := 0; i < 100; i++ { 266 if err := stack.Start(); err != failure { 267 t.Fatalf("iter %d: stack startup failure mismatch: have %v, want %v", i, err, failure) 268 } 269 for id := range services { 270 if started[id] { 271 t.Fatalf("service %s: started should not have", id) 272 } 273 delete(started, id) 274 } 275 } 276 } 277 278 //测试如果一个服务未能启动,所有其他服务将在启动之前启动 279 //关闭。 280 func TestServiceStartupAbortion(t *testing.T) { 281 stack, err := New(testNodeConfig()) 282 if err != nil { 283 t.Fatalf("failed to create protocol stack: %v", err) 284 } 285 //注册一批优质服务 286 services := map[string]InstrumentingWrapper{ 287 "A": InstrumentedServiceMakerA, 288 "B": InstrumentedServiceMakerB, 289 "C": InstrumentedServiceMakerC, 290 } 291 started := make(map[string]bool) 292 stopped := make(map[string]bool) 293 294 for id, maker := range services { 295 id := id //施工单位关闭 296 constructor := func(*ServiceContext) (Service, error) { 297 return &InstrumentedService{ 298 startHook: func(*p2p.Server) { started[id] = true }, 299 stopHook: func() { stopped[id] = true }, 300 }, nil 301 } 302 if err := stack.Register(maker(constructor)); err != nil { 303 t.Fatalf("service %s: registration failed: %v", id, err) 304 } 305 } 306 //注册无法启动的服务 307 failure := errors.New("fail") 308 failer := func(*ServiceContext) (Service, error) { 309 return &InstrumentedService{ 310 start: failure, 311 }, nil 312 } 313 if err := stack.Register(failer); err != nil { 314 t.Fatalf("failer registration failed: %v", err) 315 } 316 //启动协议栈并确保所有启动的服务都停止 317 for i := 0; i < 100; i++ { 318 if err := stack.Start(); err != failure { 319 t.Fatalf("iter %d: stack startup failure mismatch: have %v, want %v", i, err, failure) 320 } 321 for id := range services { 322 if started[id] && !stopped[id] { 323 t.Fatalf("service %s: started but not stopped", id) 324 } 325 delete(started, id) 326 delete(stopped, id) 327 } 328 } 329 } 330 331 //测试即使注册的服务无法完全关闭,它也会 332 //不会影响其余的关机调用。 333 func TestServiceTerminationGuarantee(t *testing.T) { 334 stack, err := New(testNodeConfig()) 335 if err != nil { 336 t.Fatalf("failed to create protocol stack: %v", err) 337 } 338 //注册一批优质服务 339 services := map[string]InstrumentingWrapper{ 340 "A": InstrumentedServiceMakerA, 341 "B": InstrumentedServiceMakerB, 342 "C": InstrumentedServiceMakerC, 343 } 344 started := make(map[string]bool) 345 stopped := make(map[string]bool) 346 347 for id, maker := range services { 348 id := id //施工单位关闭 349 constructor := func(*ServiceContext) (Service, error) { 350 return &InstrumentedService{ 351 startHook: func(*p2p.Server) { started[id] = true }, 352 stopHook: func() { stopped[id] = true }, 353 }, nil 354 } 355 if err := stack.Register(maker(constructor)); err != nil { 356 t.Fatalf("service %s: registration failed: %v", id, err) 357 } 358 } 359 //注册一个无法完全关闭的服务 360 failure := errors.New("fail") 361 failer := func(*ServiceContext) (Service, error) { 362 return &InstrumentedService{ 363 stop: failure, 364 }, nil 365 } 366 if err := stack.Register(failer); err != nil { 367 t.Fatalf("failer registration failed: %v", err) 368 } 369 //启动协议栈,并确保失败的关机终止所有 370 for i := 0; i < 100; i++ { 371 //启动堆栈并确保全部联机 372 if err := stack.Start(); err != nil { 373 t.Fatalf("iter %d: failed to start protocol stack: %v", i, err) 374 } 375 for id := range services { 376 if !started[id] { 377 t.Fatalf("iter %d, service %s: service not running", i, id) 378 } 379 if stopped[id] { 380 t.Fatalf("iter %d, service %s: service already stopped", i, id) 381 } 382 } 383 //停止堆栈,验证故障并检查所有终端 384 err := stack.Stop() 385 if err, ok := err.(*StopError); !ok { 386 t.Fatalf("iter %d: termination failure mismatch: have %v, want StopError", i, err) 387 } else { 388 failer := reflect.TypeOf(&InstrumentedService{}) 389 if err.Services[failer] != failure { 390 t.Fatalf("iter %d: failer termination failure mismatch: have %v, want %v", i, err.Services[failer], failure) 391 } 392 if len(err.Services) != 1 { 393 t.Fatalf("iter %d: failure count mismatch: have %d, want %d", i, len(err.Services), 1) 394 } 395 } 396 for id := range services { 397 if !stopped[id] { 398 t.Fatalf("iter %d, service %s: service not terminated", i, id) 399 } 400 delete(started, id) 401 delete(stopped, id) 402 } 403 } 404 } 405 406 //TestServiceRetrieval测试可以检索单个服务。 407 func TestServiceRetrieval(t *testing.T) { 408 //创建一个简单的堆栈并注册两种服务类型 409 stack, err := New(testNodeConfig()) 410 if err != nil { 411 t.Fatalf("failed to create protocol stack: %v", err) 412 } 413 if err := stack.Register(NewNoopService); err != nil { 414 t.Fatalf("noop service registration failed: %v", err) 415 } 416 if err := stack.Register(NewInstrumentedService); err != nil { 417 t.Fatalf("instrumented service registration failed: %v", err) 418 } 419 //确保在启动之前无法检索任何服务 420 var noopServ *NoopService 421 if err := stack.Service(&noopServ); err != ErrNodeStopped { 422 t.Fatalf("noop service retrieval mismatch: have %v, want %v", err, ErrNodeStopped) 423 } 424 var instServ *InstrumentedService 425 if err := stack.Service(&instServ); err != ErrNodeStopped { 426 t.Fatalf("instrumented service retrieval mismatch: have %v, want %v", err, ErrNodeStopped) 427 } 428 //启动堆栈并确保现在可以检索所有内容 429 if err := stack.Start(); err != nil { 430 t.Fatalf("failed to start stack: %v", err) 431 } 432 defer stack.Stop() 433 434 if err := stack.Service(&noopServ); err != nil { 435 t.Fatalf("noop service retrieval mismatch: have %v, want %v", err, nil) 436 } 437 if err := stack.Service(&instServ); err != nil { 438 t.Fatalf("instrumented service retrieval mismatch: have %v, want %v", err, nil) 439 } 440 } 441 442 //测试由单个服务定义的所有协议是否启动。 443 func TestProtocolGather(t *testing.T) { 444 stack, err := New(testNodeConfig()) 445 if err != nil { 446 t.Fatalf("failed to create protocol stack: %v", err) 447 } 448 //用一些已配置的协议数注册一批服务 449 services := map[string]struct { 450 Count int 451 Maker InstrumentingWrapper 452 }{ 453 "zero": {0, InstrumentedServiceMakerA}, 454 "one": {1, InstrumentedServiceMakerB}, 455 "many": {10, InstrumentedServiceMakerC}, 456 } 457 for id, config := range services { 458 protocols := make([]p2p.Protocol, config.Count) 459 for i := 0; i < len(protocols); i++ { 460 protocols[i].Name = id 461 protocols[i].Version = uint(i) 462 } 463 constructor := func(*ServiceContext) (Service, error) { 464 return &InstrumentedService{ 465 protocols: protocols, 466 }, nil 467 } 468 if err := stack.Register(config.Maker(constructor)); err != nil { 469 t.Fatalf("service %s: registration failed: %v", id, err) 470 } 471 } 472 //启动服务并确保所有协议成功启动 473 if err := stack.Start(); err != nil { 474 t.Fatalf("failed to start protocol stack: %v", err) 475 } 476 defer stack.Stop() 477 478 protocols := stack.Server().Protocols 479 if len(protocols) != 11 { 480 t.Fatalf("mismatching number of protocols launched: have %d, want %d", len(protocols), 26) 481 } 482 for id, config := range services { 483 for ver := 0; ver < config.Count; ver++ { 484 launched := false 485 for i := 0; i < len(protocols); i++ { 486 if protocols[i].Name == id && protocols[i].Version == uint(ver) { 487 launched = true 488 break 489 } 490 } 491 if !launched { 492 t.Errorf("configured protocol not launched: %s v%d", id, ver) 493 } 494 } 495 } 496 } 497 498 //测试由单个服务定义的所有API是否公开。 499 func TestAPIGather(t *testing.T) { 500 stack, err := New(testNodeConfig()) 501 if err != nil { 502 t.Fatalf("failed to create protocol stack: %v", err) 503 } 504 //用一些已配置的API注册一批服务 505 calls := make(chan string, 1) 506 makeAPI := func(result string) *OneMethodAPI { 507 return &OneMethodAPI{fun: func() { calls <- result }} 508 } 509 services := map[string]struct { 510 APIs []rpc.API 511 Maker InstrumentingWrapper 512 }{ 513 "Zero APIs": { 514 []rpc.API{}, InstrumentedServiceMakerA}, 515 "Single API": { 516 []rpc.API{ 517 {Namespace: "single", Version: "1", Service: makeAPI("single.v1"), Public: true}, 518 }, InstrumentedServiceMakerB}, 519 "Many APIs": { 520 []rpc.API{ 521 {Namespace: "multi", Version: "1", Service: makeAPI("multi.v1"), Public: true}, 522 {Namespace: "multi.v2", Version: "2", Service: makeAPI("multi.v2"), Public: true}, 523 {Namespace: "multi.v2.nested", Version: "2", Service: makeAPI("multi.v2.nested"), Public: true}, 524 }, InstrumentedServiceMakerC}, 525 } 526 527 for id, config := range services { 528 config := config 529 constructor := func(*ServiceContext) (Service, error) { 530 return &InstrumentedService{apis: config.APIs}, nil 531 } 532 if err := stack.Register(config.Maker(constructor)); err != nil { 533 t.Fatalf("service %s: registration failed: %v", id, err) 534 } 535 } 536 //启动服务并确保所有API成功启动 537 if err := stack.Start(); err != nil { 538 t.Fatalf("failed to start protocol stack: %v", err) 539 } 540 defer stack.Stop() 541 542 //连接到RPC服务器并验证各种已注册的终结点 543 client, err := stack.Attach() 544 if err != nil { 545 t.Fatalf("failed to connect to the inproc API server: %v", err) 546 } 547 defer client.Close() 548 549 tests := []struct { 550 Method string 551 Result string 552 }{ 553 {"single_theOneMethod", "single.v1"}, 554 {"multi_theOneMethod", "multi.v1"}, 555 {"multi.v2_theOneMethod", "multi.v2"}, 556 {"multi.v2.nested_theOneMethod", "multi.v2.nested"}, 557 } 558 for i, test := range tests { 559 if err := client.Call(nil, test.Method); err != nil { 560 t.Errorf("test %d: API request failed: %v", i, err) 561 } 562 select { 563 case result := <-calls: 564 if result != test.Result { 565 t.Errorf("test %d: result mismatch: have %s, want %s", i, result, test.Result) 566 } 567 case <-time.After(time.Second): 568 t.Fatalf("test %d: rpc execution timeout", i) 569 } 570 } 571 } 572