| (* |
| * 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( AServer : IServer ); |
| end; |
| |
| TTestHandlerImpl = class( TInterfacedObject, ITestHandler ) |
| private |
| FServer : IServer; |
| protected |
| procedure testVoid(); |
| function testString(thing: string): string; |
| function testByte(thing: ShortInt): ShortInt; |
| function testI32(thing: Integer): Integer; |
| function testI64(thing: Int64): Int64; |
| function testDouble(thing: Double): Double; |
| function testStruct(thing: IXtruct): IXtruct; |
| function testNest(thing: IXtruct2): IXtruct2; |
| function testMap(thing: IThriftDictionary<Integer, Integer>): IThriftDictionary<Integer, Integer>; |
| function testStringMap(thing: IThriftDictionary<string, string>): IThriftDictionary<string, string>; |
| function testSet(thing: IHashSet<Integer>): IHashSet<Integer>; |
| function testList(thing: IThriftList<Integer>): IThriftList<Integer>; |
| function testEnum(thing: TNumberz): TNumberz; |
| function testTypedef(thing: Int64): Int64; |
| function testMapMap(hello: Integer): IThriftDictionary<Integer, IThriftDictionary<Integer, Integer>>; |
| function testInsanity(argument: IInsanity): IThriftDictionary<Int64, IThriftDictionary<TNumberz, IInsanity>>; |
| function testMulti(arg0: ShortInt; arg1: Integer; arg2: Int64; arg3: IThriftDictionary<SmallInt, string>; arg4: TNumberz; arg5: Int64): IXtruct; |
| procedure testException(arg: string); |
| function testMultiException(arg0: string; arg1: string): IXtruct; |
| procedure testOneway(secondsToSleep: Integer); |
| |
| procedure testStop; |
| |
| procedure SetServer( AServer : IServer ); |
| end; |
| |
| class procedure Execute( args: array of string); |
| end; |
| |
| implementation |
| |
| { TTestServer.TTestHandlerImpl } |
| |
| procedure TTestServer.TTestHandlerImpl.SetServer(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(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(arg: string); |
| var |
| x : TXception; |
| begin |
| Console.WriteLine('testException(' + arg + ')'); |
| if ( arg = 'Xception') then |
| begin |
| x := TXception.Create; |
| x.ErrorCode := 1001; |
| x.Message_ := 'This is an Xception'; |
| x.UpdateMessageProperty; |
| raise x; |
| end; |
| end; |
| |
| function TTestServer.TTestHandlerImpl.testI32(thing: Integer): Integer; |
| begin |
| Console.WriteLine('testI32("' + IntToStr( thing) + '")'); |
| Result := thing; |
| end; |
| |
| function TTestServer.TTestHandlerImpl.testI64(thing: Int64): Int64; |
| begin |
| Console.WriteLine('testI64("' + IntToStr( thing) + '")'); |
| Result := thing; |
| end; |
| |
| function TTestServer.TTestHandlerImpl.testInsanity( |
| 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 := 'hello'; |
| 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.SIX, 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( |
| 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( |
| 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; |
| arg2: Int64; arg3: IThriftDictionary<SmallInt, string>; arg4: TNumberz; |
| 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(arg0, |
| arg1: string): IXtruct; |
| var |
| x : TXception; |
| x2 : TXception2; |
| begin |
| Console.WriteLine('testMultiException(' + arg0 + ', ' + arg1 + ')'); |
| if ( arg0 = 'Xception') then |
| begin |
| x := TXception.Create; |
| x.ErrorCode := 1001; |
| x.Message_ := 'This is an Xception'; |
| x.UpdateMessageProperty; |
| raise x; |
| end else |
| if ( arg0 = 'Xception2') then |
| begin |
| x2 := TXception2.Create; |
| 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(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( |
| 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(thing: string): string; |
| begin |
| Console.WriteLine('teststring("' + thing + '")'); |
| Result := thing; |
| end; |
| |
| function TTestServer.TTestHandlerImpl.testStringMap( |
| thing: IThriftDictionary<string, string>): IThriftDictionary<string, string>; |
| begin |
| |
| end; |
| |
| function TTestServer.TTestHandlerImpl.testTypedef(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(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(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. |