THRIFT-2337 Golang does not report TIMED_OUT exceptions
Patch: Chris Bannister
diff --git a/lib/go/thrift/transport_exception.go b/lib/go/thrift/transport_exception.go
index dbab4d9..9505b44 100644
--- a/lib/go/thrift/transport_exception.go
+++ b/lib/go/thrift/transport_exception.go
@@ -20,13 +20,19 @@
package thrift
import (
+ "errors"
"io"
)
+type timeoutable interface {
+ Timeout() bool
+}
+
// Thrift Transport exception
type TTransportException interface {
TException
TypeId() int
+ Err() error
}
const (
@@ -38,8 +44,8 @@
)
type tTransportException struct {
- typeId int
- message string
+ typeId int
+ err error
}
func (p *tTransportException) TypeId() int {
@@ -47,22 +53,38 @@
}
func (p *tTransportException) Error() string {
- return p.message
+ return p.err.Error()
}
-func NewTTransportException(t int, m string) TTransportException {
- return &tTransportException{typeId: t, message: m}
+func (p *tTransportException) Err() error {
+ return p.err
+}
+
+func NewTTransportException(t int, e string) TTransportException {
+ return &tTransportException{typeId: t, err: errors.New(e)}
}
func NewTTransportExceptionFromError(e error) TTransportException {
if e == nil {
return nil
}
+
if t, ok := e.(TTransportException); ok {
return t
}
- if e == io.EOF {
- return NewTTransportException(END_OF_FILE, e.Error())
+
+ switch v := e.(type) {
+ case TTransportException:
+ return v
+ case timeoutable:
+ if v.Timeout() {
+ return &tTransportException{typeId: TIMED_OUT, err: e}
+ }
}
- return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, e.Error())
+
+ if e == io.EOF {
+ return &tTransportException{typeId: END_OF_FILE, err: e}
+ }
+
+ return &tTransportException{typeId: UNKNOWN_TRANSPORT_EXCEPTION, err: e}
}
diff --git a/lib/go/thrift/transport_exception_test.go b/lib/go/thrift/transport_exception_test.go
new file mode 100644
index 0000000..55b0a77
--- /dev/null
+++ b/lib/go/thrift/transport_exception_test.go
@@ -0,0 +1,41 @@
+package thrift
+
+import (
+ "fmt"
+ "io"
+
+ "testing"
+)
+
+type timeout struct{ timedout bool }
+
+func (t *timeout) Timeout() bool {
+ return t.timedout
+}
+
+func (t *timeout) Error() string {
+ return fmt.Sprintf("Timeout: %v", t.timedout)
+}
+
+func TestTExceptionTimeout(t *testing.T) {
+ timeout := &timeout{true}
+ exception := NewTTransportExceptionFromError(timeout)
+ if timeout.Error() != exception.Error() {
+ t.Fatalf("Error did not match: expected %q, got %q", timeout.Error(), exception.Error())
+ }
+
+ if exception.TypeId() != TIMED_OUT {
+ t.Fatalf("TypeId was not TIMED_OUT: expected %v, got %v", TIMED_OUT, exception.TypeId())
+ }
+}
+
+func TestTExceptionEOF(t *testing.T) {
+ exception := NewTTransportExceptionFromError(io.EOF)
+ if io.EOF.Error() != exception.Error() {
+ t.Fatalf("Error did not match: expected %q, got %q", io.EOF.Error(), exception.Error())
+ }
+
+ if exception.TypeId() != END_OF_FILE {
+ t.Fatalf("TypeId was not END_OF_FILE: expected %v, got %v", END_OF_FILE, exception.TypeId())
+ }
+}