Thrift-1401: JSON-protocol for Delphi XE Libraries
Client: delphi
Patch: Jens Geyer
Adds support for the JSON protocol to the existing Delphi XE libraries.
git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1200538 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/delphi/test/TestClient.pas b/lib/delphi/test/TestClient.pas
index b3c9017..e8edd82 100644
--- a/lib/delphi/test/TestClient.pas
+++ b/lib/delphi/test/TestClient.pas
@@ -22,12 +22,19 @@
interface
uses
- SysUtils, Classes, Thrift.Protocol, Thrift.Transport, Thrift.Test,
- Generics.Collections, Thrift.Collections, Windows, Thrift.Console,
- DateUtils;
+ Windows, SysUtils, Classes,
+ DateUtils,
+ Generics.Collections,
+ TestConstants,
+ Thrift.Protocol.JSON,
+ Thrift.Protocol,
+ Thrift.Transport,
+ Thrift.Stream,
+ Thrift.Test,
+ Thrift.Collections,
+ Thrift.Console;
type
-
TThreadConsole = class
private
FThread : TThread;
@@ -40,14 +47,19 @@
TClientThread = class( TThread )
private
FTransport : ITransport;
+ FProtocol : IProtocol;
FNumIteration : Integer;
FConsole : TThreadConsole;
+ FErrors, FSuccesses : Integer;
+ procedure Expect( aTestResult : Boolean; const aTestInfo : string);
+
procedure ClientTest;
+ procedure JSONProtocolReadWriteTest;
protected
procedure Execute; override;
public
- constructor Create(ATransport: ITransport; ANumIteration: Integer);
+ constructor Create(ATransport: ITransport; AProtocol : IProtocol; ANumIteration: Integer);
destructor Destroy; override;
end;
@@ -62,6 +74,7 @@
implementation
+
{ TTestClient }
class procedure TTestClient.Execute(const args: array of string);
@@ -79,12 +92,14 @@
test : Integer;
thread : TThread;
trans : ITransport;
+ prot : IProtocol;
streamtrans : IStreamTransport;
http : IHTTPClient;
-
+ protType, p : TKnownProtocol;
begin
bBuffered := False;;
bFramed := False;
+ protType := prot_Binary;
try
host := 'localhost';
port := 9090;
@@ -132,6 +147,18 @@
begin
Inc( i );
FNumThread := StrToInt( args[i] );
+ end else
+ if (args[i] = '-prot') then // -prot JSON|binary
+ begin
+ Inc( i );
+ s := args[i];
+ for p:= Low(TKnownProtocol) to High(TKnownProtocol) do begin
+ if SameText( s, KNOWN_PROTOCOLS[p]) then begin
+ protType := p;
+ Console.WriteLine('Using '+KNOWN_PROTOCOLS[protType]+' protocol');
+ Break;
+ end;
+ end;
end;
finally
Inc( i );
@@ -167,7 +194,17 @@
http := THTTPClientImpl.Create( url );
trans := http;
end;
- thread := TClientThread.Create( trans, FNumIteration);
+
+ // create protocol instance, default to BinaryProtocol
+ case protType of
+ prot_Binary: prot := TBinaryProtocolImpl.Create( trans);
+ prot_JSON : prot := TJSONProtocolImpl.Create( trans);
+ else
+ ASSERT( FALSE); // unhandled case!
+ prot := TBinaryProtocolImpl.Create( trans); // use default
+ end;
+
+ thread := TClientThread.Create( trans, prot, FNumIteration);
threads[test] := thread;
{$WARN SYMBOL_DEPRECATED OFF}
thread.Resume;
@@ -201,7 +238,6 @@
procedure TClientThread.ClientTest;
var
- binaryProtocol : TBinaryProtocolImpl;
client : TThriftTest.Iface;
s : string;
i8 : ShortInt;
@@ -234,7 +270,7 @@
k2_2 : TNumberz;
k3 : TNumberz;
v2 : IInsanity;
- userMap : IThriftDictionary<TNumberz, Int64>;
+ userMap : IThriftDictionary<TNumberz, Int64>;
xtructs : IThriftList<IXtruct>;
x : IXtruct;
arg0 : ShortInt;
@@ -248,8 +284,7 @@
proc : TThreadProcedure;
begin
- binaryProtocol := TBinaryProtocolImpl.Create( FTransport );
- client := TThriftTest.TClient.Create( binaryProtocol );
+ client := TThriftTest.TClient.Create( FProtocol);
try
if not FTransport.IsOpen then
begin
@@ -523,11 +558,114 @@
end;
-constructor TClientThread.Create(ATransport: ITransport; ANumIteration: Integer);
+
+procedure TClientThread.JSONProtocolReadWriteTest;
+// Tests only then read/write procedures of the JSON protocol
+// All tests succeed, if we can read what we wrote before
+// Note that passing this test does not imply, that our JSON is really compatible to what
+// other clients or servers expect as the real JSON. This is beyond the scope of this test.
+var prot : IProtocol;
+ stm : TStringStream;
+ list : IList;
+ binary, binRead : TBytes;
+ i,iErr : Integer;
+const
+ TEST_SHORT = ShortInt( $FE);
+ TEST_SMALL = SmallInt( $FEDC);
+ TEST_LONG = LongInt( $FEDCBA98);
+ TEST_I64 = Int64( $FEDCBA9876543210);
+ TEST_DOUBLE = -1.234e-56;
+ DELTA_DOUBLE = TEST_DOUBLE * 1e-14;
+ TEST_STRING = 'abc-'#$00E4#$00f6#$00fc; // german umlauts (en-us: "funny chars")
+begin
+ stm := TStringStream.Create;
+ try
+ // prepare binary data
+ SetLength( binary, $100);
+ for i := Low(binary) to High(binary) do binary[i] := i;
+
+ // output setup
+ prot := TJSONProtocolImpl.Create(
+ TStreamTransportImpl.Create(
+ nil, TThriftStreamAdapterDelphi.Create( stm, FALSE)));
+
+ // write
+ prot.WriteListBegin( TListImpl.Create( TType.String_, 9));
+ prot.WriteBool( TRUE);
+ prot.WriteBool( FALSE);
+ prot.WriteByte( TEST_SHORT);
+ prot.WriteI16( TEST_SMALL);
+ prot.WriteI32( TEST_LONG);
+ prot.WriteI64( TEST_I64);
+ prot.WriteDouble( TEST_DOUBLE);
+ prot.WriteString( TEST_STRING);
+ prot.WriteBinary( binary);
+ prot.WriteListEnd;
+
+ // input setup
+ Expect( stm.Position = stm.Size, 'Stream position/length after write');
+ stm.Position := 0;
+ prot := TJSONProtocolImpl.Create(
+ TStreamTransportImpl.Create(
+ TThriftStreamAdapterDelphi.Create( stm, FALSE), nil));
+
+ // read and compare
+ list := prot.ReadListBegin;
+ Expect( list.ElementType = TType.String_, 'list element type');
+ Expect( list.Count = 9, 'list element count');
+ Expect( prot.ReadBool, 'WriteBool/ReadBool: TRUE');
+ Expect( not prot.ReadBool, 'WriteBool/ReadBool: FALSE');
+ Expect( prot.ReadByte = TEST_SHORT, 'WriteByte/ReadByte');
+ Expect( prot.ReadI16 = TEST_SMALL, 'WriteI16/ReadI16');
+ Expect( prot.ReadI32 = TEST_LONG, 'WriteI32/ReadI32');
+ Expect( prot.ReadI64 = TEST_I64, 'WriteI64/ReadI64');
+ Expect( abs(prot.ReadDouble-TEST_DOUBLE) < abs(DELTA_DOUBLE), 'WriteDouble/ReadDouble');
+ Expect( prot.ReadString = TEST_STRING, 'WriteString/ReadString');
+ binRead := prot.ReadBinary;
+ prot.ReadListEnd;
+
+ // test binary data
+ Expect( Length(binary) = Length(binRead), 'Binary data length check');
+ iErr := -1;
+ for i := Low(binary) to High(binary) do begin
+ if binary[i] <> binRead[i] then begin
+ iErr := i;
+ Break;
+ end;
+ end;
+ if iErr < 0
+ then Expect( TRUE, 'Binary data check ('+IntToStr(Length(binary))+' Bytes)')
+ else Expect( FALSE, 'Binary data check at offset '+IntToStr(iErr));
+
+ Expect( stm.Position = stm.Size, 'Stream position after read');
+
+ finally
+ stm.Free;
+ prot := nil; //-> Release
+ end;
+end;
+
+
+procedure TClientThread.Expect( aTestResult : Boolean; const aTestInfo : string);
+begin
+ if aTestResult then begin
+ Inc(FSuccesses);
+ Console.WriteLine( aTestInfo+' = OK');
+ end
+ else begin
+ Inc(FErrors);
+ Console.WriteLine( aTestInfo+' = FAILED');
+ ASSERT( FALSE); // we have a failed test!
+ end;
+end;
+
+
+constructor TClientThread.Create(ATransport: ITransport; AProtocol : IProtocol; ANumIteration: Integer);
begin
inherited Create( True );
FNumIteration := ANumIteration;
FTransport := ATransport;
+ FProtocol := AProtocol;
FConsole := TThreadConsole.Create( Self );
end;
@@ -545,6 +683,7 @@
for i := 0 to FNumIteration - 1 do
begin
ClientTest;
+ JSONProtocolReadWriteTest;
end;
proc := procedure