IdTestFtpServer.pas 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. unit IdTestFtpServer;
  2. //todo test commands return 'not logged in' error correctly
  3. interface
  4. uses
  5. IdGlobal,
  6. IdSys,
  7. IdObjs,
  8. IdTest,
  9. IdTcpClient,
  10. IdFTPListOutput,
  11. IdIOHandlerStack,
  12. IdLogDebug,
  13. IdFtp,
  14. IdThreadSafe,
  15. IdFtpServer;
  16. type
  17. TIdTestFtpServer = class(TIdTest)
  18. private
  19. FDirectory:TIdThreadSafeString;
  20. procedure CallbackRetrieve(ASender: TIdFTPServerContext; const AFileName: string; var VStream: TIdStream);
  21. procedure CallbackStore(ASender: TIdFTPServerContext; const AFileName: string; AAppend: Boolean; var VStream: TIdStream);
  22. procedure CallbackListDirectory(ASender: TIdFTPServerContext; const APath: string;
  23. ADirectoryListing: TIdFTPListOutput; const ACmd : String; const ASwitches : string);
  24. procedure CallbackChangeDirectory(ASender: TIdFTPServerContext; var VDirectory: string);
  25. protected
  26. procedure Setup;override;
  27. procedure TearDown;override;
  28. published
  29. procedure TestBasic;
  30. procedure TestMethods;
  31. procedure TestBasic2;
  32. end;
  33. TIdTestStream = class(TIdMemoryStream)
  34. public
  35. destructor Destroy;override;
  36. end;
  37. implementation
  38. const
  39. cGreeting='HELLO';
  40. cTestFtpPort=20021;
  41. cContent='MYCONTENT';
  42. cPathOk='okpath';
  43. cPathError='errorpath';
  44. cUploadTo='file.txt';
  45. cGoodFilename='good.txt';
  46. cUnknownFilename='unknown.txt';
  47. cErrorFilename='error.txt';
  48. procedure TIdTestFtpServer.CallbackChangeDirectory(
  49. ASender: TIdFTPServerContext; var VDirectory: string);
  50. begin
  51. FDirectory.Value:=VDirectory;
  52. end;
  53. procedure TIdTestFtpServer.CallbackListDirectory(
  54. ASender: TIdFTPServerContext; const APath: string;
  55. ADirectoryListing: TIdFTPListOutput; const ACmd, ASwitches: string);
  56. var
  57. aItem:TIdFTPListOutputItem;
  58. begin
  59. if APath=cPathError then
  60. begin
  61. end
  62. else if APath=cPathOk then
  63. begin
  64. aItem:=ADirectoryListing.Add;
  65. aItem.FileName:='file1.txt';
  66. //int64 filesize
  67. aItem.Size:=5000000000;
  68. aItem.ModifiedDate:=Sys.Now;
  69. end;
  70. end;
  71. procedure TIdTestFtpServer.CallbackRetrieve(ASender: TIdFTPServerContext;
  72. const AFileName: string; var VStream: TIdStream);
  73. begin
  74. if AFileName=cGoodFilename then
  75. begin
  76. VStream:=TIdStringStream.Create(cContent);
  77. end
  78. else if AFileName=cErrorFilename then
  79. begin
  80. Assert(False);
  81. end
  82. else if AFileName=cUnknownFilename then
  83. begin
  84. end;
  85. end;
  86. procedure TIdTestFtpServer.CallbackStore(ASender: TIdFTPServerContext;
  87. const AFileName: string; AAppend: Boolean; var VStream: TIdStream);
  88. //var
  89. // s:string;
  90. begin
  91. Assert(VStream=nil);
  92. if AFileName=cUploadTo then
  93. begin
  94. VStream:=TIdTestStream.Create;
  95. //s:=ReadStringFromStream(VStream);
  96. //Assert(s=cContent);
  97. end;
  98. end;
  99. procedure TIdTestFtpServer.Setup;
  100. begin
  101. inherited;
  102. FDirectory:=TIdThreadSafeString.Create;
  103. end;
  104. procedure TIdTestFtpServer.TearDown;
  105. begin
  106. Sys.FreeAndNil(FDirectory);
  107. inherited;
  108. end;
  109. procedure TIdTestFtpServer.TestBasic;
  110. var
  111. s:TIdFTPServer;
  112. c:TIdTCPClient;
  113. aStr:string;
  114. begin
  115. s:=TIdFTPServer.Create(nil);
  116. c:=TIdTCPClient.Create(nil);
  117. try
  118. s.Greeting.Text.Text:=cGreeting;
  119. s.DefaultPort:=cTestFtpPort;
  120. s.AllowAnonymousLogin:=True;
  121. s.OnListDirectory:=CallbackListDirectory;
  122. s.Active:=True;
  123. c.Port:=cTestFtpPort;
  124. c.Host:='127.0.0.1';
  125. c.CreateIOHandler;
  126. c.ReadTimeout:=500;
  127. c.Connect;
  128. //expect a greeting. typical="220 FTP Server Ready."
  129. aStr:=c.IOHandler.Readln;
  130. Assert(aStr = '220 ' + cGreeting, cGreeting);
  131. //ftp server should only process a command after crlf
  132. //see TIdFTPServer.ReadCommandLine
  133. c.IOHandler.Write('U');
  134. aStr:=c.IOHandler.Readln;
  135. Assert(aStr='',aStr);
  136. //complete the rest of the command
  137. c.IOHandler.WriteLn('SER ANONYMOUS');
  138. aStr:=c.IOHandler.Readln;
  139. Assert(aStr<>'',aStr);
  140. c.IOHandler.WriteLn('PASS [email protected]');
  141. aStr:=c.IOHandler.Readln;
  142. Assert(aStr<>'',aStr);
  143. //attempt to start a transfer when no datachannel setup.
  144. //should give 550 error?
  145. //typical quit='221 Goodbye.'
  146. //test commands that aren't currently in the ftp client?
  147. //nlst needs a data connection.
  148. //calling without causes an AV and memleak. should be fixed
  149. //c.IOHandler.WriteLn('NLST');
  150. //aStr:=c.IOHandler.Readln;
  151. //Assert(aStr<>'',aStr);
  152. finally
  153. Sys.FreeAndNil(c);
  154. Sys.FreeAndNil(s);
  155. end;
  156. end;
  157. procedure TIdTestFtpServer.TestBasic2;
  158. var
  159. s:TIdFTPServer;
  160. c:TIdFTP;
  161. //aStr:string;
  162. aList:TIdStringList;
  163. begin
  164. s:=TIdFTPServer.Create;
  165. c:=TIdFTP.Create;
  166. try
  167. s.Greeting.Text.Text:=cGreeting;
  168. s.DefaultPort:=cTestFtpPort;
  169. s.AllowAnonymousLogin:=True;
  170. s.Greeting.Text.Text:=cGreeting;
  171. s.OnListDirectory:=Self.CallbackListDirectory;
  172. s.OnChangeDirectory:=Self.CallbackChangeDirectory;
  173. s.Active:=True;
  174. c.Port:=cTestFtpPort;
  175. c.Host:='127.0.0.1';
  176. c.Username:='anonymous';
  177. c.Password:='[email protected]';
  178. c.Connect;
  179. Assert(c.Greeting.Text.Text=cGreeting+EOL);
  180. aList:=TIdStringList.Create;
  181. try
  182. c.List(aList);
  183. Assert(aList.Count>0);
  184. c.ChangeDir(cPathError);
  185. aList.Clear;
  186. c.List(aList);
  187. finally
  188. Sys.FreeAndNil(aList);
  189. end;
  190. finally
  191. Sys.FreeAndNil(c);
  192. Sys.FreeAndNil(s);
  193. end;
  194. end;
  195. procedure TIdTestFtpServer.TestMethods;
  196. var
  197. s:TIdFTPServer;
  198. c:TIdFTP;
  199. aStream:TIdMemoryStream;
  200. begin
  201. s:=TIdFTPServer.Create(nil);
  202. c:=TIdFTP.Create(nil);
  203. try
  204. s.Greeting.Text.Text:=cGreeting;
  205. s.DefaultPort:=cTestFtpPort;
  206. s.OnStoreFile:=CallbackStore;
  207. s.OnRetrieveFile:=CallbackRetrieve;
  208. s.Active:=True;
  209. c.Port:=cTestFtpPort;
  210. c.Host:='127.0.0.1';
  211. c.CreateIOHandler;
  212. c.IOHandler.ReadTimeout:=1000;
  213. c.AutoLogin:=False;
  214. c.Connect;
  215. //check invalid login
  216. //check valid login
  217. //check allow/disallow anonymous login
  218. s.AllowAnonymousLogin:=True;
  219. c.Username:='anonymous';
  220. c.Password:='[email protected]';
  221. c.Login;
  222. repeat
  223. //check stream upload
  224. aStream:=TIdMemoryStream.Create;
  225. try
  226. WriteStringToStream(aStream, cContent);
  227. aStream.Position := 0;
  228. c.Put(aStream,cUploadTo);
  229. finally
  230. Sys.FreeAndNil(aStream);
  231. end;
  232. //check no dest filename
  233. //check missing source file
  234. //check file upload rejected by server. eg out of space?
  235. //check normal file upload. create a temp file? use c:\?
  236. //c.Put('c:\test.txt',cUploadTo);
  237. //test resume
  238. //test download unknown file
  239. aStream:=TIdMemoryStream.Create;
  240. try
  241. //test download to stream
  242. c.Get(cGoodFilename,aStream);
  243. //Assert(aStream.DataString=cContent);
  244. //test exception on server gets sent to client
  245. { aStream.Size:=0;
  246. try
  247. c.Get(cUnknownFilename,aStream);
  248. Assert(False);
  249. except
  250. //expect to be here
  251. end;
  252. }
  253. finally
  254. Sys.FreeAndNil(aStream);
  255. end;
  256. if c.Passive then
  257. begin
  258. break;
  259. end;
  260. //OutputLn('PASV Mode tests');
  261. c.Passive := True;
  262. until False;
  263. finally
  264. Sys.FreeAndNil(c);
  265. Sys.FreeAndNil(s);
  266. end;
  267. end;
  268. destructor TIdTestStream.Destroy;
  269. begin
  270. inherited;
  271. end;
  272. initialization
  273. TIdTest.RegisterTest(TIdTestFtpServer);
  274. end.