github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/node/utils_test.go (about)

     1  // Copyright 2015 The Spectrum Authors
     2  // This file is part of the Spectrum library.
     3  //
     4  // The Spectrum 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 Spectrum 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 Spectrum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Contains a batch of utility type declarations used by the tests. As the node
    18  // operates on unique types, a lot of them are needed to check various features.
    19  
    20  package node
    21  
    22  import (
    23  	"reflect"
    24  
    25  	"github.com/SmartMeshFoundation/Spectrum/p2p"
    26  	"github.com/SmartMeshFoundation/Spectrum/rpc"
    27  )
    28  
    29  // NoopService is a trivial implementation of the Service interface.
    30  type NoopService struct{}
    31  
    32  func (s *NoopService) Protocols() []p2p.Protocol { return nil }
    33  func (s *NoopService) APIs() []rpc.API           { return nil }
    34  func (s *NoopService) Start(*p2p.Server) error   { return nil }
    35  func (s *NoopService) Stop() error               { return nil }
    36  
    37  func NewNoopService(*ServiceContext) (Service, error) { return new(NoopService), nil }
    38  
    39  // Set of services all wrapping the base NoopService resulting in the same method
    40  // signatures but different outer types.
    41  type NoopServiceA struct{ NoopService }
    42  type NoopServiceB struct{ NoopService }
    43  type NoopServiceC struct{ NoopService }
    44  
    45  func NewNoopServiceA(*ServiceContext) (Service, error) { return new(NoopServiceA), nil }
    46  func NewNoopServiceB(*ServiceContext) (Service, error) { return new(NoopServiceB), nil }
    47  func NewNoopServiceC(*ServiceContext) (Service, error) { return new(NoopServiceC), nil }
    48  
    49  // InstrumentedService is an implementation of Service for which all interface
    50  // methods can be instrumented both return value as well as event hook wise.
    51  type InstrumentedService struct {
    52  	protocols []p2p.Protocol
    53  	apis      []rpc.API
    54  	start     error
    55  	stop      error
    56  
    57  	protocolsHook func()
    58  	startHook     func(*p2p.Server)
    59  	stopHook      func()
    60  }
    61  
    62  func NewInstrumentedService(*ServiceContext) (Service, error) { return new(InstrumentedService), nil }
    63  
    64  func (s *InstrumentedService) Protocols() []p2p.Protocol {
    65  	if s.protocolsHook != nil {
    66  		s.protocolsHook()
    67  	}
    68  	return s.protocols
    69  }
    70  
    71  func (s *InstrumentedService) APIs() []rpc.API {
    72  	return s.apis
    73  }
    74  
    75  func (s *InstrumentedService) Start(server *p2p.Server) error {
    76  	if s.startHook != nil {
    77  		s.startHook(server)
    78  	}
    79  	return s.start
    80  }
    81  
    82  func (s *InstrumentedService) Stop() error {
    83  	if s.stopHook != nil {
    84  		s.stopHook()
    85  	}
    86  	return s.stop
    87  }
    88  
    89  // InstrumentingWrapper is a method to specialize a service constructor returning
    90  // a generic InstrumentedService into one returning a wrapping specific one.
    91  type InstrumentingWrapper func(base ServiceConstructor) ServiceConstructor
    92  
    93  func InstrumentingWrapperMaker(base ServiceConstructor, kind reflect.Type) ServiceConstructor {
    94  	return func(ctx *ServiceContext) (Service, error) {
    95  		obj, err := base(ctx)
    96  		if err != nil {
    97  			return nil, err
    98  		}
    99  		wrapper := reflect.New(kind)
   100  		wrapper.Elem().Field(0).Set(reflect.ValueOf(obj).Elem())
   101  
   102  		return wrapper.Interface().(Service), nil
   103  	}
   104  }
   105  
   106  // Set of services all wrapping the base InstrumentedService resulting in the
   107  // same method signatures but different outer types.
   108  type InstrumentedServiceA struct{ InstrumentedService }
   109  type InstrumentedServiceB struct{ InstrumentedService }
   110  type InstrumentedServiceC struct{ InstrumentedService }
   111  
   112  func InstrumentedServiceMakerA(base ServiceConstructor) ServiceConstructor {
   113  	return InstrumentingWrapperMaker(base, reflect.TypeOf(InstrumentedServiceA{}))
   114  }
   115  
   116  func InstrumentedServiceMakerB(base ServiceConstructor) ServiceConstructor {
   117  	return InstrumentingWrapperMaker(base, reflect.TypeOf(InstrumentedServiceB{}))
   118  }
   119  
   120  func InstrumentedServiceMakerC(base ServiceConstructor) ServiceConstructor {
   121  	return InstrumentingWrapperMaker(base, reflect.TypeOf(InstrumentedServiceC{}))
   122  }
   123  
   124  // OneMethodApi is a single-method API handler to be returned by test services.
   125  type OneMethodApi struct {
   126  	fun func()
   127  }
   128  
   129  func (api *OneMethodApi) TheOneMethod() {
   130  	if api.fun != nil {
   131  		api.fun()
   132  	}
   133  }