FtpConnectionTest.cc 9.7 KB

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