github.com/MetalBlockchain/subnet-evm@v0.4.9/rpc/testservice_test.go (about)

     1  // (c) 2019-2020, Ava Labs, Inc.
     2  //
     3  // This file is a derived work, based on the go-ethereum library whose original
     4  // notices appear below.
     5  //
     6  // It is distributed under a license compatible with the licensing terms of the
     7  // original code from which it is derived.
     8  //
     9  // Much love to the original authors for their work.
    10  // **********
    11  // Copyright 2019 The go-ethereum Authors
    12  // This file is part of the go-ethereum library.
    13  //
    14  // The go-ethereum library is free software: you can redistribute it and/or modify
    15  // it under the terms of the GNU Lesser General Public License as published by
    16  // the Free Software Foundation, either version 3 of the License, or
    17  // (at your option) any later version.
    18  //
    19  // The go-ethereum library is distributed in the hope that it will be useful,
    20  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    22  // GNU Lesser General Public License for more details.
    23  //
    24  // You should have received a copy of the GNU Lesser General Public License
    25  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    26  
    27  package rpc
    28  
    29  import (
    30  	"context"
    31  	"encoding/binary"
    32  	"errors"
    33  	"strings"
    34  	"sync"
    35  	"time"
    36  )
    37  
    38  func newTestServer() *Server {
    39  	server := NewServer(0)
    40  	server.idgen = sequentialIDGenerator()
    41  	if err := server.RegisterName("test", new(testService)); err != nil {
    42  		panic(err)
    43  	}
    44  	if err := server.RegisterName("nftest", new(notificationTestService)); err != nil {
    45  		panic(err)
    46  	}
    47  	return server
    48  }
    49  
    50  func sequentialIDGenerator() func() ID {
    51  	var (
    52  		mu      sync.Mutex
    53  		counter uint64
    54  	)
    55  	return func() ID {
    56  		mu.Lock()
    57  		defer mu.Unlock()
    58  		counter++
    59  		id := make([]byte, 8)
    60  		binary.BigEndian.PutUint64(id, counter)
    61  		return encodeID(id)
    62  	}
    63  }
    64  
    65  type testService struct{}
    66  
    67  type echoArgs struct {
    68  	S string
    69  }
    70  
    71  type echoResult struct {
    72  	String string
    73  	Int    int
    74  	Args   *echoArgs
    75  }
    76  
    77  type testError struct{}
    78  
    79  func (testError) Error() string          { return "testError" }
    80  func (testError) ErrorCode() int         { return 444 }
    81  func (testError) ErrorData() interface{} { return "testError data" }
    82  
    83  func (s *testService) NoArgsRets() {}
    84  
    85  func (s *testService) Echo(str string, i int, args *echoArgs) echoResult {
    86  	return echoResult{str, i, args}
    87  }
    88  
    89  func (s *testService) EchoWithCtx(ctx context.Context, str string, i int, args *echoArgs) echoResult {
    90  	return echoResult{str, i, args}
    91  }
    92  
    93  func (s *testService) PeerInfo(ctx context.Context) PeerInfo {
    94  	return PeerInfoFromContext(ctx)
    95  }
    96  
    97  func (s *testService) Sleep(ctx context.Context, duration time.Duration) {
    98  	time.Sleep(duration)
    99  }
   100  
   101  func (s *testService) Block(ctx context.Context) error {
   102  	<-ctx.Done()
   103  	return errors.New("context canceled in testservice_block")
   104  }
   105  
   106  func (s *testService) Rets() (string, error) {
   107  	return "", nil
   108  }
   109  
   110  //lint:ignore ST1008 returns error first on purpose.
   111  func (s *testService) InvalidRets1() (error, string) {
   112  	return nil, ""
   113  }
   114  
   115  func (s *testService) InvalidRets2() (string, string) {
   116  	return "", ""
   117  }
   118  
   119  func (s *testService) InvalidRets3() (string, string, error) {
   120  	return "", "", nil
   121  }
   122  
   123  func (s *testService) ReturnError() error {
   124  	return testError{}
   125  }
   126  
   127  func (s *testService) CallMeBack(ctx context.Context, method string, args []interface{}) (interface{}, error) {
   128  	c, ok := ClientFromContext(ctx)
   129  	if !ok {
   130  		return nil, errors.New("no client")
   131  	}
   132  	var result interface{}
   133  	err := c.Call(&result, method, args...)
   134  	return result, err
   135  }
   136  
   137  func (s *testService) CallMeBackLater(ctx context.Context, method string, args []interface{}) error {
   138  	c, ok := ClientFromContext(ctx)
   139  	if !ok {
   140  		return errors.New("no client")
   141  	}
   142  	go func() {
   143  		<-ctx.Done()
   144  		var result interface{}
   145  		c.Call(&result, method, args...)
   146  	}()
   147  	return nil
   148  }
   149  
   150  func (s *testService) Subscription(ctx context.Context) (*Subscription, error) {
   151  	return nil, nil
   152  }
   153  
   154  type notificationTestService struct {
   155  	unsubscribed            chan string
   156  	gotHangSubscriptionReq  chan struct{}
   157  	unblockHangSubscription chan struct{}
   158  }
   159  
   160  func (s *notificationTestService) Echo(i int) int {
   161  	return i
   162  }
   163  
   164  func (s *notificationTestService) Unsubscribe(subid string) {
   165  	if s.unsubscribed != nil {
   166  		s.unsubscribed <- subid
   167  	}
   168  }
   169  
   170  func (s *notificationTestService) SomeSubscription(ctx context.Context, n, val int) (*Subscription, error) {
   171  	notifier, supported := NotifierFromContext(ctx)
   172  	if !supported {
   173  		return nil, ErrNotificationsUnsupported
   174  	}
   175  
   176  	// By explicitly creating an subscription we make sure that the subscription id is send
   177  	// back to the client before the first subscription.Notify is called. Otherwise the
   178  	// events might be send before the response for the *_subscribe method.
   179  	subscription := notifier.CreateSubscription()
   180  	go func() {
   181  		for i := 0; i < n; i++ {
   182  			if err := notifier.Notify(subscription.ID, val+i); err != nil {
   183  				return
   184  			}
   185  		}
   186  		select {
   187  		case <-notifier.Closed():
   188  		case <-subscription.Err():
   189  		}
   190  		if s.unsubscribed != nil {
   191  			s.unsubscribed <- string(subscription.ID)
   192  		}
   193  	}()
   194  	return subscription, nil
   195  }
   196  
   197  // HangSubscription blocks on s.unblockHangSubscription before sending anything.
   198  func (s *notificationTestService) HangSubscription(ctx context.Context, val int) (*Subscription, error) {
   199  	notifier, supported := NotifierFromContext(ctx)
   200  	if !supported {
   201  		return nil, ErrNotificationsUnsupported
   202  	}
   203  	s.gotHangSubscriptionReq <- struct{}{}
   204  	<-s.unblockHangSubscription
   205  	subscription := notifier.CreateSubscription()
   206  
   207  	go func() {
   208  		notifier.Notify(subscription.ID, val)
   209  	}()
   210  	return subscription, nil
   211  }
   212  
   213  // largeRespService generates arbitrary-size JSON responses.
   214  type largeRespService struct {
   215  	length int
   216  }
   217  
   218  func (x largeRespService) LargeResp() string {
   219  	return strings.Repeat("x", x.length)
   220  }