github.com/klaytn/klaytn@v1.12.1/networks/rpc/server_test.go (about) 1 // Copyright 2015 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 "bytes" 21 "context" 22 "encoding/json" 23 "net" 24 "testing" 25 "time" 26 ) 27 28 type Service struct{} 29 30 type Args struct { 31 S string 32 } 33 34 func (s *Service) NoArgsRets() { 35 } 36 37 type Result struct { 38 String string 39 Int int 40 Args *Args 41 } 42 43 func (s *Service) Echo(str string, i int, args *Args) Result { 44 return Result{str, i, args} 45 } 46 47 func (s *Service) EchoWithCtx(ctx context.Context, str string, i int, args *Args) Result { 48 return Result{str, i, args} 49 } 50 51 func (s *Service) Sleep(ctx context.Context, duration time.Duration) { 52 select { 53 case <-time.After(duration): 54 case <-ctx.Done(): 55 } 56 } 57 58 func (s *Service) Rets() (string, error) { 59 return "", nil 60 } 61 62 func (s *Service) InvalidRets1() (error, string) { 63 return nil, "" 64 } 65 66 func (s *Service) InvalidRets2() (string, string) { 67 return "", "" 68 } 69 70 func (s *Service) InvalidRets3() (string, string, error) { 71 return "", "", nil 72 } 73 74 func (s *Service) Subscription(ctx context.Context) (*Subscription, error) { 75 return nil, nil 76 } 77 78 func TestServerRegisterName(t *testing.T) { 79 server := NewServer() 80 service := new(Service) 81 82 if err := server.RegisterName("calc", service); err != nil { 83 t.Fatalf("%v", err) 84 } 85 86 if len(server.services.services) != 2 { 87 t.Fatalf("Expected 2 service entries, got %d", len(server.services.services)) 88 } 89 90 svc, ok := server.services.services["calc"] 91 if !ok { 92 t.Fatalf("Expected service calc to be registered") 93 } 94 95 if len(svc.callbacks) != 5 { 96 t.Errorf("Expected 5 callbacks for service 'calc', got %d", len(svc.callbacks)) 97 } 98 99 if len(svc.subscriptions) != 1 { 100 t.Errorf("Expected 1 subscription for service 'calc', got %d", len(svc.subscriptions)) 101 } 102 } 103 104 func testServerMethodExecution(t *testing.T, method string) { 105 server := NewServer() 106 service := new(Service) 107 108 if err := server.RegisterName("test", service); err != nil { 109 t.Fatalf("%v", err) 110 } 111 112 stringArg := "string arg" 113 intArg := 1122 114 argsArg := &Args{"abcde"} 115 params := []interface{}{stringArg, intArg, argsArg} 116 117 request := map[string]interface{}{ 118 "id": 12345, 119 "method": "test_" + method, 120 "version": "2.0", 121 "params": params, 122 } 123 124 clientConn, serverConn := net.Pipe() 125 defer clientConn.Close() 126 127 go server.ServeCodec(NewCodec(serverConn), 0) 128 129 out := json.NewEncoder(clientConn) 130 in := json.NewDecoder(clientConn) 131 132 if err := out.Encode(request); err != nil { 133 t.Fatal(err) 134 } 135 136 var msg jsonrpcMessage 137 if err := in.Decode(&msg); err != nil { 138 t.Fatal(err) 139 } 140 141 if !msg.isResponse() { 142 t.Fatal("message is not response") 143 } 144 } 145 146 func TestServerMethodExecution(t *testing.T) { 147 testServerMethodExecution(t, "echo") 148 } 149 150 func TestServerMethodWithCtx(t *testing.T) { 151 testServerMethodExecution(t, "echoWithCtx") 152 } 153 154 // This test checks that responses are delivered for very short-lived connections that 155 // only carry a single request. 156 func TestServerShortLivedConn(t *testing.T) { 157 server := newTestServer("service", new(Service)) 158 defer server.Stop() 159 160 listener, err := net.Listen("tcp", "127.0.0.1:0") 161 if err != nil { 162 t.Fatal("can't listen:", err) 163 } 164 defer listener.Close() 165 go server.ServeListener(listener) 166 167 var ( 168 request = `{"jsonrpc":"2.0","id":1,"method":"rpc_modules"}` + "\n" 169 wantResp = `{"jsonrpc":"2.0","id":1,"result":{"rpc":"1.0","service":"1.0"}}` + "\n" 170 deadline = time.Now().Add(10 * time.Second) 171 ) 172 for i := 0; i < 20; i++ { 173 conn, err := net.Dial("tcp", listener.Addr().String()) 174 if err != nil { 175 t.Fatal("can't dial:", err) 176 } 177 defer conn.Close() 178 conn.SetDeadline(deadline) 179 // Write the request, then half-close the connection so the server stops reading. 180 conn.Write([]byte(request)) 181 conn.(*net.TCPConn).CloseWrite() 182 // Now try to get the response. 183 buf := make([]byte, 2000) 184 n, err := conn.Read(buf) 185 if err != nil { 186 t.Fatal("read error:", err) 187 } 188 if !bytes.Equal(buf[:n], []byte(wantResp)) { 189 t.Fatalf("wrong response: %s", buf[:n]) 190 } 191 } 192 }