| (* | 
 |  * Licensed to the Apache Software Foundation (ASF) under one | 
 |  * or more contributor license agreements. See the NOTICE file | 
 |  * distributed with this work for additional information | 
 |  * regarding copyright ownership. The ASF licenses this file | 
 |  * to you under the Apache License, Version 2.0 (the | 
 |  * "License"); you may not use this file except in compliance | 
 |  * with the License. You may obtain a copy of the License at | 
 |  * | 
 |  *   http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, | 
 |  * software distributed under the License is distributed on an | 
 |  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
 |  * KIND, either express or implied. See the License for the | 
 |  * specific language governing permissions and limitations | 
 |  * under the License. | 
 |  *) | 
 |  | 
 | unit TestServer; | 
 |  | 
 | interface | 
 |  | 
 | uses | 
 |   SysUtils, | 
 |   Generics.Collections, | 
 |   Thrift.Console, | 
 |   Thrift.Server, | 
 |   Thrift.Transport, | 
 |   Thrift.Protocol, | 
 |   Thrift.Protocol.JSON, | 
 |   Thrift.Collections, | 
 |   Thrift.Utils, | 
 |   Thrift.Test, | 
 |   Thrift, | 
 |   TestConstants, | 
 |   Contnrs; | 
 |  | 
 | type | 
 |   TTestServer = class | 
 |   public | 
 |     type | 
 |  | 
 |       ITestHandler = interface( TThriftTest.Iface ) | 
 |         procedure SetServer( const AServer : IServer ); | 
 |       end; | 
 |  | 
 |       TTestHandlerImpl = class( TInterfacedObject, ITestHandler ) | 
 |       private | 
 |         FServer : IServer; | 
 |       protected | 
 |         procedure testVoid(); | 
 |         function testString(const thing: string): string; | 
 |         function testByte(thing: ShortInt): ShortInt; | 
 |         function testI32(thing: Integer): Integer; | 
 |         function testI64(const thing: Int64): Int64; | 
 |         function testDouble(const thing: Double): Double; | 
 |         function testStruct(const thing: IXtruct): IXtruct; | 
 |         function testNest(const thing: IXtruct2): IXtruct2; | 
 |         function testMap(const thing: IThriftDictionary<Integer, Integer>): IThriftDictionary<Integer, Integer>; | 
 |         function testStringMap(const thing: IThriftDictionary<string, string>): IThriftDictionary<string, string>; | 
 |         function testSet(const thing: IHashSet<Integer>): IHashSet<Integer>; | 
 |         function testList(const thing: IThriftList<Integer>): IThriftList<Integer>; | 
 |         function testEnum(thing: TNumberz): TNumberz; | 
 |         function testTypedef(const thing: Int64): Int64; | 
 |         function testMapMap(hello: Integer): IThriftDictionary<Integer, IThriftDictionary<Integer, Integer>>; | 
 |         function testInsanity(const argument: IInsanity): IThriftDictionary<Int64, IThriftDictionary<TNumberz, IInsanity>>; | 
 |         function testMulti(arg0: ShortInt; arg1: Integer; const arg2: Int64; const arg3: IThriftDictionary<SmallInt, string>; arg4: TNumberz; const arg5: Int64): IXtruct; | 
 |         procedure testException(const arg: string); | 
 |         function testMultiException(const arg0: string; const arg1: string): IXtruct; | 
 |         procedure testOneway(secondsToSleep: Integer); | 
 |  | 
 |          procedure testStop; | 
 |  | 
 |         procedure SetServer( const AServer : IServer ); | 
 |       end; | 
 |  | 
 |       class procedure Execute( const args: array of string); | 
 |   end; | 
 |  | 
 | implementation | 
 |  | 
 | { TTestServer.TTestHandlerImpl } | 
 |  | 
 | procedure TTestServer.TTestHandlerImpl.SetServer( const AServer: IServer); | 
 | begin | 
 |   FServer := AServer; | 
 | end; | 
 |  | 
 | function TTestServer.TTestHandlerImpl.testByte(thing: ShortInt): ShortInt; | 
 | begin | 
 |   Console.WriteLine('testByte("' + IntToStr( thing) + '")'); | 
 |   Result := thing; | 
 | end; | 
 |  | 
 | function TTestServer.TTestHandlerImpl.testDouble( const thing: Double): Double; | 
 | begin | 
 |   Console.WriteLine('testDouble("' + FloatToStr( thing ) + '")'); | 
 |   Result := thing; | 
 | end; | 
 |  | 
 | function TTestServer.TTestHandlerImpl.testEnum(thing: TNumberz): TNumberz; | 
 | begin | 
 |   Console.WriteLine('testEnum(' + IntToStr( Integer( thing)) + ')'); | 
 |   Result := thing; | 
 | end; | 
 |  | 
 | procedure TTestServer.TTestHandlerImpl.testException(const arg: string); | 
 | begin | 
 |   Console.WriteLine('testException(' + arg + ')'); | 
 |   if ( arg = 'Xception') then | 
 |   begin | 
 |     raise TXception.Create( 1001, arg); | 
 |   end; | 
 |  | 
 |   if (arg = 'TException') then | 
 |   begin | 
 |     raise TException.Create(''); | 
 |   end; | 
 |  | 
 |   // else do not throw anything | 
 | end; | 
 |  | 
 | function TTestServer.TTestHandlerImpl.testI32(thing: Integer): Integer; | 
 | begin | 
 |   Console.WriteLine('testI32("' + IntToStr( thing) + '")'); | 
 |   Result := thing; | 
 | end; | 
 |  | 
 | function TTestServer.TTestHandlerImpl.testI64( const thing: Int64): Int64; | 
 | begin | 
 |   Console.WriteLine('testI64("' + IntToStr( thing) + '")'); | 
 |   Result := thing; | 
 | end; | 
 |  | 
 | function TTestServer.TTestHandlerImpl.testInsanity( | 
 |   const argument: IInsanity): IThriftDictionary<Int64, IThriftDictionary<TNumberz, IInsanity>>; | 
 | var | 
 |   hello, goodbye : IXtruct; | 
 |   crazy : IInsanity; | 
 |   looney : IInsanity; | 
 |   first_map : IThriftDictionary<TNumberz, IInsanity>; | 
 |   second_map : IThriftDictionary<TNumberz, IInsanity>; | 
 |   insane : IThriftDictionary<Int64, IThriftDictionary<TNumberz, IInsanity>>; | 
 |  | 
 | begin | 
 |  | 
 |   Console.WriteLine('testInsanity()'); | 
 |   hello := TXtructImpl.Create; | 
 |   hello.String_thing := 'Hello2'; | 
 |   hello.Byte_thing := 2; | 
 |   hello.I32_thing := 2; | 
 |   hello.I64_thing := 2; | 
 |  | 
 |   goodbye := TXtructImpl.Create; | 
 |   goodbye.String_thing := 'Goodbye4'; | 
 |   goodbye.Byte_thing := 4; | 
 |   goodbye.I32_thing := 4; | 
 |   goodbye.I64_thing := 4; | 
 |  | 
 |   crazy := TInsanityImpl.Create; | 
 |   crazy.UserMap := TThriftDictionaryImpl<TNumberz, Int64>.Create; | 
 |   crazy.UserMap.AddOrSetValue( TNumberz.EIGHT, 8); | 
 |   crazy.Xtructs := TThriftListImpl<IXtruct>.Create; | 
 |   crazy.Xtructs.Add(goodbye); | 
 |  | 
 |   looney := TInsanityImpl.Create; | 
 |   crazy.UserMap.AddOrSetValue( TNumberz.FIVE, 5); | 
 |   crazy.Xtructs.Add(hello); | 
 |  | 
 |   first_map := TThriftDictionaryImpl<TNumberz, IInsanity>.Create; | 
 |   second_map := TThriftDictionaryImpl<TNumberz, IInsanity>.Create; | 
 |  | 
 |   first_map.AddOrSetValue( TNumberz.TWO, crazy); | 
 |   first_map.AddOrSetValue( TNumberz.THREE, crazy); | 
 |  | 
 |   second_map.AddOrSetValue( TNumberz.SIX, looney); | 
 |  | 
 |   insane := TThriftDictionaryImpl<Int64, IThriftDictionary<TNumberz, IInsanity>>.Create; | 
 |  | 
 |   insane.AddOrSetValue( 1, first_map); | 
 |   insane.AddOrSetValue( 2, second_map); | 
 |  | 
 |   Result := insane; | 
 | end; | 
 |  | 
 | function TTestServer.TTestHandlerImpl.testList( | 
 |   const thing: IThriftList<Integer>): IThriftList<Integer>; | 
 | var | 
 |   first : Boolean; | 
 |   elem : Integer; | 
 | begin | 
 |   Console.Write('testList({'); | 
 |   first := True; | 
 |   for elem in thing do | 
 |   begin | 
 |     if first then | 
 |     begin | 
 |       first := False; | 
 |     end else | 
 |     begin | 
 |       Console.Write(', '); | 
 |     end; | 
 |     Console.Write( IntToStr( elem)); | 
 |   end; | 
 |   Console.WriteLine('})'); | 
 |   Result := thing; | 
 | end; | 
 |  | 
 | function TTestServer.TTestHandlerImpl.testMap( | 
 |   const thing: IThriftDictionary<Integer, Integer>): IThriftDictionary<Integer, Integer>; | 
 | var | 
 |   first : Boolean; | 
 |   key : Integer; | 
 | begin | 
 |   Console.Write('testMap({'); | 
 |   first := True; | 
 |   for key in thing.Keys do | 
 |   begin | 
 |     if (first) then | 
 |     begin | 
 |       first := false; | 
 |     end else | 
 |     begin | 
 |       Console.Write(', '); | 
 |     end; | 
 |     Console.Write(IntToStr(key) + ' => ' + IntToStr( thing[key])); | 
 |   end; | 
 |   Console.WriteLine('})'); | 
 |   Result := thing; | 
 | end; | 
 |  | 
 | function TTestServer.TTestHandlerImpl.TestMapMap( | 
 |   hello: Integer): IThriftDictionary<Integer, IThriftDictionary<Integer, Integer>>; | 
 | var | 
 |   mapmap : IThriftDictionary<Integer, IThriftDictionary<Integer, Integer>>; | 
 |   pos : IThriftDictionary<Integer, Integer>; | 
 |   neg : IThriftDictionary<Integer, Integer>; | 
 |   i : Integer; | 
 | begin | 
 |   Console.WriteLine('testMapMap(' + IntToStr( hello) + ')'); | 
 |   mapmap := TThriftDictionaryImpl<Integer, IThriftDictionary<Integer, Integer>>.Create; | 
 |   pos := TThriftDictionaryImpl<Integer, Integer>.Create; | 
 |   neg := TThriftDictionaryImpl<Integer, Integer>.Create; | 
 |  | 
 |   for i := 1 to 4 do | 
 |   begin | 
 |     pos.AddOrSetValue( i, i); | 
 |     neg.AddOrSetValue( -i, -i); | 
 |   end; | 
 |  | 
 |   mapmap.AddOrSetValue(4, pos); | 
 |   mapmap.AddOrSetValue( -4, neg); | 
 |  | 
 |   Result := mapmap; | 
 | end; | 
 |  | 
 | function TTestServer.TTestHandlerImpl.testMulti(arg0: ShortInt; arg1: Integer; | 
 |   const arg2: Int64; const arg3: IThriftDictionary<SmallInt, string>; | 
 |   arg4: TNumberz; const arg5: Int64): IXtruct; | 
 | var | 
 |   hello : IXtruct; | 
 | begin | 
 |   Console.WriteLine('testMulti()'); | 
 |   hello := TXtructImpl.Create; | 
 |   hello.String_thing := 'Hello2'; | 
 |   hello.Byte_thing := arg0; | 
 |   hello.I32_thing := arg1; | 
 |   hello.I64_thing := arg2; | 
 |   Result := hello; | 
 | end; | 
 |  | 
 | function TTestServer.TTestHandlerImpl.testMultiException( const arg0, arg1: string): IXtruct; | 
 | var | 
 |   x2 : TXception2; | 
 | begin | 
 |   Console.WriteLine('testMultiException(' + arg0 + ', ' + arg1 + ')'); | 
 |   if ( arg0 = 'Xception') then | 
 |   begin | 
 |     raise TXception.Create( 1001, 'This is an Xception');  // test the new rich CTOR  | 
 |   end else | 
 |   if ( arg0 = 'Xception2') then | 
 |   begin | 
 |     x2 := TXception2.Create;  // the old way still works too? | 
 |     x2.ErrorCode := 2002; | 
 |     x2.Struct_thing := TXtructImpl.Create; | 
 |     x2.Struct_thing.String_thing := 'This is an Xception2'; | 
 |     x2.UpdateMessageProperty; | 
 |     raise x2; | 
 |   end; | 
 |  | 
 |   Result := TXtructImpl.Create; | 
 |   Result.String_thing := arg1; | 
 | end; | 
 |  | 
 | function TTestServer.TTestHandlerImpl.testNest( const thing: IXtruct2): IXtruct2; | 
 | var | 
 |   temp : IXtruct; | 
 | begin | 
 |   temp := thing.Struct_thing; | 
 |   Console.WriteLine('testNest({' + | 
 |          IntToStr( thing.Byte_thing) + ', {' + | 
 |          '"' + temp.String_thing + '", ' + | 
 |          IntToStr( temp.Byte_thing) + ', ' + | 
 |          IntToStr( temp.I32_thing) + ', ' + | 
 |          IntToStr( temp.I64_thing) + '}, ' + | 
 |          IntToStr( temp.I32_thing) + '})'); | 
 |   Result := thing; | 
 | end; | 
 |  | 
 | procedure TTestServer.TTestHandlerImpl.testOneway(secondsToSleep: Integer); | 
 | begin | 
 |   Console.WriteLine('testOneway(' + IntToStr( secondsToSleep )+ '), sleeping...'); | 
 |   Sleep(secondsToSleep * 1000); | 
 |   Console.WriteLine('testOneway finished'); | 
 | end; | 
 |  | 
 | function TTestServer.TTestHandlerImpl.testSet( | 
 |   const thing: IHashSet<Integer>):IHashSet<Integer>; | 
 | var | 
 |   first : Boolean; | 
 |   elem : Integer; | 
 | begin | 
 |   Console.Write('testSet({'); | 
 |   first := True; | 
 |  | 
 |   for elem in thing do | 
 |   begin | 
 |     if first then | 
 |     begin | 
 |       first := False; | 
 |     end else | 
 |     begin | 
 |       Console.Write( ', '); | 
 |     end; | 
 |     Console.Write( IntToStr( elem)); | 
 |   end; | 
 |   Console.WriteLine('})'); | 
 |   Result := thing; | 
 | end; | 
 |  | 
 | procedure TTestServer.TTestHandlerImpl.testStop; | 
 | begin | 
 |   if FServer <> nil then | 
 |   begin | 
 |     FServer.Stop; | 
 |   end; | 
 | end; | 
 |  | 
 | function TTestServer.TTestHandlerImpl.testString( const thing: string): string; | 
 | begin | 
 |   Console.WriteLine('teststring("' + thing + '")'); | 
 |   Result := thing; | 
 | end; | 
 |  | 
 | function TTestServer.TTestHandlerImpl.testStringMap( | 
 |   const thing: IThriftDictionary<string, string>): IThriftDictionary<string, string>; | 
 | var | 
 |   first : Boolean; | 
 |   key : string; | 
 | begin | 
 |   Console.Write('testStringMap({'); | 
 |   first := True; | 
 |   for key in thing.Keys do | 
 |   begin | 
 |     if (first) then | 
 |     begin | 
 |       first := false; | 
 |     end else | 
 |     begin | 
 |       Console.Write(', '); | 
 |     end; | 
 |     Console.Write(key + ' => ' + thing[key]); | 
 |   end; | 
 |   Console.WriteLine('})'); | 
 |   Result := thing; | 
 | end; | 
 |  | 
 | function TTestServer.TTestHandlerImpl.testTypedef( const thing: Int64): Int64; | 
 | begin | 
 |   Console.WriteLine('testTypedef(' + IntToStr( thing) + ')'); | 
 |   Result := thing; | 
 | end; | 
 |  | 
 | procedure TTestServer.TTestHandlerImpl.TestVoid; | 
 | begin | 
 |   Console.WriteLine('testVoid()'); | 
 | end; | 
 |  | 
 | function TTestServer.TTestHandlerImpl.testStruct( const thing: IXtruct): IXtruct; | 
 | begin | 
 |   Console.WriteLine('testStruct({' + | 
 |     '"' + thing.String_thing + '", ' + | 
 |       IntToStr( thing.Byte_thing) + ', ' + | 
 |       IntToStr( thing.I32_thing) + ', ' + | 
 |       IntToStr( thing.I64_thing)); | 
 |   Result := thing; | 
 | end; | 
 |  | 
 | { TTestServer } | 
 |  | 
 | class procedure TTestServer.Execute( const args: array of string); | 
 | var | 
 |   UseBufferedSockets : Boolean; | 
 |   UseFramed : Boolean; | 
 |   Port : Integer; | 
 |   testHandler : ITestHandler; | 
 |   testProcessor : IProcessor; | 
 |   ServerSocket : IServerTransport; | 
 |   ServerEngine : IServer; | 
 |   TransportFactory : ITransportFactory; | 
 |   ProtocolFactory : IProtocolFactory; | 
 |   i : Integer; | 
 |   s : string; | 
 |   protType, p : TKnownProtocol; | 
 | begin | 
 |   try | 
 |     UseBufferedSockets := False; | 
 |     UseFramed := False; | 
 |     protType := prot_Binary; | 
 |     Port := 9090; | 
 |  | 
 |     i := 0; | 
 |     while ( i < Length(args) ) do begin | 
 |       s := args[i]; | 
 |       Inc(i); | 
 |  | 
 |       if StrToIntDef( s, -1) > 0 then | 
 |       begin | 
 |         Port :=  StrToIntDef( s, Port); | 
 |       end else | 
 |       if ( s = 'raw' ) then | 
 |       begin | 
 |         // as default | 
 |       end else | 
 |       if ( s = 'buffered' ) then | 
 |       begin | 
 |         UseBufferedSockets := True; | 
 |       end else | 
 |       if ( s = 'framed' ) then | 
 |       begin | 
 |         UseFramed := True; | 
 |       end else | 
 |       if (s = '-prot') then  // -prot JSON|binary | 
 |       begin | 
 |         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; | 
 |       end else | 
 |       begin | 
 |         // Fall back to the older boolean syntax | 
 |         UseBufferedSockets := StrToBoolDef( args[1], UseBufferedSockets); | 
 |       end | 
 |     end; | 
 |  | 
 |     // create protocol factory, default to BinaryProtocol | 
 |     case protType of | 
 |       prot_Binary:  ProtocolFactory := TBinaryProtocolImpl.TFactory.Create; | 
 |       prot_JSON  :  ProtocolFactory := TJSONProtocolImpl.TFactory.Create; | 
 |     else | 
 |       ASSERT( FALSE);  // unhandled case! | 
 |       ProtocolFactory := TBinaryProtocolImpl.TFactory.Create; | 
 |     end; | 
 |  | 
 |     testHandler := TTestHandlerImpl.Create; | 
 |  | 
 |     testProcessor := TThriftTest.TProcessorImpl.Create( testHandler ); | 
 |     ServerSocket := TServerSocketImpl.Create( Port, 0, UseBufferedSockets ); | 
 |  | 
 |     if UseFramed | 
 |     then TransportFactory := TFramedTransportImpl.TFactory.Create | 
 |     else TransportFactory := TTransportFactoryImpl.Create; | 
 |  | 
 |     ServerEngine := TSimpleServer.Create( testProcessor, | 
 |                                           ServerSocket, | 
 |                                           TransportFactory, | 
 |                                           ProtocolFactory); | 
 |  | 
 |     testHandler.SetServer( ServerEngine); | 
 |  | 
 |     Console.WriteLine('Starting the server on port ' + IntToStr( Port) + | 
 |       IfValue(UseBufferedSockets, ' with buffered socket', '') + | 
 |       IfValue(useFramed, ' with framed transport', '') + | 
 |       ' using '+KNOWN_PROTOCOLS[protType]+' protocol' + | 
 |       '...'); | 
 |  | 
 |     serverEngine.Serve; | 
 |     testHandler.SetServer( nil); | 
 |  | 
 |   except | 
 |     on E: Exception do | 
 |     begin | 
 |       Console.Write( E.Message); | 
 |     end; | 
 |   end; | 
 |   Console.WriteLine( 'done.'); | 
 | end; | 
 |  | 
 | end. |