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.
31 type ArithAddResp
struct {
32 Id
interface{} `json:"id"`
33 Result Reply
`json:"result"`
34 Error
interface{} `json:"error"`
37 func (t
*Arith
) Add(args
*Args
, reply
*Reply
) error
{
38 reply
.C
= args
.A
+ args
.B
42 func (t
*Arith
) Mul(args
*Args
, reply
*Reply
) error
{
43 reply
.C
= args
.A
* args
.B
47 func (t
*Arith
) Div(args
*Args
, reply
*Reply
) error
{
49 return errors
.New("divide by zero")
51 reply
.C
= args
.A
/ args
.B
55 func (t
*Arith
) Error(args
*Args
, reply
*Reply
) error
{
59 type BuiltinTypes
struct{}
61 func (BuiltinTypes
) Map(i
int, reply
*map[int]int) error
{
66 func (BuiltinTypes
) Slice(i
int, reply
*[]int) error
{
67 *reply
= append(*reply
, i
)
71 func (BuiltinTypes
) Array(i
int, reply
*[1]int) error
{
77 rpc
.Register(new(Arith
))
78 rpc
.Register(BuiltinTypes
{})
81 func TestServerNoParams(t
*testing
.T
) {
82 cli
, srv
:= net
.Pipe()
85 dec
:= json
.NewDecoder(cli
)
87 fmt
.Fprintf(cli
, `{"method": "Arith.Add", "id": "123"}`)
89 if err
:= dec
.Decode(&resp
); err
!= nil {
90 t
.Fatalf("Decode after no params: %s", err
)
92 if resp
.Error
== nil {
93 t
.Fatalf("Expected error, got nil")
97 func TestServerEmptyMessage(t
*testing
.T
) {
98 cli
, srv
:= net
.Pipe()
101 dec
:= json
.NewDecoder(cli
)
103 fmt
.Fprintf(cli
, "{}")
104 var resp ArithAddResp
105 if err
:= dec
.Decode(&resp
); err
!= nil {
106 t
.Fatalf("Decode after empty: %s", err
)
108 if resp
.Error
== nil {
109 t
.Fatalf("Expected error, got nil")
113 func TestServer(t
*testing
.T
) {
114 cli
, srv
:= net
.Pipe()
117 dec
:= json
.NewDecoder(cli
)
119 // Send hand-coded requests to server, parse responses.
120 for i
:= 0; i
< 10; i
++ {
121 fmt
.Fprintf(cli
, `{"method": "Arith.Add", "id": "\u%04d", "params": [{"A": %d, "B": %d}]}`, i
, i
, i
+1)
122 var resp ArithAddResp
123 err
:= dec
.Decode(&resp
)
125 t
.Fatalf("Decode: %s", err
)
127 if resp
.Error
!= nil {
128 t
.Fatalf("resp.Error: %s", resp
.Error
)
130 if resp
.Id
.(string) != string(i
) {
131 t
.Fatalf("resp: bad id %q want %q", resp
.Id
.(string), string(i
))
133 if resp
.Result
.C
!= 2*i
+1 {
134 t
.Fatalf("resp: bad result: %d+%d=%d", i
, i
+1, resp
.Result
.C
)
139 func TestClient(t
*testing
.T
) {
140 // Assume server is okay (TestServer is above).
141 // Test client against server.
142 cli
, srv
:= net
.Pipe()
145 client
:= NewClient(cli
)
151 err
:= client
.Call("Arith.Add", args
, reply
)
153 t
.Errorf("Add: expected no error but got string %q", err
.Error())
155 if reply
.C
!= args
.A
+args
.B
{
156 t
.Errorf("Add: got %d expected %d", reply
.C
, args
.A
+args
.B
)
161 err
= client
.Call("Arith.Mul", args
, reply
)
163 t
.Errorf("Mul: expected no error but got string %q", err
.Error())
165 if reply
.C
!= args
.A
*args
.B
{
166 t
.Errorf("Mul: got %d expected %d", reply
.C
, args
.A
*args
.B
)
171 mulReply
:= new(Reply
)
172 mulCall
:= client
.Go("Arith.Mul", args
, mulReply
, nil)
173 addReply
:= new(Reply
)
174 addCall
:= client
.Go("Arith.Add", args
, addReply
, nil)
176 addCall
= <-addCall
.Done
177 if addCall
.Error
!= nil {
178 t
.Errorf("Add: expected no error but got string %q", addCall
.Error
.Error())
180 if addReply
.C
!= args
.A
+args
.B
{
181 t
.Errorf("Add: got %d expected %d", addReply
.C
, args
.A
+args
.B
)
184 mulCall
= <-mulCall
.Done
185 if mulCall
.Error
!= nil {
186 t
.Errorf("Mul: expected no error but got string %q", mulCall
.Error
.Error())
188 if mulReply
.C
!= args
.A
*args
.B
{
189 t
.Errorf("Mul: got %d expected %d", mulReply
.C
, args
.A
*args
.B
)
195 err
= client
.Call("Arith.Div", args
, reply
)
196 // expect an error: zero divide
198 t
.Error("Div: expected error")
199 } else if err
.Error() != "divide by zero" {
200 t
.Error("Div: expected divide by zero error; got", err
)
204 func TestBuiltinTypes(t
*testing
.T
) {
205 cli
, srv
:= net
.Pipe()
208 client
:= NewClient(cli
)
213 replyMap
:= map[int]int{}
214 err
:= client
.Call("BuiltinTypes.Map", arg
, &replyMap
)
216 t
.Errorf("Map: expected no error but got string %q", err
.Error())
218 if replyMap
[arg
] != arg
{
219 t
.Errorf("Map: expected %d got %d", arg
, replyMap
[arg
])
223 replySlice
:= []int{}
224 err
= client
.Call("BuiltinTypes.Slice", arg
, &replySlice
)
226 t
.Errorf("Slice: expected no error but got string %q", err
.Error())
228 if e
:= []int{arg
}; !reflect
.DeepEqual(replySlice
, e
) {
229 t
.Errorf("Slice: expected %v got %v", e
, replySlice
)
233 replyArray
:= [1]int{}
234 err
= client
.Call("BuiltinTypes.Array", arg
, &replyArray
)
236 t
.Errorf("Array: expected no error but got string %q", err
.Error())
238 if e
:= [1]int{arg
}; !reflect
.DeepEqual(replyArray
, e
) {
239 t
.Errorf("Array: expected %v got %v", e
, replyArray
)
243 func TestMalformedInput(t
*testing
.T
) {
244 cli
, srv
:= net
.Pipe()
245 go cli
.Write([]byte(`{id:1}`)) // invalid json
246 ServeConn(srv
) // must return, not loop
249 func TestMalformedOutput(t
*testing
.T
) {
250 cli
, srv
:= net
.Pipe()
251 go srv
.Write([]byte(`{"id":0,"result":null,"error":null}`))
252 go ioutil
.ReadAll(srv
)
254 client
:= NewClient(cli
)
259 err
:= client
.Call("Arith.Add", args
, reply
)
261 t
.Error("expected error")
265 func TestServerErrorHasNullResult(t
*testing
.T
) {
267 sc
:= NewServerCodec(struct {
272 Reader
: strings
.NewReader(`{"method": "Arith.Add", "id": "123", "params": []}`),
274 Closer
: ioutil
.NopCloser(nil),
276 r
:= new(rpc
.Request
)
277 if err
:= sc
.ReadRequestHeader(r
); err
!= nil {
280 const valueText
= "the value we don't want to see"
281 const errorText
= "some error"
282 err
:= sc
.WriteResponse(&rpc
.Response
{
283 ServiceMethod
: "Method",
290 if !strings
.Contains(out
.String(), errorText
) {
291 t
.Fatalf("Response didn't contain expected error %q: %s", errorText
, &out
)
293 if strings
.Contains(out
.String(), valueText
) {
294 t
.Errorf("Response contains both an error and value: %s", &out
)
298 func TestUnexpectedError(t
*testing
.T
) {
300 go cli
.PipeWriter
.CloseWithError(errors
.New("unexpected error!")) // reader will get this error
301 ServeConn(srv
) // must return, not loop
304 // Copied from package net.
305 func myPipe() (*pipe
, *pipe
) {
309 return &pipe
{r1
, w2
}, &pipe
{r2
, w1
}
319 func (pipeAddr
) Network() string {
323 func (pipeAddr
) String() string {
327 func (p
*pipe
) Close() error
{
328 err
:= p
.PipeReader
.Close()
329 err1
:= p
.PipeWriter
.Close()
336 func (p
*pipe
) LocalAddr() net
.Addr
{
340 func (p
*pipe
) RemoteAddr() net
.Addr
{
344 func (p
*pipe
) SetTimeout(nsec
int64) error
{
345 return errors
.New("net.Pipe does not support timeouts")
348 func (p
*pipe
) SetReadTimeout(nsec
int64) error
{
349 return errors
.New("net.Pipe does not support timeouts")
352 func (p
*pipe
) SetWriteTimeout(nsec
int64) error
{
353 return errors
.New("net.Pipe does not support timeouts")