github.com/kisexp/xdchain@v0.0.0-20211206025815-490d6b732aa7/rpc/testservice_test.go (about)

     1  // Copyright 2019 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 rpc
    18  
    19  import (
    20  	"context"
    21  	"encoding/binary"
    22  	"errors"
    23  	"fmt"
    24  	"sync"
    25  	"time"
    26  
    27  	"github.com/kisexp/xdchain/core/types"
    28  )
    29  
    30  func newTestServer() *Server {
    31  	server := NewServer()
    32  	server.idgen = sequentialIDGenerator()
    33  	if err := server.RegisterName("test", new(testService)); err != nil {
    34  		panic(err)
    35  	}
    36  	if err := server.RegisterName("nftest", new(notificationTestService)); err != nil {
    37  		panic(err)
    38  	}
    39  	return server
    40  }
    41  
    42  func sequentialIDGenerator() func() ID {
    43  	var (
    44  		mu      sync.Mutex
    45  		counter uint64
    46  	)
    47  	return func() ID {
    48  		mu.Lock()
    49  		defer mu.Unlock()
    50  		counter++
    51  		id := make([]byte, 8)
    52  		binary.BigEndian.PutUint64(id, counter)
    53  		return encodeID(id)
    54  	}
    55  }
    56  
    57  type testService struct{}
    58  
    59  type echoArgs struct {
    60  	S string
    61  }
    62  
    63  type echoResult struct {
    64  	String string
    65  	Int    int
    66  	Args   *echoArgs
    67  }
    68  
    69  type echoPSIResult struct {
    70  	PSI types.PrivateStateIdentifier
    71  }
    72  
    73  type testError struct{}
    74  
    75  func (testError) Error() string          { return "testError" }
    76  func (testError) ErrorCode() int         { return 444 }
    77  func (testError) ErrorData() interface{} { return "testError data" }
    78  
    79  func (s *testService) NoArgsRets() {}
    80  
    81  func (s *testService) Echo(str string, i int, args *echoArgs) echoResult {
    82  	return echoResult{str, i, args}
    83  }
    84  
    85  func (s *testService) EchoWithCtx(ctx context.Context, str string, i int, args *echoArgs) echoResult {
    86  	return echoResult{str, i, args}
    87  }
    88  
    89  func (s *testService) EchoCtxId(ctx context.Context) interface{} {
    90  	return ctx.Value("id")
    91  }
    92  
    93  func (s *testService) EchoCtxPSI(ctx context.Context) (echoPSIResult, error) {
    94  	value := ctx.Value(ctxPrivateStateIdentifier)
    95  	if value == nil {
    96  		return echoPSIResult{}, fmt.Errorf("no PSI found in the context")
    97  	}
    98  	return echoPSIResult{PSI: value.(types.PrivateStateIdentifier)}, nil
    99  }
   100  
   101  func (s *testService) Sleep(ctx context.Context, duration time.Duration) {
   102  	time.Sleep(duration)
   103  }
   104  
   105  func (s *testService) Block(ctx context.Context) error {
   106  	<-ctx.Done()
   107  	return errors.New("context canceled in testservice_block")
   108  }
   109  
   110  func (s *testService) Rets() (string, error) {
   111  	return "", nil
   112  }
   113  
   114  //lint:ignore ST1008 returns error first on purpose.
   115  func (s *testService) InvalidRets1() (error, string) {
   116  	return nil, ""
   117  }
   118  
   119  func (s *testService) InvalidRets2() (string, string) {
   120  	return "", ""
   121  }
   122  
   123  func (s *testService) InvalidRets3() (string, string, error) {
   124  	return "", "", nil
   125  }
   126  
   127  func (s *testService) ReturnError() error {
   128  	return testError{}
   129  }
   130  
   131  func (s *testService) CallMeBack(ctx context.Context, method string, args []interface{}) (interface{}, error) {
   132  	c, ok := ClientFromContext(ctx)
   133  	if !ok {
   134  		return nil, errors.New("no client")
   135  	}
   136  	var result interface{}
   137  	err := c.Call(&result, method, args...)
   138  	return result, err
   139  }
   140  
   141  func (s *testService) CallMeBackLater(ctx context.Context, method string, args []interface{}) error {
   142  	c, ok := ClientFromContext(ctx)
   143  	if !ok {
   144  		return errors.New("no client")
   145  	}
   146  	go func() {
   147  		<-ctx.Done()
   148  		var result interface{}
   149  		c.Call(&result, method, args...)
   150  	}()
   151  	return nil
   152  }
   153  
   154  func (s *testService) Subscription(ctx context.Context) (*Subscription, error) {
   155  	return nil, nil
   156  }
   157  
   158  type notificationTestService struct {
   159  	unsubscribed            chan string
   160  	gotHangSubscriptionReq  chan struct{}
   161  	unblockHangSubscription chan struct{}
   162  }
   163  
   164  func (s *notificationTestService) Echo(i int) int {
   165  	return i
   166  }
   167  
   168  func (s *notificationTestService) Unsubscribe(subid string) {
   169  	if s.unsubscribed != nil {
   170  		s.unsubscribed <- subid
   171  	}
   172  }
   173  
   174  func (s *notificationTestService) SomeSubscription(ctx context.Context, n, val int) (*Subscription, error) {
   175  	notifier, supported := NotifierFromContext(ctx)
   176  	if !supported {
   177  		return nil, ErrNotificationsUnsupported
   178  	}
   179  
   180  	// By explicitly creating an subscription we make sure that the subscription id is send
   181  	// back to the client before the first subscription.Notify is called. Otherwise the
   182  	// events might be send before the response for the *_subscribe method.
   183  	subscription := notifier.CreateSubscription()
   184  	go func() {
   185  		for i := 0; i < n; i++ {
   186  			if err := notifier.Notify(subscription.ID, val+i); err != nil {
   187  				return
   188  			}
   189  		}
   190  		select {
   191  		case <-notifier.Closed():
   192  		case <-subscription.Err():
   193  		}
   194  		if s.unsubscribed != nil {
   195  			s.unsubscribed <- string(subscription.ID)
   196  		}
   197  	}()
   198  	return subscription, nil
   199  }
   200  
   201  // HangSubscription blocks on s.unblockHangSubscription before sending anything.
   202  func (s *notificationTestService) HangSubscription(ctx context.Context, val int) (*Subscription, error) {
   203  	notifier, supported := NotifierFromContext(ctx)
   204  	if !supported {
   205  		return nil, ErrNotificationsUnsupported
   206  	}
   207  	s.gotHangSubscriptionReq <- struct{}{}
   208  	<-s.unblockHangSubscription
   209  	subscription := notifier.CreateSubscription()
   210  
   211  	go func() {
   212  		notifier.Notify(subscription.ID, val)
   213  	}()
   214  	return subscription, nil
   215  }