FtpConnectionTest.cc 8.9 KB

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