| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- unit IdTestTcpClient;
- //todo add test to TIdCustomTCPServer to ensure OnDisconnect is called
- //when connection is closed, also when exception happens, eg graceful close
- {
- observations:
- IdDefTimeout = 0;
- IdTimeoutDefault = -1;
- IdTimeoutInfinite = -2;
- IdTimeoutDefault when passed as a default param means 'use Self.ReadTimeout' ?
- From help file:
- IdDefTimeout
- Default timeout value when establishing socket-based connections.
- IdDefTimeout is an Integer constant that represents the value to
- use as the default timeout value for socket-based connection operations.
- used in
- TIdIOHandlerStack.ReadTimeout,
- TIdFTP.TransferTimeout (but actually sets FDataChannel.IOHandler.ReadTimeout)
- property TIdIOHandlerStack.ReadTimeout: Integer;
- Indicates the milliseconds to wait for a readable IOHandler connection.
- If ReadTimeout contains the value 0 (zero), the value in IdTimeoutInfinite
- is used as the timeout interval.
- TIdIOHandlerStack
- published
- property ReadTimeout default IdDefTimeout;
- but actually initialised to:
- FReadTimeOut := IdTimeoutDefault;
- It can seem more intuitive that timeout=0 means immediate timeout?
- or assume it means 'no timeout' eg infinite
- currently have 2 options for infinite, none for immediate
- how to test that a client is actually using infinite timeout?
- }
- interface
- uses
- IdTest,
- IdStack,
- IdComponent,
- IdGlobal,
- IdExceptionCore,
- IdTcpClient,
- IdObjs,
- IdSys,
- IdThreadSafe,
- IdTcpServer,
- IdContext;
- type
- TIdTestTcpClient = class(TIdTest)
- private
- FList:TIdThreadSafeStringList;
- FServerShouldEcho: Boolean;
- procedure DoServerExecute(AContext: TIdContext);
- procedure CallbackConnect(Sender:TObject);
- procedure CallbackDisconnect(Sender:TObject);
- procedure CallbackStatus(ASender: TObject; const AStatus: TIdStatus; const AStatusText: string);
- published
- procedure TestTimeouts;
- procedure TestConnectErrors;
- procedure TestEvent;
- end;
- implementation
- procedure TIdTestTcpClient.CallbackConnect(Sender: TObject);
- var
- astr:string;
- begin
- aStr:='OnConnect: Sender='+sender.Classname;
- FList.Add(astr);
- end;
- procedure TIdTestTcpClient.CallbackDisconnect(Sender: TObject);
- var
- astr:string;
- begin
- aStr:='OnDisconnect: Sender='+Sender.ClassName;
- FList.Add(astr);
- end;
- procedure TIdTestTcpClient.CallbackStatus(ASender: TObject;
- const AStatus: TIdStatus; const AStatusText: string);
- var
- astr:string;
- begin
- aStr:='OnStatus: Sender='+ASender.ClassName+' Text='+AStatusText;
- FList.Add(aStr);
- end;
- procedure TIdTestTcpClient.DoServerExecute(AContext: TIdContext);
- var
- aStr:string;
- begin
- aStr:=AContext.Connection.IOHandler.Readln;
- if FServerShouldEcho then
- begin
- AContext.Connection.IOHandler.WriteLn(aStr);
- end;
- if aStr='normal' then
- begin
- AContext.Connection.IOHandler.WriteLn('reply');
- end
- else if aStr='dropme' then
- begin
- AContext.Connection.Disconnect;
- end;
- end;
- procedure TIdTestTcpClient.TestConnectErrors;
- //checks that exceptions are raised as expected
- var
- aClient:TIdTCPClient;
- aExpected:Boolean;
- begin
- aClient:=TIdTCPClient.Create(nil);
- try
- //no host given
- try
- aExpected:=False;
- aClient.Port:=80;
- aClient.Host:='';
- aClient.Connect;
- except
- on e:Exception do
- begin
- aExpected:=e is EIdHostRequired;
- end;
- end;
- Assert(aExpected);
- //no port given
- try
- aExpected:=False;
- aClient.Port:=0;
- aClient.Host:='127.0.0.1';
- aClient.Connect;
- except
- on e:Exception do
- begin
- aExpected:=e is EIdPortRequired;
- end;
- end;
- Assert(aExpected);
- //hoping that this port is unused (its the max port number)
- try
- aExpected:=False;
- aClient.Port:=65535;
- aClient.Host:='127.0.0.1';
- //odd. specifying timeout gives EIdNotASocket
- //aClient.ConnectTimeout:=500;
- aClient.Connect;
- except
- on e:Exception do
- begin
- aExpected:=e is EIdSocketError;
- end;
- end;
- Assert(aExpected);
- finally
- Sys.FreeAndNil(aClient);
- end;
- end;
- function ListToCommaText(const aSafe:TIdThreadSafeStringList):string;
- begin
- with aSafe.Lock do
- try
- Result:=CommaText;
- finally
- aSafe.Unlock;
- end;
- end;
- procedure ListToDebug(const aList:TIdStringList);
- var
- i:Integer;
- begin
- for i:=0 to aList.Count-1 do
- begin
- DebugOutput(aList[i]);
- end;
- end;
- procedure SafeListToDebug(const aSafe:TIdThreadSafeStringList);
- var
- aList:TIdStringList;
- begin
- aList:=aSafe.Lock;
- try
- ListToDebug(aList);
- finally
- aSafe.Unlock;
- end;
- end;
- procedure TIdTestTcpClient.TestEvent;
- var
- aClient:TIdTCPClient;
- aServer:TIdTCPServer;
- aStr:string;
- //TIdIOHandlerStack.CheckForDisconnect( commented disconnect
- begin
- FList:=TIdThreadSafeStringList.Create;
- aClient:=TIdTCPClient.Create;
- aServer:=TIdTCPServer.Create;
- try
- aServer.OnExecute:=Self.DoServerExecute;
- aServer.DefaultPort:=12121;
- aServer.Active:=True;
- aClient.OnStatus:=Self.CallbackStatus;
- aClient.OnDisconnected:=Self.CallbackDisconnect;
- aClient.OnConnected:=Self.CallbackConnect;
- aClient.Host:='127.0.0.1';
- aClient.Port:=12121;
- //scenario #1
- DebugOutput('Client Disconnects:');
- FList.Clear;
- aClient.Connect;
- aClient.IOHandler.WriteLn('normal');
- aStr:=aClient.IOHandler.Readln;
- aClient.Disconnect;
- SafeListToDebug(FList);
- //scenario #2
- DebugOutput('Server Disconnects:');
- FList.Clear;
- try
- aClient.Connect;
- aClient.IOHandler.WriteLn('dropme');
- aStr:=aClient.IOHandler.Readln;
- except
- //ignore the graceful disconnect exception
- end;
- SafeListToDebug(FList);
- //aStr:=ListToCommaText(FList);
- //Assert(aStr='',aStr);
- finally
- sys.FreeAndNil(aClient);
- sys.FreeAndNil(aServer);
- sys.FreeAndNil(FList);
- end;
- end;
- procedure TIdTestTcpClient.TestTimeouts;
- const
- cServerPort = 20200;
- var
- FServer: TIdTcpServer;
- FClient: TIdTcpClient;
- LResult: string;
- //LStart: Integer;
- //LEnd: Integer;
- begin
- FServerShouldEcho := False;
- FServer := TIdTcpServer.Create;
- try
- FServer.DefaultPort := cServerPort;
- FServer.OnExecute := DoServerExecute;
- FServer.Active := true;
- FClient := TIdTcpClient.Create;
- try
- FClient.Connect('127.0.0.1', cServerPort);
- FClient.ReadTimeout := 500;
- LResult:=FClient.IOHandler.Readln;
- Assert(LResult = '');
- Assert(FClient.IOHandler.ReadLnTimedOut);
- FServerShouldEcho := True;
- FClient.IOHandler.WriteLn('Hello, World!');
- LResult := FClient.IOHandler.ReadLn;
- Assert(LResult = 'Hello, World!', LResult);
- {
- Make some test regarding the readtimeout property and the atimeout param
- of some methods.
- So the methods needing tests include:
- WriteChar
- ReadChar
- WriteString
- ReadString
- WriteBytes
- ReadBytes
- WriteInteger
- ReadInteger
- Try for some of them the timeout stuff. the ReadTimeout property is the default.
- It defaults to -1 (IdTimeoutInfinite). When ReadTimeout is set, that's the
- default for all read* methods. when a specific read method has a ATimeout property,
- try setting that one to see if it overrides the ReadTimeout property.
- the length of timeout should also be measured.
- eg set timeout to 3000. read. check that the read method blocked for between 2 and 4 seconds.
- this ensures that timeouts aren't occurring instantly.
- needs a portable timing mechanism? gettickcount on windows?
- }
- finally
- Sys.FreeAndNil(FClient);
- end;
- finally
- Sys.FreeAndNil(FServer);
- end;
- end;
- initialization
- TIdTest.RegisterTest(TIdTestTcpClient);
- end.
|