diff options
Diffstat (limited to 'src/pkg/rpc/server_test.go')
-rw-r--r-- | src/pkg/rpc/server_test.go | 126 |
1 files changed, 108 insertions, 18 deletions
diff --git a/src/pkg/rpc/server_test.go b/src/pkg/rpc/server_test.go index e502db4e3..355d51ce4 100644 --- a/src/pkg/rpc/server_test.go +++ b/src/pkg/rpc/server_test.go @@ -9,17 +9,23 @@ import ( "http" "log" "net" - "once" "os" "strings" + "sync" "testing" + "time" ) -var serverAddr string -var httpServerAddr string - -const second = 1e9 +var ( + serverAddr, newServerAddr string + httpServerAddr string + once, newOnce, httpOnce sync.Once +) +const ( + second = 1e9 + newHttpPath = "/foo" +) type Args struct { A, B int @@ -63,32 +69,56 @@ func (t *Arith) Error(args *Args, reply *Reply) os.Error { panic("ERROR") } -func startServer() { - Register(new(Arith)) - +func listenTCP() (net.Listener, string) { l, e := net.Listen("tcp", "127.0.0.1:0") // any available address if e != nil { log.Exitf("net.Listen tcp :0: %v", e) } - serverAddr = l.Addr().String() - log.Stderr("Test RPC server listening on ", serverAddr) + return l, l.Addr().String() +} + +func startServer() { + Register(new(Arith)) + + var l net.Listener + l, serverAddr = listenTCP() + log.Println("Test RPC server listening on", serverAddr) go Accept(l) HandleHTTP() - l, e = net.Listen("tcp", "127.0.0.1:0") // any available address - if e != nil { - log.Stderrf("net.Listen tcp :0: %v", e) - os.Exit(1) - } + httpOnce.Do(startHttpServer) +} + +func startNewServer() { + s := NewServer() + s.Register(new(Arith)) + + var l net.Listener + l, newServerAddr = listenTCP() + log.Println("NewServer test RPC server listening on", newServerAddr) + go Accept(l) + + s.HandleHTTP(newHttpPath, "/bar") + httpOnce.Do(startHttpServer) +} + +func startHttpServer() { + var l net.Listener + l, httpServerAddr = listenTCP() httpServerAddr = l.Addr().String() - log.Stderr("Test HTTP RPC server listening on ", httpServerAddr) + log.Println("Test HTTP RPC server listening on", httpServerAddr) go http.Serve(l, nil) } func TestRPC(t *testing.T) { once.Do(startServer) + testRPC(t, serverAddr) + newOnce.Do(startNewServer) + testRPC(t, newServerAddr) +} - client, err := Dial("tcp", serverAddr) +func testRPC(t *testing.T, addr string) { + client, err := Dial("tcp", addr) if err != nil { t.Fatal("dialing", err) } @@ -174,8 +204,19 @@ func TestRPC(t *testing.T) { func TestHTTPRPC(t *testing.T) { once.Do(startServer) + testHTTPRPC(t, "") + newOnce.Do(startNewServer) + testHTTPRPC(t, newHttpPath) +} - client, err := DialHTTP("tcp", httpServerAddr) +func testHTTPRPC(t *testing.T, path string) { + var client *Client + var err os.Error + if path == "" { + client, err = DialHTTP("tcp", httpServerAddr) + } else { + client, err = DialHTTPPath("tcp", httpServerAddr, path) + } if err != nil { t.Fatal("dialing", err) } @@ -292,3 +333,52 @@ func TestRegistrationError(t *testing.T) { t.Errorf("expected error registering ReplyNotPublic") } } + +type WriteFailCodec int + +func (WriteFailCodec) WriteRequest(*Request, interface{}) os.Error { + // the panic caused by this error used to not unlock a lock. + return os.NewError("fail") +} + +func (WriteFailCodec) ReadResponseHeader(*Response) os.Error { + time.Sleep(60e9) + panic("unreachable") +} + +func (WriteFailCodec) ReadResponseBody(interface{}) os.Error { + time.Sleep(60e9) + panic("unreachable") +} + +func (WriteFailCodec) Close() os.Error { + return nil +} + +func TestSendDeadlock(t *testing.T) { + client := NewClientWithCodec(WriteFailCodec(0)) + + done := make(chan bool) + go func() { + testSendDeadlock(client) + testSendDeadlock(client) + done <- true + }() + for i := 0; i < 50; i++ { + time.Sleep(100 * 1e6) + _, ok := <-done + if ok { + return + } + } + t.Fatal("deadlock") +} + +func testSendDeadlock(client *Client) { + defer func() { + recover() + }() + args := &Args{7, 8} + reply := new(Reply) + client.Call("Arith.Add", args, reply) +} |