github.com/zhiqiangxu/go-ethereum@v1.9.16-0.20210824055606-be91cfdebc48/node/node_test.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package node 18 19 import ( 20 "errors" 21 "io/ioutil" 22 "net/http" 23 "os" 24 "reflect" 25 "testing" 26 "time" 27 28 "github.com/zhiqiangxu/go-ethereum/crypto" 29 "github.com/zhiqiangxu/go-ethereum/p2p" 30 "github.com/zhiqiangxu/go-ethereum/rpc" 31 32 "github.com/stretchr/testify/assert" 33 ) 34 35 var ( 36 testNodeKey, _ = crypto.GenerateKey() 37 ) 38 39 func testNodeConfig() *Config { 40 return &Config{ 41 Name: "test node", 42 P2P: p2p.Config{PrivateKey: testNodeKey}, 43 } 44 } 45 46 // Tests that an empty protocol stack can be started, restarted and stopped. 47 func TestNodeLifeCycle(t *testing.T) { 48 stack, err := New(testNodeConfig()) 49 if err != nil { 50 t.Fatalf("failed to create protocol stack: %v", err) 51 } 52 defer stack.Close() 53 54 // Ensure that a stopped node can be stopped again 55 for i := 0; i < 3; i++ { 56 if err := stack.Stop(); err != ErrNodeStopped { 57 t.Fatalf("iter %d: stop failure mismatch: have %v, want %v", i, err, ErrNodeStopped) 58 } 59 } 60 // Ensure that a node can be successfully started, but only once 61 if err := stack.Start(); err != nil { 62 t.Fatalf("failed to start node: %v", err) 63 } 64 if err := stack.Start(); err != ErrNodeRunning { 65 t.Fatalf("start failure mismatch: have %v, want %v ", err, ErrNodeRunning) 66 } 67 // Ensure that a node can be restarted arbitrarily many times 68 for i := 0; i < 3; i++ { 69 if err := stack.Restart(); err != nil { 70 t.Fatalf("iter %d: failed to restart node: %v", i, err) 71 } 72 } 73 // Ensure that a node can be stopped, but only once 74 if err := stack.Stop(); err != nil { 75 t.Fatalf("failed to stop node: %v", err) 76 } 77 if err := stack.Stop(); err != ErrNodeStopped { 78 t.Fatalf("stop failure mismatch: have %v, want %v ", err, ErrNodeStopped) 79 } 80 } 81 82 // Tests that if the data dir is already in use, an appropriate error is returned. 83 func TestNodeUsedDataDir(t *testing.T) { 84 // Create a temporary folder to use as the data directory 85 dir, err := ioutil.TempDir("", "") 86 if err != nil { 87 t.Fatalf("failed to create temporary data directory: %v", err) 88 } 89 defer os.RemoveAll(dir) 90 91 // Create a new node based on the data directory 92 original, err := New(&Config{DataDir: dir}) 93 if err != nil { 94 t.Fatalf("failed to create original protocol stack: %v", err) 95 } 96 defer original.Close() 97 98 if err := original.Start(); err != nil { 99 t.Fatalf("failed to start original protocol stack: %v", err) 100 } 101 defer original.Stop() 102 103 // Create a second node based on the same data directory and ensure failure 104 duplicate, err := New(&Config{DataDir: dir}) 105 if err != nil { 106 t.Fatalf("failed to create duplicate protocol stack: %v", err) 107 } 108 defer duplicate.Close() 109 110 if err := duplicate.Start(); err != ErrDatadirUsed { 111 t.Fatalf("duplicate datadir failure mismatch: have %v, want %v", err, ErrDatadirUsed) 112 } 113 } 114 115 // Tests whether services can be registered and duplicates caught. 116 func TestServiceRegistry(t *testing.T) { 117 stack, err := New(testNodeConfig()) 118 if err != nil { 119 t.Fatalf("failed to create protocol stack: %v", err) 120 } 121 defer stack.Close() 122 123 // Register a batch of unique services and ensure they start successfully 124 services := []ServiceConstructor{NewNoopServiceA, NewNoopServiceB, NewNoopServiceC} 125 for i, constructor := range services { 126 if err := stack.Register(constructor); err != nil { 127 t.Fatalf("service #%d: registration failed: %v", i, err) 128 } 129 } 130 if err := stack.Start(); err != nil { 131 t.Fatalf("failed to start original service stack: %v", err) 132 } 133 if err := stack.Stop(); err != nil { 134 t.Fatalf("failed to stop original service stack: %v", err) 135 } 136 // Duplicate one of the services and retry starting the node 137 if err := stack.Register(NewNoopServiceB); err != nil { 138 t.Fatalf("duplicate registration failed: %v", err) 139 } 140 if err := stack.Start(); err == nil { 141 t.Fatalf("duplicate service started") 142 } else { 143 if _, ok := err.(*DuplicateServiceError); !ok { 144 t.Fatalf("duplicate error mismatch: have %v, want %v", err, DuplicateServiceError{}) 145 } 146 } 147 } 148 149 // Tests that registered services get started and stopped correctly. 150 func TestServiceLifeCycle(t *testing.T) { 151 stack, err := New(testNodeConfig()) 152 if err != nil { 153 t.Fatalf("failed to create protocol stack: %v", err) 154 } 155 defer stack.Close() 156 157 // Register a batch of life-cycle instrumented services 158 services := map[string]InstrumentingWrapper{ 159 "A": InstrumentedServiceMakerA, 160 "B": InstrumentedServiceMakerB, 161 "C": InstrumentedServiceMakerC, 162 } 163 started := make(map[string]bool) 164 stopped := make(map[string]bool) 165 166 for id, maker := range services { 167 id := id // Closure for the constructor 168 constructor := func(*ServiceContext) (Service, error) { 169 return &InstrumentedService{ 170 startHook: func(*p2p.Server) { started[id] = true }, 171 stopHook: func() { stopped[id] = true }, 172 }, nil 173 } 174 if err := stack.Register(maker(constructor)); err != nil { 175 t.Fatalf("service %s: registration failed: %v", id, err) 176 } 177 } 178 // Start the node and check that all services are running 179 if err := stack.Start(); err != nil { 180 t.Fatalf("failed to start protocol stack: %v", err) 181 } 182 for id := range services { 183 if !started[id] { 184 t.Fatalf("service %s: freshly started service not running", id) 185 } 186 if stopped[id] { 187 t.Fatalf("service %s: freshly started service already stopped", id) 188 } 189 } 190 // Stop the node and check that all services have been stopped 191 if err := stack.Stop(); err != nil { 192 t.Fatalf("failed to stop protocol stack: %v", err) 193 } 194 for id := range services { 195 if !stopped[id] { 196 t.Fatalf("service %s: freshly terminated service still running", id) 197 } 198 } 199 } 200 201 // Tests that services are restarted cleanly as new instances. 202 func TestServiceRestarts(t *testing.T) { 203 stack, err := New(testNodeConfig()) 204 if err != nil { 205 t.Fatalf("failed to create protocol stack: %v", err) 206 } 207 defer stack.Close() 208 209 // Define a service that does not support restarts 210 var ( 211 running bool 212 started int 213 ) 214 constructor := func(*ServiceContext) (Service, error) { 215 running = false 216 217 return &InstrumentedService{ 218 startHook: func(*p2p.Server) { 219 if running { 220 panic("already running") 221 } 222 running = true 223 started++ 224 }, 225 }, nil 226 } 227 // Register the service and start the protocol stack 228 if err := stack.Register(constructor); err != nil { 229 t.Fatalf("failed to register the service: %v", err) 230 } 231 if err := stack.Start(); err != nil { 232 t.Fatalf("failed to start protocol stack: %v", err) 233 } 234 defer stack.Stop() 235 236 if !running || started != 1 { 237 t.Fatalf("running/started mismatch: have %v/%d, want true/1", running, started) 238 } 239 // Restart the stack a few times and check successful service restarts 240 for i := 0; i < 3; i++ { 241 if err := stack.Restart(); err != nil { 242 t.Fatalf("iter %d: failed to restart stack: %v", i, err) 243 } 244 } 245 if !running || started != 4 { 246 t.Fatalf("running/started mismatch: have %v/%d, want true/4", running, started) 247 } 248 } 249 250 // Tests that if a service fails to initialize itself, none of the other services 251 // will be allowed to even start. 252 func TestServiceConstructionAbortion(t *testing.T) { 253 stack, err := New(testNodeConfig()) 254 if err != nil { 255 t.Fatalf("failed to create protocol stack: %v", err) 256 } 257 defer stack.Close() 258 259 // Define a batch of good services 260 services := map[string]InstrumentingWrapper{ 261 "A": InstrumentedServiceMakerA, 262 "B": InstrumentedServiceMakerB, 263 "C": InstrumentedServiceMakerC, 264 } 265 started := make(map[string]bool) 266 for id, maker := range services { 267 id := id // Closure for the constructor 268 constructor := func(*ServiceContext) (Service, error) { 269 return &InstrumentedService{ 270 startHook: func(*p2p.Server) { started[id] = true }, 271 }, nil 272 } 273 if err := stack.Register(maker(constructor)); err != nil { 274 t.Fatalf("service %s: registration failed: %v", id, err) 275 } 276 } 277 // Register a service that fails to construct itself 278 failure := errors.New("fail") 279 failer := func(*ServiceContext) (Service, error) { 280 return nil, failure 281 } 282 if err := stack.Register(failer); err != nil { 283 t.Fatalf("failer registration failed: %v", err) 284 } 285 // Start the protocol stack and ensure none of the services get started 286 for i := 0; i < 100; i++ { 287 if err := stack.Start(); err != failure { 288 t.Fatalf("iter %d: stack startup failure mismatch: have %v, want %v", i, err, failure) 289 } 290 for id := range services { 291 if started[id] { 292 t.Fatalf("service %s: started should not have", id) 293 } 294 delete(started, id) 295 } 296 } 297 } 298 299 // Tests that if a service fails to start, all others started before it will be 300 // shut down. 301 func TestServiceStartupAbortion(t *testing.T) { 302 stack, err := New(testNodeConfig()) 303 if err != nil { 304 t.Fatalf("failed to create protocol stack: %v", err) 305 } 306 defer stack.Close() 307 308 // Register a batch of good services 309 services := map[string]InstrumentingWrapper{ 310 "A": InstrumentedServiceMakerA, 311 "B": InstrumentedServiceMakerB, 312 "C": InstrumentedServiceMakerC, 313 } 314 started := make(map[string]bool) 315 stopped := make(map[string]bool) 316 317 for id, maker := range services { 318 id := id // Closure for the constructor 319 constructor := func(*ServiceContext) (Service, error) { 320 return &InstrumentedService{ 321 startHook: func(*p2p.Server) { started[id] = true }, 322 stopHook: func() { stopped[id] = true }, 323 }, nil 324 } 325 if err := stack.Register(maker(constructor)); err != nil { 326 t.Fatalf("service %s: registration failed: %v", id, err) 327 } 328 } 329 // Register a service that fails to start 330 failure := errors.New("fail") 331 failer := func(*ServiceContext) (Service, error) { 332 return &InstrumentedService{ 333 start: failure, 334 }, nil 335 } 336 if err := stack.Register(failer); err != nil { 337 t.Fatalf("failer registration failed: %v", err) 338 } 339 // Start the protocol stack and ensure all started services stop 340 for i := 0; i < 100; i++ { 341 if err := stack.Start(); err != failure { 342 t.Fatalf("iter %d: stack startup failure mismatch: have %v, want %v", i, err, failure) 343 } 344 for id := range services { 345 if started[id] && !stopped[id] { 346 t.Fatalf("service %s: started but not stopped", id) 347 } 348 delete(started, id) 349 delete(stopped, id) 350 } 351 } 352 } 353 354 // Tests that even if a registered service fails to shut down cleanly, it does 355 // not influence the rest of the shutdown invocations. 356 func TestServiceTerminationGuarantee(t *testing.T) { 357 stack, err := New(testNodeConfig()) 358 if err != nil { 359 t.Fatalf("failed to create protocol stack: %v", err) 360 } 361 defer stack.Close() 362 363 // Register a batch of good services 364 services := map[string]InstrumentingWrapper{ 365 "A": InstrumentedServiceMakerA, 366 "B": InstrumentedServiceMakerB, 367 "C": InstrumentedServiceMakerC, 368 } 369 started := make(map[string]bool) 370 stopped := make(map[string]bool) 371 372 for id, maker := range services { 373 id := id // Closure for the constructor 374 constructor := func(*ServiceContext) (Service, error) { 375 return &InstrumentedService{ 376 startHook: func(*p2p.Server) { started[id] = true }, 377 stopHook: func() { stopped[id] = true }, 378 }, nil 379 } 380 if err := stack.Register(maker(constructor)); err != nil { 381 t.Fatalf("service %s: registration failed: %v", id, err) 382 } 383 } 384 // Register a service that fails to shot down cleanly 385 failure := errors.New("fail") 386 failer := func(*ServiceContext) (Service, error) { 387 return &InstrumentedService{ 388 stop: failure, 389 }, nil 390 } 391 if err := stack.Register(failer); err != nil { 392 t.Fatalf("failer registration failed: %v", err) 393 } 394 // Start the protocol stack, and ensure that a failing shut down terminates all 395 for i := 0; i < 100; i++ { 396 // Start the stack and make sure all is online 397 if err := stack.Start(); err != nil { 398 t.Fatalf("iter %d: failed to start protocol stack: %v", i, err) 399 } 400 for id := range services { 401 if !started[id] { 402 t.Fatalf("iter %d, service %s: service not running", i, id) 403 } 404 if stopped[id] { 405 t.Fatalf("iter %d, service %s: service already stopped", i, id) 406 } 407 } 408 // Stop the stack, verify failure and check all terminations 409 err := stack.Stop() 410 if err, ok := err.(*StopError); !ok { 411 t.Fatalf("iter %d: termination failure mismatch: have %v, want StopError", i, err) 412 } else { 413 failer := reflect.TypeOf(&InstrumentedService{}) 414 if err.Services[failer] != failure { 415 t.Fatalf("iter %d: failer termination failure mismatch: have %v, want %v", i, err.Services[failer], failure) 416 } 417 if len(err.Services) != 1 { 418 t.Fatalf("iter %d: failure count mismatch: have %d, want %d", i, len(err.Services), 1) 419 } 420 } 421 for id := range services { 422 if !stopped[id] { 423 t.Fatalf("iter %d, service %s: service not terminated", i, id) 424 } 425 delete(started, id) 426 delete(stopped, id) 427 } 428 } 429 } 430 431 // TestServiceRetrieval tests that individual services can be retrieved. 432 func TestServiceRetrieval(t *testing.T) { 433 // Create a simple stack and register two service types 434 stack, err := New(testNodeConfig()) 435 if err != nil { 436 t.Fatalf("failed to create protocol stack: %v", err) 437 } 438 defer stack.Close() 439 440 if err := stack.Register(NewNoopService); err != nil { 441 t.Fatalf("noop service registration failed: %v", err) 442 } 443 if err := stack.Register(NewInstrumentedService); err != nil { 444 t.Fatalf("instrumented service registration failed: %v", err) 445 } 446 // Make sure none of the services can be retrieved until started 447 var noopServ *NoopService 448 if err := stack.Service(&noopServ); err != ErrNodeStopped { 449 t.Fatalf("noop service retrieval mismatch: have %v, want %v", err, ErrNodeStopped) 450 } 451 var instServ *InstrumentedService 452 if err := stack.Service(&instServ); err != ErrNodeStopped { 453 t.Fatalf("instrumented service retrieval mismatch: have %v, want %v", err, ErrNodeStopped) 454 } 455 // Start the stack and ensure everything is retrievable now 456 if err := stack.Start(); err != nil { 457 t.Fatalf("failed to start stack: %v", err) 458 } 459 defer stack.Stop() 460 461 if err := stack.Service(&noopServ); err != nil { 462 t.Fatalf("noop service retrieval mismatch: have %v, want %v", err, nil) 463 } 464 if err := stack.Service(&instServ); err != nil { 465 t.Fatalf("instrumented service retrieval mismatch: have %v, want %v", err, nil) 466 } 467 } 468 469 // Tests that all protocols defined by individual services get launched. 470 func TestProtocolGather(t *testing.T) { 471 stack, err := New(testNodeConfig()) 472 if err != nil { 473 t.Fatalf("failed to create protocol stack: %v", err) 474 } 475 defer stack.Close() 476 477 // Register a batch of services with some configured number of protocols 478 services := map[string]struct { 479 Count int 480 Maker InstrumentingWrapper 481 }{ 482 "zero": {0, InstrumentedServiceMakerA}, 483 "one": {1, InstrumentedServiceMakerB}, 484 "many": {10, InstrumentedServiceMakerC}, 485 } 486 for id, config := range services { 487 protocols := make([]p2p.Protocol, config.Count) 488 for i := 0; i < len(protocols); i++ { 489 protocols[i].Name = id 490 protocols[i].Version = uint(i) 491 } 492 constructor := func(*ServiceContext) (Service, error) { 493 return &InstrumentedService{ 494 protocols: protocols, 495 }, nil 496 } 497 if err := stack.Register(config.Maker(constructor)); err != nil { 498 t.Fatalf("service %s: registration failed: %v", id, err) 499 } 500 } 501 // Start the services and ensure all protocols start successfully 502 if err := stack.Start(); err != nil { 503 t.Fatalf("failed to start protocol stack: %v", err) 504 } 505 defer stack.Stop() 506 507 protocols := stack.Server().Protocols 508 if len(protocols) != 11 { 509 t.Fatalf("mismatching number of protocols launched: have %d, want %d", len(protocols), 26) 510 } 511 for id, config := range services { 512 for ver := 0; ver < config.Count; ver++ { 513 launched := false 514 for i := 0; i < len(protocols); i++ { 515 if protocols[i].Name == id && protocols[i].Version == uint(ver) { 516 launched = true 517 break 518 } 519 } 520 if !launched { 521 t.Errorf("configured protocol not launched: %s v%d", id, ver) 522 } 523 } 524 } 525 } 526 527 // Tests that all APIs defined by individual services get exposed. 528 func TestAPIGather(t *testing.T) { 529 stack, err := New(testNodeConfig()) 530 if err != nil { 531 t.Fatalf("failed to create protocol stack: %v", err) 532 } 533 defer stack.Close() 534 535 // Register a batch of services with some configured APIs 536 calls := make(chan string, 1) 537 makeAPI := func(result string) *OneMethodAPI { 538 return &OneMethodAPI{fun: func() { calls <- result }} 539 } 540 services := map[string]struct { 541 APIs []rpc.API 542 Maker InstrumentingWrapper 543 }{ 544 "Zero APIs": { 545 []rpc.API{}, InstrumentedServiceMakerA}, 546 "Single API": { 547 []rpc.API{ 548 {Namespace: "single", Version: "1", Service: makeAPI("single.v1"), Public: true}, 549 }, InstrumentedServiceMakerB}, 550 "Many APIs": { 551 []rpc.API{ 552 {Namespace: "multi", Version: "1", Service: makeAPI("multi.v1"), Public: true}, 553 {Namespace: "multi.v2", Version: "2", Service: makeAPI("multi.v2"), Public: true}, 554 {Namespace: "multi.v2.nested", Version: "2", Service: makeAPI("multi.v2.nested"), Public: true}, 555 }, InstrumentedServiceMakerC}, 556 } 557 558 for id, config := range services { 559 config := config 560 constructor := func(*ServiceContext) (Service, error) { 561 return &InstrumentedService{apis: config.APIs}, nil 562 } 563 if err := stack.Register(config.Maker(constructor)); err != nil { 564 t.Fatalf("service %s: registration failed: %v", id, err) 565 } 566 } 567 // Start the services and ensure all API start successfully 568 if err := stack.Start(); err != nil { 569 t.Fatalf("failed to start protocol stack: %v", err) 570 } 571 defer stack.Stop() 572 573 // Connect to the RPC server and verify the various registered endpoints 574 client, err := stack.Attach() 575 if err != nil { 576 t.Fatalf("failed to connect to the inproc API server: %v", err) 577 } 578 defer client.Close() 579 580 tests := []struct { 581 Method string 582 Result string 583 }{ 584 {"single_theOneMethod", "single.v1"}, 585 {"multi_theOneMethod", "multi.v1"}, 586 {"multi.v2_theOneMethod", "multi.v2"}, 587 {"multi.v2.nested_theOneMethod", "multi.v2.nested"}, 588 } 589 for i, test := range tests { 590 if err := client.Call(nil, test.Method); err != nil { 591 t.Errorf("test %d: API request failed: %v", i, err) 592 } 593 select { 594 case result := <-calls: 595 if result != test.Result { 596 t.Errorf("test %d: result mismatch: have %s, want %s", i, result, test.Result) 597 } 598 case <-time.After(time.Second): 599 t.Fatalf("test %d: rpc execution timeout", i) 600 } 601 } 602 } 603 604 func TestWebsocketHTTPOnSamePort_WebsocketRequest(t *testing.T) { 605 node := startHTTP(t) 606 defer node.stopHTTP() 607 608 wsReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:7453", nil) 609 if err != nil { 610 t.Error("could not issue new http request ", err) 611 } 612 wsReq.Header.Set("Connection", "upgrade") 613 wsReq.Header.Set("Upgrade", "websocket") 614 wsReq.Header.Set("Sec-WebSocket-Version", "13") 615 wsReq.Header.Set("Sec-Websocket-Key", "SGVsbG8sIHdvcmxkIQ==") 616 617 resp := doHTTPRequest(t, wsReq) 618 assert.Equal(t, "websocket", resp.Header.Get("Upgrade")) 619 } 620 621 func TestWebsocketHTTPOnSamePort_HTTPRequest(t *testing.T) { 622 node := startHTTP(t) 623 defer node.stopHTTP() 624 625 httpReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:7453", nil) 626 if err != nil { 627 t.Error("could not issue new http request ", err) 628 } 629 httpReq.Header.Set("Accept-Encoding", "gzip") 630 631 resp := doHTTPRequest(t, httpReq) 632 assert.Equal(t, "gzip", resp.Header.Get("Content-Encoding")) 633 } 634 635 func startHTTP(t *testing.T) *Node { 636 conf := &Config{HTTPPort: 7453, WSPort: 7453} 637 node, err := New(conf) 638 if err != nil { 639 t.Error("could not create a new node ", err) 640 } 641 642 err = node.startHTTP("127.0.0.1:7453", []rpc.API{}, []string{}, []string{}, []string{}, rpc.HTTPTimeouts{}, []string{}) 643 if err != nil { 644 t.Error("could not start http service on node ", err) 645 } 646 647 return node 648 } 649 650 func doHTTPRequest(t *testing.T, req *http.Request) *http.Response { 651 client := &http.Client{} 652 resp, err := client.Do(req) 653 if err != nil { 654 t.Error("could not issue a GET request to the given endpoint", err) 655 } 656 return resp 657 }