summaryrefslogtreecommitdiff
path: root/src/pkg/rpc/server_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/rpc/server_test.go')
-rw-r--r--src/pkg/rpc/server_test.go126
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)
+}