FtpConnectionTest.cc 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. #include "FtpConnection.h"
  2. #include <iostream>
  3. #include <cstring>
  4. #include <cppunit/extensions/HelperMacros.h>
  5. #include "Exception.h"
  6. #include "Util.h"
  7. #include "SocketCore.h"
  8. #include "Request.h"
  9. #include "Option.h"
  10. #include "DlRetryEx.h"
  11. #include "DlAbortEx.h"
  12. #include "AuthConfigFactory.h"
  13. #include "AuthConfig.h"
  14. namespace aria2 {
  15. class FtpConnectionTest:public CppUnit::TestFixture {
  16. CPPUNIT_TEST_SUITE(FtpConnectionTest);
  17. CPPUNIT_TEST(testReceiveResponse);
  18. CPPUNIT_TEST(testReceiveResponse_overflow);
  19. CPPUNIT_TEST(testSendMdtm);
  20. CPPUNIT_TEST(testReceiveMdtmResponse);
  21. CPPUNIT_TEST(testSendPwd);
  22. CPPUNIT_TEST(testReceivePwdResponse);
  23. CPPUNIT_TEST(testReceivePwdResponse_unquotedResponse);
  24. CPPUNIT_TEST(testReceivePwdResponse_badStatus);
  25. CPPUNIT_TEST(testSendCwd);
  26. CPPUNIT_TEST(testSendCwd_baseWorkingDir);
  27. CPPUNIT_TEST_SUITE_END();
  28. private:
  29. SharedHandle<SocketCore> _serverSocket;
  30. uint16_t _listenPort;
  31. SharedHandle<SocketCore> _clientSocket;
  32. SharedHandle<FtpConnection> _ftp;
  33. SharedHandle<Option> _option;
  34. SharedHandle<AuthConfigFactory> _authConfigFactory;
  35. public:
  36. void setUp()
  37. {
  38. _option.reset(new Option());
  39. _authConfigFactory.reset(new AuthConfigFactory(_option.get()));
  40. //_ftpServerSocket.reset(new SocketCore());
  41. SharedHandle<SocketCore> listenSocket(new SocketCore());
  42. listenSocket->bind(0);
  43. listenSocket->beginListen();
  44. std::pair<std::string, uint16_t> addrinfo;
  45. listenSocket->getAddrInfo(addrinfo);
  46. _listenPort = addrinfo.second;
  47. SharedHandle<Request> req(new Request());
  48. req->setUrl("ftp://localhost/dir/file.img");
  49. _clientSocket.reset(new SocketCore());
  50. _clientSocket->establishConnection("127.0.0.1", _listenPort);
  51. while(!_clientSocket->isWritable(0));
  52. _clientSocket->setBlockingMode();
  53. _serverSocket.reset(listenSocket->acceptConnection());
  54. _ftp.reset(new FtpConnection(1, _clientSocket, req,
  55. _authConfigFactory->createAuthConfig(req),
  56. _option.get()));
  57. }
  58. void tearDown() {}
  59. void testSendMdtm();
  60. void testReceiveMdtmResponse();
  61. void testReceiveResponse();
  62. void testReceiveResponse_overflow();
  63. void testSendPwd();
  64. void testReceivePwdResponse();
  65. void testReceivePwdResponse_unquotedResponse();
  66. void testReceivePwdResponse_badStatus();
  67. void testSendCwd();
  68. void testSendCwd_baseWorkingDir();
  69. };
  70. CPPUNIT_TEST_SUITE_REGISTRATION(FtpConnectionTest);
  71. static void waitRead(const SharedHandle<SocketCore>& socket)
  72. {
  73. while(!socket->isReadable(0));
  74. }
  75. void FtpConnectionTest::testReceiveResponse()
  76. {
  77. _serverSocket->writeData("100");
  78. waitRead(_clientSocket);
  79. CPPUNIT_ASSERT_EQUAL((unsigned int)0, _ftp->receiveResponse());
  80. _serverSocket->writeData(" single line response");
  81. waitRead(_clientSocket);
  82. CPPUNIT_ASSERT_EQUAL((unsigned int)0, _ftp->receiveResponse());
  83. _serverSocket->writeData("\r\n");
  84. waitRead(_clientSocket);
  85. CPPUNIT_ASSERT_EQUAL((unsigned int)100, _ftp->receiveResponse());
  86. // 2 responses in the buffer
  87. _serverSocket->writeData("101 single1\r\n"
  88. "102 single2\r\n");
  89. waitRead(_clientSocket);
  90. CPPUNIT_ASSERT_EQUAL((unsigned int)101, _ftp->receiveResponse());
  91. CPPUNIT_ASSERT_EQUAL((unsigned int)102, _ftp->receiveResponse());
  92. _serverSocket->writeData("103-multi line response\r\n");
  93. waitRead(_clientSocket);
  94. CPPUNIT_ASSERT_EQUAL((unsigned int)0, _ftp->receiveResponse());
  95. _serverSocket->writeData("103-line2\r\n");
  96. waitRead(_clientSocket);
  97. CPPUNIT_ASSERT_EQUAL((unsigned int)0, _ftp->receiveResponse());
  98. _serverSocket->writeData("103");
  99. waitRead(_clientSocket);
  100. CPPUNIT_ASSERT_EQUAL((unsigned int)0, _ftp->receiveResponse());
  101. _serverSocket->writeData(" ");
  102. waitRead(_clientSocket);
  103. CPPUNIT_ASSERT_EQUAL((unsigned int)0, _ftp->receiveResponse());
  104. _serverSocket->writeData("last\r\n");
  105. waitRead(_clientSocket);
  106. CPPUNIT_ASSERT_EQUAL((unsigned int)103, _ftp->receiveResponse());
  107. _serverSocket->writeData("104-multi\r\n"
  108. "104 \r\n"
  109. "105-multi\r\n"
  110. "105 \r\n");
  111. waitRead(_clientSocket);
  112. CPPUNIT_ASSERT_EQUAL((unsigned int)104, _ftp->receiveResponse());
  113. CPPUNIT_ASSERT_EQUAL((unsigned int)105, _ftp->receiveResponse());
  114. }
  115. void FtpConnectionTest::testSendMdtm()
  116. {
  117. _ftp->sendMdtm();
  118. char data[32];
  119. size_t len = sizeof(data);
  120. _serverSocket->readData(data, len);
  121. CPPUNIT_ASSERT_EQUAL((size_t)15, len);
  122. data[len] = '\0';
  123. CPPUNIT_ASSERT_EQUAL(std::string("MDTM file.img\r\n"), std::string(data));
  124. }
  125. void FtpConnectionTest::testReceiveMdtmResponse()
  126. {
  127. {
  128. Time t;
  129. _serverSocket->writeData("213 20080908124312");
  130. waitRead(_clientSocket);
  131. CPPUNIT_ASSERT_EQUAL((unsigned int)0, _ftp->receiveMdtmResponse(t));
  132. _serverSocket->writeData("\r\n");
  133. waitRead(_clientSocket);
  134. CPPUNIT_ASSERT_EQUAL((unsigned int)213, _ftp->receiveMdtmResponse(t));
  135. CPPUNIT_ASSERT_EQUAL((time_t)1220877792, t.getTime());
  136. }
  137. {
  138. // see milli second part is ignored
  139. Time t;
  140. _serverSocket->writeData("213 20080908124312.014\r\n");
  141. waitRead(_clientSocket);
  142. CPPUNIT_ASSERT_EQUAL((unsigned int)213, _ftp->receiveMdtmResponse(t));
  143. CPPUNIT_ASSERT_EQUAL((time_t)1220877792, t.getTime());
  144. }
  145. {
  146. // hhmmss part is missing
  147. Time t;
  148. _serverSocket->writeData("213 20080908\r\n");
  149. waitRead(_clientSocket);
  150. CPPUNIT_ASSERT_EQUAL((unsigned int)213, _ftp->receiveMdtmResponse(t));
  151. CPPUNIT_ASSERT(t.bad());
  152. }
  153. {
  154. // invalid month: 19, we don't care about invalid month..
  155. Time t;
  156. _serverSocket->writeData("213 20081908124312\r\n");
  157. waitRead(_clientSocket);
  158. CPPUNIT_ASSERT_EQUAL((unsigned int)213, _ftp->receiveMdtmResponse(t));
  159. // Wed Jul 8 12:43:12 2009
  160. CPPUNIT_ASSERT_EQUAL((time_t)1247056992, t.getTime());
  161. }
  162. {
  163. Time t;
  164. _serverSocket->writeData("550 File Not Found\r\n");
  165. waitRead(_clientSocket);
  166. CPPUNIT_ASSERT_EQUAL((unsigned int)550, _ftp->receiveMdtmResponse(t));
  167. }
  168. }
  169. void FtpConnectionTest::testReceiveResponse_overflow()
  170. {
  171. char data[1024];
  172. memset(data, 0, sizeof(data));
  173. memcpy(data, "213 ", 4);
  174. for(int i = 0; i < 4; ++i) {
  175. _serverSocket->writeData(data, sizeof(data));
  176. waitRead(_clientSocket);
  177. CPPUNIT_ASSERT_EQUAL((unsigned int)0, _ftp->receiveResponse());
  178. }
  179. _serverSocket->writeData(data, sizeof(data));
  180. waitRead(_clientSocket);
  181. try {
  182. _ftp->receiveResponse();
  183. CPPUNIT_FAIL("exception must be thrown.");
  184. } catch(DlRetryEx& e) {
  185. // success
  186. }
  187. }
  188. void FtpConnectionTest::testSendPwd()
  189. {
  190. _ftp->sendPwd();
  191. char data[32];
  192. size_t len = sizeof(data);
  193. _serverSocket->readData(data, len);
  194. CPPUNIT_ASSERT_EQUAL((size_t)5, len);
  195. data[len] = '\0';
  196. CPPUNIT_ASSERT_EQUAL(std::string("PWD\r\n"), std::string(data));
  197. }
  198. void FtpConnectionTest::testReceivePwdResponse()
  199. {
  200. std::string pwd;
  201. _serverSocket->writeData("257 ");
  202. waitRead(_clientSocket);
  203. CPPUNIT_ASSERT_EQUAL((unsigned int)0, _ftp->receivePwdResponse(pwd));
  204. CPPUNIT_ASSERT(pwd.empty());
  205. _serverSocket->writeData("\"/dir/to\" is your directory.\r\n");
  206. waitRead(_clientSocket);
  207. CPPUNIT_ASSERT_EQUAL((unsigned int)257, _ftp->receivePwdResponse(pwd));
  208. CPPUNIT_ASSERT_EQUAL(std::string("/dir/to"), pwd);
  209. }
  210. void FtpConnectionTest::testReceivePwdResponse_unquotedResponse()
  211. {
  212. std::string pwd;
  213. _serverSocket->writeData("257 /dir/to\r\n");
  214. waitRead(_clientSocket);
  215. try {
  216. _ftp->receivePwdResponse(pwd);
  217. CPPUNIT_FAIL("exception must be thrown.");
  218. } catch(DlAbortEx& e) {
  219. // success
  220. }
  221. }
  222. void FtpConnectionTest::testReceivePwdResponse_badStatus()
  223. {
  224. std::string pwd;
  225. _serverSocket->writeData("500 failed\r\n");
  226. waitRead(_clientSocket);
  227. CPPUNIT_ASSERT_EQUAL((unsigned int)500, _ftp->receivePwdResponse(pwd));
  228. CPPUNIT_ASSERT(pwd.empty());
  229. }
  230. void FtpConnectionTest::testSendCwd()
  231. {
  232. _ftp->sendCwd();
  233. char data[32];
  234. size_t len = sizeof(data);
  235. _serverSocket->readData(data, len);
  236. CPPUNIT_ASSERT_EQUAL((size_t)10, len);
  237. data[len] = '\0';
  238. CPPUNIT_ASSERT_EQUAL(std::string("CWD /dir\r\n"), std::string(data));
  239. }
  240. void FtpConnectionTest::testSendCwd_baseWorkingDir()
  241. {
  242. _ftp->setBaseWorkingDir("/base");
  243. _ftp->sendCwd();
  244. char data[32];
  245. size_t len = sizeof(data);
  246. _serverSocket->readData(data, len);
  247. CPPUNIT_ASSERT_EQUAL((size_t)15, len);
  248. data[len] = '\0';
  249. CPPUNIT_ASSERT_EQUAL(std::string("CWD /base/dir\r\n"), std::string(data));
  250. }
  251. } // namespace aria2