THRIFT-5048 EnumUtils<T>.ToString() throws for elements not known to the receiving end [ci skip]
Client: Delphi
Patch: Jens Geyer
diff --git a/lib/delphi/src/Thrift.Utils.pas b/lib/delphi/src/Thrift.Utils.pas
index ede2656..bc9b460 100644
--- a/lib/delphi/src/Thrift.Utils.pas
+++ b/lib/delphi/src/Thrift.Utils.pas
@@ -97,7 +97,7 @@
THRIFT_MIMETYPE = 'application/x-thrift';
{$IFDEF Win64}
-function InterlockedExchangeAdd64( var Addend : Int64; Value : Int64) : Int64;
+function InterlockedExchangeAdd64( var Addend : Int64; Value : Int64) : Int64;
{$ENDIF}
@@ -289,8 +289,15 @@
var pType : PTypeInfo;
begin
pType := PTypeInfo(TypeInfo(T));
- if Assigned(pType) and (pType^.Kind = tkEnumeration)
- then result := GetEnumName(pType,value)
+ if Assigned(pType)
+ and (pType^.Kind = tkEnumeration)
+ {$IF CompilerVersion >= 23.0} // TODO: Range correct? What we know is that XE does not offer it, but Rio has it
+ and (pType^.TypeData^.MaxValue >= value)
+ and (pType^.TypeData^.MinValue <= value)
+ {$ELSE}
+ and FALSE // THRIFT-5048: pType^.TypeData^ member not supported -> prevent GetEnumName() from reading outside the legal range
+ {$IFEND}
+ then result := GetEnumName( PTypeInfo(pType), value)
else result := IntToStr(Ord(value));
end;
diff --git a/lib/delphi/test/skip/idl/skiptest_version_1.thrift b/lib/delphi/test/skip/idl/skiptest_version_1.thrift
index 8353c5e..4221177 100644
--- a/lib/delphi/test/skip/idl/skiptest_version_1.thrift
+++ b/lib/delphi/test/skip/idl/skiptest_version_1.thrift
@@ -24,12 +24,14 @@
const i32 SKIPTESTSERVICE_VERSION = 1
-struct Pong {
- 1 : optional i32 version1
+enum PingPongEnum {
+ PingOne = 0,
+ PongOne = 1,
}
struct Ping {
1 : optional i32 version1
+ 100 : PingPongEnum EnumTest
}
exception PongFailed {
@@ -38,7 +40,7 @@
service SkipTestService {
- void PingPong( 1: Ping pong) throws (444: PongFailed pof);
+ Ping PingPong( 1: Ping ping) throws (444: PongFailed pof);
}
diff --git a/lib/delphi/test/skip/idl/skiptest_version_2.thrift b/lib/delphi/test/skip/idl/skiptest_version_2.thrift
index f3352d3..3ea69f7 100644
--- a/lib/delphi/test/skip/idl/skiptest_version_2.thrift
+++ b/lib/delphi/test/skip/idl/skiptest_version_2.thrift
@@ -24,9 +24,17 @@
const i32 SKIPTESTSERVICE_VERSION = 2
+enum PingPongEnum {
+ PingOne = 0,
+ PongOne = 1,
+ PingTwo = 2,
+ PongTwo = 3,
+}
+
struct Pong {
1 : optional i32 version1
2 : optional i16 version2
+ 100 : PingPongEnum EnumTest
}
struct Ping {
@@ -40,6 +48,7 @@
16 : optional string strVal
17 : optional Pong structVal
18 : optional map< list< Pong>, set< string>> mapVal
+ 100 : PingPongEnum EnumTest
}
exception PingFailed {
diff --git a/lib/delphi/test/skip/skiptest_version1.dpr b/lib/delphi/test/skip/skiptest_version1.dpr
index c97e50b..f7cde2f 100644
--- a/lib/delphi/test/skip/skiptest_version1.dpr
+++ b/lib/delphi/test/skip/skiptest_version1.dpr
@@ -30,6 +30,7 @@
Thrift.Transport in '..\..\src\Thrift.Transport.pas',
Thrift.Protocol in '..\..\src\Thrift.Protocol.pas',
Thrift.Protocol.JSON in '..\..\src\Thrift.Protocol.JSON.pas',
+ Thrift.Protocol.Compact in '..\..\src\Thrift.Protocol.Compact.pas',
Thrift.Collections in '..\..\src\Thrift.Collections.pas',
Thrift.Configuration in '..\..\src\Thrift.Configuration.pas',
Thrift.Server in '..\..\src\Thrift.Server.pas',
@@ -47,6 +48,7 @@
begin
result := TPingImpl.Create;
result.Version1 := Tskiptest_version_1Constants.SKIPTESTSERVICE_VERSION;
+ result.EnumTest := TPingPongEnum.PingOne;
end;
@@ -54,14 +56,16 @@
TDummyServer = class( TInterfacedObject, TSkipTestService.Iface)
protected
// TSkipTestService.Iface
- procedure PingPong(const ping: IPing);
+ function PingPong(const ping: IPing): IPing;
end;
-procedure TDummyServer.PingPong(const ping: IPing);
+function TDummyServer.PingPong(const ping: IPing): IPing;
// TSkipTestService.Iface
begin
Writeln('- performing request from version '+IntToStr(ping.Version1)+' client');
+ Writeln( ping.ToString);
+ result := CreatePing;
end;
@@ -109,6 +113,7 @@
procedure ReadResponse( protfact : IProtocolFactory; fname : string);
var stm : TFileStream;
+ ping : IPing;
proto : IProtocol;
client : TSkipTestService.TClient; // we need access to send/recv_pingpong()
cliRef : IUnknown; // holds the refcount
@@ -116,11 +121,11 @@
Writeln('- reading response');
stm := TFileStream.Create( fname+RESPONSE_EXT, fmOpenRead);
try
- // save request data
+ // load request data
proto := CreateProtocol( protfact, stm, TRUE);
client := TSkipTestService.TClient.Create( proto, nil);
cliRef := client as IUnknown;
- client.recv_PingPong;
+ ping := client.recv_PingPong;
finally
client := nil; // not Free!
@@ -164,12 +169,14 @@
procedure Test( protfact : IProtocolFactory; fname : string);
begin
// try to read an existing request
+ Writeln('Reading data file '+fname);
if FileExists( fname + REQUEST_EXT) then begin
ProcessFile( protfact, fname);
ReadResponse( protfact, fname);
end;
// create a new request and try to process
+ Writeln('Writing data file '+fname);
CreateRequest( protfact, fname);
ProcessFile( protfact, fname);
ReadResponse( protfact, fname);
@@ -177,8 +184,9 @@
const
- FILE_BINARY = 'pingpong.bin';
- FILE_JSON = 'pingpong.json';
+ FILE_BINARY = 'pingpong.bin';
+ FILE_JSON = 'pingpong.json';
+ FILE_COMPACT = 'pingpong.compact';
begin
try
Writeln( 'Delphi SkipTest '+IntToStr(Tskiptest_version_1Constants.SKIPTESTSERVICE_VERSION)+' using '+Thrift.Version);
@@ -192,6 +200,10 @@
Test( TJSONProtocolImpl.TFactory.Create, FILE_JSON);
Writeln;
+ Writeln('Compact protocol');
+ Test( TCompactProtocolImpl.TFactory.Create, FILE_COMPACT);
+
+ Writeln;
Writeln('Test completed without errors.');
Writeln;
Write('Press ENTER to close ...'); Readln;
diff --git a/lib/delphi/test/skip/skiptest_version2.dpr b/lib/delphi/test/skip/skiptest_version2.dpr
index 07c2c9a..478ea7c 100644
--- a/lib/delphi/test/skip/skiptest_version2.dpr
+++ b/lib/delphi/test/skip/skiptest_version2.dpr
@@ -30,6 +30,7 @@
Thrift.Transport in '..\..\src\Thrift.Transport.pas',
Thrift.Protocol in '..\..\src\Thrift.Protocol.pas',
Thrift.Protocol.JSON in '..\..\src\Thrift.Protocol.JSON.pas',
+ Thrift.Protocol.Compact in '..\..\src\Thrift.Protocol.Compact.pas',
Thrift.Collections in '..\..\src\Thrift.Collections.pas',
Thrift.Configuration in '..\..\src\Thrift.Configuration.pas',
Thrift.Server in '..\..\src\Thrift.Server.pas',
@@ -42,12 +43,15 @@
REQUEST_EXT = '.request';
RESPONSE_EXT = '.response';
+
function CreatePing : IPing;
var list : IThriftList<IPong>;
set_ : IHashSet<string>;
begin
result := TPingImpl.Create;
result.Version1 := Tskiptest_version_2Constants.SKIPTESTSERVICE_VERSION;
+ result.EnumTest := TPingPongEnum.PingTwo;
+
result.BoolVal := TRUE;
result.ByteVal := 2;
result.DbVal := 3;
@@ -59,6 +63,7 @@
result.StructVal := TPongImpl.Create;
result.StructVal.Version1 := -1;
result.StructVal.Version2 := -2;
+ result.StructVal.EnumTest := TPingPongEnum.PongTwo;
list := TThriftListImpl<IPong>.Create;
list.Add( result.StructVal);
@@ -87,6 +92,7 @@
// TSkipTestService.Iface
begin
Writeln('- performing request from version '+IntToStr(ping.Version1)+' client');
+ Writeln( ping.ToString);
result := CreatePing;
end;
@@ -143,7 +149,7 @@
Writeln('- reading response');
stm := TFileStream.Create( fname+RESPONSE_EXT, fmOpenRead);
try
- // save request data
+ // load request data
proto := CreateProtocol( protfact, stm, TRUE);
client := TSkipTestService.TClient.Create( proto, nil);
cliRef := client as IUnknown;
@@ -191,12 +197,16 @@
procedure Test( protfact : IProtocolFactory; fname : string);
begin
// try to read an existing request
+ Writeln;
+ Writeln('Reading data file '+fname);
if FileExists( fname + REQUEST_EXT) then begin
ProcessFile( protfact, fname);
ReadResponse( protfact, fname);
end;
// create a new request and try to process
+ Writeln;
+ Writeln('Writing data file '+fname);
CreateRequest( protfact, fname);
ProcessFile( protfact, fname);
ReadResponse( protfact, fname);
@@ -204,8 +214,9 @@
const
- FILE_BINARY = 'pingpong.bin';
- FILE_JSON = 'pingpong.json';
+ FILE_BINARY = 'pingpong.bin';
+ FILE_JSON = 'pingpong.json';
+ FILE_COMPACT = 'pingpong.compact';
begin
try
Writeln( 'Delphi SkipTest '+IntToStr(Tskiptest_version_2Constants.SKIPTESTSERVICE_VERSION)+' using '+Thrift.Version);
@@ -219,6 +230,10 @@
Test( TJSONProtocolImpl.TFactory.Create, FILE_JSON);
Writeln;
+ Writeln('Compact protocol');
+ Test( TCompactProtocolImpl.TFactory.Create, FILE_COMPACT);
+
+ Writeln;
Writeln('Test completed without errors.');
Writeln;
Write('Press ENTER to close ...'); Readln;