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.
27 func (t *Arith) Add(args *Args, reply *Reply) os.Error {
28 reply.C = args.A + args.B
32 func (t *Arith) Mul(args *Args, reply *Reply) os.Error {
33 reply.C = args.A * args.B
37 func (t *Arith) Div(args *Args, reply *Reply) os.Error {
39 return os.NewError("divide by zero")
41 reply.C = args.A / args.B
45 func (t *Arith) Error(args *Args, reply *Reply) os.Error {
50 rpc.Register(new(Arith))
53 func TestServer(t *testing.T) {
55 Id interface{} `json:"id"`
56 Result Reply `json:"result"`
57 Error interface{} `json:"error"`
60 cli, srv := net.Pipe()
63 dec := json.NewDecoder(cli)
65 // Send hand-coded requests to server, parse responses.
66 for i := 0; i < 10; i++ {
67 fmt.Fprintf(cli, `{"method": "Arith.Add", "id": "\u%04d", "params": [{"A": %d, "B": %d}]}`, i, i, i+1)
69 err := dec.Decode(&resp)
71 t.Fatalf("Decode: %s", err)
73 if resp.Error != nil {
74 t.Fatalf("resp.Error: %s", resp.Error)
76 if resp.Id.(string) != string(i) {
77 t.Fatalf("resp: bad id %q want %q", resp.Id.(string), string(i))
79 if resp.Result.C != 2*i+1 {
80 t.Fatalf("resp: bad result: %d+%d=%d", i, i+1, resp.Result.C)
84 fmt.Fprintf(cli, "{}\n")
86 if err := dec.Decode(&resp); err != nil {
87 t.Fatalf("Decode after empty: %s", err)
89 if resp.Error == nil {
90 t.Fatalf("Expected error, got nil")
94 func TestClient(t *testing.T) {
95 // Assume server is okay (TestServer is above).
96 // Test client against server.
97 cli, srv := net.Pipe()
100 client := NewClient(cli)
106 err := client.Call("Arith.Add", args, reply)
108 t.Errorf("Add: expected no error but got string %q", err.String())
110 if reply.C != args.A+args.B {
111 t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
116 err = client.Call("Arith.Mul", args, reply)
118 t.Errorf("Mul: expected no error but got string %q", err.String())
120 if reply.C != args.A*args.B {
121 t.Errorf("Mul: expected %d got %d", reply.C, args.A*args.B)
126 mulReply := new(Reply)
127 mulCall := client.Go("Arith.Mul", args, mulReply, nil)
128 addReply := new(Reply)
129 addCall := client.Go("Arith.Add", args, addReply, nil)
131 addCall = <-addCall.Done
132 if addCall.Error != nil {
133 t.Errorf("Add: expected no error but got string %q", addCall.Error.String())
135 if addReply.C != args.A+args.B {
136 t.Errorf("Add: expected %d got %d", addReply.C, args.A+args.B)
139 mulCall = <-mulCall.Done
140 if mulCall.Error != nil {
141 t.Errorf("Mul: expected no error but got string %q", mulCall.Error.String())
143 if mulReply.C != args.A*args.B {
144 t.Errorf("Mul: expected %d got %d", mulReply.C, args.A*args.B)
150 err = client.Call("Arith.Div", args, reply)
151 // expect an error: zero divide
153 t.Error("Div: expected error")
154 } else if err.String() != "divide by zero" {
155 t.Error("Div: expected divide by zero error; got", err)
159 func TestMalformedInput(t *testing.T) {
160 cli, srv := net.Pipe()
161 go cli.Write([]byte(`{id:1}`)) // invalid json
162 ServeConn(srv) // must return, not loop
165 func TestUnexpectedError(t *testing.T) {
167 go cli.PipeWriter.CloseWithError(os.NewError("unexpected error!")) // reader will get this error
168 ServeConn(srv) // must return, not loop
171 // Copied from package net.
172 func myPipe() (*pipe, *pipe) {
176 return &pipe{r1, w2}, &pipe{r2, w1}
186 func (pipeAddr) Network() string {
190 func (pipeAddr) String() string {
194 func (p *pipe) Close() os.Error {
195 err := p.PipeReader.Close()
196 err1 := p.PipeWriter.Close()
203 func (p *pipe) LocalAddr() net.Addr {
207 func (p *pipe) RemoteAddr() net.Addr {
211 func (p *pipe) SetTimeout(nsec int64) os.Error {
212 return os.NewError("net.Pipe does not support timeouts")
215 func (p *pipe) SetReadTimeout(nsec int64) os.Error {
216 return os.NewError("net.Pipe does not support timeouts")
219 func (p *pipe) SetWriteTimeout(nsec int64) os.Error {
220 return os.NewError("net.Pipe does not support timeouts")