IdTestIOHandler.pas 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. unit IdTestIOHandler;
  2. interface
  3. uses
  4. IdTest,
  5. IdIOHandler,
  6. IdObjs,
  7. IdStream,
  8. IdIntercept,
  9. IdExceptionCore,
  10. IdResourceStringsCore,
  11. IdGlobal,
  12. IdSys;
  13. type
  14. //reads and writes to its own inputbuffer, makes easy to test
  15. TIdLoopbackIOHandler = class(TIdIOHandler)
  16. protected
  17. function ReadFromSource(
  18. ARaiseExceptionIfDisconnected: Boolean;
  19. ATimeout: Integer;
  20. ARaiseExceptionOnTimeout: Boolean
  21. ): Integer; override;
  22. public
  23. procedure CheckForDataOnSource(ATimeout:Integer); override;
  24. procedure CheckForDisconnect(
  25. ARaiseExceptionIfDisconnected: Boolean;
  26. AIgnoreBuffer: Boolean
  27. ); override;
  28. procedure WriteDirect(var ABuffer: TIdBytes); override;
  29. end;
  30. TIdExampleIntercept = class(TIdConnectionIntercept)
  31. public
  32. procedure Send(var ABuffer: TIdBytes); override;
  33. end;
  34. TIdTestIOHandler = class(TIdTest)
  35. private
  36. procedure RunStream(const io:TIdIOHandler;const aLarge:Boolean);
  37. published
  38. procedure TestReadWrite;
  39. procedure TestReadLn;
  40. procedure TestStreamSize;
  41. procedure TestIntercept;
  42. procedure TestWriteBuffered;
  43. procedure TestBuffered;
  44. end;
  45. implementation
  46. const
  47. cStr='abc123';
  48. //for intercept test
  49. cPlain='abcdef';
  50. cEncoded='123456';
  51. procedure TIdLoopbackIOHandler.CheckForDataOnSource(ATimeout: Integer);
  52. begin
  53. // inherited;
  54. end;
  55. procedure TIdLoopbackIOHandler.CheckForDisconnect;
  56. begin
  57. // inherited;
  58. end;
  59. function TIdLoopbackIOHandler.ReadFromSource(
  60. ARaiseExceptionIfDisconnected: Boolean; ATimeout: Integer;
  61. ARaiseExceptionOnTimeout: Boolean): Integer;
  62. begin
  63. //always report a timeout happened, ie there's no more data expected
  64. Result:=-1;
  65. EIdReadTimeout.IfTrue(ARaiseExceptionOnTimeout and (Result = -1), RSReadTimeout);
  66. end;
  67. procedure TIdLoopbackIOHandler.WriteDirect(var ABuffer: TIdBytes);
  68. begin
  69. inherited;
  70. FInputBuffer.Write(abuffer);
  71. end;
  72. procedure TIdTestIOHandler.RunStream(const io: TIdIOHandler;const aLarge:Boolean);
  73. //given iohandler in large/smallfile mode, check read/write ok
  74. var
  75. aStream:TIdStringStream;
  76. aStr:string;
  77. begin
  78. io.InputBuffer.Clear;
  79. io.LargeStream:=aLarge;
  80. aStream:=TIdStringStream.Create(cStr);
  81. try
  82. //write the stream to the iohandler
  83. io.Write(aStream,0,True);
  84. //buffer should contain length+data. stream unchanged.
  85. Assert(io.InputBuffer.Size>0);
  86. Assert(aStream.DataString=cStr);
  87. //reset and read
  88. aStream.Size:=0;
  89. io.ReadStream(aStream,-1);
  90. aStream.Position:=0;
  91. aStr:=aStream.DataString;
  92. Assert(aStr=cStr);
  93. finally
  94. Sys.FreeAndNil(aStream);
  95. end;
  96. end;
  97. procedure TIdTestIOHandler.TestBuffered;
  98. var
  99. io:TIdLoopbackIOHandler;
  100. begin
  101. io:=TIdLoopbackIOHandler.Create(nil);
  102. try
  103. io.Open;
  104. io.WriteBufferOpen(2);
  105. //check that writes less than buffer size arent sent
  106. io.Write('1');
  107. Assert(io.InputBufferAsString='');
  108. //write >1 buffersize of data, check all is sent
  109. io.Write('2345');
  110. Assert(io.InputBufferAsString='1234');
  111. finally
  112. Sys.FreeAndNil(io);
  113. end;
  114. end;
  115. procedure TIdTestIOHandler.TestIntercept;
  116. var
  117. io:TIdLoopbackIOHandler;
  118. aStr:string;
  119. aIntercept:TIdExampleIntercept;
  120. begin
  121. io:=TIdLoopbackIOHandler.Create(nil);
  122. aIntercept:=TIdExampleIntercept.Create;
  123. try
  124. io.Intercept:=aIntercept;
  125. io.Open;
  126. //check that the intercept actually changes data that gets written
  127. io.Write(cPlain);
  128. aStr:=io.InputBuffer.AsString;
  129. Assert(aStr=cEncoded,aStr);
  130. //todo test nested intercepts
  131. finally
  132. Sys.FreeAndNil(io);
  133. Sys.FreeAndNil(aIntercept);
  134. end;
  135. end;
  136. procedure TIdTestIOHandler.TestReadLn;
  137. //tests that read timeout happens
  138. var
  139. io:TIdLoopbackIOHandler;
  140. aStr:string;
  141. const
  142. cPart='U';
  143. begin
  144. io:=TIdLoopbackIOHandler.Create(nil);
  145. try
  146. io.Open;
  147. //check with no data in buffer
  148. aStr:=io.Readln;
  149. Assert(aStr = '');
  150. //check with some data in buffer
  151. io.Write(cPart);
  152. aStr:=io.Readln;
  153. Assert(aStr = '');
  154. //check that buffer still contains expected data
  155. Assert(io.FInputBuffer.Size = 1, Sys.IntToStr(io.FInputBuffer.Size));
  156. //complete the data line
  157. io.WriteLn('');
  158. aStr:=io.Readln;
  159. Assert(aStr = cPart);
  160. Assert(io.FInputBuffer.Size = 0);
  161. finally
  162. Sys.FreeAndNil(io);
  163. end;
  164. end;
  165. procedure TIdTestIOHandler.TestReadWrite;
  166. //use specific cast variables in the write calls to ensure correct
  167. //overload is called
  168. var
  169. io:TIdLoopbackIOHandler;
  170. aInt:Integer;
  171. aInt64:Int64;
  172. aSmall:Smallint;
  173. aStr:string;
  174. aCardinal:Cardinal;
  175. aChar:Char;
  176. const
  177. cInt=High(Integer)-1;
  178. cCard=Cardinal(4000000000);
  179. cInt64=Low(Int64)+1;
  180. cSmall=High(Smallint)-1;
  181. cChar='x';
  182. begin
  183. io:=TIdLoopbackIOHandler.Create(nil);
  184. try
  185. io.Open;
  186. //should check with/without conversion parameter
  187. //should also check edge cases, eg high/low
  188. //test with no data in buffer
  189. //aChar:=io.ReadChar;
  190. //Assert(aChar=#0);
  191. //integer types
  192. Assert(io.FInputBuffer.Size=0);
  193. aSmall:=cSmall;
  194. io.Write(aSmall,True);
  195. Assert(io.FInputBuffer.Size>0);
  196. aSmall:=io.ReadSmallInt(True);
  197. Assert(aSmall=cSmall);
  198. Assert(io.FInputBuffer.Size=0);
  199. aInt:=cInt;
  200. io.Write(aInt,True);
  201. aInt:=io.ReadInteger(True);
  202. Assert(aInt=cInt);
  203. Assert(io.FInputBuffer.Size=0);
  204. aCardinal:=cCard;
  205. io.Write(aCardinal,True);
  206. aCardinal:=io.ReadCardinal(True);
  207. Assert(aCardinal=cCard);
  208. Assert(io.FInputBuffer.Size=0);
  209. aInt64:=cInt64;
  210. io.Write(aInt64,True);
  211. aInt64:=io.ReadInt64(True);
  212. Assert(aInt64=cInt64);
  213. Assert(io.FInputBuffer.Size=0);
  214. //string types
  215. aChar:=cChar;
  216. io.Write(aChar);
  217. aChar:=io.ReadChar;
  218. Assert(aChar=cChar);
  219. Assert(io.FInputBuffer.Size=0);
  220. //test normal readln
  221. aStr:=cStr;
  222. io.WriteLn(aStr);
  223. Assert(io.FInputBuffer.Size>0);
  224. aStr:=io.Readln;
  225. Assert(aStr=cStr,aStr);
  226. Assert(io.FInputBuffer.Size=0);
  227. finally
  228. Sys.FreeAndNil(io);
  229. end;
  230. end;
  231. procedure TIdTestIOHandler.TestStreamSize;
  232. var
  233. io:TIdLoopbackIOHandler;
  234. begin
  235. io:=TIdLoopbackIOHandler.Create(nil);
  236. try
  237. io.Open;
  238. //integer-size stream
  239. RunStream(io,False);
  240. //int64 streams
  241. RunStream(io,True);
  242. finally
  243. Sys.FreeAndNil(io);
  244. end;
  245. end;
  246. procedure TIdExampleIntercept.Send(var ABuffer: TIdBytes);
  247. begin
  248. inherited;
  249. ABuffer:=ToBytes(cEncoded);
  250. end;
  251. procedure TIdTestIOHandler.TestWriteBuffered;
  252. var
  253. io:TIdLoopbackIOHandler;
  254. aStr:string;
  255. aIntercept:TIdExampleIntercept;
  256. begin
  257. io:=TIdLoopbackIOHandler.Create(nil);
  258. aIntercept:=TIdExampleIntercept.Create;
  259. try
  260. io.Open;
  261. Assert(not io.WriteBufferingActive);
  262. io.WriteBufferOpen;
  263. Assert(io.WriteBufferingActive);
  264. //write some data. it should not be sent
  265. io.Write(cStr);
  266. aStr:=io.InputBuffer.AsString;
  267. Assert(aStr='');
  268. //flush the buffer. data should now be sent
  269. io.WriteBufferFlush;
  270. aStr:=io.InputBuffer.AsString;
  271. Assert(aStr=cStr);
  272. io.WriteBufferClose;
  273. //todo test threshhold. currently not implemented
  274. //leave the writebuffer open, to check for memory leaks
  275. io.WriteBufferOpen;
  276. //if writebuffer has contents when iohandler closed, should it
  277. //be flushed by iohandler?
  278. finally
  279. Sys.FreeAndNil(io);
  280. Sys.FreeAndNil(aIntercept);
  281. end;
  282. end;
  283. initialization
  284. TIdTest.RegisterTest(TIdTestIOHandler);
  285. end.