Merge from mainline (167278:168000).
[official-gcc/graphite-test-results.git] / libgo / go / rpc / server_test.go
blob355d51ce46b828c99729c9d3cc285c6fa70a677f
1 // Copyright 2009 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.
5 package rpc
7 import (
8 "fmt"
9 "http"
10 "log"
11 "net"
12 "os"
13 "strings"
14 "sync"
15 "testing"
16 "time"
19 var (
20 serverAddr, newServerAddr string
21 httpServerAddr string
22 once, newOnce, httpOnce sync.Once
25 const (
26 second = 1e9
27 newHttpPath = "/foo"
30 type Args struct {
31 A, B int
34 type Reply struct {
35 C int
38 type Arith int
40 func (t *Arith) Add(args *Args, reply *Reply) os.Error {
41 reply.C = args.A + args.B
42 return nil
45 func (t *Arith) Mul(args *Args, reply *Reply) os.Error {
46 reply.C = args.A * args.B
47 return nil
50 func (t *Arith) Div(args *Args, reply *Reply) os.Error {
51 if args.B == 0 {
52 return os.ErrorString("divide by zero")
54 reply.C = args.A / args.B
55 return nil
58 func (t *Arith) String(args *Args, reply *string) os.Error {
59 *reply = fmt.Sprintf("%d+%d=%d", args.A, args.B, args.A+args.B)
60 return nil
63 func (t *Arith) Scan(args *string, reply *Reply) (err os.Error) {
64 _, err = fmt.Sscan(*args, &reply.C)
65 return
68 func (t *Arith) Error(args *Args, reply *Reply) os.Error {
69 panic("ERROR")
72 func listenTCP() (net.Listener, string) {
73 l, e := net.Listen("tcp", "127.0.0.1:0") // any available address
74 if e != nil {
75 log.Exitf("net.Listen tcp :0: %v", e)
77 return l, l.Addr().String()
80 func startServer() {
81 Register(new(Arith))
83 var l net.Listener
84 l, serverAddr = listenTCP()
85 log.Println("Test RPC server listening on", serverAddr)
86 go Accept(l)
88 HandleHTTP()
89 httpOnce.Do(startHttpServer)
92 func startNewServer() {
93 s := NewServer()
94 s.Register(new(Arith))
96 var l net.Listener
97 l, newServerAddr = listenTCP()
98 log.Println("NewServer test RPC server listening on", newServerAddr)
99 go Accept(l)
101 s.HandleHTTP(newHttpPath, "/bar")
102 httpOnce.Do(startHttpServer)
105 func startHttpServer() {
106 var l net.Listener
107 l, httpServerAddr = listenTCP()
108 httpServerAddr = l.Addr().String()
109 log.Println("Test HTTP RPC server listening on", httpServerAddr)
110 go http.Serve(l, nil)
113 func TestRPC(t *testing.T) {
114 once.Do(startServer)
115 testRPC(t, serverAddr)
116 newOnce.Do(startNewServer)
117 testRPC(t, newServerAddr)
120 func testRPC(t *testing.T, addr string) {
121 client, err := Dial("tcp", addr)
122 if err != nil {
123 t.Fatal("dialing", err)
126 // Synchronous calls
127 args := &Args{7, 8}
128 reply := new(Reply)
129 err = client.Call("Arith.Add", args, reply)
130 if err != nil {
131 t.Errorf("Add: expected no error but got string %q", err.String())
133 if reply.C != args.A+args.B {
134 t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
137 args = &Args{7, 8}
138 reply = new(Reply)
139 err = client.Call("Arith.Mul", args, reply)
140 if err != nil {
141 t.Errorf("Mul: expected no error but got string %q", err.String())
143 if reply.C != args.A*args.B {
144 t.Errorf("Mul: expected %d got %d", reply.C, args.A*args.B)
147 // Out of order.
148 args = &Args{7, 8}
149 mulReply := new(Reply)
150 mulCall := client.Go("Arith.Mul", args, mulReply, nil)
151 addReply := new(Reply)
152 addCall := client.Go("Arith.Add", args, addReply, nil)
154 addCall = <-addCall.Done
155 if addCall.Error != nil {
156 t.Errorf("Add: expected no error but got string %q", addCall.Error.String())
158 if addReply.C != args.A+args.B {
159 t.Errorf("Add: expected %d got %d", addReply.C, args.A+args.B)
162 mulCall = <-mulCall.Done
163 if mulCall.Error != nil {
164 t.Errorf("Mul: expected no error but got string %q", mulCall.Error.String())
166 if mulReply.C != args.A*args.B {
167 t.Errorf("Mul: expected %d got %d", mulReply.C, args.A*args.B)
170 // Error test
171 args = &Args{7, 0}
172 reply = new(Reply)
173 err = client.Call("Arith.Div", args, reply)
174 // expect an error: zero divide
175 if err == nil {
176 t.Error("Div: expected error")
177 } else if err.String() != "divide by zero" {
178 t.Error("Div: expected divide by zero error; got", err)
181 // Non-struct argument
182 const Val = 12345
183 str := fmt.Sprint(Val)
184 reply = new(Reply)
185 err = client.Call("Arith.Scan", &str, reply)
186 if err != nil {
187 t.Errorf("Scan: expected no error but got string %q", err.String())
188 } else if reply.C != Val {
189 t.Errorf("Scan: expected %d got %d", Val, reply.C)
192 // Non-struct reply
193 args = &Args{27, 35}
194 str = ""
195 err = client.Call("Arith.String", args, &str)
196 if err != nil {
197 t.Errorf("String: expected no error but got string %q", err.String())
199 expect := fmt.Sprintf("%d+%d=%d", args.A, args.B, args.A+args.B)
200 if str != expect {
201 t.Errorf("String: expected %s got %s", expect, str)
205 func TestHTTPRPC(t *testing.T) {
206 once.Do(startServer)
207 testHTTPRPC(t, "")
208 newOnce.Do(startNewServer)
209 testHTTPRPC(t, newHttpPath)
212 func testHTTPRPC(t *testing.T, path string) {
213 var client *Client
214 var err os.Error
215 if path == "" {
216 client, err = DialHTTP("tcp", httpServerAddr)
217 } else {
218 client, err = DialHTTPPath("tcp", httpServerAddr, path)
220 if err != nil {
221 t.Fatal("dialing", err)
224 // Synchronous calls
225 args := &Args{7, 8}
226 reply := new(Reply)
227 err = client.Call("Arith.Add", args, reply)
228 if err != nil {
229 t.Errorf("Add: expected no error but got string %q", err.String())
231 if reply.C != args.A+args.B {
232 t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
236 func TestCheckUnknownService(t *testing.T) {
237 once.Do(startServer)
239 conn, err := net.Dial("tcp", "", serverAddr)
240 if err != nil {
241 t.Fatal("dialing:", err)
244 client := NewClient(conn)
246 args := &Args{7, 8}
247 reply := new(Reply)
248 err = client.Call("Unknown.Add", args, reply)
249 if err == nil {
250 t.Error("expected error calling unknown service")
251 } else if strings.Index(err.String(), "service") < 0 {
252 t.Error("expected error about service; got", err)
256 func TestCheckUnknownMethod(t *testing.T) {
257 once.Do(startServer)
259 conn, err := net.Dial("tcp", "", serverAddr)
260 if err != nil {
261 t.Fatal("dialing:", err)
264 client := NewClient(conn)
266 args := &Args{7, 8}
267 reply := new(Reply)
268 err = client.Call("Arith.Unknown", args, reply)
269 if err == nil {
270 t.Error("expected error calling unknown service")
271 } else if strings.Index(err.String(), "method") < 0 {
272 t.Error("expected error about method; got", err)
276 func TestCheckBadType(t *testing.T) {
277 once.Do(startServer)
279 conn, err := net.Dial("tcp", "", serverAddr)
280 if err != nil {
281 t.Fatal("dialing:", err)
284 client := NewClient(conn)
286 reply := new(Reply)
287 err = client.Call("Arith.Add", reply, reply) // args, reply would be the correct thing to use
288 if err == nil {
289 t.Error("expected error calling Arith.Add with wrong arg type")
290 } else if strings.Index(err.String(), "type") < 0 {
291 t.Error("expected error about type; got", err)
295 type ArgNotPointer int
296 type ReplyNotPointer int
297 type ArgNotPublic int
298 type ReplyNotPublic int
299 type local struct{}
301 func (t *ArgNotPointer) ArgNotPointer(args Args, reply *Reply) os.Error {
302 return nil
305 func (t *ReplyNotPointer) ReplyNotPointer(args *Args, reply Reply) os.Error {
306 return nil
309 func (t *ArgNotPublic) ArgNotPublic(args *local, reply *Reply) os.Error {
310 return nil
313 func (t *ReplyNotPublic) ReplyNotPublic(args *Args, reply *local) os.Error {
314 return nil
317 // Check that registration handles lots of bad methods and a type with no suitable methods.
318 func TestRegistrationError(t *testing.T) {
319 err := Register(new(ArgNotPointer))
320 if err == nil {
321 t.Errorf("expected error registering ArgNotPointer")
323 err = Register(new(ReplyNotPointer))
324 if err == nil {
325 t.Errorf("expected error registering ReplyNotPointer")
327 err = Register(new(ArgNotPublic))
328 if err == nil {
329 t.Errorf("expected error registering ArgNotPublic")
331 err = Register(new(ReplyNotPublic))
332 if err == nil {
333 t.Errorf("expected error registering ReplyNotPublic")
337 type WriteFailCodec int
339 func (WriteFailCodec) WriteRequest(*Request, interface{}) os.Error {
340 // the panic caused by this error used to not unlock a lock.
341 return os.NewError("fail")
344 func (WriteFailCodec) ReadResponseHeader(*Response) os.Error {
345 time.Sleep(60e9)
346 panic("unreachable")
349 func (WriteFailCodec) ReadResponseBody(interface{}) os.Error {
350 time.Sleep(60e9)
351 panic("unreachable")
354 func (WriteFailCodec) Close() os.Error {
355 return nil
358 func TestSendDeadlock(t *testing.T) {
359 client := NewClientWithCodec(WriteFailCodec(0))
361 done := make(chan bool)
362 go func() {
363 testSendDeadlock(client)
364 testSendDeadlock(client)
365 done <- true
367 for i := 0; i < 50; i++ {
368 time.Sleep(100 * 1e6)
369 _, ok := <-done
370 if ok {
371 return
374 t.Fatal("deadlock")
377 func testSendDeadlock(client *Client) {
378 defer func() {
379 recover()
381 args := &Args{7, 8}
382 reply := new(Reply)
383 client.Call("Arith.Add", args, reply)