THRIFT-4285 Move TX/RX methods from gen. code to library
This change removes a lot of duplication from generated code and allows
the caller to customize how they can read from / write to the
transport. Backwards compatible adapters make the change compatible
with existing code in use by consuming applications.
Client: Go
This closes #1382
diff --git a/lib/go/test/tests/client_error_test.go b/lib/go/test/tests/client_error_test.go
index ad43447..4a8ef13 100644
--- a/lib/go/test/tests/client_error_test.go
+++ b/lib/go/test/tests/client_error_test.go
@@ -20,11 +20,12 @@
package tests
import (
- "github.com/golang/mock/gomock"
"errors"
"errortest"
"testing"
"thrift"
+
+ "github.com/golang/mock/gomock"
)
// TestCase: Comprehensive call and reply workflow in the client.
@@ -397,7 +398,6 @@
// Expecting TTransportError on fail.
func TestClientReportTTransportErrors(t *testing.T) {
mockCtrl := gomock.NewController(t)
- transport := thrift.NewTMemoryBuffer()
thing := errortest.NewTestStruct()
thing.M = make(map[string]string)
@@ -411,6 +411,38 @@
if !prepareClientCallReply(protocol, i, err) {
return
}
+ client := errortest.NewErrorTestClient(thrift.NewTStandardClient(protocol, protocol))
+ _, retErr := client.TestStruct(defaultCtx, thing)
+ mockCtrl.Finish()
+ err2, ok := retErr.(thrift.TTransportException)
+ if !ok {
+ t.Fatal("Expected a TTrasportException")
+ }
+
+ if err2.TypeId() != thrift.TIMED_OUT {
+ t.Fatal("Expected TIMED_OUT error")
+ }
+ }
+}
+
+// TestCase: Comprehensive call and reply workflow in the client.
+// Expecting TTransportError on fail.
+// Similar to TestClientReportTTransportErrors, but using legacy client constructor.
+func TestClientReportTTransportErrorsLegacy(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ transport := thrift.NewTMemoryBuffer()
+ thing := errortest.NewTestStruct()
+ thing.M = make(map[string]string)
+ thing.L = make([]string, 0)
+ thing.S = make([]string, 0)
+ thing.I = 3
+
+ err := thrift.NewTTransportException(thrift.TIMED_OUT, "test")
+ for i := 0; ; i++ {
+ protocol := NewMockTProtocol(mockCtrl)
+ if !prepareClientCallReply(protocol, i, err) {
+ return
+ }
client := errortest.NewErrorTestClientProtocol(transport, protocol, protocol)
_, retErr := client.TestStruct(defaultCtx, thing)
mockCtrl.Finish()
@@ -429,7 +461,6 @@
// Expecting TTProtocolErrors on fail.
func TestClientReportTProtocolErrors(t *testing.T) {
mockCtrl := gomock.NewController(t)
- transport := thrift.NewTMemoryBuffer()
thing := errortest.NewTestStruct()
thing.M = make(map[string]string)
@@ -443,6 +474,37 @@
if !prepareClientCallReply(protocol, i, err) {
return
}
+ client := errortest.NewErrorTestClient(thrift.NewTStandardClient(protocol, protocol))
+ _, retErr := client.TestStruct(defaultCtx, thing)
+ mockCtrl.Finish()
+ err2, ok := retErr.(thrift.TProtocolException)
+ if !ok {
+ t.Fatal("Expected a TProtocolException")
+ }
+ if err2.TypeId() != thrift.INVALID_DATA {
+ t.Fatal("Expected INVALID_DATA error")
+ }
+ }
+}
+
+// TestCase: Comprehensive call and reply workflow in the client.
+// Expecting TTProtocolErrors on fail.
+// Similar to TestClientReportTProtocolErrors, but using legacy client constructor.
+func TestClientReportTProtocolErrorsLegacy(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ transport := thrift.NewTMemoryBuffer()
+ thing := errortest.NewTestStruct()
+ thing.M = make(map[string]string)
+ thing.L = make([]string, 0)
+ thing.S = make([]string, 0)
+ thing.I = 3
+
+ err := thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, errors.New("test"))
+ for i := 0; ; i++ {
+ protocol := NewMockTProtocol(mockCtrl)
+ if !prepareClientCallReply(protocol, i, err) {
+ return
+ }
client := errortest.NewErrorTestClientProtocol(transport, protocol, protocol)
_, retErr := client.TestStruct(defaultCtx, thing)
mockCtrl.Finish()
@@ -557,13 +619,47 @@
// TestCase: call and reply with exception workflow in the client.
func TestClientCallException(t *testing.T) {
mockCtrl := gomock.NewController(t)
- transport := thrift.NewTMemoryBuffer()
err := thrift.NewTTransportException(thrift.TIMED_OUT, "test")
for i := 0; ; i++ {
protocol := NewMockTProtocol(mockCtrl)
willComplete := !prepareClientCallException(protocol, i, err)
+ client := errortest.NewErrorTestClient(thrift.NewTStandardClient(protocol, protocol))
+ _, retErr := client.TestString(defaultCtx, "test")
+ mockCtrl.Finish()
+
+ if !willComplete {
+ err2, ok := retErr.(thrift.TTransportException)
+ if !ok {
+ t.Fatal("Expected a TTransportException")
+ }
+ if err2.TypeId() != thrift.TIMED_OUT {
+ t.Fatal("Expected TIMED_OUT error")
+ }
+ } else {
+ err2, ok := retErr.(thrift.TApplicationException)
+ if !ok {
+ t.Fatal("Expected a TApplicationException")
+ }
+ if err2.TypeId() != thrift.PROTOCOL_ERROR {
+ t.Fatal("Expected PROTOCOL_ERROR error")
+ }
+ break
+ }
+ }
+}
+
+// TestCase: call and reply with exception workflow in the client.
+// Similar to TestClientCallException, but using legacy client constructor.
+func TestClientCallExceptionLegacy(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ transport := thrift.NewTMemoryBuffer()
+ err := thrift.NewTTransportException(thrift.TIMED_OUT, "test")
+ for i := 0; ; i++ {
+ protocol := NewMockTProtocol(mockCtrl)
+ willComplete := !prepareClientCallException(protocol, i, err)
+
client := errortest.NewErrorTestClientProtocol(transport, protocol, protocol)
_, retErr := client.TestString(defaultCtx, "test")
mockCtrl.Finish()
@@ -592,6 +688,36 @@
// TestCase: Mismatching sequence id has been received in the client.
func TestClientSeqIdMismatch(t *testing.T) {
mockCtrl := gomock.NewController(t)
+ protocol := NewMockTProtocol(mockCtrl)
+ gomock.InOrder(
+ protocol.EXPECT().WriteMessageBegin("testString", thrift.CALL, int32(1)),
+ protocol.EXPECT().WriteStructBegin("testString_args"),
+ protocol.EXPECT().WriteFieldBegin("s", thrift.TType(thrift.STRING), int16(1)),
+ protocol.EXPECT().WriteString("test"),
+ protocol.EXPECT().WriteFieldEnd(),
+ protocol.EXPECT().WriteFieldStop(),
+ protocol.EXPECT().WriteStructEnd(),
+ protocol.EXPECT().WriteMessageEnd(),
+ protocol.EXPECT().Flush(),
+ protocol.EXPECT().ReadMessageBegin().Return("testString", thrift.REPLY, int32(2), nil),
+ )
+
+ client := errortest.NewErrorTestClient(thrift.NewTStandardClient(protocol, protocol))
+ _, err := client.TestString(defaultCtx, "test")
+ mockCtrl.Finish()
+ appErr, ok := err.(thrift.TApplicationException)
+ if !ok {
+ t.Fatal("Expected TApplicationException")
+ }
+ if appErr.TypeId() != thrift.BAD_SEQUENCE_ID {
+ t.Fatal("Expected BAD_SEQUENCE_ID error")
+ }
+}
+
+// TestCase: Mismatching sequence id has been received in the client.
+// Similar to TestClientSeqIdMismatch, but using legacy client constructor.
+func TestClientSeqIdMismatchLegeacy(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
transport := thrift.NewTMemoryBuffer()
protocol := NewMockTProtocol(mockCtrl)
gomock.InOrder(
@@ -622,6 +748,36 @@
// TestCase: Wrong method name has been received in the client.
func TestClientWrongMethodName(t *testing.T) {
mockCtrl := gomock.NewController(t)
+ protocol := NewMockTProtocol(mockCtrl)
+ gomock.InOrder(
+ protocol.EXPECT().WriteMessageBegin("testString", thrift.CALL, int32(1)),
+ protocol.EXPECT().WriteStructBegin("testString_args"),
+ protocol.EXPECT().WriteFieldBegin("s", thrift.TType(thrift.STRING), int16(1)),
+ protocol.EXPECT().WriteString("test"),
+ protocol.EXPECT().WriteFieldEnd(),
+ protocol.EXPECT().WriteFieldStop(),
+ protocol.EXPECT().WriteStructEnd(),
+ protocol.EXPECT().WriteMessageEnd(),
+ protocol.EXPECT().Flush(),
+ protocol.EXPECT().ReadMessageBegin().Return("unknown", thrift.REPLY, int32(1), nil),
+ )
+
+ client := errortest.NewErrorTestClient(thrift.NewTStandardClient(protocol, protocol))
+ _, err := client.TestString(defaultCtx, "test")
+ mockCtrl.Finish()
+ appErr, ok := err.(thrift.TApplicationException)
+ if !ok {
+ t.Fatal("Expected TApplicationException")
+ }
+ if appErr.TypeId() != thrift.WRONG_METHOD_NAME {
+ t.Fatal("Expected WRONG_METHOD_NAME error")
+ }
+}
+
+// TestCase: Wrong method name has been received in the client.
+// Similar to TestClientWrongMethodName, but using legacy client constructor.
+func TestClientWrongMethodNameLegacy(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
transport := thrift.NewTMemoryBuffer()
protocol := NewMockTProtocol(mockCtrl)
gomock.InOrder(
@@ -652,6 +808,36 @@
// TestCase: Wrong message type has been received in the client.
func TestClientWrongMessageType(t *testing.T) {
mockCtrl := gomock.NewController(t)
+ protocol := NewMockTProtocol(mockCtrl)
+ gomock.InOrder(
+ protocol.EXPECT().WriteMessageBegin("testString", thrift.CALL, int32(1)),
+ protocol.EXPECT().WriteStructBegin("testString_args"),
+ protocol.EXPECT().WriteFieldBegin("s", thrift.TType(thrift.STRING), int16(1)),
+ protocol.EXPECT().WriteString("test"),
+ protocol.EXPECT().WriteFieldEnd(),
+ protocol.EXPECT().WriteFieldStop(),
+ protocol.EXPECT().WriteStructEnd(),
+ protocol.EXPECT().WriteMessageEnd(),
+ protocol.EXPECT().Flush(),
+ protocol.EXPECT().ReadMessageBegin().Return("testString", thrift.INVALID_TMESSAGE_TYPE, int32(1), nil),
+ )
+
+ client := errortest.NewErrorTestClient(thrift.NewTStandardClient(protocol, protocol))
+ _, err := client.TestString(defaultCtx, "test")
+ mockCtrl.Finish()
+ appErr, ok := err.(thrift.TApplicationException)
+ if !ok {
+ t.Fatal("Expected TApplicationException")
+ }
+ if appErr.TypeId() != thrift.INVALID_MESSAGE_TYPE_EXCEPTION {
+ t.Fatal("Expected INVALID_MESSAGE_TYPE_EXCEPTION error")
+ }
+}
+
+// TestCase: Wrong message type has been received in the client.
+// Similar to TestClientWrongMessageType, but using legacy client constructor.
+func TestClientWrongMessageTypeLegacy(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
transport := thrift.NewTMemoryBuffer()
protocol := NewMockTProtocol(mockCtrl)
gomock.InOrder(
diff --git a/lib/go/test/tests/multiplexed_protocol_test.go b/lib/go/test/tests/multiplexed_protocol_test.go
index 27802e5..0b5896b 100644
--- a/lib/go/test/tests/multiplexed_protocol_test.go
+++ b/lib/go/test/tests/multiplexed_protocol_test.go
@@ -36,15 +36,22 @@
}
}
+func createTransport(addr net.Addr) (thrift.TTransport, error) {
+ socket := thrift.NewTSocketFromAddrTimeout(addr, TIMEOUT)
+ transport := thrift.NewTFramedTransport(socket)
+ err := transport.Open()
+ if err != nil {
+ return nil, err
+ }
+ return transport, nil
+}
-var processor = thrift.NewTMultiplexedProcessor()
-
-func TestInitTwoServers(t *testing.T) {
- var err error
+func TestMultiplexedProtocolFirst(t *testing.T) {
+ processor := thrift.NewTMultiplexedProcessor()
protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
transportFactory := thrift.NewTTransportFactory()
transportFactory = thrift.NewTFramedTransportFactory(transportFactory)
- addr = FindAvailableTCPServerPort()
+ addr := FindAvailableTCPServerPort()
serverTransport, err := thrift.NewTServerSocketTimeout(addr.String(), TIMEOUT)
if err != nil {
t.Fatal("Unable to create server socket", err)
@@ -57,82 +64,117 @@
secondProcessor := multiplexedprotocoltest.NewSecondProcessor(&SecondImpl{})
processor.RegisterProcessor("SecondService", secondProcessor)
+ defer server.Stop()
go server.Serve()
time.Sleep(10 * time.Millisecond)
-}
-var firstClient *multiplexedprotocoltest.FirstClient
-
-func TestInitClient1(t *testing.T) {
- socket := thrift.NewTSocketFromAddrTimeout(addr, TIMEOUT)
- transport := thrift.NewTFramedTransport(socket)
- var protocol thrift.TProtocol = thrift.NewTBinaryProtocolTransport(transport)
- protocol = thrift.NewTMultiplexedProtocol(protocol, "FirstService")
- firstClient = multiplexedprotocoltest.NewFirstClientProtocol(transport, protocol, protocol)
- err := transport.Open()
+ transport, err := createTransport(addr)
if err != nil {
- t.Fatal("Unable to open client socket", err)
+ t.Fatal(err)
}
-}
+ defer transport.Close()
+ protocol := thrift.NewTMultiplexedProtocol(thrift.NewTBinaryProtocolTransport(transport), "FirstService")
-var secondClient *multiplexedprotocoltest.SecondClient
+ client := multiplexedprotocoltest.NewFirstClient(thrift.NewTStandardClient(protocol, protocol))
-func TestInitClient2(t *testing.T) {
- socket := thrift.NewTSocketFromAddrTimeout(addr, TIMEOUT)
- transport := thrift.NewTFramedTransport(socket)
- var protocol thrift.TProtocol = thrift.NewTBinaryProtocolTransport(transport)
- protocol = thrift.NewTMultiplexedProtocol(protocol, "SecondService")
- secondClient = multiplexedprotocoltest.NewSecondClientProtocol(transport, protocol, protocol)
- err := transport.Open()
- if err != nil {
- t.Fatal("Unable to open client socket", err)
- }
-}
-
-//create client without service prefix
-func createLegacyClient(t *testing.T) *multiplexedprotocoltest.SecondClient {
- socket := thrift.NewTSocketFromAddrTimeout(addr, TIMEOUT)
- transport := thrift.NewTFramedTransport(socket)
- var protocol thrift.TProtocol = thrift.NewTBinaryProtocolTransport(transport)
- legacyClient := multiplexedprotocoltest.NewSecondClientProtocol(transport, protocol, protocol)
- err := transport.Open()
- if err != nil {
- t.Fatal("Unable to open client socket", err)
- }
- return legacyClient
-}
-
-func TestCallFirst(t *testing.T) {
- ret, err := firstClient.ReturnOne(defaultCtx)
+ ret, err := client.ReturnOne(defaultCtx)
if err != nil {
t.Fatal("Unable to call first server:", err)
- }
- if ret != 1 {
+ } else if ret != 1 {
t.Fatal("Unexpected result from server: ", ret)
}
}
-func TestCallSecond(t *testing.T) {
- ret, err := secondClient.ReturnTwo(defaultCtx)
+func TestMultiplexedProtocolSecond(t *testing.T) {
+ processor := thrift.NewTMultiplexedProcessor()
+ protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
+ transportFactory := thrift.NewTTransportFactory()
+ transportFactory = thrift.NewTFramedTransportFactory(transportFactory)
+ addr := FindAvailableTCPServerPort()
+ serverTransport, err := thrift.NewTServerSocketTimeout(addr.String(), TIMEOUT)
+ if err != nil {
+ t.Fatal("Unable to create server socket", err)
+ }
+ server = thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory)
+
+ firstProcessor := multiplexedprotocoltest.NewFirstProcessor(&FirstImpl{})
+ processor.RegisterProcessor("FirstService", firstProcessor)
+
+ secondProcessor := multiplexedprotocoltest.NewSecondProcessor(&SecondImpl{})
+ processor.RegisterProcessor("SecondService", secondProcessor)
+
+ defer server.Stop()
+ go server.Serve()
+ time.Sleep(10 * time.Millisecond)
+
+ transport, err := createTransport(addr)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer transport.Close()
+ protocol := thrift.NewTMultiplexedProtocol(thrift.NewTBinaryProtocolTransport(transport), "SecondService")
+
+ client := multiplexedprotocoltest.NewSecondClient(thrift.NewTStandardClient(protocol, protocol))
+
+ ret, err := client.ReturnTwo(defaultCtx)
if err != nil {
t.Fatal("Unable to call second server:", err)
- }
- if ret != 2 {
+ } else if ret != 2 {
t.Fatal("Unexpected result from server: ", ret)
}
}
-func TestCallLegacy(t *testing.T) {
- legacyClient := createLegacyClient(t)
- ret, err := legacyClient.ReturnTwo(defaultCtx)
+func TestMultiplexedProtocolLegacy(t *testing.T) {
+ processor := thrift.NewTMultiplexedProcessor()
+ protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
+ transportFactory := thrift.NewTTransportFactory()
+ transportFactory = thrift.NewTFramedTransportFactory(transportFactory)
+ addr := FindAvailableTCPServerPort()
+ serverTransport, err := thrift.NewTServerSocketTimeout(addr.String(), TIMEOUT)
+ if err != nil {
+ t.Fatal("Unable to create server socket", err)
+ }
+ server = thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory)
+
+ firstProcessor := multiplexedprotocoltest.NewFirstProcessor(&FirstImpl{})
+ processor.RegisterProcessor("FirstService", firstProcessor)
+
+ secondProcessor := multiplexedprotocoltest.NewSecondProcessor(&SecondImpl{})
+ processor.RegisterProcessor("SecondService", secondProcessor)
+
+ defer server.Stop()
+ go server.Serve()
+ time.Sleep(10 * time.Millisecond)
+
+ transport, err := createTransport(addr)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ defer transport.Close()
+
+ protocol := thrift.NewTBinaryProtocolTransport(transport)
+ client := multiplexedprotocoltest.NewSecondClient(thrift.NewTStandardClient(protocol, protocol))
+
+ ret, err := client.ReturnTwo(defaultCtx)
//expect error since default processor is not registered
if err == nil {
t.Fatal("Expecting error")
}
+
//register default processor and call again
processor.RegisterDefault(multiplexedprotocoltest.NewSecondProcessor(&SecondImpl{}))
- legacyClient = createLegacyClient(t)
- ret, err = legacyClient.ReturnTwo(defaultCtx)
+ transport, err = createTransport(addr)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ defer transport.Close()
+
+ protocol = thrift.NewTBinaryProtocolTransport(transport)
+ client = multiplexedprotocoltest.NewSecondClient(thrift.NewTStandardClient(protocol, protocol))
+
+ ret, err = client.ReturnTwo(defaultCtx)
if err != nil {
t.Fatal("Unable to call legacy server:", err)
}
@@ -140,9 +182,3 @@
t.Fatal("Unexpected result from server: ", ret)
}
}
-
-func TestShutdownServerAndClients(t *testing.T) {
- firstClient.Transport.Close()
- secondClient.Transport.Close()
- server.Stop()
-}
diff --git a/lib/go/test/tests/one_way_test.go b/lib/go/test/tests/one_way_test.go
index 32881e2..8abd671 100644
--- a/lib/go/test/tests/one_way_test.go
+++ b/lib/go/test/tests/one_way_test.go
@@ -59,7 +59,7 @@
func TestInitOnewayClient(t *testing.T) {
transport := thrift.NewTSocketFromAddrTimeout(addr, TIMEOUT)
protocol := thrift.NewTBinaryProtocolTransport(transport)
- client = onewaytest.NewOneWayClientProtocol(transport, protocol, protocol)
+ client = onewaytest.NewOneWayClient(thrift.NewTStandardClient(protocol, protocol))
err := transport.Open()
if err != nil {
t.Fatal("Unable to open client socket", err)
diff --git a/lib/go/test/tests/protocol_mock.go b/lib/go/test/tests/protocol_mock.go
index 9197fed..8476c86 100644
--- a/lib/go/test/tests/protocol_mock.go
+++ b/lib/go/test/tests/protocol_mock.go
@@ -24,6 +24,7 @@
import (
thrift "thrift"
+
gomock "github.com/golang/mock/gomock"
)
diff --git a/lib/go/test/tests/protocols_test.go b/lib/go/test/tests/protocols_test.go
index 1580678..cffd9c3 100644
--- a/lib/go/test/tests/protocols_test.go
+++ b/lib/go/test/tests/protocols_test.go
@@ -47,7 +47,7 @@
t.Fatal(err)
}
var protocol thrift.TProtocol = protocolFactory.GetProtocol(transport)
- thriftTestClient := thrifttest.NewThriftTestClientProtocol(transport, protocol, protocol)
+ thriftTestClient := thrifttest.NewThriftTestClient(thrift.NewTStandardClient(protocol, protocol))
err = transport.Open()
if err != nil {
t.Fatal("Unable to open client socket", err)