blob: da804fdc027a55ff462d0ff184f07b321c6ccc3f [file] [log] [blame]
Jake Farrell27274222011-11-10 20:32:44 +00001(*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *)
19
20unit TestServer;
21
Jens Geyer9f7f11e2016-04-14 21:37:11 +020022{$I ../src/Thrift.Defines.inc}
Roger Meier3bef8c22012-10-06 06:58:00 +000023{$WARN SYMBOL_PLATFORM OFF}
24
Jens Geyer06045cf2013-03-27 20:26:25 +020025{.$DEFINE RunEndless} // activate to interactively stress-test the server stop routines via Ctrl+C
26
Jake Farrell27274222011-11-10 20:32:44 +000027interface
28
29uses
Roger Meier3bef8c22012-10-06 06:58:00 +000030 Windows, SysUtils,
Jake Farrell27274222011-11-10 20:32:44 +000031 Generics.Collections,
Jake Farrell27274222011-11-10 20:32:44 +000032 Thrift.Server,
33 Thrift.Transport,
Roger Meier3bef8c22012-10-06 06:58:00 +000034 Thrift.Transport.Pipes,
Jake Farrell27274222011-11-10 20:32:44 +000035 Thrift.Protocol,
36 Thrift.Protocol.JSON,
Jens Geyerf0e63312015-03-01 18:47:49 +010037 Thrift.Protocol.Compact,
Jake Farrell27274222011-11-10 20:32:44 +000038 Thrift.Collections,
39 Thrift.Utils,
40 Thrift.Test,
41 Thrift,
42 TestConstants,
Jens Geyer01640402013-09-25 21:12:21 +020043 TestServerEvents,
Jens Geyer3d556242018-01-24 19:14:32 +010044 ConsoleHelper,
Jake Farrell27274222011-11-10 20:32:44 +000045 Contnrs;
46
47type
48 TTestServer = class
49 public
50 type
51
52 ITestHandler = interface( TThriftTest.Iface )
Roger Meier333bbf32012-01-08 21:51:08 +000053 procedure SetServer( const AServer : IServer );
Jens Geyer06045cf2013-03-27 20:26:25 +020054 procedure TestStop;
Jake Farrell27274222011-11-10 20:32:44 +000055 end;
56
57 TTestHandlerImpl = class( TInterfacedObject, ITestHandler )
58 private
59 FServer : IServer;
60 protected
61 procedure testVoid();
Jens Geyer39ba6b72015-09-22 00:00:49 +020062 function testBool(thing: Boolean): Boolean;
Roger Meier333bbf32012-01-08 21:51:08 +000063 function testString(const thing: string): string;
Jake Farrell7ae13e12011-10-18 14:35:26 +000064 function testByte(thing: ShortInt): ShortInt;
65 function testI32(thing: Integer): Integer;
Roger Meier333bbf32012-01-08 21:51:08 +000066 function testI64(const thing: Int64): Int64;
67 function testDouble(const thing: Double): Double;
Jens Geyerfd1b3582014-12-13 23:42:58 +010068 function testBinary(const thing: TBytes): TBytes;
Roger Meier333bbf32012-01-08 21:51:08 +000069 function testStruct(const thing: IXtruct): IXtruct;
70 function testNest(const thing: IXtruct2): IXtruct2;
71 function testMap(const thing: IThriftDictionary<Integer, Integer>): IThriftDictionary<Integer, Integer>;
72 function testStringMap(const thing: IThriftDictionary<string, string>): IThriftDictionary<string, string>;
73 function testSet(const thing: IHashSet<Integer>): IHashSet<Integer>;
74 function testList(const thing: IThriftList<Integer>): IThriftList<Integer>;
Jake Farrell7ae13e12011-10-18 14:35:26 +000075 function testEnum(thing: TNumberz): TNumberz;
Roger Meier333bbf32012-01-08 21:51:08 +000076 function testTypedef(const thing: Int64): Int64;
Jake Farrell7ae13e12011-10-18 14:35:26 +000077 function testMapMap(hello: Integer): IThriftDictionary<Integer, IThriftDictionary<Integer, Integer>>;
Roger Meier333bbf32012-01-08 21:51:08 +000078 function testInsanity(const argument: IInsanity): IThriftDictionary<Int64, IThriftDictionary<TNumberz, IInsanity>>;
79 function testMulti(arg0: ShortInt; arg1: Integer; const arg2: Int64; const arg3: IThriftDictionary<SmallInt, string>; arg4: TNumberz; const arg5: Int64): IXtruct;
80 procedure testException(const arg: string);
81 function testMultiException(const arg0: string; const arg1: string): IXtruct;
Jake Farrell7ae13e12011-10-18 14:35:26 +000082 procedure testOneway(secondsToSleep: Integer);
Jake Farrell27274222011-11-10 20:32:44 +000083
Jens Geyer06045cf2013-03-27 20:26:25 +020084 procedure TestStop;
Roger Meier333bbf32012-01-08 21:51:08 +000085 procedure SetServer( const AServer : IServer );
Jake Farrell27274222011-11-10 20:32:44 +000086 end;
87
Jens Geyerf8a1b7a2014-09-24 00:26:46 +020088 class procedure PrintCmdLineHelp;
89 class procedure InvalidArgs;
90
Jens Geyer06045cf2013-03-27 20:26:25 +020091 class procedure LaunchAnonPipeChild( const app : string; const transport : IAnonymousPipeServerTransport);
Roger Meier333bbf32012-01-08 21:51:08 +000092 class procedure Execute( const args: array of string);
Jake Farrell27274222011-11-10 20:32:44 +000093 end;
94
95implementation
96
Jens Geyer06045cf2013-03-27 20:26:25 +020097
98var g_Handler : TTestServer.ITestHandler = nil;
99
100
101function MyConsoleEventHandler( dwCtrlType : DWORD) : BOOL; stdcall;
102// Note that this Handler procedure is called from another thread
103var handler : TTestServer.ITestHandler;
104begin
105 result := TRUE;
106 try
107 case dwCtrlType of
108 CTRL_C_EVENT : Console.WriteLine( 'Ctrl+C pressed');
109 CTRL_BREAK_EVENT : Console.WriteLine( 'Ctrl+Break pressed');
110 CTRL_CLOSE_EVENT : Console.WriteLine( 'Received CloseTask signal');
111 CTRL_LOGOFF_EVENT : Console.WriteLine( 'Received LogOff signal');
112 CTRL_SHUTDOWN_EVENT : Console.WriteLine( 'Received Shutdown signal');
113 else
114 Console.WriteLine( 'Received console event #'+IntToStr(Integer(dwCtrlType)));
115 end;
116
117 handler := g_Handler;
118 if handler <> nil then handler.TestStop;
119
120 except
121 // catch all
122 end;
123end;
124
125
Jake Farrell27274222011-11-10 20:32:44 +0000126{ TTestServer.TTestHandlerImpl }
127
Roger Meier333bbf32012-01-08 21:51:08 +0000128procedure TTestServer.TTestHandlerImpl.SetServer( const AServer: IServer);
Jake Farrell27274222011-11-10 20:32:44 +0000129begin
130 FServer := AServer;
131end;
132
133function TTestServer.TTestHandlerImpl.testByte(thing: ShortInt): ShortInt;
134begin
135 Console.WriteLine('testByte("' + IntToStr( thing) + '")');
136 Result := thing;
137end;
138
Roger Meier333bbf32012-01-08 21:51:08 +0000139function TTestServer.TTestHandlerImpl.testDouble( const thing: Double): Double;
Jake Farrell27274222011-11-10 20:32:44 +0000140begin
141 Console.WriteLine('testDouble("' + FloatToStr( thing ) + '")');
142 Result := thing;
143end;
144
Jens Geyerfd1b3582014-12-13 23:42:58 +0100145function TTestServer.TTestHandlerImpl.testBinary(const thing: TBytes): TBytes;
146begin
Jens Geyerbd1a2732019-06-26 22:52:44 +0200147 Console.WriteLine('testBinary('+IntToStr(Length(thing)) + ' bytes)');
Jens Geyerfd1b3582014-12-13 23:42:58 +0100148 Result := thing;
149end;
150
Jake Farrell27274222011-11-10 20:32:44 +0000151function TTestServer.TTestHandlerImpl.testEnum(thing: TNumberz): TNumberz;
152begin
Jens Geyer8f7487e2019-05-09 22:21:32 +0200153 Console.WriteLine('testEnum(' + EnumUtils<TNumberz>.ToString(Ord(thing)) + ')');
Jake Farrell27274222011-11-10 20:32:44 +0000154 Result := thing;
155end;
156
Roger Meier333bbf32012-01-08 21:51:08 +0000157procedure TTestServer.TTestHandlerImpl.testException(const arg: string);
Jake Farrell27274222011-11-10 20:32:44 +0000158begin
159 Console.WriteLine('testException(' + arg + ')');
Jens Geyerc140bb92019-11-27 22:18:12 +0100160 if ( arg = 'Xception') then begin
Roger Meierbb6de7a2012-05-04 23:35:45 +0000161 raise TXception.Create( 1001, arg);
Jake Farrell27274222011-11-10 20:32:44 +0000162 end;
Roger Meierbb6de7a2012-05-04 23:35:45 +0000163
Jens Geyerc140bb92019-11-27 22:18:12 +0100164 if (arg = 'TException') then begin
Jens Geyer92d80622018-05-02 22:28:44 +0200165 raise TException.Create('TException');
Roger Meierbb6de7a2012-05-04 23:35:45 +0000166 end;
167
168 // else do not throw anything
Jake Farrell27274222011-11-10 20:32:44 +0000169end;
170
171function TTestServer.TTestHandlerImpl.testI32(thing: Integer): Integer;
172begin
173 Console.WriteLine('testI32("' + IntToStr( thing) + '")');
174 Result := thing;
175end;
176
Roger Meier333bbf32012-01-08 21:51:08 +0000177function TTestServer.TTestHandlerImpl.testI64( const thing: Int64): Int64;
Jake Farrell27274222011-11-10 20:32:44 +0000178begin
179 Console.WriteLine('testI64("' + IntToStr( thing) + '")');
180 Result := thing;
181end;
182
183function TTestServer.TTestHandlerImpl.testInsanity(
Roger Meier333bbf32012-01-08 21:51:08 +0000184 const argument: IInsanity): IThriftDictionary<Int64, IThriftDictionary<TNumberz, IInsanity>>;
Jake Farrell27274222011-11-10 20:32:44 +0000185var
Jake Farrell27274222011-11-10 20:32:44 +0000186 looney : IInsanity;
187 first_map : IThriftDictionary<TNumberz, IInsanity>;
188 second_map : IThriftDictionary<TNumberz, IInsanity>;
189 insane : IThriftDictionary<Int64, IThriftDictionary<TNumberz, IInsanity>>;
190
191begin
Jens Geyer8f7487e2019-05-09 22:21:32 +0200192 Console.Write('testInsanity(');
193 if argument <> nil then Console.Write(argument.ToString);
194 Console.WriteLine(')');
195
Jake Farrell27274222011-11-10 20:32:44 +0000196
Jens Geyer540e3462016-12-28 14:25:41 +0100197 (**
198 * So you think you've got this all worked, out eh?
199 *
200 * Creates a the returned map with these values and prints it out:
201 * { 1 => { 2 => argument,
202 * 3 => argument,
203 * },
204 * 2 => { 6 => <empty Insanity struct>, },
205 * }
206 * @return map<UserId, map<Numberz,Insanity>> - a map with the above values
207 *)
Jake Farrell27274222011-11-10 20:32:44 +0000208
209 first_map := TThriftDictionaryImpl<TNumberz, IInsanity>.Create;
210 second_map := TThriftDictionaryImpl<TNumberz, IInsanity>.Create;
211
Jens Geyer540e3462016-12-28 14:25:41 +0100212 first_map.AddOrSetValue( TNumberz.TWO, argument);
213 first_map.AddOrSetValue( TNumberz.THREE, argument);
Jake Farrell27274222011-11-10 20:32:44 +0000214
Jens Geyer540e3462016-12-28 14:25:41 +0100215 looney := TInsanityImpl.Create;
Jake Farrell27274222011-11-10 20:32:44 +0000216 second_map.AddOrSetValue( TNumberz.SIX, looney);
217
218 insane := TThriftDictionaryImpl<Int64, IThriftDictionary<TNumberz, IInsanity>>.Create;
219
220 insane.AddOrSetValue( 1, first_map);
221 insane.AddOrSetValue( 2, second_map);
222
223 Result := insane;
224end;
225
Jens Geyer8f7487e2019-05-09 22:21:32 +0200226function TTestServer.TTestHandlerImpl.testList( const thing: IThriftList<Integer>): IThriftList<Integer>;
Jake Farrell27274222011-11-10 20:32:44 +0000227begin
Jens Geyer8f7487e2019-05-09 22:21:32 +0200228 Console.Write('testList(');
229 if thing <> nil then Console.Write(thing.ToString);
230 Console.WriteLine(')');
Jake Farrell27274222011-11-10 20:32:44 +0000231 Result := thing;
232end;
233
234function TTestServer.TTestHandlerImpl.testMap(
Roger Meier333bbf32012-01-08 21:51:08 +0000235 const thing: IThriftDictionary<Integer, Integer>): IThriftDictionary<Integer, Integer>;
Jake Farrell27274222011-11-10 20:32:44 +0000236begin
Jens Geyer8f7487e2019-05-09 22:21:32 +0200237 Console.Write('testMap(');
238 if thing <> nil then Console.Write(thing.ToString);
239 Console.WriteLine(')');
Jake Farrell27274222011-11-10 20:32:44 +0000240 Result := thing;
241end;
242
243function TTestServer.TTestHandlerImpl.TestMapMap(
244 hello: Integer): IThriftDictionary<Integer, IThriftDictionary<Integer, Integer>>;
245var
246 mapmap : IThriftDictionary<Integer, IThriftDictionary<Integer, Integer>>;
247 pos : IThriftDictionary<Integer, Integer>;
248 neg : IThriftDictionary<Integer, Integer>;
249 i : Integer;
250begin
251 Console.WriteLine('testMapMap(' + IntToStr( hello) + ')');
252 mapmap := TThriftDictionaryImpl<Integer, IThriftDictionary<Integer, Integer>>.Create;
253 pos := TThriftDictionaryImpl<Integer, Integer>.Create;
254 neg := TThriftDictionaryImpl<Integer, Integer>.Create;
255
256 for i := 1 to 4 do
257 begin
258 pos.AddOrSetValue( i, i);
259 neg.AddOrSetValue( -i, -i);
260 end;
261
262 mapmap.AddOrSetValue(4, pos);
263 mapmap.AddOrSetValue( -4, neg);
264
265 Result := mapmap;
266end;
267
268function TTestServer.TTestHandlerImpl.testMulti(arg0: ShortInt; arg1: Integer;
Roger Meier333bbf32012-01-08 21:51:08 +0000269 const arg2: Int64; const arg3: IThriftDictionary<SmallInt, string>;
270 arg4: TNumberz; const arg5: Int64): IXtruct;
Jake Farrell27274222011-11-10 20:32:44 +0000271var
272 hello : IXtruct;
273begin
274 Console.WriteLine('testMulti()');
275 hello := TXtructImpl.Create;
276 hello.String_thing := 'Hello2';
277 hello.Byte_thing := arg0;
278 hello.I32_thing := arg1;
279 hello.I64_thing := arg2;
280 Result := hello;
281end;
282
Roger Meier333bbf32012-01-08 21:51:08 +0000283function TTestServer.TTestHandlerImpl.testMultiException( const arg0, arg1: string): IXtruct;
Jake Farrell27274222011-11-10 20:32:44 +0000284var
Jake Farrell27274222011-11-10 20:32:44 +0000285 x2 : TXception2;
286begin
287 Console.WriteLine('testMultiException(' + arg0 + ', ' + arg1 + ')');
Jens Geyer8f7487e2019-05-09 22:21:32 +0200288 if ( arg0 = 'Xception') then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200289 raise TXception.Create( 1001, 'This is an Xception'); // test the new rich CTOR
Jens Geyer8f7487e2019-05-09 22:21:32 +0200290 end;
291
292 if ( arg0 = 'Xception2') then begin
Jake Farrell343c61d2011-12-09 02:29:56 +0000293 x2 := TXception2.Create; // the old way still works too?
Jake Farrell27274222011-11-10 20:32:44 +0000294 x2.ErrorCode := 2002;
295 x2.Struct_thing := TXtructImpl.Create;
296 x2.Struct_thing.String_thing := 'This is an Xception2';
Jake Farrellac102562011-11-23 14:30:41 +0000297 x2.UpdateMessageProperty;
Jake Farrell27274222011-11-10 20:32:44 +0000298 raise x2;
299 end;
300
301 Result := TXtructImpl.Create;
302 Result.String_thing := arg1;
303end;
304
Roger Meier333bbf32012-01-08 21:51:08 +0000305function TTestServer.TTestHandlerImpl.testNest( const thing: IXtruct2): IXtruct2;
Jake Farrell27274222011-11-10 20:32:44 +0000306begin
Jens Geyer8f7487e2019-05-09 22:21:32 +0200307 Console.Write('testNest(');
308 if thing <> nil then Console.Write(thing.ToString);
309 Console.WriteLine(')');
310
Jake Farrell27274222011-11-10 20:32:44 +0000311 Result := thing;
312end;
313
314procedure TTestServer.TTestHandlerImpl.testOneway(secondsToSleep: Integer);
315begin
316 Console.WriteLine('testOneway(' + IntToStr( secondsToSleep )+ '), sleeping...');
317 Sleep(secondsToSleep * 1000);
318 Console.WriteLine('testOneway finished');
319end;
320
Jens Geyer8f7487e2019-05-09 22:21:32 +0200321function TTestServer.TTestHandlerImpl.testSet( const thing: IHashSet<Integer>):IHashSet<Integer>;
Jake Farrell27274222011-11-10 20:32:44 +0000322begin
Jens Geyer8f7487e2019-05-09 22:21:32 +0200323 Console.Write('testSet(');
324 if thing <> nil then Console.Write(thing.ToString);
325 Console.WriteLine(')');;
Jake Farrell27274222011-11-10 20:32:44 +0000326
Jake Farrell27274222011-11-10 20:32:44 +0000327 Result := thing;
328end;
329
330procedure TTestServer.TTestHandlerImpl.testStop;
331begin
Jens Geyer8f7487e2019-05-09 22:21:32 +0200332 if FServer <> nil then begin
Jake Farrell27274222011-11-10 20:32:44 +0000333 FServer.Stop;
334 end;
335end;
336
Jens Geyer39ba6b72015-09-22 00:00:49 +0200337function TTestServer.TTestHandlerImpl.testBool(thing: Boolean): Boolean;
338begin
339 Console.WriteLine('testBool(' + BoolToStr(thing,true) + ')');
340 Result := thing;
341end;
342
Roger Meier333bbf32012-01-08 21:51:08 +0000343function TTestServer.TTestHandlerImpl.testString( const thing: string): string;
Jake Farrell27274222011-11-10 20:32:44 +0000344begin
345 Console.WriteLine('teststring("' + thing + '")');
346 Result := thing;
347end;
348
349function TTestServer.TTestHandlerImpl.testStringMap(
Roger Meier333bbf32012-01-08 21:51:08 +0000350 const thing: IThriftDictionary<string, string>): IThriftDictionary<string, string>;
Jake Farrell27274222011-11-10 20:32:44 +0000351begin
Jens Geyer8f7487e2019-05-09 22:21:32 +0200352 Console.Write('testStringMap(');
353 if thing <> nil then Console.Write(thing.ToString);
354 Console.WriteLine(')');
355
Roger Meierbb6de7a2012-05-04 23:35:45 +0000356 Result := thing;
Jake Farrell27274222011-11-10 20:32:44 +0000357end;
358
Roger Meier333bbf32012-01-08 21:51:08 +0000359function TTestServer.TTestHandlerImpl.testTypedef( const thing: Int64): Int64;
Jake Farrell27274222011-11-10 20:32:44 +0000360begin
361 Console.WriteLine('testTypedef(' + IntToStr( thing) + ')');
362 Result := thing;
363end;
364
365procedure TTestServer.TTestHandlerImpl.TestVoid;
366begin
367 Console.WriteLine('testVoid()');
368end;
369
Roger Meier333bbf32012-01-08 21:51:08 +0000370function TTestServer.TTestHandlerImpl.testStruct( const thing: IXtruct): IXtruct;
Jake Farrell27274222011-11-10 20:32:44 +0000371begin
Jens Geyer8f7487e2019-05-09 22:21:32 +0200372 Console.Write('testStruct(');
373 if thing <> nil then Console.Write(thing.ToString);
374 Console.WriteLine(')');
375
Jake Farrell27274222011-11-10 20:32:44 +0000376 Result := thing;
377end;
378
Roger Meier3bef8c22012-10-06 06:58:00 +0000379
Jake Farrell27274222011-11-10 20:32:44 +0000380{ TTestServer }
381
Roger Meier3bef8c22012-10-06 06:58:00 +0000382
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200383class procedure TTestServer.PrintCmdLineHelp;
384const HELPTEXT = ' [options]'#10
385 + #10
386 + 'Allowed options:'#10
387 + ' -h [ --help ] produce help message'#10
388 + ' --port arg (=9090) Port number to listen'#10
389 + ' --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift)'#10
390 + ' --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe)'#10
391 + ' --server-type arg (=simple) type of server, "simple", "thread-pool",'#10
392 + ' "threaded", or "nonblocking"'#10
393 + ' --transport arg (=socket) transport: buffered, framed, http, anonpipe'#10
394 + ' --protocol arg (=binary) protocol: binary, compact, json'#10
395 + ' --ssl Encrypted Transport using SSL'#10
396 + ' --processor-events processor-events'#10
397 + ' -n [ --workers ] arg (=4) Number of thread pools workers. Only valid for'#10
398 + ' thread-pool server type'#10
399 ;
400begin
401 Console.WriteLine( ChangeFileExt(ExtractFileName(ParamStr(0)),'') + HELPTEXT);
402end;
403
404class procedure TTestServer.InvalidArgs;
405begin
406 Console.WriteLine( 'Invalid args.');
407 Console.WriteLine( ChangeFileExt(ExtractFileName(ParamStr(0)),'') + ' -h for more information');
408 Abort;
409end;
410
Jens Geyer06045cf2013-03-27 20:26:25 +0200411class procedure TTestServer.LaunchAnonPipeChild( const app : string; const transport : IAnonymousPipeServerTransport);
Roger Meier3bef8c22012-10-06 06:58:00 +0000412//Launch child process and pass R/W anonymous pipe handles on cmd line.
413//This is a simple example and does not include elevation or other
414//advanced features.
415var pi : PROCESS_INFORMATION;
Jens Geyerd5436f52014-10-03 19:50:38 +0200416 si : STARTUPINFO;
417 sArg, sHandles, sCmdLine : string;
Roger Meier3bef8c22012-10-06 06:58:00 +0000418 i : Integer;
419begin
420 GetStartupInfo( si); //set startupinfo for the spawned process
421
422 // preformat handles args
423 sHandles := Format( '%d %d',
424 [ Integer(transport.ClientAnonRead),
425 Integer(transport.ClientAnonWrite)]);
426
427 // pass all settings to client
428 sCmdLine := app;
429 for i := 1 to ParamCount do begin
430 sArg := ParamStr(i);
431
432 // add anonymous handles and quote strings where appropriate
433 if sArg = '-anon'
434 then sArg := sArg +' '+ sHandles
435 else begin
436 if Pos(' ',sArg) > 0
437 then sArg := '"'+sArg+'"';
438 end;;
439
440 sCmdLine := sCmdLine +' '+ sArg;
441 end;
442
443 // spawn the child process
444 Console.WriteLine('Starting client '+sCmdLine);
445 Win32Check( CreateProcess( nil, PChar(sCmdLine), nil,nil,TRUE,0,nil,nil,si,pi));
446
447 CloseHandle( pi.hThread);
Jens Geyerd5436f52014-10-03 19:50:38 +0200448 CloseHandle( pi.hProcess);
Roger Meier3bef8c22012-10-06 06:58:00 +0000449end;
450
451
Roger Meier333bbf32012-01-08 21:51:08 +0000452class procedure TTestServer.Execute( const args: array of string);
Jake Farrell27274222011-11-10 20:32:44 +0000453var
Jake Farrell27274222011-11-10 20:32:44 +0000454 Port : Integer;
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200455 ServerEvents : Boolean;
Roger Meier3bef8c22012-10-06 06:58:00 +0000456 sPipeName : string;
Jake Farrell27274222011-11-10 20:32:44 +0000457 testHandler : ITestHandler;
458 testProcessor : IProcessor;
Roger Meier3bef8c22012-10-06 06:58:00 +0000459 ServerTrans : IServerTransport;
Jake Farrell27274222011-11-10 20:32:44 +0000460 ServerEngine : IServer;
Jens Geyer06045cf2013-03-27 20:26:25 +0200461 anonymouspipe : IAnonymousPipeServerTransport;
462 namedpipe : INamedPipeServerTransport;
Jake Farrell27274222011-11-10 20:32:44 +0000463 TransportFactory : ITransportFactory;
464 ProtocolFactory : IProtocolFactory;
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200465 i, numWorker : Integer;
Jake Farrell27274222011-11-10 20:32:44 +0000466 s : string;
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200467 protType : TKnownProtocol;
468 servertype : TServerType;
469 endpoint : TEndpointTransport;
470 layered : TLayeredTransports;
471 UseSSL : Boolean; // include where appropriate (TLayeredTransport?)
Jake Farrell27274222011-11-10 20:32:44 +0000472begin
473 try
Jens Geyer01640402013-09-25 21:12:21 +0200474 ServerEvents := FALSE;
Jake Farrell27274222011-11-10 20:32:44 +0000475 protType := prot_Binary;
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200476 servertype := srv_Simple;
477 endpoint := trns_Sockets;
478 layered := [];
479 UseSSL := FALSE;
Jake Farrell27274222011-11-10 20:32:44 +0000480 Port := 9090;
Roger Meier3bef8c22012-10-06 06:58:00 +0000481 sPipeName := '';
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200482 numWorker := 4;
Jake Farrell27274222011-11-10 20:32:44 +0000483
484 i := 0;
485 while ( i < Length(args) ) do begin
486 s := args[i];
487 Inc(i);
488
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200489 // Allowed options:
490 if (s = '-h') or (s = '--help') then begin
491 // -h [ --help ] produce help message
492 PrintCmdLineHelp;
493 Exit;
Roger Meier3bef8c22012-10-06 06:58:00 +0000494 end
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200495 else if (s = '--port') then begin
496 // --port arg (=9090) Port number to listen
497 s := args[i];
498 Inc(i);
499 Port := StrToIntDef( s, Port);
Roger Meier3bef8c22012-10-06 06:58:00 +0000500 end
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200501 else if (s = '--domain-socket') then begin
502 // --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift)
503 raise Exception.Create('domain-socket not supported');
Roger Meier3bef8c22012-10-06 06:58:00 +0000504 end
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200505 else if (s = '--named-pipe') then begin
506 // --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe)
507 endpoint := trns_NamedPipes;
Roger Meier3bef8c22012-10-06 06:58:00 +0000508 sPipeName := args[i]; // -pipe <name>
509 Inc( i );
510 end
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200511 else if (s = '--server-type') then begin
512 // --server-type arg (=simple) type of server,
513 // arg = "simple", "thread-pool", "threaded", or "nonblocking"
Jake Farrell27274222011-11-10 20:32:44 +0000514 s := args[i];
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200515 Inc(i);
516
517 if s = 'simple' then servertype := srv_Simple
518 else if s = 'thread-pool' then servertype := srv_Threadpool
519 else if s = 'threaded' then servertype := srv_Threaded
520 else if s = 'nonblocking' then servertype := srv_Nonblocking
521 else InvalidArgs;
Jens Geyer01640402013-09-25 21:12:21 +0200522 end
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200523 else if (s = '--transport') then begin
524 // --transport arg (=buffered) transport: buffered, framed, http
525 s := args[i];
526 Inc(i);
527
528 if s = 'buffered' then Include( layered, trns_Buffered)
529 else if s = 'framed' then Include( layered, trns_Framed)
Jens Geyer02230912019-04-03 01:12:51 +0200530 else if s = 'http' then endpoint := trns_MsxmlHttp
531 else if s = 'winhttp' then endpoint := trns_WinHttp
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200532 else if s = 'anonpipe' then endpoint := trns_AnonPipes
533 else InvalidArgs;
534 end
535 else if (s = '--protocol') then begin
536 // --protocol arg (=binary) protocol: binary, compact, json
537 s := args[i];
538 Inc(i);
539
540 if s = 'binary' then protType := prot_Binary
541 else if s = 'compact' then protType := prot_Compact
542 else if s = 'json' then protType := prot_JSON
543 else InvalidArgs;
544 end
545 else if (s = '--ssl') then begin
546 // --ssl Encrypted Transport using SSL
547 UseSSL := TRUE;
548 end
549 else if (s = '--processor-events') then begin
550 // --processor-events processor-events
551 ServerEvents := TRUE;
552 end
553 else if (s = '-n') or (s = '--workers') then begin
554 // -n [ --workers ] arg (=4) Number of thread pools workers.
555 // Only valid for thread-pool server type
556 s := args[i];
557 numWorker := StrToIntDef(s,0);
558 if numWorker > 0
559 then Inc(i)
560 else numWorker := 4;
Jens Geyer01640402013-09-25 21:12:21 +0200561 end
562 else begin
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200563 InvalidArgs;
564 end;
Jake Farrell27274222011-11-10 20:32:44 +0000565 end;
566
Roger Meier3bef8c22012-10-06 06:58:00 +0000567
568 Console.WriteLine('Server configuration: ');
569
Jake Farrell27274222011-11-10 20:32:44 +0000570 // create protocol factory, default to BinaryProtocol
571 case protType of
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200572 prot_Binary : ProtocolFactory := TBinaryProtocolImpl.TFactory.Create( BINARY_STRICT_READ, BINARY_STRICT_WRITE);
573 prot_JSON : ProtocolFactory := TJSONProtocolImpl.TFactory.Create;
Jens Geyerf0e63312015-03-01 18:47:49 +0100574 prot_Compact : ProtocolFactory := TCompactProtocolImpl.TFactory.Create;
Jake Farrell27274222011-11-10 20:32:44 +0000575 else
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200576 raise Exception.Create('Unhandled protocol');
Jake Farrell27274222011-11-10 20:32:44 +0000577 end;
Roger Meier3bef8c22012-10-06 06:58:00 +0000578 ASSERT( ProtocolFactory <> nil);
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200579 Console.WriteLine('- '+THRIFT_PROTOCOLS[protType]+' protocol');
Jake Farrell27274222011-11-10 20:32:44 +0000580
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200581 case endpoint of
Jake Farrell27274222011-11-10 20:32:44 +0000582
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200583 trns_Sockets : begin
584 Console.WriteLine('- sockets (port '+IntToStr(port)+')');
585 if (trns_Buffered in layered) then Console.WriteLine('- buffered');
Jens Geyer41f47af2019-11-09 23:24:52 +0100586 servertrans := TServerSocketImpl.Create( Port, DEFAULT_THRIFT_TIMEOUT, (trns_Buffered in layered));
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200587 end;
588
Jens Geyer02230912019-04-03 01:12:51 +0200589 trns_MsxmlHttp,
590 trns_WinHttp : begin
591 raise Exception.Create('HTTP server transport not implemented');
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200592 end;
593
594 trns_NamedPipes : begin
595 Console.WriteLine('- named pipe ('+sPipeName+')');
Jens Geyer2ad6c302015-02-26 19:38:53 +0100596 namedpipe := TNamedPipeServerTransportImpl.Create( sPipeName, 4096, PIPE_UNLIMITED_INSTANCES);
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200597 servertrans := namedpipe;
598 end;
599
600 trns_AnonPipes : begin
601 Console.WriteLine('- anonymous pipes');
602 anonymouspipe := TAnonymousPipeServerTransportImpl.Create;
603 servertrans := anonymouspipe;
604 end
605
606 else
607 raise Exception.Create('Unhandled endpoint transport');
Roger Meier3bef8c22012-10-06 06:58:00 +0000608 end;
609 ASSERT( servertrans <> nil);
610
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200611 if UseSSL then begin
612 raise Exception.Create('SSL not implemented');
613 end;
614
615 if (trns_Framed in layered) then begin
Roger Meier3bef8c22012-10-06 06:58:00 +0000616 Console.WriteLine('- framed transport');
617 TransportFactory := TFramedTransportImpl.TFactory.Create
618 end
619 else begin
620 TransportFactory := TTransportFactoryImpl.Create;
621 end;
622 ASSERT( TransportFactory <> nil);
623
624 testHandler := TTestHandlerImpl.Create;
Jake Farrell27274222011-11-10 20:32:44 +0000625 testProcessor := TThriftTest.TProcessorImpl.Create( testHandler );
Jake Farrell27274222011-11-10 20:32:44 +0000626
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200627 case servertype of
628 srv_Simple : begin
629 ServerEngine := TSimpleServer.Create( testProcessor, ServerTrans, TransportFactory, ProtocolFactory);
630 end;
631
632 srv_Nonblocking : begin
633 raise Exception.Create(SERVER_TYPES[servertype]+' server not implemented');
634 end;
635
636 srv_Threadpool,
637 srv_Threaded: begin
638 if numWorker > 1 then {use here};
639 raise Exception.Create(SERVER_TYPES[servertype]+' server not implemented');
640 end;
641
642 else
643 raise Exception.Create('Unhandled server type');
644 end;
645 ASSERT( ServerEngine <> nil);
Jake Farrell27274222011-11-10 20:32:44 +0000646
647 testHandler.SetServer( ServerEngine);
648
Jens Geyer01640402013-09-25 21:12:21 +0200649 // test events?
650 if ServerEvents then begin
651 Console.WriteLine('- server events test enabled');
652 ServerEngine.ServerEvents := TServerEventsImpl.Create;
653 end;
654
Roger Meier3bef8c22012-10-06 06:58:00 +0000655 // start the client now when we have the anon handles, but before the server starts
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200656 if endpoint = trns_AnonPipes
Roger Meier79655fb2012-10-20 20:59:41 +0000657 then LaunchAnonPipeChild( ExtractFilePath(ParamStr(0))+'client.exe', anonymouspipe);
Jake Farrell27274222011-11-10 20:32:44 +0000658
Jens Geyer06045cf2013-03-27 20:26:25 +0200659 // install Ctrl+C handler before the server starts
660 g_Handler := testHandler;
661 SetConsoleCtrlHandler( @MyConsoleEventHandler, TRUE);
Roger Meier3bef8c22012-10-06 06:58:00 +0000662
663 Console.WriteLine('');
Jens Geyer06045cf2013-03-27 20:26:25 +0200664 repeat
665 Console.WriteLine('Starting the server ...');
666 serverEngine.Serve;
667 until {$IFDEF RunEndless} FALSE {$ELSE} TRUE {$ENDIF};
668
Jake Farrell27274222011-11-10 20:32:44 +0000669 testHandler.SetServer( nil);
Jens Geyer06045cf2013-03-27 20:26:25 +0200670 g_Handler := nil;
Jake Farrell27274222011-11-10 20:32:44 +0000671
672 except
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200673 on E: EAbort do raise;
674 on E: Exception do begin
675 Console.WriteLine( E.Message + #10 + E.StackTrace );
Jake Farrell27274222011-11-10 20:32:44 +0000676 end;
677 end;
678 Console.WriteLine( 'done.');
679end;
680
Jens Geyer06045cf2013-03-27 20:26:25 +0200681
Jake Farrell27274222011-11-10 20:32:44 +0000682end.