FtpConnectionTest.cc 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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. #ifdef HAVE_STRPTIME
  155. // invalid month: 19
  156. Time t;
  157. _serverSocket->writeData("213 20081908124312\r\n");
  158. waitRead(_clientSocket);
  159. CPPUNIT_ASSERT_EQUAL((unsigned int)213, _ftp->receiveMdtmResponse(t));
  160. CPPUNIT_ASSERT(t.bad());
  161. #endif
  162. }
  163. {
  164. Time t;
  165. _serverSocket->writeData("550 File Not Found\r\n");
  166. waitRead(_clientSocket);
  167. CPPUNIT_ASSERT_EQUAL((unsigned int)550, _ftp->receiveMdtmResponse(t));
  168. }
  169. }
  170. void FtpConnectionTest::testReceiveResponse_overflow()
  171. {
  172. char data[1024];
  173. memset(data, 0, sizeof(data));
  174. memcpy(data, "213 ", 4);
  175. for(int i = 0; i < 4; ++i) {
  176. _serverSocket->writeData(data, sizeof(data));
  177. waitRead(_clientSocket);
  178. CPPUNIT_ASSERT_EQUAL((unsigned int)0, _ftp->receiveResponse());
  179. }
  180. _serverSocket->writeData(data, sizeof(data));
  181. waitRead(_clientSocket);
  182. try {
  183. _ftp->receiveResponse();
  184. CPPUNIT_FAIL("exception must be thrown.");
  185. } catch(DlRetryEx& e) {
  186. // success
  187. }
  188. }
  189. void FtpConnectionTest::testSendPwd()
  190. {
  191. _ftp->sendPwd();
  192. char data[32];
  193. size_t len = sizeof(data);
  194. _serverSocket->readData(data, len);
  195. CPPUNIT_ASSERT_EQUAL((size_t)5, len);
  196. data[len] = '\0';
  197. CPPUNIT_ASSERT_EQUAL(std::string("PWD\r\n"), std::string(data));
  198. }
  199. void FtpConnectionTest::testReceivePwdResponse()
  200. {
  201. std::string pwd;
  202. _serverSocket->writeData("257 ");
  203. waitRead(_clientSocket);
  204. CPPUNIT_ASSERT_EQUAL((unsigned int)0, _ftp->receivePwdResponse(pwd));
  205. CPPUNIT_ASSERT(pwd.empty());
  206. _serverSocket->writeData("\"/dir/to\" is your directory.\r\n");
  207. waitRead(_clientSocket);
  208. CPPUNIT_ASSERT_EQUAL((unsigned int)257, _ftp->receivePwdResponse(pwd));
  209. CPPUNIT_ASSERT_EQUAL(std::string("/dir/to"), pwd);
  210. }
  211. void FtpConnectionTest::testReceivePwdResponse_unquotedResponse()
  212. {
  213. std::string pwd;
  214. _serverSocket->writeData("257 /dir/to\r\n");
  215. waitRead(_clientSocket);
  216. try {
  217. _ftp->receivePwdResponse(pwd);
  218. CPPUNIT_FAIL("exception must be thrown.");
  219. } catch(DlAbortEx& e) {
  220. // success
  221. }
  222. }
  223. void FtpConnectionTest::testReceivePwdResponse_badStatus()
  224. {
  225. std::string pwd;
  226. _serverSocket->writeData("500 failed\r\n");
  227. waitRead(_clientSocket);
  228. CPPUNIT_ASSERT_EQUAL((unsigned int)500, _ftp->receivePwdResponse(pwd));
  229. CPPUNIT_ASSERT(pwd.empty());
  230. }
  231. void FtpConnectionTest::testSendCwd()
  232. {
  233. _ftp->sendCwd();
  234. char data[32];
  235. size_t len = sizeof(data);
  236. _serverSocket->readData(data, len);
  237. CPPUNIT_ASSERT_EQUAL((size_t)10, len);
  238. data[len] = '\0';
  239. CPPUNIT_ASSERT_EQUAL(std::string("CWD /dir\r\n"), std::string(data));
  240. }
  241. void FtpConnectionTest::testSendCwd_baseWorkingDir()
  242. {
  243. _ftp->setBaseWorkingDir("/base");
  244. _ftp->sendCwd();
  245. char data[32];
  246. size_t len = sizeof(data);
  247. _serverSocket->readData(data, len);
  248. CPPUNIT_ASSERT_EQUAL((size_t)15, len);
  249. data[len] = '\0';
  250. CPPUNIT_ASSERT_EQUAL(std::string("CWD /base/dir\r\n"), std::string(data));
  251. }
  252. } // namespace aria2