client.request.Seq = c.seq
client.request.ServiceMethod = c.ServiceMethod
if err := client.codec.WriteRequest(&client.request, c.Args); err != nil {
- panic("rpc: client encode error: " + err.String())
+ c.Error = err
+ c.done()
}
}
// the same Call object. If done is nil, Go will allocate a new channel.
// If non-nil, done must be buffered or Go will deliberately crash.
func (client *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call) *Call {
- c := new(Call)
- c.ServiceMethod = serviceMethod
- c.Args = args
- c.Reply = reply
+ call := new(Call)
+ call.ServiceMethod = serviceMethod
+ call.Args = args
+ call.Reply = reply
if done == nil {
done = make(chan *Call, 10) // buffered.
} else {
log.Panic("rpc: done channel is unbuffered")
}
}
- c.Done = done
+ call.Done = done
if client.shutdown {
- c.Error = ErrShutdown
- c.done()
- return c
+ call.Error = ErrShutdown
+ call.done()
+ return call
}
- client.send(c)
- return c
+ client.send(call)
+ return call
}
// Call invokes the named function, waits for it to complete, and returns its error status.
fmt.Printf("mallocs per HTTP rpc round trip: %d\n", countMallocs(dialHTTP, t))
}
+type writeCrasher struct{}
+
+func (writeCrasher) Close() os.Error {
+ return nil
+}
+
+func (writeCrasher) Read(p []byte) (int, os.Error) {
+ return 0, os.EOF
+}
+
+func (writeCrasher) Write(p []byte) (int, os.Error) {
+ return 0, os.NewError("fake write failure")
+}
+
+func TestClientWriteError(t *testing.T) {
+ c := NewClient(writeCrasher{})
+ res := false
+ err := c.Call("foo", 1, &res)
+ if err == nil {
+ t.Fatal("expected error")
+ }
+ if err.String() != "fake write failure" {
+ t.Error("unexpected value of error:", err)
+ }
+}
+
func benchmarkEndToEnd(dial func() (*Client, os.Error), b *testing.B) {
b.StopTimer()
once.Do(startServer)