From 9c53ced962a2d1841bf524caf4685a4a62c80df0 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 28 Oct 2026 09:54:12 +0100 Subject: [PATCH] THRIFT-6459: Return a buffered transport from TBufferedTransportImpl.TFactory Client: delphi TBufferedTransportImpl.TFactory.GetTransport() created a TFramedTransportImpl, so a server, TSerializer or TDeserializer set up with this factory read and wrote the framed format. It now creates a TBufferedTransportImpl over the transport's IStreamTransport interface and raises TTransportExceptionBadArgs for a transport that does not offer one. The serializer test now also runs the protocol conformity checks, which read the plain wire format, through the buffered transport factory, and a new test checks the transport classes that both factories return. Co-Authored-By: Claude Opus 5.5 --- lib/delphi/src/Thrift.Transport.pas | 5 ++- .../test/serializer/TestSerializer.Tests.pas | 37 ++++++++++++++++++- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/lib/delphi/src/Thrift.Transport.pas b/lib/delphi/src/Thrift.Transport.pas index 22c11bc4590..04630b4db6a 100644 --- a/lib/delphi/src/Thrift.Transport.pas +++ b/lib/delphi/src/Thrift.Transport.pas @@ -1446,8 +1446,11 @@ procedure TBufferedTransportImpl.CheckReadBytesAvailable( const value : Int64); { TBufferedTransportImpl.TFactory } function TBufferedTransportImpl.TFactory.GetTransport( const aTransport: ITransport): ITransport; +var stream : IStreamTransport; begin - Result := TFramedTransportImpl.Create( aTransport); + if Supports( aTransport, IStreamTransport, stream) + then Result := TBufferedTransportImpl.Create( stream) + else raise TTransportExceptionBadArgs.Create('TBufferedTransportImpl requires an IStreamTransport'); end; diff --git a/lib/delphi/test/serializer/TestSerializer.Tests.pas b/lib/delphi/test/serializer/TestSerializer.Tests.pas index 27830335028..1faee2cba1d 100644 --- a/lib/delphi/test/serializer/TestSerializer.Tests.pas +++ b/lib/delphi/test/serializer/TestSerializer.Tests.pas @@ -83,6 +83,7 @@ TTestSerializer = class //extends TestCase { class function DataPtrOf( const bytes : IThriftBytes) : Pointer; overload; inline; procedure Test_Serializer_Deserializer; + procedure Test_TransportFactories; procedure Test_COM_Types; procedure Test_ThriftBytesCTORs; procedure Test_Equal; @@ -437,8 +438,9 @@ procedure TTestSerializer.Test_Serializer_Deserializer; for factory in FProtocols do begin Writeln('- '+UserFriendlyName(factory)); - // protocol conformity tests - if (method = TMethod.mt_Bytes) and (factory.trans = nil) + // protocol conformity tests, on the plain wire format, which a buffered transport does not change + if (method = TMethod.mt_Bytes) + and ((factory.trans = nil) or ((factory.trans as TObject) is TBufferedTransportImpl.TFactory)) then Test_ProtocolConformity( factory, stream); // normal objects @@ -803,10 +805,41 @@ procedure TTestSerializer.Test_Equal; end; +procedure TTestSerializer.Test_TransportFactories; +var config : IThriftConfiguration; + stm : IStreamTransport; + framed : ITransport; + trans : ITransport; + factory : ITransportFactory; +begin + config := TThriftConfigurationImpl.Create; + stm := TStreamTransportImpl.Create( nil, nil, config); + + factory := TBufferedTransportImpl.TFactory.Create; + trans := factory.GetTransport( stm); + ASSERT( (trans as TObject) is TBufferedTransportImpl); + + factory := TFramedTransportImpl.TFactory.Create; + framed := factory.GetTransport( stm); + ASSERT( (framed as TObject) is TFramedTransportImpl); + + // a buffered transport needs the stream interface of the transport below it + factory := TBufferedTransportImpl.TFactory.Create; + try + factory.GetTransport( framed); + raise EInOutError.Create('Expected exception not thrown?'); + except + on e:TTransportExceptionBadArgs do {expected}; + on e:Exception do raise; // unexpected + end; +end; + + procedure TTestSerializer.RunTests; begin try Test_Serializer_Deserializer; + Test_TransportFactories; Test_COM_Types; Test_ThriftBytesCTORs; Test_Equal;