diff options
Diffstat (limited to 'node/node_test.go')
-rw-r--r-- | node/node_test.go | 101 |
1 files changed, 90 insertions, 11 deletions
diff --git a/node/node_test.go b/node/node_test.go index ef096fc91..53dcbcf74 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -18,27 +18,34 @@ package node import ( "errors" + "fmt" "io/ioutil" + "math/rand" "os" "reflect" "testing" + "time" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/rpc" ) var ( testNodeKey, _ = crypto.GenerateKey() +) - testNodeConfig = &Config{ +func testNodeConfig() *Config { + return &Config{ + IpcPath: fmt.Sprintf("test-%d.ipc", rand.Int63()), PrivateKey: testNodeKey, Name: "test node", } -) +} // Tests that an empty protocol stack can be started, restarted and stopped. func TestNodeLifeCycle(t *testing.T) { - stack, err := New(testNodeConfig) + stack, err := New(testNodeConfig()) if err != nil { t.Fatalf("failed to create protocol stack: %v", err) } @@ -101,7 +108,7 @@ func TestNodeUsedDataDir(t *testing.T) { // Tests whether services can be registered and duplicates caught. func TestServiceRegistry(t *testing.T) { - stack, err := New(testNodeConfig) + stack, err := New(testNodeConfig()) if err != nil { t.Fatalf("failed to create protocol stack: %v", err) } @@ -133,7 +140,7 @@ func TestServiceRegistry(t *testing.T) { // Tests that registered services get started and stopped correctly. func TestServiceLifeCycle(t *testing.T) { - stack, err := New(testNodeConfig) + stack, err := New(testNodeConfig()) if err != nil { t.Fatalf("failed to create protocol stack: %v", err) } @@ -183,7 +190,7 @@ func TestServiceLifeCycle(t *testing.T) { // Tests that services are restarted cleanly as new instances. func TestServiceRestarts(t *testing.T) { - stack, err := New(testNodeConfig) + stack, err := New(testNodeConfig()) if err != nil { t.Fatalf("failed to create protocol stack: %v", err) } @@ -231,7 +238,7 @@ func TestServiceRestarts(t *testing.T) { // Tests that if a service fails to initialize itself, none of the other services // will be allowed to even start. func TestServiceConstructionAbortion(t *testing.T) { - stack, err := New(testNodeConfig) + stack, err := New(testNodeConfig()) if err != nil { t.Fatalf("failed to create protocol stack: %v", err) } @@ -278,7 +285,7 @@ func TestServiceConstructionAbortion(t *testing.T) { // Tests that if a service fails to start, all others started before it will be // shut down. func TestServiceStartupAbortion(t *testing.T) { - stack, err := New(testNodeConfig) + stack, err := New(testNodeConfig()) if err != nil { t.Fatalf("failed to create protocol stack: %v", err) } @@ -331,7 +338,7 @@ func TestServiceStartupAbortion(t *testing.T) { // Tests that even if a registered service fails to shut down cleanly, it does // not influece the rest of the shutdown invocations. func TestServiceTerminationGuarantee(t *testing.T) { - stack, err := New(testNodeConfig) + stack, err := New(testNodeConfig()) if err != nil { t.Fatalf("failed to create protocol stack: %v", err) } @@ -406,7 +413,7 @@ func TestServiceTerminationGuarantee(t *testing.T) { // TestServiceRetrieval tests that individual services can be retrieved. func TestServiceRetrieval(t *testing.T) { // Create a simple stack and register two service types - stack, err := New(testNodeConfig) + stack, err := New(testNodeConfig()) if err != nil { t.Fatalf("failed to create protocol stack: %v", err) } @@ -441,7 +448,7 @@ func TestServiceRetrieval(t *testing.T) { // Tests that all protocols defined by individual services get launched. func TestProtocolGather(t *testing.T) { - stack, err := New(testNodeConfig) + stack, err := New(testNodeConfig()) if err != nil { t.Fatalf("failed to create protocol stack: %v", err) } @@ -494,3 +501,75 @@ func TestProtocolGather(t *testing.T) { } } } + +// Tests that all APIs defined by individual services get exposed. +func TestAPIGather(t *testing.T) { + stack, err := New(testNodeConfig()) + if err != nil { + t.Fatalf("failed to create protocol stack: %v", err) + } + // Register a batch of services with some configured APIs + calls := make(chan string, 1) + + services := map[string]struct { + APIs []rpc.API + Maker InstrumentingWrapper + }{ + "Zero APIs": {[]rpc.API{}, InstrumentedServiceMakerA}, + "Single API": {[]rpc.API{ + {"single", "1", &OneMethodApi{fun: func() { calls <- "single.v1" }}, true}, + }, InstrumentedServiceMakerB}, + "Many APIs": {[]rpc.API{ + {"multi", "1", &OneMethodApi{fun: func() { calls <- "multi.v1" }}, true}, + {"multi.v2", "2", &OneMethodApi{fun: func() { calls <- "multi.v2" }}, true}, + {"multi.v2.nested", "2", &OneMethodApi{fun: func() { calls <- "multi.v2.nested" }}, true}, + }, InstrumentedServiceMakerC}, + } + for id, config := range services { + config := config + constructor := func(*ServiceContext) (Service, error) { + return &InstrumentedService{apis: config.APIs}, nil + } + if err := stack.Register(config.Maker(constructor)); err != nil { + t.Fatalf("service %s: registration failed: %v", id, err) + } + } + // Start the services and ensure all API start successfully + if err := stack.Start(); err != nil { + t.Fatalf("failed to start protocol stack: %v", err) + } + defer stack.Stop() + + // Connect to the RPC server and verify the various registered endpoints + ipcClient, err := rpc.NewIPCClient(stack.IpcEndpoint()) + if err != nil { + t.Fatalf("failed to connect to the IPC API server: %v", err) + } + + tests := []struct { + Method string + Result string + }{ + {"single_theOneMethod", "single.v1"}, + {"multi_theOneMethod", "multi.v1"}, + {"multi.v2_theOneMethod", "multi.v2"}, + {"multi.v2.nested_theOneMethod", "multi.v2.nested"}, + } + for i, test := range tests { + if err := ipcClient.Send(rpc.JSONRequest{Id: new(int64), Version: "2.0", Method: test.Method}); err != nil { + t.Fatalf("test %d: failed to send API request: %v", i, err) + } + reply := new(rpc.JSONSuccessResponse) + if err := ipcClient.Recv(reply); err != nil { + t.Fatalf("test %d: failed to read API reply: %v", i, err) + } + select { + case result := <-calls: + if result != test.Result { + t.Errorf("test %d: result mismatch: have %s, want %s", i, result, test.Result) + } + case <-time.After(time.Second): + t.Fatalf("test %d: rpc execution timeout", i) + } + } +} |