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