blob: fa48e818d54ae804dd466011e7cf2ffdf3375c29 [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
22interface
23
24uses
25 SysUtils,
26 Generics.Collections,
27 Thrift.Console,
28 Thrift.Server,
29 Thrift.Transport,
30 Thrift.Protocol,
31 Thrift.Protocol.JSON,
32 Thrift.Collections,
33 Thrift.Utils,
34 Thrift.Test,
35 Thrift,
36 TestConstants,
37 Contnrs;
38
39type
40 TTestServer = class
41 public
42 type
43
44 ITestHandler = interface( TThriftTest.Iface )
Roger Meier333bbf32012-01-08 21:51:08 +000045 procedure SetServer( const AServer : IServer );
Jake Farrell27274222011-11-10 20:32:44 +000046 end;
47
48 TTestHandlerImpl = class( TInterfacedObject, ITestHandler )
49 private
50 FServer : IServer;
51 protected
52 procedure testVoid();
Roger Meier333bbf32012-01-08 21:51:08 +000053 function testString(const thing: string): string;
Jake Farrell7ae13e12011-10-18 14:35:26 +000054 function testByte(thing: ShortInt): ShortInt;
55 function testI32(thing: Integer): Integer;
Roger Meier333bbf32012-01-08 21:51:08 +000056 function testI64(const thing: Int64): Int64;
57 function testDouble(const thing: Double): Double;
58 function testStruct(const thing: IXtruct): IXtruct;
59 function testNest(const thing: IXtruct2): IXtruct2;
60 function testMap(const thing: IThriftDictionary<Integer, Integer>): IThriftDictionary<Integer, Integer>;
61 function testStringMap(const thing: IThriftDictionary<string, string>): IThriftDictionary<string, string>;
62 function testSet(const thing: IHashSet<Integer>): IHashSet<Integer>;
63 function testList(const thing: IThriftList<Integer>): IThriftList<Integer>;
Jake Farrell7ae13e12011-10-18 14:35:26 +000064 function testEnum(thing: TNumberz): TNumberz;
Roger Meier333bbf32012-01-08 21:51:08 +000065 function testTypedef(const thing: Int64): Int64;
Jake Farrell7ae13e12011-10-18 14:35:26 +000066 function testMapMap(hello: Integer): IThriftDictionary<Integer, IThriftDictionary<Integer, Integer>>;
Roger Meier333bbf32012-01-08 21:51:08 +000067 function testInsanity(const argument: IInsanity): IThriftDictionary<Int64, IThriftDictionary<TNumberz, IInsanity>>;
68 function testMulti(arg0: ShortInt; arg1: Integer; const arg2: Int64; const arg3: IThriftDictionary<SmallInt, string>; arg4: TNumberz; const arg5: Int64): IXtruct;
69 procedure testException(const arg: string);
70 function testMultiException(const arg0: string; const arg1: string): IXtruct;
Jake Farrell7ae13e12011-10-18 14:35:26 +000071 procedure testOneway(secondsToSleep: Integer);
Jake Farrell27274222011-11-10 20:32:44 +000072
73 procedure testStop;
74
Roger Meier333bbf32012-01-08 21:51:08 +000075 procedure SetServer( const AServer : IServer );
Jake Farrell27274222011-11-10 20:32:44 +000076 end;
77
Roger Meier333bbf32012-01-08 21:51:08 +000078 class procedure Execute( const args: array of string);
Jake Farrell27274222011-11-10 20:32:44 +000079 end;
80
81implementation
82
83{ TTestServer.TTestHandlerImpl }
84
Roger Meier333bbf32012-01-08 21:51:08 +000085procedure TTestServer.TTestHandlerImpl.SetServer( const AServer: IServer);
Jake Farrell27274222011-11-10 20:32:44 +000086begin
87 FServer := AServer;
88end;
89
90function TTestServer.TTestHandlerImpl.testByte(thing: ShortInt): ShortInt;
91begin
92 Console.WriteLine('testByte("' + IntToStr( thing) + '")');
93 Result := thing;
94end;
95
Roger Meier333bbf32012-01-08 21:51:08 +000096function TTestServer.TTestHandlerImpl.testDouble( const thing: Double): Double;
Jake Farrell27274222011-11-10 20:32:44 +000097begin
98 Console.WriteLine('testDouble("' + FloatToStr( thing ) + '")');
99 Result := thing;
100end;
101
102function TTestServer.TTestHandlerImpl.testEnum(thing: TNumberz): TNumberz;
103begin
104 Console.WriteLine('testEnum(' + IntToStr( Integer( thing)) + ')');
105 Result := thing;
106end;
107
Roger Meier333bbf32012-01-08 21:51:08 +0000108procedure TTestServer.TTestHandlerImpl.testException(const arg: string);
Jake Farrell27274222011-11-10 20:32:44 +0000109begin
110 Console.WriteLine('testException(' + arg + ')');
111 if ( arg = 'Xception') then
112 begin
Roger Meierbb6de7a2012-05-04 23:35:45 +0000113 raise TXception.Create( 1001, arg);
Jake Farrell27274222011-11-10 20:32:44 +0000114 end;
Roger Meierbb6de7a2012-05-04 23:35:45 +0000115
116 if (arg = 'TException') then
117 begin
118 raise TException.Create('');
119 end;
120
121 // else do not throw anything
Jake Farrell27274222011-11-10 20:32:44 +0000122end;
123
124function TTestServer.TTestHandlerImpl.testI32(thing: Integer): Integer;
125begin
126 Console.WriteLine('testI32("' + IntToStr( thing) + '")');
127 Result := thing;
128end;
129
Roger Meier333bbf32012-01-08 21:51:08 +0000130function TTestServer.TTestHandlerImpl.testI64( const thing: Int64): Int64;
Jake Farrell27274222011-11-10 20:32:44 +0000131begin
132 Console.WriteLine('testI64("' + IntToStr( thing) + '")');
133 Result := thing;
134end;
135
136function TTestServer.TTestHandlerImpl.testInsanity(
Roger Meier333bbf32012-01-08 21:51:08 +0000137 const argument: IInsanity): IThriftDictionary<Int64, IThriftDictionary<TNumberz, IInsanity>>;
Jake Farrell27274222011-11-10 20:32:44 +0000138var
139 hello, goodbye : IXtruct;
140 crazy : IInsanity;
141 looney : IInsanity;
142 first_map : IThriftDictionary<TNumberz, IInsanity>;
143 second_map : IThriftDictionary<TNumberz, IInsanity>;
144 insane : IThriftDictionary<Int64, IThriftDictionary<TNumberz, IInsanity>>;
145
146begin
147
148 Console.WriteLine('testInsanity()');
149 hello := TXtructImpl.Create;
Roger Meierbb6de7a2012-05-04 23:35:45 +0000150 hello.String_thing := 'Hello2';
Jake Farrell27274222011-11-10 20:32:44 +0000151 hello.Byte_thing := 2;
152 hello.I32_thing := 2;
153 hello.I64_thing := 2;
154
155 goodbye := TXtructImpl.Create;
156 goodbye.String_thing := 'Goodbye4';
157 goodbye.Byte_thing := 4;
158 goodbye.I32_thing := 4;
159 goodbye.I64_thing := 4;
160
161 crazy := TInsanityImpl.Create;
162 crazy.UserMap := TThriftDictionaryImpl<TNumberz, Int64>.Create;
163 crazy.UserMap.AddOrSetValue( TNumberz.EIGHT, 8);
164 crazy.Xtructs := TThriftListImpl<IXtruct>.Create;
165 crazy.Xtructs.Add(goodbye);
166
167 looney := TInsanityImpl.Create;
168 crazy.UserMap.AddOrSetValue( TNumberz.FIVE, 5);
169 crazy.Xtructs.Add(hello);
170
171 first_map := TThriftDictionaryImpl<TNumberz, IInsanity>.Create;
172 second_map := TThriftDictionaryImpl<TNumberz, IInsanity>.Create;
173
Roger Meierbb6de7a2012-05-04 23:35:45 +0000174 first_map.AddOrSetValue( TNumberz.TWO, crazy);
Jake Farrell27274222011-11-10 20:32:44 +0000175 first_map.AddOrSetValue( TNumberz.THREE, crazy);
176
177 second_map.AddOrSetValue( TNumberz.SIX, looney);
178
179 insane := TThriftDictionaryImpl<Int64, IThriftDictionary<TNumberz, IInsanity>>.Create;
180
181 insane.AddOrSetValue( 1, first_map);
182 insane.AddOrSetValue( 2, second_map);
183
184 Result := insane;
185end;
186
187function TTestServer.TTestHandlerImpl.testList(
Roger Meier333bbf32012-01-08 21:51:08 +0000188 const thing: IThriftList<Integer>): IThriftList<Integer>;
Jake Farrell27274222011-11-10 20:32:44 +0000189var
190 first : Boolean;
191 elem : Integer;
192begin
193 Console.Write('testList({');
194 first := True;
195 for elem in thing do
196 begin
197 if first then
198 begin
199 first := False;
200 end else
201 begin
202 Console.Write(', ');
203 end;
204 Console.Write( IntToStr( elem));
205 end;
206 Console.WriteLine('})');
207 Result := thing;
208end;
209
210function TTestServer.TTestHandlerImpl.testMap(
Roger Meier333bbf32012-01-08 21:51:08 +0000211 const thing: IThriftDictionary<Integer, Integer>): IThriftDictionary<Integer, Integer>;
Jake Farrell27274222011-11-10 20:32:44 +0000212var
213 first : Boolean;
214 key : Integer;
215begin
216 Console.Write('testMap({');
217 first := True;
218 for key in thing.Keys do
219 begin
220 if (first) then
221 begin
222 first := false;
223 end else
224 begin
225 Console.Write(', ');
226 end;
227 Console.Write(IntToStr(key) + ' => ' + IntToStr( thing[key]));
228 end;
229 Console.WriteLine('})');
230 Result := thing;
231end;
232
233function TTestServer.TTestHandlerImpl.TestMapMap(
234 hello: Integer): IThriftDictionary<Integer, IThriftDictionary<Integer, Integer>>;
235var
236 mapmap : IThriftDictionary<Integer, IThriftDictionary<Integer, Integer>>;
237 pos : IThriftDictionary<Integer, Integer>;
238 neg : IThriftDictionary<Integer, Integer>;
239 i : Integer;
240begin
241 Console.WriteLine('testMapMap(' + IntToStr( hello) + ')');
242 mapmap := TThriftDictionaryImpl<Integer, IThriftDictionary<Integer, Integer>>.Create;
243 pos := TThriftDictionaryImpl<Integer, Integer>.Create;
244 neg := TThriftDictionaryImpl<Integer, Integer>.Create;
245
246 for i := 1 to 4 do
247 begin
248 pos.AddOrSetValue( i, i);
249 neg.AddOrSetValue( -i, -i);
250 end;
251
252 mapmap.AddOrSetValue(4, pos);
253 mapmap.AddOrSetValue( -4, neg);
254
255 Result := mapmap;
256end;
257
258function TTestServer.TTestHandlerImpl.testMulti(arg0: ShortInt; arg1: Integer;
Roger Meier333bbf32012-01-08 21:51:08 +0000259 const arg2: Int64; const arg3: IThriftDictionary<SmallInt, string>;
260 arg4: TNumberz; const arg5: Int64): IXtruct;
Jake Farrell27274222011-11-10 20:32:44 +0000261var
262 hello : IXtruct;
263begin
264 Console.WriteLine('testMulti()');
265 hello := TXtructImpl.Create;
266 hello.String_thing := 'Hello2';
267 hello.Byte_thing := arg0;
268 hello.I32_thing := arg1;
269 hello.I64_thing := arg2;
270 Result := hello;
271end;
272
Roger Meier333bbf32012-01-08 21:51:08 +0000273function TTestServer.TTestHandlerImpl.testMultiException( const arg0, arg1: string): IXtruct;
Jake Farrell27274222011-11-10 20:32:44 +0000274var
Jake Farrell27274222011-11-10 20:32:44 +0000275 x2 : TXception2;
276begin
277 Console.WriteLine('testMultiException(' + arg0 + ', ' + arg1 + ')');
278 if ( arg0 = 'Xception') then
279 begin
Jake Farrell343c61d2011-12-09 02:29:56 +0000280 raise TXception.Create( 1001, 'This is an Xception'); // test the new rich CTOR
Jake Farrell27274222011-11-10 20:32:44 +0000281 end else
282 if ( arg0 = 'Xception2') then
283 begin
Jake Farrell343c61d2011-12-09 02:29:56 +0000284 x2 := TXception2.Create; // the old way still works too?
Jake Farrell27274222011-11-10 20:32:44 +0000285 x2.ErrorCode := 2002;
286 x2.Struct_thing := TXtructImpl.Create;
287 x2.Struct_thing.String_thing := 'This is an Xception2';
Jake Farrellac102562011-11-23 14:30:41 +0000288 x2.UpdateMessageProperty;
Jake Farrell27274222011-11-10 20:32:44 +0000289 raise x2;
290 end;
291
292 Result := TXtructImpl.Create;
293 Result.String_thing := arg1;
294end;
295
Roger Meier333bbf32012-01-08 21:51:08 +0000296function TTestServer.TTestHandlerImpl.testNest( const thing: IXtruct2): IXtruct2;
Jake Farrell27274222011-11-10 20:32:44 +0000297var
298 temp : IXtruct;
299begin
300 temp := thing.Struct_thing;
301 Console.WriteLine('testNest({' +
302 IntToStr( thing.Byte_thing) + ', {' +
303 '"' + temp.String_thing + '", ' +
304 IntToStr( temp.Byte_thing) + ', ' +
305 IntToStr( temp.I32_thing) + ', ' +
306 IntToStr( temp.I64_thing) + '}, ' +
307 IntToStr( temp.I32_thing) + '})');
308 Result := thing;
309end;
310
311procedure TTestServer.TTestHandlerImpl.testOneway(secondsToSleep: Integer);
312begin
313 Console.WriteLine('testOneway(' + IntToStr( secondsToSleep )+ '), sleeping...');
314 Sleep(secondsToSleep * 1000);
315 Console.WriteLine('testOneway finished');
316end;
317
318function TTestServer.TTestHandlerImpl.testSet(
Roger Meier333bbf32012-01-08 21:51:08 +0000319 const thing: IHashSet<Integer>):IHashSet<Integer>;
Jake Farrell27274222011-11-10 20:32:44 +0000320var
321 first : Boolean;
322 elem : Integer;
323begin
324 Console.Write('testSet({');
325 first := True;
326
327 for elem in thing do
328 begin
329 if first then
330 begin
331 first := False;
332 end else
333 begin
334 Console.Write( ', ');
335 end;
336 Console.Write( IntToStr( elem));
337 end;
338 Console.WriteLine('})');
339 Result := thing;
340end;
341
342procedure TTestServer.TTestHandlerImpl.testStop;
343begin
344 if FServer <> nil then
345 begin
346 FServer.Stop;
347 end;
348end;
349
Roger Meier333bbf32012-01-08 21:51:08 +0000350function TTestServer.TTestHandlerImpl.testString( const thing: string): string;
Jake Farrell27274222011-11-10 20:32:44 +0000351begin
352 Console.WriteLine('teststring("' + thing + '")');
353 Result := thing;
354end;
355
356function TTestServer.TTestHandlerImpl.testStringMap(
Roger Meier333bbf32012-01-08 21:51:08 +0000357 const thing: IThriftDictionary<string, string>): IThriftDictionary<string, string>;
Roger Meierbb6de7a2012-05-04 23:35:45 +0000358var
359 first : Boolean;
360 key : string;
Jake Farrell27274222011-11-10 20:32:44 +0000361begin
Roger Meierbb6de7a2012-05-04 23:35:45 +0000362 Console.Write('testStringMap({');
363 first := True;
364 for key in thing.Keys do
365 begin
366 if (first) then
367 begin
368 first := false;
369 end else
370 begin
371 Console.Write(', ');
372 end;
373 Console.Write(key + ' => ' + thing[key]);
374 end;
375 Console.WriteLine('})');
376 Result := thing;
Jake Farrell27274222011-11-10 20:32:44 +0000377end;
378
Roger Meier333bbf32012-01-08 21:51:08 +0000379function TTestServer.TTestHandlerImpl.testTypedef( const thing: Int64): Int64;
Jake Farrell27274222011-11-10 20:32:44 +0000380begin
381 Console.WriteLine('testTypedef(' + IntToStr( thing) + ')');
382 Result := thing;
383end;
384
385procedure TTestServer.TTestHandlerImpl.TestVoid;
386begin
387 Console.WriteLine('testVoid()');
388end;
389
Roger Meier333bbf32012-01-08 21:51:08 +0000390function TTestServer.TTestHandlerImpl.testStruct( const thing: IXtruct): IXtruct;
Jake Farrell27274222011-11-10 20:32:44 +0000391begin
392 Console.WriteLine('testStruct({' +
393 '"' + thing.String_thing + '", ' +
394 IntToStr( thing.Byte_thing) + ', ' +
395 IntToStr( thing.I32_thing) + ', ' +
396 IntToStr( thing.I64_thing));
397 Result := thing;
398end;
399
400{ TTestServer }
401
Roger Meier333bbf32012-01-08 21:51:08 +0000402class procedure TTestServer.Execute( const args: array of string);
Jake Farrell27274222011-11-10 20:32:44 +0000403var
404 UseBufferedSockets : Boolean;
405 UseFramed : Boolean;
406 Port : Integer;
407 testHandler : ITestHandler;
408 testProcessor : IProcessor;
409 ServerSocket : IServerTransport;
410 ServerEngine : IServer;
411 TransportFactory : ITransportFactory;
412 ProtocolFactory : IProtocolFactory;
413 i : Integer;
414 s : string;
415 protType, p : TKnownProtocol;
416begin
417 try
418 UseBufferedSockets := False;
419 UseFramed := False;
420 protType := prot_Binary;
421 Port := 9090;
422
423 i := 0;
424 while ( i < Length(args) ) do begin
425 s := args[i];
426 Inc(i);
427
428 if StrToIntDef( s, -1) > 0 then
429 begin
430 Port := StrToIntDef( s, Port);
431 end else
432 if ( s = 'raw' ) then
433 begin
434 // as default
435 end else
436 if ( s = 'buffered' ) then
437 begin
438 UseBufferedSockets := True;
439 end else
440 if ( s = 'framed' ) then
441 begin
442 UseFramed := True;
443 end else
444 if (s = '-prot') then // -prot JSON|binary
445 begin
446 s := args[i];
447 Inc( i );
448 for p:= Low(TKnownProtocol) to High(TKnownProtocol) do begin
449 if SameText( s, KNOWN_PROTOCOLS[p]) then begin
450 protType := p;
451 Break;
452 end;
453 end;
454 end else
455 begin
456 // Fall back to the older boolean syntax
457 UseBufferedSockets := StrToBoolDef( args[1], UseBufferedSockets);
458 end
459 end;
460
461 // create protocol factory, default to BinaryProtocol
462 case protType of
463 prot_Binary: ProtocolFactory := TBinaryProtocolImpl.TFactory.Create;
464 prot_JSON : ProtocolFactory := TJSONProtocolImpl.TFactory.Create;
465 else
466 ASSERT( FALSE); // unhandled case!
467 ProtocolFactory := TBinaryProtocolImpl.TFactory.Create;
468 end;
469
470 testHandler := TTestHandlerImpl.Create;
471
472 testProcessor := TThriftTest.TProcessorImpl.Create( testHandler );
473 ServerSocket := TServerSocketImpl.Create( Port, 0, UseBufferedSockets );
474
475 if UseFramed
476 then TransportFactory := TFramedTransportImpl.TFactory.Create
477 else TransportFactory := TTransportFactoryImpl.Create;
478
479 ServerEngine := TSimpleServer.Create( testProcessor,
480 ServerSocket,
481 TransportFactory,
482 ProtocolFactory);
483
484 testHandler.SetServer( ServerEngine);
485
486 Console.WriteLine('Starting the server on port ' + IntToStr( Port) +
487 IfValue(UseBufferedSockets, ' with buffered socket', '') +
488 IfValue(useFramed, ' with framed transport', '') +
489 ' using '+KNOWN_PROTOCOLS[protType]+' protocol' +
490 '...');
491
492 serverEngine.Serve;
493 testHandler.SetServer( nil);
494
495 except
496 on E: Exception do
497 begin
498 Console.Write( E.Message);
499 end;
500 end;
501 Console.WriteLine( 'done.');
502end;
503
504end.