blob: e3576dd8489393837fbea035e80bc50b3377ea3f [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,
32 Thrift.Console,
33 Thrift.Server,
34 Thrift.Transport,
Roger Meier3bef8c22012-10-06 06:58:00 +000035 Thrift.Transport.Pipes,
Jake Farrell27274222011-11-10 20:32:44 +000036 Thrift.Protocol,
37 Thrift.Protocol.JSON,
Jens Geyerf0e63312015-03-01 18:47:49 +010038 Thrift.Protocol.Compact,
Jake Farrell27274222011-11-10 20:32:44 +000039 Thrift.Collections,
40 Thrift.Utils,
41 Thrift.Test,
42 Thrift,
43 TestConstants,
Jens Geyer01640402013-09-25 21:12:21 +020044 TestServerEvents,
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
147 Console.WriteLine('testBinary("' + BytesToHex( thing ) + '")');
148 Result := thing;
149end;
150
Jake Farrell27274222011-11-10 20:32:44 +0000151function TTestServer.TTestHandlerImpl.testEnum(thing: TNumberz): TNumberz;
152begin
153 Console.WriteLine('testEnum(' + IntToStr( Integer( thing)) + ')');
154 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 + ')');
160 if ( arg = 'Xception') then
161 begin
Roger Meierbb6de7a2012-05-04 23:35:45 +0000162 raise TXception.Create( 1001, arg);
Jake Farrell27274222011-11-10 20:32:44 +0000163 end;
Roger Meierbb6de7a2012-05-04 23:35:45 +0000164
165 if (arg = 'TException') then
166 begin
167 raise TException.Create('');
168 end;
169
170 // else do not throw anything
Jake Farrell27274222011-11-10 20:32:44 +0000171end;
172
173function TTestServer.TTestHandlerImpl.testI32(thing: Integer): Integer;
174begin
175 Console.WriteLine('testI32("' + IntToStr( thing) + '")');
176 Result := thing;
177end;
178
Roger Meier333bbf32012-01-08 21:51:08 +0000179function TTestServer.TTestHandlerImpl.testI64( const thing: Int64): Int64;
Jake Farrell27274222011-11-10 20:32:44 +0000180begin
181 Console.WriteLine('testI64("' + IntToStr( thing) + '")');
182 Result := thing;
183end;
184
185function TTestServer.TTestHandlerImpl.testInsanity(
Roger Meier333bbf32012-01-08 21:51:08 +0000186 const argument: IInsanity): IThriftDictionary<Int64, IThriftDictionary<TNumberz, IInsanity>>;
Jake Farrell27274222011-11-10 20:32:44 +0000187var
188 hello, goodbye : IXtruct;
189 crazy : IInsanity;
190 looney : IInsanity;
191 first_map : IThriftDictionary<TNumberz, IInsanity>;
192 second_map : IThriftDictionary<TNumberz, IInsanity>;
193 insane : IThriftDictionary<Int64, IThriftDictionary<TNumberz, IInsanity>>;
194
195begin
196
197 Console.WriteLine('testInsanity()');
198 hello := TXtructImpl.Create;
Roger Meierbb6de7a2012-05-04 23:35:45 +0000199 hello.String_thing := 'Hello2';
Jake Farrell27274222011-11-10 20:32:44 +0000200 hello.Byte_thing := 2;
201 hello.I32_thing := 2;
202 hello.I64_thing := 2;
203
204 goodbye := TXtructImpl.Create;
205 goodbye.String_thing := 'Goodbye4';
206 goodbye.Byte_thing := 4;
207 goodbye.I32_thing := 4;
208 goodbye.I64_thing := 4;
209
210 crazy := TInsanityImpl.Create;
211 crazy.UserMap := TThriftDictionaryImpl<TNumberz, Int64>.Create;
212 crazy.UserMap.AddOrSetValue( TNumberz.EIGHT, 8);
213 crazy.Xtructs := TThriftListImpl<IXtruct>.Create;
214 crazy.Xtructs.Add(goodbye);
215
216 looney := TInsanityImpl.Create;
217 crazy.UserMap.AddOrSetValue( TNumberz.FIVE, 5);
218 crazy.Xtructs.Add(hello);
219
220 first_map := TThriftDictionaryImpl<TNumberz, IInsanity>.Create;
221 second_map := TThriftDictionaryImpl<TNumberz, IInsanity>.Create;
222
Roger Meierbb6de7a2012-05-04 23:35:45 +0000223 first_map.AddOrSetValue( TNumberz.TWO, crazy);
Jake Farrell27274222011-11-10 20:32:44 +0000224 first_map.AddOrSetValue( TNumberz.THREE, crazy);
225
226 second_map.AddOrSetValue( TNumberz.SIX, looney);
227
228 insane := TThriftDictionaryImpl<Int64, IThriftDictionary<TNumberz, IInsanity>>.Create;
229
230 insane.AddOrSetValue( 1, first_map);
231 insane.AddOrSetValue( 2, second_map);
232
233 Result := insane;
234end;
235
236function TTestServer.TTestHandlerImpl.testList(
Roger Meier333bbf32012-01-08 21:51:08 +0000237 const thing: IThriftList<Integer>): IThriftList<Integer>;
Jake Farrell27274222011-11-10 20:32:44 +0000238var
239 first : Boolean;
240 elem : Integer;
241begin
242 Console.Write('testList({');
243 first := True;
244 for elem in thing do
245 begin
246 if first then
247 begin
248 first := False;
249 end else
250 begin
251 Console.Write(', ');
252 end;
253 Console.Write( IntToStr( elem));
254 end;
255 Console.WriteLine('})');
256 Result := thing;
257end;
258
259function TTestServer.TTestHandlerImpl.testMap(
Roger Meier333bbf32012-01-08 21:51:08 +0000260 const thing: IThriftDictionary<Integer, Integer>): IThriftDictionary<Integer, Integer>;
Jake Farrell27274222011-11-10 20:32:44 +0000261var
262 first : Boolean;
263 key : Integer;
264begin
265 Console.Write('testMap({');
266 first := True;
267 for key in thing.Keys do
268 begin
269 if (first) then
270 begin
271 first := false;
272 end else
273 begin
274 Console.Write(', ');
275 end;
276 Console.Write(IntToStr(key) + ' => ' + IntToStr( thing[key]));
277 end;
278 Console.WriteLine('})');
279 Result := thing;
280end;
281
282function TTestServer.TTestHandlerImpl.TestMapMap(
283 hello: Integer): IThriftDictionary<Integer, IThriftDictionary<Integer, Integer>>;
284var
285 mapmap : IThriftDictionary<Integer, IThriftDictionary<Integer, Integer>>;
286 pos : IThriftDictionary<Integer, Integer>;
287 neg : IThriftDictionary<Integer, Integer>;
288 i : Integer;
289begin
290 Console.WriteLine('testMapMap(' + IntToStr( hello) + ')');
291 mapmap := TThriftDictionaryImpl<Integer, IThriftDictionary<Integer, Integer>>.Create;
292 pos := TThriftDictionaryImpl<Integer, Integer>.Create;
293 neg := TThriftDictionaryImpl<Integer, Integer>.Create;
294
295 for i := 1 to 4 do
296 begin
297 pos.AddOrSetValue( i, i);
298 neg.AddOrSetValue( -i, -i);
299 end;
300
301 mapmap.AddOrSetValue(4, pos);
302 mapmap.AddOrSetValue( -4, neg);
303
304 Result := mapmap;
305end;
306
307function TTestServer.TTestHandlerImpl.testMulti(arg0: ShortInt; arg1: Integer;
Roger Meier333bbf32012-01-08 21:51:08 +0000308 const arg2: Int64; const arg3: IThriftDictionary<SmallInt, string>;
309 arg4: TNumberz; const arg5: Int64): IXtruct;
Jake Farrell27274222011-11-10 20:32:44 +0000310var
311 hello : IXtruct;
312begin
313 Console.WriteLine('testMulti()');
314 hello := TXtructImpl.Create;
315 hello.String_thing := 'Hello2';
316 hello.Byte_thing := arg0;
317 hello.I32_thing := arg1;
318 hello.I64_thing := arg2;
319 Result := hello;
320end;
321
Roger Meier333bbf32012-01-08 21:51:08 +0000322function TTestServer.TTestHandlerImpl.testMultiException( const arg0, arg1: string): IXtruct;
Jake Farrell27274222011-11-10 20:32:44 +0000323var
Jake Farrell27274222011-11-10 20:32:44 +0000324 x2 : TXception2;
325begin
326 Console.WriteLine('testMultiException(' + arg0 + ', ' + arg1 + ')');
327 if ( arg0 = 'Xception') then
328 begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200329 raise TXception.Create( 1001, 'This is an Xception'); // test the new rich CTOR
Jake Farrell27274222011-11-10 20:32:44 +0000330 end else
331 if ( arg0 = 'Xception2') then
332 begin
Jake Farrell343c61d2011-12-09 02:29:56 +0000333 x2 := TXception2.Create; // the old way still works too?
Jake Farrell27274222011-11-10 20:32:44 +0000334 x2.ErrorCode := 2002;
335 x2.Struct_thing := TXtructImpl.Create;
336 x2.Struct_thing.String_thing := 'This is an Xception2';
Jake Farrellac102562011-11-23 14:30:41 +0000337 x2.UpdateMessageProperty;
Jake Farrell27274222011-11-10 20:32:44 +0000338 raise x2;
339 end;
340
341 Result := TXtructImpl.Create;
342 Result.String_thing := arg1;
343end;
344
Roger Meier333bbf32012-01-08 21:51:08 +0000345function TTestServer.TTestHandlerImpl.testNest( const thing: IXtruct2): IXtruct2;
Jake Farrell27274222011-11-10 20:32:44 +0000346var
347 temp : IXtruct;
348begin
349 temp := thing.Struct_thing;
350 Console.WriteLine('testNest({' +
351 IntToStr( thing.Byte_thing) + ', {' +
352 '"' + temp.String_thing + '", ' +
353 IntToStr( temp.Byte_thing) + ', ' +
354 IntToStr( temp.I32_thing) + ', ' +
355 IntToStr( temp.I64_thing) + '}, ' +
356 IntToStr( temp.I32_thing) + '})');
357 Result := thing;
358end;
359
360procedure TTestServer.TTestHandlerImpl.testOneway(secondsToSleep: Integer);
361begin
362 Console.WriteLine('testOneway(' + IntToStr( secondsToSleep )+ '), sleeping...');
363 Sleep(secondsToSleep * 1000);
364 Console.WriteLine('testOneway finished');
365end;
366
367function TTestServer.TTestHandlerImpl.testSet(
Roger Meier333bbf32012-01-08 21:51:08 +0000368 const thing: IHashSet<Integer>):IHashSet<Integer>;
Jake Farrell27274222011-11-10 20:32:44 +0000369var
370 first : Boolean;
371 elem : Integer;
372begin
373 Console.Write('testSet({');
374 first := True;
375
376 for elem in thing do
377 begin
378 if first then
379 begin
380 first := False;
381 end else
382 begin
383 Console.Write( ', ');
384 end;
385 Console.Write( IntToStr( elem));
386 end;
387 Console.WriteLine('})');
388 Result := thing;
389end;
390
391procedure TTestServer.TTestHandlerImpl.testStop;
392begin
393 if FServer <> nil then
394 begin
395 FServer.Stop;
396 end;
397end;
398
Jens Geyer39ba6b72015-09-22 00:00:49 +0200399function TTestServer.TTestHandlerImpl.testBool(thing: Boolean): Boolean;
400begin
401 Console.WriteLine('testBool(' + BoolToStr(thing,true) + ')');
402 Result := thing;
403end;
404
Roger Meier333bbf32012-01-08 21:51:08 +0000405function TTestServer.TTestHandlerImpl.testString( const thing: string): string;
Jake Farrell27274222011-11-10 20:32:44 +0000406begin
407 Console.WriteLine('teststring("' + thing + '")');
408 Result := thing;
409end;
410
411function TTestServer.TTestHandlerImpl.testStringMap(
Roger Meier333bbf32012-01-08 21:51:08 +0000412 const thing: IThriftDictionary<string, string>): IThriftDictionary<string, string>;
Roger Meierbb6de7a2012-05-04 23:35:45 +0000413var
414 first : Boolean;
415 key : string;
Jake Farrell27274222011-11-10 20:32:44 +0000416begin
Roger Meierbb6de7a2012-05-04 23:35:45 +0000417 Console.Write('testStringMap({');
418 first := True;
419 for key in thing.Keys do
420 begin
421 if (first) then
422 begin
423 first := false;
424 end else
425 begin
426 Console.Write(', ');
427 end;
428 Console.Write(key + ' => ' + thing[key]);
429 end;
430 Console.WriteLine('})');
431 Result := thing;
Jake Farrell27274222011-11-10 20:32:44 +0000432end;
433
Roger Meier333bbf32012-01-08 21:51:08 +0000434function TTestServer.TTestHandlerImpl.testTypedef( const thing: Int64): Int64;
Jake Farrell27274222011-11-10 20:32:44 +0000435begin
436 Console.WriteLine('testTypedef(' + IntToStr( thing) + ')');
437 Result := thing;
438end;
439
440procedure TTestServer.TTestHandlerImpl.TestVoid;
441begin
442 Console.WriteLine('testVoid()');
443end;
444
Roger Meier333bbf32012-01-08 21:51:08 +0000445function TTestServer.TTestHandlerImpl.testStruct( const thing: IXtruct): IXtruct;
Jake Farrell27274222011-11-10 20:32:44 +0000446begin
447 Console.WriteLine('testStruct({' +
448 '"' + thing.String_thing + '", ' +
449 IntToStr( thing.Byte_thing) + ', ' +
450 IntToStr( thing.I32_thing) + ', ' +
451 IntToStr( thing.I64_thing));
452 Result := thing;
453end;
454
Roger Meier3bef8c22012-10-06 06:58:00 +0000455
Jake Farrell27274222011-11-10 20:32:44 +0000456{ TTestServer }
457
Roger Meier3bef8c22012-10-06 06:58:00 +0000458
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200459class procedure TTestServer.PrintCmdLineHelp;
460const HELPTEXT = ' [options]'#10
461 + #10
462 + 'Allowed options:'#10
463 + ' -h [ --help ] produce help message'#10
464 + ' --port arg (=9090) Port number to listen'#10
465 + ' --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift)'#10
466 + ' --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe)'#10
467 + ' --server-type arg (=simple) type of server, "simple", "thread-pool",'#10
468 + ' "threaded", or "nonblocking"'#10
469 + ' --transport arg (=socket) transport: buffered, framed, http, anonpipe'#10
470 + ' --protocol arg (=binary) protocol: binary, compact, json'#10
471 + ' --ssl Encrypted Transport using SSL'#10
472 + ' --processor-events processor-events'#10
473 + ' -n [ --workers ] arg (=4) Number of thread pools workers. Only valid for'#10
474 + ' thread-pool server type'#10
475 ;
476begin
477 Console.WriteLine( ChangeFileExt(ExtractFileName(ParamStr(0)),'') + HELPTEXT);
478end;
479
480class procedure TTestServer.InvalidArgs;
481begin
482 Console.WriteLine( 'Invalid args.');
483 Console.WriteLine( ChangeFileExt(ExtractFileName(ParamStr(0)),'') + ' -h for more information');
484 Abort;
485end;
486
Jens Geyer06045cf2013-03-27 20:26:25 +0200487class procedure TTestServer.LaunchAnonPipeChild( const app : string; const transport : IAnonymousPipeServerTransport);
Roger Meier3bef8c22012-10-06 06:58:00 +0000488//Launch child process and pass R/W anonymous pipe handles on cmd line.
489//This is a simple example and does not include elevation or other
490//advanced features.
491var pi : PROCESS_INFORMATION;
Jens Geyerd5436f52014-10-03 19:50:38 +0200492 si : STARTUPINFO;
493 sArg, sHandles, sCmdLine : string;
Roger Meier3bef8c22012-10-06 06:58:00 +0000494 i : Integer;
495begin
496 GetStartupInfo( si); //set startupinfo for the spawned process
497
498 // preformat handles args
499 sHandles := Format( '%d %d',
500 [ Integer(transport.ClientAnonRead),
501 Integer(transport.ClientAnonWrite)]);
502
503 // pass all settings to client
504 sCmdLine := app;
505 for i := 1 to ParamCount do begin
506 sArg := ParamStr(i);
507
508 // add anonymous handles and quote strings where appropriate
509 if sArg = '-anon'
510 then sArg := sArg +' '+ sHandles
511 else begin
512 if Pos(' ',sArg) > 0
513 then sArg := '"'+sArg+'"';
514 end;;
515
516 sCmdLine := sCmdLine +' '+ sArg;
517 end;
518
519 // spawn the child process
520 Console.WriteLine('Starting client '+sCmdLine);
521 Win32Check( CreateProcess( nil, PChar(sCmdLine), nil,nil,TRUE,0,nil,nil,si,pi));
522
523 CloseHandle( pi.hThread);
Jens Geyerd5436f52014-10-03 19:50:38 +0200524 CloseHandle( pi.hProcess);
Roger Meier3bef8c22012-10-06 06:58:00 +0000525end;
526
527
Roger Meier333bbf32012-01-08 21:51:08 +0000528class procedure TTestServer.Execute( const args: array of string);
Jake Farrell27274222011-11-10 20:32:44 +0000529var
Jake Farrell27274222011-11-10 20:32:44 +0000530 Port : Integer;
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200531 ServerEvents : Boolean;
Roger Meier3bef8c22012-10-06 06:58:00 +0000532 sPipeName : string;
Jake Farrell27274222011-11-10 20:32:44 +0000533 testHandler : ITestHandler;
534 testProcessor : IProcessor;
Roger Meier3bef8c22012-10-06 06:58:00 +0000535 ServerTrans : IServerTransport;
Jake Farrell27274222011-11-10 20:32:44 +0000536 ServerEngine : IServer;
Jens Geyer06045cf2013-03-27 20:26:25 +0200537 anonymouspipe : IAnonymousPipeServerTransport;
538 namedpipe : INamedPipeServerTransport;
Jake Farrell27274222011-11-10 20:32:44 +0000539 TransportFactory : ITransportFactory;
540 ProtocolFactory : IProtocolFactory;
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200541 i, numWorker : Integer;
Jake Farrell27274222011-11-10 20:32:44 +0000542 s : string;
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200543 protType : TKnownProtocol;
544 servertype : TServerType;
545 endpoint : TEndpointTransport;
546 layered : TLayeredTransports;
547 UseSSL : Boolean; // include where appropriate (TLayeredTransport?)
Jake Farrell27274222011-11-10 20:32:44 +0000548begin
549 try
Jens Geyer01640402013-09-25 21:12:21 +0200550 ServerEvents := FALSE;
Jake Farrell27274222011-11-10 20:32:44 +0000551 protType := prot_Binary;
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200552 servertype := srv_Simple;
553 endpoint := trns_Sockets;
554 layered := [];
555 UseSSL := FALSE;
Jake Farrell27274222011-11-10 20:32:44 +0000556 Port := 9090;
Roger Meier3bef8c22012-10-06 06:58:00 +0000557 sPipeName := '';
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200558 numWorker := 4;
Jake Farrell27274222011-11-10 20:32:44 +0000559
560 i := 0;
561 while ( i < Length(args) ) do begin
562 s := args[i];
563 Inc(i);
564
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200565 // Allowed options:
566 if (s = '-h') or (s = '--help') then begin
567 // -h [ --help ] produce help message
568 PrintCmdLineHelp;
569 Exit;
Roger Meier3bef8c22012-10-06 06:58:00 +0000570 end
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200571 else if (s = '--port') then begin
572 // --port arg (=9090) Port number to listen
573 s := args[i];
574 Inc(i);
575 Port := StrToIntDef( s, Port);
Roger Meier3bef8c22012-10-06 06:58:00 +0000576 end
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200577 else if (s = '--domain-socket') then begin
578 // --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift)
579 raise Exception.Create('domain-socket not supported');
Roger Meier3bef8c22012-10-06 06:58:00 +0000580 end
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200581 else if (s = '--named-pipe') then begin
582 // --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe)
583 endpoint := trns_NamedPipes;
Roger Meier3bef8c22012-10-06 06:58:00 +0000584 sPipeName := args[i]; // -pipe <name>
585 Inc( i );
586 end
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200587 else if (s = '--server-type') then begin
588 // --server-type arg (=simple) type of server,
589 // arg = "simple", "thread-pool", "threaded", or "nonblocking"
Jake Farrell27274222011-11-10 20:32:44 +0000590 s := args[i];
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200591 Inc(i);
592
593 if s = 'simple' then servertype := srv_Simple
594 else if s = 'thread-pool' then servertype := srv_Threadpool
595 else if s = 'threaded' then servertype := srv_Threaded
596 else if s = 'nonblocking' then servertype := srv_Nonblocking
597 else InvalidArgs;
Jens Geyer01640402013-09-25 21:12:21 +0200598 end
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200599 else if (s = '--transport') then begin
600 // --transport arg (=buffered) transport: buffered, framed, http
601 s := args[i];
602 Inc(i);
603
604 if s = 'buffered' then Include( layered, trns_Buffered)
605 else if s = 'framed' then Include( layered, trns_Framed)
606 else if s = 'http' then endpoint := trns_Http
607 else if s = 'anonpipe' then endpoint := trns_AnonPipes
608 else InvalidArgs;
609 end
610 else if (s = '--protocol') then begin
611 // --protocol arg (=binary) protocol: binary, compact, json
612 s := args[i];
613 Inc(i);
614
615 if s = 'binary' then protType := prot_Binary
616 else if s = 'compact' then protType := prot_Compact
617 else if s = 'json' then protType := prot_JSON
618 else InvalidArgs;
619 end
620 else if (s = '--ssl') then begin
621 // --ssl Encrypted Transport using SSL
622 UseSSL := TRUE;
623 end
624 else if (s = '--processor-events') then begin
625 // --processor-events processor-events
626 ServerEvents := TRUE;
627 end
628 else if (s = '-n') or (s = '--workers') then begin
629 // -n [ --workers ] arg (=4) Number of thread pools workers.
630 // Only valid for thread-pool server type
631 s := args[i];
632 numWorker := StrToIntDef(s,0);
633 if numWorker > 0
634 then Inc(i)
635 else numWorker := 4;
Jens Geyer01640402013-09-25 21:12:21 +0200636 end
637 else begin
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200638 InvalidArgs;
639 end;
Jake Farrell27274222011-11-10 20:32:44 +0000640 end;
641
Roger Meier3bef8c22012-10-06 06:58:00 +0000642
643 Console.WriteLine('Server configuration: ');
644
Jake Farrell27274222011-11-10 20:32:44 +0000645 // create protocol factory, default to BinaryProtocol
646 case protType of
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200647 prot_Binary : ProtocolFactory := TBinaryProtocolImpl.TFactory.Create( BINARY_STRICT_READ, BINARY_STRICT_WRITE);
648 prot_JSON : ProtocolFactory := TJSONProtocolImpl.TFactory.Create;
Jens Geyerf0e63312015-03-01 18:47:49 +0100649 prot_Compact : ProtocolFactory := TCompactProtocolImpl.TFactory.Create;
Jake Farrell27274222011-11-10 20:32:44 +0000650 else
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200651 raise Exception.Create('Unhandled protocol');
Jake Farrell27274222011-11-10 20:32:44 +0000652 end;
Roger Meier3bef8c22012-10-06 06:58:00 +0000653 ASSERT( ProtocolFactory <> nil);
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200654 Console.WriteLine('- '+THRIFT_PROTOCOLS[protType]+' protocol');
Jake Farrell27274222011-11-10 20:32:44 +0000655
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200656 case endpoint of
Jake Farrell27274222011-11-10 20:32:44 +0000657
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200658 trns_Sockets : begin
659 Console.WriteLine('- sockets (port '+IntToStr(port)+')');
660 if (trns_Buffered in layered) then Console.WriteLine('- buffered');
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200661 {$IFDEF OLD_SOCKETS}
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200662 servertrans := TServerSocketImpl.Create( Port, 0, (trns_Buffered in layered));
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200663 {$ELSE}
664 raise Exception.Create(ENDPOINT_TRANSPORTS[endpoint]+' server transport not implemented');
665 {$ENDIF}
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200666 end;
667
668 trns_Http : begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200669 raise Exception.Create(ENDPOINT_TRANSPORTS[endpoint]+' server transport not implemented');
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200670 end;
671
672 trns_NamedPipes : begin
673 Console.WriteLine('- named pipe ('+sPipeName+')');
Jens Geyer2ad6c302015-02-26 19:38:53 +0100674 namedpipe := TNamedPipeServerTransportImpl.Create( sPipeName, 4096, PIPE_UNLIMITED_INSTANCES);
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200675 servertrans := namedpipe;
676 end;
677
678 trns_AnonPipes : begin
679 Console.WriteLine('- anonymous pipes');
680 anonymouspipe := TAnonymousPipeServerTransportImpl.Create;
681 servertrans := anonymouspipe;
682 end
683
684 else
685 raise Exception.Create('Unhandled endpoint transport');
Roger Meier3bef8c22012-10-06 06:58:00 +0000686 end;
687 ASSERT( servertrans <> nil);
688
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200689 if UseSSL then begin
690 raise Exception.Create('SSL not implemented');
691 end;
692
693 if (trns_Framed in layered) then begin
Roger Meier3bef8c22012-10-06 06:58:00 +0000694 Console.WriteLine('- framed transport');
695 TransportFactory := TFramedTransportImpl.TFactory.Create
696 end
697 else begin
698 TransportFactory := TTransportFactoryImpl.Create;
699 end;
700 ASSERT( TransportFactory <> nil);
701
702 testHandler := TTestHandlerImpl.Create;
Jake Farrell27274222011-11-10 20:32:44 +0000703 testProcessor := TThriftTest.TProcessorImpl.Create( testHandler );
Jake Farrell27274222011-11-10 20:32:44 +0000704
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200705 case servertype of
706 srv_Simple : begin
707 ServerEngine := TSimpleServer.Create( testProcessor, ServerTrans, TransportFactory, ProtocolFactory);
708 end;
709
710 srv_Nonblocking : begin
711 raise Exception.Create(SERVER_TYPES[servertype]+' server not implemented');
712 end;
713
714 srv_Threadpool,
715 srv_Threaded: begin
716 if numWorker > 1 then {use here};
717 raise Exception.Create(SERVER_TYPES[servertype]+' server not implemented');
718 end;
719
720 else
721 raise Exception.Create('Unhandled server type');
722 end;
723 ASSERT( ServerEngine <> nil);
Jake Farrell27274222011-11-10 20:32:44 +0000724
725 testHandler.SetServer( ServerEngine);
726
Jens Geyer01640402013-09-25 21:12:21 +0200727 // test events?
728 if ServerEvents then begin
729 Console.WriteLine('- server events test enabled');
730 ServerEngine.ServerEvents := TServerEventsImpl.Create;
731 end;
732
Roger Meier3bef8c22012-10-06 06:58:00 +0000733 // start the client now when we have the anon handles, but before the server starts
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200734 if endpoint = trns_AnonPipes
Roger Meier79655fb2012-10-20 20:59:41 +0000735 then LaunchAnonPipeChild( ExtractFilePath(ParamStr(0))+'client.exe', anonymouspipe);
Jake Farrell27274222011-11-10 20:32:44 +0000736
Jens Geyer06045cf2013-03-27 20:26:25 +0200737 // install Ctrl+C handler before the server starts
738 g_Handler := testHandler;
739 SetConsoleCtrlHandler( @MyConsoleEventHandler, TRUE);
Roger Meier3bef8c22012-10-06 06:58:00 +0000740
741 Console.WriteLine('');
Jens Geyer06045cf2013-03-27 20:26:25 +0200742 repeat
743 Console.WriteLine('Starting the server ...');
744 serverEngine.Serve;
745 until {$IFDEF RunEndless} FALSE {$ELSE} TRUE {$ENDIF};
746
Jake Farrell27274222011-11-10 20:32:44 +0000747 testHandler.SetServer( nil);
Jens Geyer06045cf2013-03-27 20:26:25 +0200748 g_Handler := nil;
Jake Farrell27274222011-11-10 20:32:44 +0000749
750 except
Jens Geyerf8a1b7a2014-09-24 00:26:46 +0200751 on E: EAbort do raise;
752 on E: Exception do begin
753 Console.WriteLine( E.Message + #10 + E.StackTrace );
Jake Farrell27274222011-11-10 20:32:44 +0000754 end;
755 end;
756 Console.WriteLine( 'done.');
757end;
758
Jens Geyer06045cf2013-03-27 20:26:25 +0200759
Jake Farrell27274222011-11-10 20:32:44 +0000760end.