gitlab.com/flarenetwork/coreth@v0.1.1/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) Sleep(ctx context.Context, duration time.Duration) {
    94  	time.Sleep(duration)
    95  }
    96  
    97  func (s *testService) Block(ctx context.Context) error {
    98  	<-ctx.Done()
    99  	return errors.New("context canceled in testservice_block")
   100  }
   101  
   102  func (s *testService) Rets() (string, error) {
   103  	return "", nil
   104  }
   105  
   106  //lint:ignore ST1008 returns error first on purpose.
   107  func (s *testService) InvalidRets1() (error, string) {
   108  	return nil, ""
   109  }
   110  
   111  func (s *testService) InvalidRets2() (string, string) {
   112  	return "", ""
   113  }
   114  
   115  func (s *testService) InvalidRets3() (string, string, error) {
   116  	return "", "", nil
   117  }
   118  
   119  func (s *testService) ReturnError() error {
   120  	return testError{}
   121  }
   122  
   123  func (s *testService) CallMeBack(ctx context.Context, method string, args []interface{}) (interface{}, error) {
   124  	c, ok := ClientFromContext(ctx)
   125  	if !ok {
   126  		return nil, errors.New("no client")
   127  	}
   128  	var result interface{}
   129  	err := c.Call(&result, method, args...)
   130  	return result, err
   131  }
   132  
   133  func (s *testService) CallMeBackLater(ctx context.Context, method string, args []interface{}) error {
   134  	c, ok := ClientFromContext(ctx)
   135  	if !ok {
   136  		return errors.New("no client")
   137  	}
   138  	go func() {
   139  		<-ctx.Done()
   140  		var result interface{}
   141  		c.Call(&result, method, args...)
   142  	}()
   143  	return nil
   144  }
   145  
   146  func (s *testService) Subscription(ctx context.Context) (*Subscription, error) {
   147  	return nil, nil
   148  }
   149  
   150  type notificationTestService struct {
   151  	unsubscribed            chan string
   152  	gotHangSubscriptionReq  chan struct{}
   153  	unblockHangSubscription chan struct{}
   154  }
   155  
   156  func (s *notificationTestService) Echo(i int) int {
   157  	return i
   158  }
   159  
   160  func (s *notificationTestService) Unsubscribe(subid string) {
   161  	if s.unsubscribed != nil {
   162  		s.unsubscribed <- subid
   163  	}
   164  }
   165  
   166  func (s *notificationTestService) SomeSubscription(ctx context.Context, n, val int) (*Subscription, error) {
   167  	notifier, supported := NotifierFromContext(ctx)
   168  	if !supported {
   169  		return nil, ErrNotificationsUnsupported
   170  	}
   171  
   172  	// By explicitly creating an subscription we make sure that the subscription id is send
   173  	// back to the client before the first subscription.Notify is called. Otherwise the
   174  	// events might be send before the response for the *_subscribe method.
   175  	subscription := notifier.CreateSubscription()
   176  	go func() {
   177  		for i := 0; i < n; i++ {
   178  			if err := notifier.Notify(subscription.ID, val+i); err != nil {
   179  				return
   180  			}
   181  		}
   182  		select {
   183  		case <-notifier.Closed():
   184  		case <-subscription.Err():
   185  		}
   186  		if s.unsubscribed != nil {
   187  			s.unsubscribed <- string(subscription.ID)
   188  		}
   189  	}()
   190  	return subscription, nil
   191  }
   192  
   193  // HangSubscription blocks on s.unblockHangSubscription before sending anything.
   194  func (s *notificationTestService) HangSubscription(ctx context.Context, val int) (*Subscription, error) {
   195  	notifier, supported := NotifierFromContext(ctx)
   196  	if !supported {
   197  		return nil, ErrNotificationsUnsupported
   198  	}
   199  	s.gotHangSubscriptionReq <- struct{}{}
   200  	<-s.unblockHangSubscription
   201  	subscription := notifier.CreateSubscription()
   202  
   203  	go func() {
   204  		notifier.Notify(subscription.ID, val)
   205  	}()
   206  	return subscription, nil
   207  }
   208  
   209  // largeRespService generates arbitrary-size JSON responses.
   210  type largeRespService struct {
   211  	length int
   212  }
   213  
   214  func (x largeRespService) LargeResp() string {
   215  	return strings.Repeat("x", x.length)
   216  }