testservice_test.go 4.5 KB

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