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  }