THRIFT-2718 Align cmdline help and return codes for Thrift test server/client
Client: Delphi
Patch: Jens Geyer
diff --git a/lib/delphi/test/TestServer.pas b/lib/delphi/test/TestServer.pas
index 9d06e8e..286047d 100644
--- a/lib/delphi/test/TestServer.pas
+++ b/lib/delphi/test/TestServer.pas
@@ -81,6 +81,9 @@
procedure SetServer( const AServer : IServer );
end;
+ class procedure PrintCmdLineHelp;
+ class procedure InvalidArgs;
+
class procedure LaunchAnonPipeChild( const app : string; const transport : IAnonymousPipeServerTransport);
class procedure Execute( const args: array of string);
end;
@@ -437,6 +440,34 @@
{ TTestServer }
+class procedure TTestServer.PrintCmdLineHelp;
+const HELPTEXT = ' [options]'#10
+ + #10
+ + 'Allowed options:'#10
+ + ' -h [ --help ] produce help message'#10
+ + ' --port arg (=9090) Port number to listen'#10
+ + ' --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift)'#10
+ + ' --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe)'#10
+ + ' --server-type arg (=simple) type of server, "simple", "thread-pool",'#10
+ + ' "threaded", or "nonblocking"'#10
+ + ' --transport arg (=socket) transport: buffered, framed, http, anonpipe'#10
+ + ' --protocol arg (=binary) protocol: binary, compact, json'#10
+ + ' --ssl Encrypted Transport using SSL'#10
+ + ' --processor-events processor-events'#10
+ + ' -n [ --workers ] arg (=4) Number of thread pools workers. Only valid for'#10
+ + ' thread-pool server type'#10
+ ;
+begin
+ Console.WriteLine( ChangeFileExt(ExtractFileName(ParamStr(0)),'') + HELPTEXT);
+end;
+
+class procedure TTestServer.InvalidArgs;
+begin
+ Console.WriteLine( 'Invalid args.');
+ Console.WriteLine( ChangeFileExt(ExtractFileName(ParamStr(0)),'') + ' -h for more information');
+ Abort;
+end;
+
class procedure TTestServer.LaunchAnonPipeChild( const app : string; const transport : IAnonymousPipeServerTransport);
//Launch child process and pass R/W anonymous pipe handles on cmd line.
//This is a simple example and does not include elevation or other
@@ -480,10 +511,8 @@
class procedure TTestServer.Execute( const args: array of string);
var
- UseBufferedSockets : Boolean;
- UseFramed : Boolean;
Port : Integer;
- AnonPipe, ServerEvents : Boolean;
+ ServerEvents : Boolean;
sPipeName : string;
testHandler : ITestHandler;
testProcessor : IProcessor;
@@ -493,9 +522,13 @@
namedpipe : INamedPipeServerTransport;
TransportFactory : ITransportFactory;
ProtocolFactory : IProtocolFactory;
- i : Integer;
+ i, numWorker : Integer;
s : string;
- protType, p : TKnownProtocol;
+ protType : TKnownProtocol;
+ servertype : TServerType;
+ endpoint : TEndpointTransport;
+ layered : TLayeredTransports;
+ UseSSL : Boolean; // include where appropriate (TLayeredTransport?)
const
// pipe timeouts to be used
DEBUG_TIMEOUT = 30 * 1000;
@@ -503,63 +536,96 @@
TIMEOUT = RELEASE_TIMEOUT;
begin
try
- UseBufferedSockets := False;
- UseFramed := False;
- AnonPipe := FALSE;
ServerEvents := FALSE;
protType := prot_Binary;
+ servertype := srv_Simple;
+ endpoint := trns_Sockets;
+ layered := [];
+ UseSSL := FALSE;
Port := 9090;
sPipeName := '';
+ numWorker := 4;
i := 0;
while ( i < Length(args) ) do begin
s := args[i];
Inc(i);
- if StrToIntDef( s, -1) > 0 then
- begin
- Port := StrToIntDef( s, Port);
+ // Allowed options:
+ if (s = '-h') or (s = '--help') then begin
+ // -h [ --help ] produce help message
+ PrintCmdLineHelp;
+ Exit;
end
- else if ( s = 'raw' ) then
- begin
- // as default
+ else if (s = '--port') then begin
+ // --port arg (=9090) Port number to listen
+ s := args[i];
+ Inc(i);
+ Port := StrToIntDef( s, Port);
end
- else if ( s = 'buffered' ) then
- begin
- UseBufferedSockets := True;
+ else if (s = '--domain-socket') then begin
+ // --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift)
+ raise Exception.Create('domain-socket not supported');
end
- else if ( s = 'framed' ) then
- begin
- UseFramed := True;
- end
- else if (s = '-pipe') then
- begin
+ else if (s = '--named-pipe') then begin
+ // --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe)
+ endpoint := trns_NamedPipes;
sPipeName := args[i]; // -pipe <name>
Inc( i );
end
- else if (s = '-anon') then
- begin
- AnonPipe := TRUE;
- end
- else if (s = '-prot') then // -prot JSON|binary
- begin
+ else if (s = '--server-type') then begin
+ // --server-type arg (=simple) type of server,
+ // arg = "simple", "thread-pool", "threaded", or "nonblocking"
s := args[i];
- Inc( i );
- for p:= Low(TKnownProtocol) to High(TKnownProtocol) do begin
- if SameText( s, KNOWN_PROTOCOLS[p]) then begin
- protType := p;
- Break;
- end;
- end;
+ Inc(i);
+
+ if s = 'simple' then servertype := srv_Simple
+ else if s = 'thread-pool' then servertype := srv_Threadpool
+ else if s = 'threaded' then servertype := srv_Threaded
+ else if s = 'nonblocking' then servertype := srv_Nonblocking
+ else InvalidArgs;
end
- else if ( s = '-events' ) then
- begin
- ServerEvents := True;
+ else if (s = '--transport') then begin
+ // --transport arg (=buffered) transport: buffered, framed, http
+ s := args[i];
+ Inc(i);
+
+ if s = 'buffered' then Include( layered, trns_Buffered)
+ else if s = 'framed' then Include( layered, trns_Framed)
+ else if s = 'http' then endpoint := trns_Http
+ else if s = 'anonpipe' then endpoint := trns_AnonPipes
+ else InvalidArgs;
+ end
+ else if (s = '--protocol') then begin
+ // --protocol arg (=binary) protocol: binary, compact, json
+ s := args[i];
+ Inc(i);
+
+ if s = 'binary' then protType := prot_Binary
+ else if s = 'compact' then protType := prot_Compact
+ else if s = 'json' then protType := prot_JSON
+ else InvalidArgs;
+ end
+ else if (s = '--ssl') then begin
+ // --ssl Encrypted Transport using SSL
+ UseSSL := TRUE;
+ end
+ else if (s = '--processor-events') then begin
+ // --processor-events processor-events
+ ServerEvents := TRUE;
+ end
+ else if (s = '-n') or (s = '--workers') then begin
+ // -n [ --workers ] arg (=4) Number of thread pools workers.
+ // Only valid for thread-pool server type
+ s := args[i];
+ numWorker := StrToIntDef(s,0);
+ if numWorker > 0
+ then Inc(i)
+ else numWorker := 4;
end
else begin
- // Fall back to the older boolean syntax
- UseBufferedSockets := StrToBoolDef( args[1], UseBufferedSockets);
- end
+ InvalidArgs;
+ end;
end;
@@ -567,34 +633,49 @@
// create protocol factory, default to BinaryProtocol
case protType of
- prot_Binary: ProtocolFactory := TBinaryProtocolImpl.TFactory.Create( BINARY_STRICT_READ, BINARY_STRICT_WRITE);
- prot_JSON : ProtocolFactory := TJSONProtocolImpl.TFactory.Create;
+ prot_Binary : ProtocolFactory := TBinaryProtocolImpl.TFactory.Create( BINARY_STRICT_READ, BINARY_STRICT_WRITE);
+ prot_JSON : ProtocolFactory := TJSONProtocolImpl.TFactory.Create;
+ prot_Compact : raise Exception.Create('Compact protocol not implemented');
else
- ASSERT( FALSE); // unhandled case!
- ProtocolFactory := TBinaryProtocolImpl.TFactory.Create( BINARY_STRICT_READ, BINARY_STRICT_WRITE);
+ raise Exception.Create('Unhandled protocol');
end;
ASSERT( ProtocolFactory <> nil);
- Console.WriteLine('- '+KNOWN_PROTOCOLS[protType]+' protocol');
+ Console.WriteLine('- '+THRIFT_PROTOCOLS[protType]+' protocol');
+ case endpoint of
- if sPipeName <> '' then begin
- Console.WriteLine('- named pipe ('+sPipeName+')');
- namedpipe := TNamedPipeServerTransportImpl.Create( sPipeName, 4096, PIPE_UNLIMITED_INSTANCES, TIMEOUT);
- servertrans := namedpipe;
- end
- else if AnonPipe then begin
- Console.WriteLine('- anonymous pipes');
- anonymouspipe := TAnonymousPipeServerTransportImpl.Create;
- servertrans := anonymouspipe;
- end
- else begin
- Console.WriteLine('- sockets (port '+IntToStr(port)+')');
- if UseBufferedSockets then Console.WriteLine('- buffered sockets');
- servertrans := TServerSocketImpl.Create( Port, 0, UseBufferedSockets);
+ trns_Sockets : begin
+ Console.WriteLine('- sockets (port '+IntToStr(port)+')');
+ if (trns_Buffered in layered) then Console.WriteLine('- buffered');
+ servertrans := TServerSocketImpl.Create( Port, 0, (trns_Buffered in layered));
+ end;
+
+ trns_Http : begin
+ raise Exception.Create('HTTP server transport not implemented');
+ end;
+
+ trns_NamedPipes : begin
+ Console.WriteLine('- named pipe ('+sPipeName+')');
+ namedpipe := TNamedPipeServerTransportImpl.Create( sPipeName, 4096, PIPE_UNLIMITED_INSTANCES, TIMEOUT);
+ servertrans := namedpipe;
+ end;
+
+ trns_AnonPipes : begin
+ Console.WriteLine('- anonymous pipes');
+ anonymouspipe := TAnonymousPipeServerTransportImpl.Create;
+ servertrans := anonymouspipe;
+ end
+
+ else
+ raise Exception.Create('Unhandled endpoint transport');
end;
ASSERT( servertrans <> nil);
- if UseFramed then begin
+ if UseSSL then begin
+ raise Exception.Create('SSL not implemented');
+ end;
+
+ if (trns_Framed in layered) then begin
Console.WriteLine('- framed transport');
TransportFactory := TFramedTransportImpl.TFactory.Create
end
@@ -606,10 +687,25 @@
testHandler := TTestHandlerImpl.Create;
testProcessor := TThriftTest.TProcessorImpl.Create( testHandler );
- ServerEngine := TSimpleServer.Create( testProcessor,
- ServerTrans,
- TransportFactory,
- ProtocolFactory);
+ case servertype of
+ srv_Simple : begin
+ ServerEngine := TSimpleServer.Create( testProcessor, ServerTrans, TransportFactory, ProtocolFactory);
+ end;
+
+ srv_Nonblocking : begin
+ raise Exception.Create(SERVER_TYPES[servertype]+' server not implemented');
+ end;
+
+ srv_Threadpool,
+ srv_Threaded: begin
+ if numWorker > 1 then {use here};
+ raise Exception.Create(SERVER_TYPES[servertype]+' server not implemented');
+ end;
+
+ else
+ raise Exception.Create('Unhandled server type');
+ end;
+ ASSERT( ServerEngine <> nil);
testHandler.SetServer( ServerEngine);
@@ -620,7 +716,7 @@
end;
// start the client now when we have the anon handles, but before the server starts
- if AnonPipe
+ if endpoint = trns_AnonPipes
then LaunchAnonPipeChild( ExtractFilePath(ParamStr(0))+'client.exe', anonymouspipe);
// install Ctrl+C handler before the server starts
@@ -637,9 +733,9 @@
g_Handler := nil;
except
- on E: Exception do
- begin
- Console.Write( E.Message);
+ on E: EAbort do raise;
+ on E: Exception do begin
+ Console.WriteLine( E.Message + #10 + E.StackTrace );
end;
end;
Console.WriteLine( 'done.');