testservice_test.go 5.2 KB

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