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)