github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/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 "encoding/json" 9 "errors" 10 "fmt" 11 "io" 12 "io/ioutil" 13 "net" 14 "net/rpc" 15 "testing" 16 ) 17 18 type Args struct { 19 A, B int 20 } 21 22 type Reply struct { 23 C int 24 } 25 26 type Arith int 27 28 type ArithAddResp struct { 29 Id interface{} `json:"id"` 30 Result Reply `json:"result"` 31 Error interface{} `json:"error"` 32 } 33 34 func (t *Arith) Add(args *Args, reply *Reply) error { 35 reply.C = args.A + args.B 36 return nil 37 } 38 39 func (t *Arith) Mul(args *Args, reply *Reply) error { 40 reply.C = args.A * args.B 41 return nil 42 } 43 44 func (t *Arith) Div(args *Args, reply *Reply) error { 45 if args.B == 0 { 46 return errors.New("divide by zero") 47 } 48 reply.C = args.A / args.B 49 return nil 50 } 51 52 func (t *Arith) Error(args *Args, reply *Reply) error { 53 panic("ERROR") 54 } 55 56 func init() { 57 rpc.Register(new(Arith)) 58 } 59 60 func TestServerNoParams(t *testing.T) { 61 cli, srv := net.Pipe() 62 defer cli.Close() 63 go ServeConn(srv) 64 dec := json.NewDecoder(cli) 65 66 fmt.Fprintf(cli, `{"method": "Arith.Add", "id": "123"}`) 67 var resp ArithAddResp 68 if err := dec.Decode(&resp); err != nil { 69 t.Fatalf("Decode after no params: %s", err) 70 } 71 if resp.Error == nil { 72 t.Fatalf("Expected error, got nil") 73 } 74 } 75 76 func TestServerEmptyMessage(t *testing.T) { 77 cli, srv := net.Pipe() 78 defer cli.Close() 79 go ServeConn(srv) 80 dec := json.NewDecoder(cli) 81 82 fmt.Fprintf(cli, "{}") 83 var resp ArithAddResp 84 if err := dec.Decode(&resp); err != nil { 85 t.Fatalf("Decode after empty: %s", err) 86 } 87 if resp.Error == nil { 88 t.Fatalf("Expected error, got nil") 89 } 90 } 91 92 func TestServer(t *testing.T) { 93 cli, srv := net.Pipe() 94 defer cli.Close() 95 go ServeConn(srv) 96 dec := json.NewDecoder(cli) 97 98 // Send hand-coded requests to server, parse responses. 99 for i := 0; i < 10; i++ { 100 fmt.Fprintf(cli, `{"method": "Arith.Add", "id": "\u%04d", "params": [{"A": %d, "B": %d}]}`, i, i, i+1) 101 var resp ArithAddResp 102 err := dec.Decode(&resp) 103 if err != nil { 104 t.Fatalf("Decode: %s", err) 105 } 106 if resp.Error != nil { 107 t.Fatalf("resp.Error: %s", resp.Error) 108 } 109 if resp.Id.(string) != string(i) { 110 t.Fatalf("resp: bad id %q want %q", resp.Id.(string), string(i)) 111 } 112 if resp.Result.C != 2*i+1 { 113 t.Fatalf("resp: bad result: %d+%d=%d", i, i+1, resp.Result.C) 114 } 115 } 116 } 117 118 func TestClient(t *testing.T) { 119 // Assume server is okay (TestServer is above). 120 // Test client against server. 121 cli, srv := net.Pipe() 122 go ServeConn(srv) 123 124 client := NewClient(cli) 125 defer client.Close() 126 127 // Synchronous calls 128 args := &Args{7, 8} 129 reply := new(Reply) 130 err := client.Call("Arith.Add", args, reply) 131 if err != nil { 132 t.Errorf("Add: expected no error but got string %q", err.Error()) 133 } 134 if reply.C != args.A+args.B { 135 t.Errorf("Add: got %d expected %d", reply.C, args.A+args.B) 136 } 137 138 args = &Args{7, 8} 139 reply = new(Reply) 140 err = client.Call("Arith.Mul", args, reply) 141 if err != nil { 142 t.Errorf("Mul: expected no error but got string %q", err.Error()) 143 } 144 if reply.C != args.A*args.B { 145 t.Errorf("Mul: got %d expected %d", reply.C, args.A*args.B) 146 } 147 148 // Out of order. 149 args = &Args{7, 8} 150 mulReply := new(Reply) 151 mulCall := client.Go("Arith.Mul", args, mulReply, nil) 152 addReply := new(Reply) 153 addCall := client.Go("Arith.Add", args, addReply, nil) 154 155 addCall = <-addCall.Done 156 if addCall.Error != nil { 157 t.Errorf("Add: expected no error but got string %q", addCall.Error.Error()) 158 } 159 if addReply.C != args.A+args.B { 160 t.Errorf("Add: got %d expected %d", addReply.C, args.A+args.B) 161 } 162 163 mulCall = <-mulCall.Done 164 if mulCall.Error != nil { 165 t.Errorf("Mul: expected no error but got string %q", mulCall.Error.Error()) 166 } 167 if mulReply.C != args.A*args.B { 168 t.Errorf("Mul: got %d expected %d", mulReply.C, args.A*args.B) 169 } 170 171 // Error test 172 args = &Args{7, 0} 173 reply = new(Reply) 174 err = client.Call("Arith.Div", args, reply) 175 // expect an error: zero divide 176 if err == nil { 177 t.Error("Div: expected error") 178 } else if err.Error() != "divide by zero" { 179 t.Error("Div: expected divide by zero error; got", err) 180 } 181 } 182 183 func TestMalformedInput(t *testing.T) { 184 cli, srv := net.Pipe() 185 go cli.Write([]byte(`{id:1}`)) // invalid json 186 ServeConn(srv) // must return, not loop 187 } 188 189 func TestMalformedOutput(t *testing.T) { 190 cli, srv := net.Pipe() 191 go srv.Write([]byte(`{"id":0,"result":null,"error":null}`)) 192 go ioutil.ReadAll(srv) 193 194 client := NewClient(cli) 195 defer client.Close() 196 197 args := &Args{7, 8} 198 reply := new(Reply) 199 err := client.Call("Arith.Add", args, reply) 200 if err == nil { 201 t.Error("expected error") 202 } 203 } 204 205 func TestUnexpectedError(t *testing.T) { 206 cli, srv := myPipe() 207 go cli.PipeWriter.CloseWithError(errors.New("unexpected error!")) // reader will get this error 208 ServeConn(srv) // must return, not loop 209 } 210 211 // Copied from package net. 212 func myPipe() (*pipe, *pipe) { 213 r1, w1 := io.Pipe() 214 r2, w2 := io.Pipe() 215 216 return &pipe{r1, w2}, &pipe{r2, w1} 217 } 218 219 type pipe struct { 220 *io.PipeReader 221 *io.PipeWriter 222 } 223 224 type pipeAddr int 225 226 func (pipeAddr) Network() string { 227 return "pipe" 228 } 229 230 func (pipeAddr) String() string { 231 return "pipe" 232 } 233 234 func (p *pipe) Close() error { 235 err := p.PipeReader.Close() 236 err1 := p.PipeWriter.Close() 237 if err == nil { 238 err = err1 239 } 240 return err 241 } 242 243 func (p *pipe) LocalAddr() net.Addr { 244 return pipeAddr(0) 245 } 246 247 func (p *pipe) RemoteAddr() net.Addr { 248 return pipeAddr(0) 249 } 250 251 func (p *pipe) SetTimeout(nsec int64) error { 252 return errors.New("net.Pipe does not support timeouts") 253 } 254 255 func (p *pipe) SetReadTimeout(nsec int64) error { 256 return errors.New("net.Pipe does not support timeouts") 257 } 258 259 func (p *pipe) SetWriteTimeout(nsec int64) error { 260 return errors.New("net.Pipe does not support timeouts") 261 }