github.com/r8d8/go-ethereum@v5.5.2+incompatible/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 "reflect" 22 "testing" 23 "time" 24 25 "github.com/ethereumproject/go-ethereum/crypto" 26 "github.com/ethereumproject/go-ethereum/logger/glog" 27 "github.com/ethereumproject/go-ethereum/p2p" 28 "github.com/ethereumproject/go-ethereum/rpc" 29 "github.com/spf13/afero" 30 ) 31 32 var ( 33 testNodeKey, _ = crypto.GenerateKey() 34 ) 35 36 func init() { 37 glog.SetD(0) 38 glog.SetV(0) 39 } 40 41 func testNodeConfig() *Config { 42 return &Config{ 43 PrivateKey: testNodeKey, 44 Name: "test node", 45 fs: &fs{afero.NewMemMapFs()}, 46 } 47 } 48 49 // Tests that an empty protocol stack can be started, restarted and stopped. 50 func TestNodeLifeCycle(t *testing.T) { 51 stack, err := New(testNodeConfig()) 52 if err != nil { 53 t.Fatalf("failed to create protocol stack: %v", err) 54 } 55 // Ensure that a stopped node can be stopped again 56 for i := 0; i < 3; i++ { 57 if err := stack.Stop(); err != ErrNodeStopped { 58 t.Fatalf("iter %d: stop failure mismatch: have %v, want %v", i, err, ErrNodeStopped) 59 } 60 } 61 // Ensure that a node can be successfully started, but only once 62 if err := stack.Start(); err != nil { 63 t.Fatalf("failed to start node: %v", err) 64 } 65 if err := stack.Start(); err != ErrNodeRunning { 66 t.Fatalf("start failure mismatch: have %v, want %v ", err, ErrNodeRunning) 67 } 68 // Ensure that a node can be restarted arbitrarily many times 69 for i := 0; i < 3; i++ { 70 if err := stack.Restart(); err != nil { 71 t.Fatalf("iter %d: failed to restart node: %v", i, err) 72 } 73 } 74 // Ensure that a node can be stopped, but only once 75 if err := stack.Stop(); err != nil { 76 t.Fatalf("failed to stop node: %v", err) 77 } 78 if err := stack.Stop(); err != ErrNodeStopped { 79 t.Fatalf("stop failure mismatch: have %v, want %v ", err, ErrNodeStopped) 80 } 81 } 82 83 // Tests that if the data dir is already in use, an appropriate error is returned. 84 func TestNodeUsedDataDir(t *testing.T) { 85 afs := afero.NewMemMapFs() 86 // Create a temporary folder to use as the data directory 87 dir, err := afero.TempDir(afs, "", "") 88 if err != nil { 89 t.Fatalf("failed to create temporary data directory: %v", err) 90 } 91 defer afs.RemoveAll(dir) 92 93 // Create a new node based on the data directory 94 original, err := New(&Config{DataDir: dir, fs: &fs{afs}}) 95 if err != nil { 96 t.Fatalf("failed to create original protocol stack: %v", err) 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, fs: &fs{afs}}) 105 if err != nil { 106 t.Fatalf("failed to create duplicate protocol stack: %v", err) 107 } 108 if err := duplicate.Start(); err != ErrDatadirUsed { 109 t.Fatalf("duplicate datadir failure mismatch: have %v, want %v", err, ErrDatadirUsed) 110 } 111 } 112 113 // Tests whether services can be registered and duplicates caught. 114 func TestServiceRegistry(t *testing.T) { 115 stack, err := New(testNodeConfig()) 116 if err != nil { 117 t.Fatalf("failed to create protocol stack: %v", err) 118 } 119 // Register a batch of unique services and ensure they start successfully 120 services := []ServiceConstructor{NewNoopServiceA, NewNoopServiceB, NewNoopServiceC} 121 for i, constructor := range services { 122 if err := stack.Register(constructor); err != nil { 123 t.Fatalf("service #%d: registration failed: %v", i, err) 124 } 125 } 126 if err := stack.Start(); err != nil { 127 t.Fatalf("failed to start original service stack: %v", err) 128 } 129 if err := stack.Stop(); err != nil { 130 t.Fatalf("failed to stop original service stack: %v", err) 131 } 132 // Duplicate one of the services and retry starting the node 133 if err := stack.Register(NewNoopServiceB); err != nil { 134 t.Fatalf("duplicate registration failed: %v", err) 135 } 136 if err := stack.Start(); err == nil { 137 t.Fatalf("duplicate service started") 138 } else { 139 if _, ok := err.(*DuplicateServiceError); !ok { 140 t.Fatalf("duplicate error mismatch: have %v, want %v", err, DuplicateServiceError{}) 141 } 142 } 143 } 144 145 // Tests that registered services get started and stopped correctly. 146 func TestServiceLifeCycle(t *testing.T) { 147 stack, err := New(testNodeConfig()) 148 if err != nil { 149 t.Fatalf("failed to create protocol stack: %v", err) 150 } 151 // Register a batch of life-cycle instrumented services 152 services := map[string]InstrumentingWrapper{ 153 "A": InstrumentedServiceMakerA, 154 "B": InstrumentedServiceMakerB, 155 "C": InstrumentedServiceMakerC, 156 } 157 started := make(map[string]bool) 158 stopped := make(map[string]bool) 159 160 for id, maker := range services { 161 id := id // Closure for the constructor 162 constructor := func(*ServiceContext) (Service, error) { 163 return &InstrumentedService{ 164 startHook: func(*p2p.Server) { started[id] = true }, 165 stopHook: func() { stopped[id] = true }, 166 }, nil 167 } 168 if err := stack.Register(maker(constructor)); err != nil { 169 t.Fatalf("service %s: registration failed: %v", id, err) 170 } 171 } 172 // Start the node and check that all services are running 173 if err := stack.Start(); err != nil { 174 t.Fatalf("failed to start protocol stack: %v", err) 175 } 176 for id := range services { 177 if !started[id] { 178 t.Fatalf("service %s: freshly started service not running", id) 179 } 180 if stopped[id] { 181 t.Fatalf("service %s: freshly started service already stopped", id) 182 } 183 } 184 // Stop the node and check that all services have been stopped 185 if err := stack.Stop(); err != nil { 186 t.Fatalf("failed to stop protocol stack: %v", err) 187 } 188 for id := range services { 189 if !stopped[id] { 190 t.Fatalf("service %s: freshly terminated service still running", id) 191 } 192 } 193 } 194 195 // Tests that services are restarted cleanly as new instances. 196 func TestServiceRestarts(t *testing.T) { 197 stack, err := New(testNodeConfig()) 198 if err != nil { 199 t.Fatalf("failed to create protocol stack: %v", err) 200 } 201 // Define a service that does not support restarts 202 var ( 203 running bool 204 started int 205 ) 206 constructor := func(*ServiceContext) (Service, error) { 207 running = false 208 209 return &InstrumentedService{ 210 startHook: func(*p2p.Server) { 211 if running { 212 panic("already running") 213 } 214 running = true 215 started++ 216 }, 217 }, nil 218 } 219 // Register the service and start the protocol stack 220 if err := stack.Register(constructor); err != nil { 221 t.Fatalf("failed to register the service: %v", err) 222 } 223 if err := stack.Start(); err != nil { 224 t.Fatalf("failed to start protocol stack: %v", err) 225 } 226 defer stack.Stop() 227 228 if running != true || started != 1 { 229 t.Fatalf("running/started mismatch: have %v/%d, want true/1", running, started) 230 } 231 // Restart the stack a few times and check successful service restarts 232 for i := 0; i < 3; i++ { 233 if err := stack.Restart(); err != nil { 234 t.Fatalf("iter %d: failed to restart stack: %v", i, err) 235 } 236 } 237 if running != true || started != 4 { 238 t.Fatalf("running/started mismatch: have %v/%d, want true/4", running, started) 239 } 240 } 241 242 // Tests that if a service fails to initialize itself, none of the other services 243 // will be allowed to even start. 244 func TestServiceConstructionAbortion(t *testing.T) { 245 stack, err := New(testNodeConfig()) 246 if err != nil { 247 t.Fatalf("failed to create protocol stack: %v", err) 248 } 249 // Define a batch of good services 250 services := map[string]InstrumentingWrapper{ 251 "A": InstrumentedServiceMakerA, 252 "B": InstrumentedServiceMakerB, 253 "C": InstrumentedServiceMakerC, 254 } 255 started := make(map[string]bool) 256 for id, maker := range services { 257 id := id // Closure for the constructor 258 constructor := func(*ServiceContext) (Service, error) { 259 return &InstrumentedService{ 260 startHook: func(*p2p.Server) { started[id] = true }, 261 }, nil 262 } 263 if err := stack.Register(maker(constructor)); err != nil { 264 t.Fatalf("service %s: registration failed: %v", id, err) 265 } 266 } 267 // Register a service that fails to construct itself 268 failure := errors.New("fail") 269 failer := func(*ServiceContext) (Service, error) { 270 return nil, failure 271 } 272 if err := stack.Register(failer); err != nil { 273 t.Fatalf("failer registration failed: %v", err) 274 } 275 // Start the protocol stack and ensure none of the services get started 276 for i := 0; i < 100; i++ { 277 if err := stack.Start(); err != failure { 278 t.Fatalf("iter %d: stack startup failure mismatch: have %v, want %v", i, err, failure) 279 } 280 for id := range services { 281 if started[id] { 282 t.Fatalf("service %s: started should not have", id) 283 } 284 delete(started, id) 285 } 286 } 287 } 288 289 // Tests that if a service fails to start, all others started before it will be 290 // shut down. 291 func TestServiceStartupAbortion(t *testing.T) { 292 stack, err := New(testNodeConfig()) 293 if err != nil { 294 t.Fatalf("failed to create protocol stack: %v", err) 295 } 296 // Register a batch of good services 297 services := map[string]InstrumentingWrapper{ 298 "A": InstrumentedServiceMakerA, 299 "B": InstrumentedServiceMakerB, 300 "C": InstrumentedServiceMakerC, 301 } 302 started := make(map[string]bool) 303 stopped := make(map[string]bool) 304 305 for id, maker := range services { 306 id := id // Closure for the constructor 307 constructor := func(*ServiceContext) (Service, error) { 308 return &InstrumentedService{ 309 startHook: func(*p2p.Server) { started[id] = true }, 310 stopHook: func() { stopped[id] = true }, 311 }, nil 312 } 313 if err := stack.Register(maker(constructor)); err != nil { 314 t.Fatalf("service %s: registration failed: %v", id, err) 315 } 316 } 317 // Register a service that fails to start 318 failure := errors.New("fail") 319 failer := func(*ServiceContext) (Service, error) { 320 return &InstrumentedService{ 321 start: failure, 322 }, nil 323 } 324 if err := stack.Register(failer); err != nil { 325 t.Fatalf("failer registration failed: %v", err) 326 } 327 // Start the protocol stack and ensure all started services stop 328 for i := 0; i < 100; i++ { 329 if err := stack.Start(); err != failure { 330 t.Fatalf("iter %d: stack startup failure mismatch: have %v, want %v", i, err, failure) 331 } 332 for id := range services { 333 if started[id] && !stopped[id] { 334 t.Fatalf("service %s: started but not stopped", id) 335 } 336 delete(started, id) 337 delete(stopped, id) 338 } 339 } 340 } 341 342 // Tests that even if a registered service fails to shut down cleanly, it does 343 // not influece the rest of the shutdown invocations. 344 func TestServiceTerminationGuarantee(t *testing.T) { 345 stack, err := New(testNodeConfig()) 346 if err != nil { 347 t.Fatalf("failed to create protocol stack: %v", err) 348 } 349 // Register a batch of good services 350 services := map[string]InstrumentingWrapper{ 351 "A": InstrumentedServiceMakerA, 352 "B": InstrumentedServiceMakerB, 353 "C": InstrumentedServiceMakerC, 354 } 355 started := make(map[string]bool) 356 stopped := make(map[string]bool) 357 358 for id, maker := range services { 359 id := id // Closure for the constructor 360 constructor := func(*ServiceContext) (Service, error) { 361 return &InstrumentedService{ 362 startHook: func(*p2p.Server) { started[id] = true }, 363 stopHook: func() { stopped[id] = true }, 364 }, nil 365 } 366 if err := stack.Register(maker(constructor)); err != nil { 367 t.Fatalf("service %s: registration failed: %v", id, err) 368 } 369 } 370 // Register a service that fails to shot down cleanly 371 failure := errors.New("fail") 372 failer := func(*ServiceContext) (Service, error) { 373 return &InstrumentedService{ 374 stop: failure, 375 }, nil 376 } 377 if err := stack.Register(failer); err != nil { 378 t.Fatalf("failer registration failed: %v", err) 379 } 380 // Start the protocol stack, and ensure that a failing shut down terminates all 381 for i := 0; i < 100; i++ { 382 // Start the stack and make sure all is online 383 if err := stack.Start(); err != nil { 384 t.Fatalf("iter %d: failed to start protocol stack: %v", i, err) 385 } 386 for id := range services { 387 if !started[id] { 388 t.Fatalf("iter %d, service %s: service not running", i, id) 389 } 390 if stopped[id] { 391 t.Fatalf("iter %d, service %s: service already stopped", i, id) 392 } 393 } 394 // Stop the stack, verify failure and check all terminations 395 err := stack.Stop() 396 if err, ok := err.(*StopError); !ok { 397 t.Fatalf("iter %d: termination failure mismatch: have %v, want StopError", i, err) 398 } else { 399 failer := reflect.TypeOf(&InstrumentedService{}) 400 if err.Services[failer] != failure { 401 t.Fatalf("iter %d: failer termination failure mismatch: have %v, want %v", i, err.Services[failer], failure) 402 } 403 if len(err.Services) != 1 { 404 t.Fatalf("iter %d: failure count mismatch: have %d, want %d", i, len(err.Services), 1) 405 } 406 } 407 for id := range services { 408 if !stopped[id] { 409 t.Fatalf("iter %d, service %s: service not terminated", i, id) 410 } 411 delete(started, id) 412 delete(stopped, id) 413 } 414 } 415 } 416 417 // TestServiceRetrieval tests that individual services can be retrieved. 418 func TestServiceRetrieval(t *testing.T) { 419 // Create a simple stack and register two service types 420 stack, err := New(testNodeConfig()) 421 if err != nil { 422 t.Fatalf("failed to create protocol stack: %v", err) 423 } 424 if err := stack.Register(NewNoopService); err != nil { 425 t.Fatalf("noop service registration failed: %v", err) 426 } 427 if err := stack.Register(NewInstrumentedService); err != nil { 428 t.Fatalf("instrumented service registration failed: %v", err) 429 } 430 // Make sure none of the services can be retrieved until started 431 var noopServ *NoopService 432 if err := stack.Service(&noopServ); err != ErrNodeStopped { 433 t.Fatalf("noop service retrieval mismatch: have %v, want %v", err, ErrNodeStopped) 434 } 435 var instServ *InstrumentedService 436 if err := stack.Service(&instServ); err != ErrNodeStopped { 437 t.Fatalf("instrumented service retrieval mismatch: have %v, want %v", err, ErrNodeStopped) 438 } 439 // Start the stack and ensure everything is retrievable now 440 if err := stack.Start(); err != nil { 441 t.Fatalf("failed to start stack: %v", err) 442 } 443 defer stack.Stop() 444 445 if err := stack.Service(&noopServ); err != nil { 446 t.Fatalf("noop service retrieval mismatch: have %v, want %v", err, nil) 447 } 448 if err := stack.Service(&instServ); err != nil { 449 t.Fatalf("instrumented service retrieval mismatch: have %v, want %v", err, nil) 450 } 451 } 452 453 // Tests that all protocols defined by individual services get launched. 454 func TestProtocolGather(t *testing.T) { 455 stack, err := New(testNodeConfig()) 456 if err != nil { 457 t.Fatalf("failed to create protocol stack: %v", err) 458 } 459 // Register a batch of services with some configured number of protocols 460 services := map[string]struct { 461 Count int 462 Maker InstrumentingWrapper 463 }{ 464 "Zero Protocols": {0, InstrumentedServiceMakerA}, 465 "Single Protocol": {1, InstrumentedServiceMakerB}, 466 "Many Protocols": {25, InstrumentedServiceMakerC}, 467 } 468 for id, config := range services { 469 protocols := make([]p2p.Protocol, config.Count) 470 for i := 0; i < len(protocols); i++ { 471 protocols[i].Name = id 472 protocols[i].Version = uint(i) 473 } 474 constructor := func(*ServiceContext) (Service, error) { 475 return &InstrumentedService{ 476 protocols: protocols, 477 }, nil 478 } 479 if err := stack.Register(config.Maker(constructor)); err != nil { 480 t.Fatalf("service %s: registration failed: %v", id, err) 481 } 482 } 483 // Start the services and ensure all protocols start successfully 484 if err := stack.Start(); err != nil { 485 t.Fatalf("failed to start protocol stack: %v", err) 486 } 487 defer stack.Stop() 488 489 protocols := stack.Server().Protocols 490 if len(protocols) != 26 { 491 t.Fatalf("mismatching number of protocols launched: have %d, want %d", len(protocols), 26) 492 } 493 for id, config := range services { 494 for ver := 0; ver < config.Count; ver++ { 495 launched := false 496 for i := 0; i < len(protocols); i++ { 497 if protocols[i].Name == id && protocols[i].Version == uint(ver) { 498 launched = true 499 break 500 } 501 } 502 if !launched { 503 t.Errorf("configured protocol not launched: %s v%d", id, ver) 504 } 505 } 506 } 507 } 508 509 // Tests that all APIs defined by individual services get exposed. 510 func TestAPIGather(t *testing.T) { 511 stack, err := New(testNodeConfig()) 512 if err != nil { 513 t.Fatalf("failed to create protocol stack: %v", err) 514 } 515 // Register a batch of services with some configured APIs 516 calls := make(chan string, 1) 517 518 services := map[string]struct { 519 APIs []rpc.API 520 Maker InstrumentingWrapper 521 }{ 522 "Zero APIs": {[]rpc.API{}, InstrumentedServiceMakerA}, 523 "Single API": {[]rpc.API{ 524 { 525 Namespace: "single", 526 Version: "1", 527 Service: &OneMethodApi{fun: func() { calls <- "single.v1" }}, 528 Public: true, 529 }, 530 }, InstrumentedServiceMakerB}, 531 "Many APIs": {[]rpc.API{ 532 { 533 Namespace: "multi", 534 Version: "1", 535 Service: &OneMethodApi{fun: func() { calls <- "multi.v1" }}, 536 Public: true, 537 }, 538 { 539 Namespace: "multi.v2", 540 Version: "2", 541 Service: &OneMethodApi{fun: func() { calls <- "multi.v2" }}, 542 Public: true, 543 }, 544 { 545 Namespace: "multi.v2.nested", 546 Version: "2", 547 Service: &OneMethodApi{fun: func() { calls <- "multi.v2.nested" }}, 548 Public: true, 549 }, 550 }, InstrumentedServiceMakerC}, 551 } 552 for id, config := range services { 553 config := config 554 constructor := func(*ServiceContext) (Service, error) { 555 return &InstrumentedService{apis: config.APIs}, nil 556 } 557 if err := stack.Register(config.Maker(constructor)); err != nil { 558 t.Fatalf("service %s: registration failed: %v", id, err) 559 } 560 } 561 // Start the services and ensure all API start successfully 562 if err := stack.Start(); err != nil { 563 t.Fatalf("failed to start protocol stack: %v", err) 564 } 565 defer stack.Stop() 566 567 // Connect to the RPC server and verify the various registered endpoints 568 client, err := stack.Attach() 569 if err != nil { 570 t.Fatalf("failed to connect to the inproc API server: %v", err) 571 } 572 defer client.Close() 573 574 tests := []struct { 575 Method string 576 Result string 577 }{ 578 {"single_theOneMethod", "single.v1"}, 579 {"multi_theOneMethod", "multi.v1"}, 580 {"multi.v2_theOneMethod", "multi.v2"}, 581 {"multi.v2.nested_theOneMethod", "multi.v2.nested"}, 582 } 583 for i, test := range tests { 584 if err := client.Send(rpc.JSONRequest{Id: []byte("1"), Version: "2.0", Method: test.Method}); err != nil { 585 t.Fatalf("test %d: failed to send API request: %v", i, err) 586 } 587 reply := new(rpc.JSONResponse) 588 if err := client.Recv(reply); err != nil { 589 t.Fatalf("test %d: failed to read API reply: %v", i, err) 590 } 591 select { 592 case result := <-calls: 593 if result != test.Result { 594 t.Errorf("test %d: result mismatch: have %s, want %s", i, result, test.Result) 595 } 596 case <-time.After(time.Second): 597 t.Fatalf("test %d: rpc execution timeout", i) 598 } 599 } 600 }