github.com/shyftnetwork/go-empyrean@v1.8.3-0.20191127201940-fbfca9338f04/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 "os" 23 "reflect" 24 "testing" 25 "time" 26 27 "math/big" 28 29 "github.com/ShyftNetwork/go-empyrean/accounts/abi/bind" 30 "github.com/ShyftNetwork/go-empyrean/accounts/abi/bind/backends" 31 "github.com/ShyftNetwork/go-empyrean/core" 32 "github.com/ShyftNetwork/go-empyrean/crypto" 33 "github.com/ShyftNetwork/go-empyrean/generated_bindings" 34 "github.com/ShyftNetwork/go-empyrean/p2p" 35 "github.com/ShyftNetwork/go-empyrean/rpc" 36 whisper "github.com/ShyftNetwork/go-empyrean/whisper/whisperv6" 37 ) 38 39 var ( 40 testNodeKey, _ = crypto.GenerateKey() 41 ) 42 43 func testNodeConfig() *Config { 44 return &Config{ 45 Name: "test node", 46 P2P: p2p.Config{PrivateKey: testNodeKey}, 47 } 48 } 49 50 // Tests that an empty protocol stack can be started, restarted and stopped. 51 func TestNodeLifeCycle(t *testing.T) { 52 stack, err := New(testNodeConfig()) 53 if err != nil { 54 t.Fatalf("failed to create protocol stack: %v", err) 55 } 56 // Ensure that a stopped node can be stopped again 57 for i := 0; i < 3; i++ { 58 if err := stack.Stop(); err != ErrNodeStopped { 59 t.Fatalf("iter %d: stop failure mismatch: have %v, want %v", i, err, ErrNodeStopped) 60 } 61 } 62 // Ensure that a node can be successfully started, but only once 63 if err := stack.Start(); err != nil { 64 t.Fatalf("failed to start node: %v", err) 65 } 66 if err := stack.Start(); err != ErrNodeRunning { 67 t.Fatalf("start failure mismatch: have %v, want %v ", err, ErrNodeRunning) 68 } 69 // Ensure that a node can be restarted arbitrarily many times 70 for i := 0; i < 3; i++ { 71 if err := stack.Restart(); err != nil { 72 t.Fatalf("iter %d: failed to restart node: %v", i, err) 73 } 74 } 75 // Ensure that a node can be stopped, but only once 76 if err := stack.Stop(); err != nil { 77 t.Fatalf("failed to stop node: %v", err) 78 } 79 if err := stack.Stop(); err != ErrNodeStopped { 80 t.Fatalf("stop failure mismatch: have %v, want %v ", err, ErrNodeStopped) 81 } 82 } 83 84 // Tests that if the data dir is already in use, an appropriate error is returned. 85 func TestNodeUsedDataDir(t *testing.T) { 86 // Create a temporary folder to use as the data directory 87 dir, err := ioutil.TempDir("", "") 88 if err != nil { 89 t.Fatalf("failed to create temporary data directory: %v", err) 90 } 91 defer os.RemoveAll(dir) 92 93 // Create a new node based on the data directory 94 original, err := New(&Config{DataDir: dir}) 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}) 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 || 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 || 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": {0, InstrumentedServiceMakerA}, 465 "one": {1, InstrumentedServiceMakerB}, 466 "many": {10, 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) != 11 { 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 makeAPI := func(result string) *OneMethodAPI { 518 return &OneMethodAPI{fun: func() { calls <- result }} 519 } 520 services := map[string]struct { 521 APIs []rpc.API 522 Maker InstrumentingWrapper 523 }{ 524 "Zero APIs": { 525 []rpc.API{}, InstrumentedServiceMakerA}, 526 "Single API": { 527 []rpc.API{ 528 {Namespace: "single", Version: "1", Service: makeAPI("single.v1"), Public: true}, 529 }, InstrumentedServiceMakerB}, 530 "Many APIs": { 531 []rpc.API{ 532 {Namespace: "multi", Version: "1", Service: makeAPI("multi.v1"), Public: true}, 533 {Namespace: "multi.v2", Version: "2", Service: makeAPI("multi.v2"), Public: true}, 534 {Namespace: "multi.v2.nested", Version: "2", Service: makeAPI("multi.v2.nested"), Public: true}, 535 }, InstrumentedServiceMakerC}, 536 } 537 538 for id, config := range services { 539 config := config 540 constructor := func(*ServiceContext) (Service, error) { 541 return &InstrumentedService{apis: config.APIs}, nil 542 } 543 if err := stack.Register(config.Maker(constructor)); err != nil { 544 t.Fatalf("service %s: registration failed: %v", id, err) 545 } 546 } 547 // Start the services and ensure all API start successfully 548 if err := stack.Start(); err != nil { 549 t.Fatalf("failed to start protocol stack: %v", err) 550 } 551 defer stack.Stop() 552 553 // Connect to the RPC server and verify the various registered endpoints 554 client, err := stack.Attach() 555 if err != nil { 556 t.Fatalf("failed to connect to the inproc API server: %v", err) 557 } 558 defer client.Close() 559 560 tests := []struct { 561 Method string 562 Result string 563 }{ 564 {"single_theOneMethod", "single.v1"}, 565 {"multi_theOneMethod", "multi.v1"}, 566 {"multi.v2_theOneMethod", "multi.v2"}, 567 {"multi.v2.nested_theOneMethod", "multi.v2.nested"}, 568 } 569 for i, test := range tests { 570 if err := client.Call(nil, test.Method); err != nil { 571 t.Errorf("test %d: API request failed: %v", i, err) 572 } 573 select { 574 case result := <-calls: 575 if result != test.Result { 576 t.Errorf("test %d: result mismatch: have %s, want %s", i, result, test.Result) 577 } 578 case <-time.After(time.Second): 579 t.Fatalf("test %d: rpc execution timeout", i) 580 } 581 } 582 } 583 584 // for stubbing purposes 585 type TestType struct { 586 str string 587 } 588 589 func (sub *TestType) Unsubscribe() { 590 // stub 591 } 592 593 func (sub *TestType) Err() <-chan error { 594 return make(chan error, 1) 595 } 596 597 func TestWhisperChannels(t *testing.T) { 598 stack, err := New(testNodeConfig()) 599 if err != nil { 600 t.Fatalf("failed to create protocol stack: %v", err) 601 } 602 var sub *TestType = &TestType{"foo"} 603 messages := make(chan *whisper.Message) 604 605 // signer of the test messages 606 testAddrA := "0x7dA99dF96259305Ee38c9fA9E9D551118B12eC3b" 607 608 stack.config.WhisperKeys = append(stack.config.WhisperKeys, testAddrA) 609 stack.config.WhisperSignersContract = "" 610 stack.config.WhisperChannel = make(chan string) 611 612 go stack.whisperMessageReceiver(sub, messages) 613 msg := &whisper.Message{ 614 // valid signature for "notablockhash" for the testAddr 615 Payload: []byte("notablockhash--0x5944a150e7cc2d77cd47d94dfe7665c7921768d4eb8a1479026751e7574e70d37a8b5ba5ec55111572ea30a9c9d9504efebdd8311b7b6bad05c4fd48e51bd3841c"), 616 } 617 618 messages <- msg 619 resp := <-stack.config.WhisperChannel 620 if "notablockhash" != resp { 621 t.Errorf("result mismatch: have %s, want %s", resp, testAddrA) 622 } 623 } 624 625 func TestCheckContractAdminStatus(t *testing.T) { 626 key0, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 627 addr0 := crypto.PubkeyToAddress(key0.PublicKey) 628 deployTransactor := bind.NewKeyedTransactor(key0) 629 backend := backends.NewSimulatedBackend(core.GenesisAlloc{addr0: {Balance: big.NewInt(1000000000)}}, 10000000) 630 addr, _, _, err := shyft_contracts.DeployValidSigners(deployTransactor, backend) 631 if err != nil { 632 t.Errorf("Deploy Valid Signers Contract failed %+v \n", err) 633 } 634 t.Log("add is ", addr) 635 stack, err := New(testNodeConfig()) 636 if err != nil { 637 t.Fatalf("failed to create protocol stack: %v", err) 638 } 639 result := stack.CheckContractAdminStatus(addr0, backend) 640 641 if result { 642 t.Errorf("result mismatch: have %v, want %v", result, false) 643 } 644 }