github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/net/rpc/jsonrpc/all_test.go (about) 1 // Copyright 2010 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package jsonrpc 6 7 import ( 8 "bytes" 9 "encoding/json" 10 "errors" 11 "fmt" 12 "io" 13 "net" 14 "net/rpc" 15 "reflect" 16 "strings" 17 "testing" 18 ) 19 20 type Args struct { 21 A, B int 22 } 23 24 type Reply struct { 25 C int 26 } 27 28 type Arith int 29 30 type ArithAddResp struct { 31 Id interface{} `json:"id"` 32 Result Reply `json:"result"` 33 Error interface{} `json:"error"` 34 } 35 36 func (t *Arith) Add(args *Args, reply *Reply) error { 37 reply.C = args.A + args.B 38 return nil 39 } 40 41 func (t *Arith) Mul(args *Args, reply *Reply) error { 42 reply.C = args.A * args.B 43 return nil 44 } 45 46 func (t *Arith) Div(args *Args, reply *Reply) error { 47 if args.B == 0 { 48 return errors.New("divide by zero") 49 } 50 reply.C = args.A / args.B 51 return nil 52 } 53 54 func (t *Arith) Error(args *Args, reply *Reply) error { 55 panic("ERROR") 56 } 57 58 type BuiltinTypes struct{} 59 60 func (BuiltinTypes) Map(i int, reply *map[int]int) error { 61 (*reply)[i] = i 62 return nil 63 } 64 65 func (BuiltinTypes) Slice(i int, reply *[]int) error { 66 *reply = append(*reply, i) 67 return nil 68 } 69 70 func (BuiltinTypes) Array(i int, reply *[1]int) error { 71 (*reply)[0] = i 72 return nil 73 } 74 75 func init() { 76 rpc.Register(new(Arith)) 77 rpc.Register(BuiltinTypes{}) 78 } 79 80 func TestServerNoParams(t *testing.T) { 81 cli, srv := net.Pipe() 82 defer cli.Close() 83 go ServeConn(srv) 84 dec := json.NewDecoder(cli) 85 86 fmt.Fprintf(cli, `{"method": "Arith.Add", "id": "123"}`) 87 var resp ArithAddResp 88 if err := dec.Decode(&resp); err != nil { 89 t.Fatalf("Decode after no params: %s", err) 90 } 91 if resp.Error == nil { 92 t.Fatalf("Expected error, got nil") 93 } 94 } 95 96 func TestServerEmptyMessage(t *testing.T) { 97 cli, srv := net.Pipe() 98 defer cli.Close() 99 go ServeConn(srv) 100 dec := json.NewDecoder(cli) 101 102 fmt.Fprintf(cli, "{}") 103 var resp ArithAddResp 104 if err := dec.Decode(&resp); err != nil { 105 t.Fatalf("Decode after empty: %s", err) 106 } 107 if resp.Error == nil { 108 t.Fatalf("Expected error, got nil") 109 } 110 } 111 112 func TestServer(t *testing.T) { 113 cli, srv := net.Pipe() 114 defer cli.Close() 115 go ServeConn(srv) 116 dec := json.NewDecoder(cli) 117 118 // Send hand-coded requests to server, parse responses. 119 for i := 0; i < 10; i++ { 120 fmt.Fprintf(cli, `{"method": "Arith.Add", "id": "\u%04d", "params": [{"A": %d, "B": %d}]}`, i, i, i+1) 121 var resp ArithAddResp 122 err := dec.Decode(&resp) 123 if err != nil { 124 t.Fatalf("Decode: %s", err) 125 } 126 if resp.Error != nil { 127 t.Fatalf("resp.Error: %s", resp.Error) 128 } 129 if resp.Id.(string) != string(rune(i)) { 130 t.Fatalf("resp: bad id %q want %q", resp.Id.(string), string(rune(i))) 131 } 132 if resp.Result.C != 2*i+1 { 133 t.Fatalf("resp: bad result: %d+%d=%d", i, i+1, resp.Result.C) 134 } 135 } 136 } 137 138 func TestClient(t *testing.T) { 139 // Assume server is okay (TestServer is above). 140 // Test client against server. 141 cli, srv := net.Pipe() 142 go ServeConn(srv) 143 144 client := NewClient(cli) 145 defer client.Close() 146 147 // Synchronous calls 148 args := &Args{7, 8} 149 reply := new(Reply) 150 err := client.Call("Arith.Add", args, reply) 151 if err != nil { 152 t.Errorf("Add: expected no error but got string %q", err.Error()) 153 } 154 if reply.C != args.A+args.B { 155 t.Errorf("Add: got %d expected %d", reply.C, args.A+args.B) 156 } 157 158 args = &Args{7, 8} 159 reply = new(Reply) 160 err = client.Call("Arith.Mul", args, reply) 161 if err != nil { 162 t.Errorf("Mul: expected no error but got string %q", err.Error()) 163 } 164 if reply.C != args.A*args.B { 165 t.Errorf("Mul: got %d expected %d", reply.C, args.A*args.B) 166 } 167 168 // Out of order. 169 args = &Args{7, 8} 170 mulReply := new(Reply) 171 mulCall := client.Go("Arith.Mul", args, mulReply, nil) 172 addReply := new(Reply) 173 addCall := client.Go("Arith.Add", args, addReply, nil) 174 175 addCall = <-addCall.Done 176 if addCall.Error != nil { 177 t.Errorf("Add: expected no error but got string %q", addCall.Error.Error()) 178 } 179 if addReply.C != args.A+args.B { 180 t.Errorf("Add: got %d expected %d", addReply.C, args.A+args.B) 181 } 182 183 mulCall = <-mulCall.Done 184 if mulCall.Error != nil { 185 t.Errorf("Mul: expected no error but got string %q", mulCall.Error.Error()) 186 } 187 if mulReply.C != args.A*args.B { 188 t.Errorf("Mul: got %d expected %d", mulReply.C, args.A*args.B) 189 } 190 191 // Error test 192 args = &Args{7, 0} 193 reply = new(Reply) 194 err = client.Call("Arith.Div", args, reply) 195 // expect an error: zero divide 196 if err == nil { 197 t.Error("Div: expected error") 198 } else if err.Error() != "divide by zero" { 199 t.Error("Div: expected divide by zero error; got", err) 200 } 201 } 202 203 func TestBuiltinTypes(t *testing.T) { 204 cli, srv := net.Pipe() 205 go ServeConn(srv) 206 207 client := NewClient(cli) 208 defer client.Close() 209 210 // Map 211 arg := 7 212 replyMap := map[int]int{} 213 err := client.Call("BuiltinTypes.Map", arg, &replyMap) 214 if err != nil { 215 t.Errorf("Map: expected no error but got string %q", err.Error()) 216 } 217 if replyMap[arg] != arg { 218 t.Errorf("Map: expected %d got %d", arg, replyMap[arg]) 219 } 220 221 // Slice 222 replySlice := []int{} 223 err = client.Call("BuiltinTypes.Slice", arg, &replySlice) 224 if err != nil { 225 t.Errorf("Slice: expected no error but got string %q", err.Error()) 226 } 227 if e := []int{arg}; !reflect.DeepEqual(replySlice, e) { 228 t.Errorf("Slice: expected %v got %v", e, replySlice) 229 } 230 231 // Array 232 replyArray := [1]int{} 233 err = client.Call("BuiltinTypes.Array", arg, &replyArray) 234 if err != nil { 235 t.Errorf("Array: expected no error but got string %q", err.Error()) 236 } 237 if e := [1]int{arg}; !reflect.DeepEqual(replyArray, e) { 238 t.Errorf("Array: expected %v got %v", e, replyArray) 239 } 240 } 241 242 func TestMalformedInput(t *testing.T) { 243 cli, srv := net.Pipe() 244 go cli.Write([]byte(`{id:1}`)) // invalid json 245 ServeConn(srv) // must return, not loop 246 } 247 248 func TestMalformedOutput(t *testing.T) { 249 cli, srv := net.Pipe() 250 go srv.Write([]byte(`{"id":0,"result":null,"error":null}`)) 251 go io.ReadAll(srv) 252 253 client := NewClient(cli) 254 defer client.Close() 255 256 args := &Args{7, 8} 257 reply := new(Reply) 258 err := client.Call("Arith.Add", args, reply) 259 if err == nil { 260 t.Error("expected error") 261 } 262 } 263 264 func TestServerErrorHasNullResult(t *testing.T) { 265 var out bytes.Buffer 266 sc := NewServerCodec(struct { 267 io.Reader 268 io.Writer 269 io.Closer 270 }{ 271 Reader: strings.NewReader(`{"method": "Arith.Add", "id": "123", "params": []}`), 272 Writer: &out, 273 Closer: io.NopCloser(nil), 274 }) 275 r := new(rpc.Request) 276 if err := sc.ReadRequestHeader(r); err != nil { 277 t.Fatal(err) 278 } 279 const valueText = "the value we don't want to see" 280 const errorText = "some error" 281 err := sc.WriteResponse(&rpc.Response{ 282 ServiceMethod: "Method", 283 Seq: 1, 284 Error: errorText, 285 }, valueText) 286 if err != nil { 287 t.Fatal(err) 288 } 289 if !strings.Contains(out.String(), errorText) { 290 t.Fatalf("Response didn't contain expected error %q: %s", errorText, &out) 291 } 292 if strings.Contains(out.String(), valueText) { 293 t.Errorf("Response contains both an error and value: %s", &out) 294 } 295 } 296 297 func TestUnexpectedError(t *testing.T) { 298 cli, srv := myPipe() 299 go cli.PipeWriter.CloseWithError(errors.New("unexpected error!")) // reader will get this error 300 ServeConn(srv) // must return, not loop 301 } 302 303 // Copied from package net. 304 func myPipe() (*pipe, *pipe) { 305 r1, w1 := io.Pipe() 306 r2, w2 := io.Pipe() 307 308 return &pipe{r1, w2}, &pipe{r2, w1} 309 } 310 311 type pipe struct { 312 *io.PipeReader 313 *io.PipeWriter 314 } 315 316 type pipeAddr int 317 318 func (pipeAddr) Network() string { 319 return "pipe" 320 } 321 322 func (pipeAddr) String() string { 323 return "pipe" 324 } 325 326 func (p *pipe) Close() error { 327 err := p.PipeReader.Close() 328 err1 := p.PipeWriter.Close() 329 if err == nil { 330 err = err1 331 } 332 return err 333 } 334 335 func (p *pipe) LocalAddr() net.Addr { 336 return pipeAddr(0) 337 } 338 339 func (p *pipe) RemoteAddr() net.Addr { 340 return pipeAddr(0) 341 } 342 343 func (p *pipe) SetTimeout(nsec int64) error { 344 return errors.New("net.Pipe does not support timeouts") 345 } 346 347 func (p *pipe) SetReadTimeout(nsec int64) error { 348 return errors.New("net.Pipe does not support timeouts") 349 } 350 351 func (p *pipe) SetWriteTimeout(nsec int64) error { 352 return errors.New("net.Pipe does not support timeouts") 353 }