RpcMethodTest.cc 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389
  1. #include "RpcMethod.h"
  2. #include <cppunit/extensions/HelperMacros.h>
  3. #include "DownloadEngine.h"
  4. #include "SelectEventPoll.h"
  5. #include "Option.h"
  6. #include "RequestGroupMan.h"
  7. #include "RequestGroup.h"
  8. #include "RpcMethodImpl.h"
  9. #include "OptionParser.h"
  10. #include "OptionHandler.h"
  11. #include "RpcRequest.h"
  12. #include "RpcResponse.h"
  13. #include "prefs.h"
  14. #include "TestUtil.h"
  15. #include "DownloadContext.h"
  16. #include "FeatureConfig.h"
  17. #include "util.h"
  18. #include "array_fun.h"
  19. #include "download_helper.h"
  20. #include "FileEntry.h"
  21. #include "RpcMethodFactory.h"
  22. #ifdef ENABLE_BITTORRENT
  23. # include "BtRegistry.h"
  24. # include "BtRuntime.h"
  25. # include "bittorrent_helper.h"
  26. #endif // ENABLE_BITTORRENT
  27. namespace aria2 {
  28. namespace rpc {
  29. class RpcMethodTest:public CppUnit::TestFixture {
  30. CPPUNIT_TEST_SUITE(RpcMethodTest);
  31. CPPUNIT_TEST(testAuthorize);
  32. CPPUNIT_TEST(testAddUri);
  33. CPPUNIT_TEST(testAddUri_withoutUri);
  34. CPPUNIT_TEST(testAddUri_notUri);
  35. CPPUNIT_TEST(testAddUri_withBadOption);
  36. CPPUNIT_TEST(testAddUri_withPosition);
  37. CPPUNIT_TEST(testAddUri_withBadPosition);
  38. #ifdef ENABLE_BITTORRENT
  39. CPPUNIT_TEST(testAddTorrent);
  40. CPPUNIT_TEST(testAddTorrent_withoutTorrent);
  41. CPPUNIT_TEST(testAddTorrent_notBase64Torrent);
  42. CPPUNIT_TEST(testAddTorrent_withPosition);
  43. #endif // ENABLE_BITTORRENT
  44. #ifdef ENABLE_METALINK
  45. CPPUNIT_TEST(testAddMetalink);
  46. CPPUNIT_TEST(testAddMetalink_withoutMetalink);
  47. CPPUNIT_TEST(testAddMetalink_notBase64Metalink);
  48. CPPUNIT_TEST(testAddMetalink_withPosition);
  49. #endif // ENABLE_METALINK
  50. CPPUNIT_TEST(testGetOption);
  51. CPPUNIT_TEST(testChangeOption);
  52. CPPUNIT_TEST(testChangeOption_withBadOption);
  53. CPPUNIT_TEST(testChangeOption_withNotAllowedOption);
  54. CPPUNIT_TEST(testChangeOption_withoutGid);
  55. CPPUNIT_TEST(testChangeGlobalOption);
  56. CPPUNIT_TEST(testChangeGlobalOption_withBadOption);
  57. CPPUNIT_TEST(testChangeGlobalOption_withNotAllowedOption);
  58. CPPUNIT_TEST(testTellStatus_withoutGid);
  59. CPPUNIT_TEST(testTellWaiting);
  60. CPPUNIT_TEST(testTellWaiting_fail);
  61. CPPUNIT_TEST(testGetVersion);
  62. CPPUNIT_TEST(testNoSuchMethod);
  63. CPPUNIT_TEST(testGatherStoppedDownload);
  64. CPPUNIT_TEST(testGatherProgressCommon);
  65. #ifdef ENABLE_BITTORRENT
  66. CPPUNIT_TEST(testGatherBitTorrentMetadata);
  67. #endif // ENABLE_BITTORRENT
  68. CPPUNIT_TEST(testChangePosition);
  69. CPPUNIT_TEST(testChangePosition_fail);
  70. CPPUNIT_TEST(testGetSessionInfo);
  71. CPPUNIT_TEST(testChangeUri);
  72. CPPUNIT_TEST(testChangeUri_fail);
  73. CPPUNIT_TEST(testPause);
  74. CPPUNIT_TEST(testSystemMulticall);
  75. CPPUNIT_TEST(testSystemMulticall_fail);
  76. CPPUNIT_TEST(testSystemListMethods);
  77. CPPUNIT_TEST_SUITE_END();
  78. private:
  79. std::shared_ptr<DownloadEngine> e_;
  80. std::shared_ptr<Option> option_;
  81. public:
  82. void setUp()
  83. {
  84. option_ = std::make_shared<Option>();
  85. option_->put(PREF_DIR, A2_TEST_OUT_DIR"/aria2_RpcMethodTest");
  86. option_->put(PREF_PIECE_LENGTH, "1048576");
  87. option_->put(PREF_MAX_DOWNLOAD_RESULT, "10");
  88. File(option_->get(PREF_DIR)).mkdirs();
  89. e_ = make_unique<DownloadEngine>(make_unique<SelectEventPoll>());
  90. e_->setOption(option_.get());
  91. e_->setRequestGroupMan
  92. (make_unique<RequestGroupMan>
  93. (std::vector<std::shared_ptr<RequestGroup>>{}, 1, option_.get()));
  94. }
  95. void testAuthorize();
  96. void testAddUri();
  97. void testAddUri_withoutUri();
  98. void testAddUri_notUri();
  99. void testAddUri_withBadOption();
  100. void testAddUri_withPosition();
  101. void testAddUri_withBadPosition();
  102. #ifdef ENABLE_BITTORRENT
  103. void testAddTorrent();
  104. void testAddTorrent_withoutTorrent();
  105. void testAddTorrent_notBase64Torrent();
  106. void testAddTorrent_withPosition();
  107. #endif // ENABLE_BITTORRENT
  108. #ifdef ENABLE_METALINK
  109. void testAddMetalink();
  110. void testAddMetalink_withoutMetalink();
  111. void testAddMetalink_notBase64Metalink();
  112. void testAddMetalink_withPosition();
  113. #endif // ENABLE_METALINK
  114. void testGetOption();
  115. void testChangeOption();
  116. void testChangeOption_withBadOption();
  117. void testChangeOption_withNotAllowedOption();
  118. void testChangeOption_withoutGid();
  119. void testChangeGlobalOption();
  120. void testChangeGlobalOption_withBadOption();
  121. void testChangeGlobalOption_withNotAllowedOption();
  122. void testTellStatus_withoutGid();
  123. void testTellWaiting();
  124. void testTellWaiting_fail();
  125. void testGetVersion();
  126. void testNoSuchMethod();
  127. void testGatherStoppedDownload();
  128. void testGatherProgressCommon();
  129. #ifdef ENABLE_BITTORRENT
  130. void testGatherBitTorrentMetadata();
  131. #endif // ENABLE_BITTORRENT
  132. void testChangePosition();
  133. void testChangePosition_fail();
  134. void testGetSessionInfo();
  135. void testChangeUri();
  136. void testChangeUri_fail();
  137. void testPause();
  138. void testSystemMulticall();
  139. void testSystemMulticall_fail();
  140. void testSystemListMethods();
  141. };
  142. CPPUNIT_TEST_SUITE_REGISTRATION(RpcMethodTest);
  143. namespace {
  144. std::string getString(const Dict* dict, const std::string& key)
  145. {
  146. return downcast<String>(dict->get(key))->s();
  147. }
  148. } // namespace
  149. namespace {
  150. RpcRequest createReq(std::string methodName)
  151. {
  152. return {std::move(methodName), List::g()};
  153. }
  154. } // namespace
  155. void RpcMethodTest::testAuthorize()
  156. {
  157. // Select RPC method which takes non-string parameter to make sure
  158. // that token: prefixed parameter is stripped before the call.
  159. TellActiveRpcMethod m;
  160. // no secret token set and no token: prefixed parameter is given
  161. {
  162. auto req = createReq(TellActiveRpcMethod::getMethodName());
  163. auto res = m.execute(std::move(req), e_.get());
  164. CPPUNIT_ASSERT_EQUAL(0, res.code);
  165. }
  166. // no secret token set and token: prefixed parameter is given
  167. {
  168. auto req = createReq(GetVersionRpcMethod::getMethodName());
  169. req.params->append("token:foo");
  170. auto res = m.execute(std::move(req), e_.get());
  171. CPPUNIT_ASSERT_EQUAL(0, res.code);
  172. }
  173. e_->getOption()->put(PREF_RPC_SECRET, "foo");
  174. // secret token set and no token: prefixed parameter is given
  175. {
  176. auto req = createReq(GetVersionRpcMethod::getMethodName());
  177. auto res = m.execute(std::move(req), e_.get());
  178. CPPUNIT_ASSERT_EQUAL(1, res.code);
  179. }
  180. // secret token set and token: prefixed parameter is given
  181. {
  182. auto req = createReq(GetVersionRpcMethod::getMethodName());
  183. req.params->append("token:foo");
  184. auto res = m.execute(std::move(req), e_.get());
  185. CPPUNIT_ASSERT_EQUAL(0, res.code);
  186. }
  187. // secret token set and bad token: prefixed parameter is given
  188. {
  189. auto req = createReq(GetVersionRpcMethod::getMethodName());
  190. req.params->append("token:foo2");
  191. auto res = m.execute(std::move(req), e_.get());
  192. CPPUNIT_ASSERT_EQUAL(1, res.code);
  193. }
  194. }
  195. void RpcMethodTest::testAddUri()
  196. {
  197. AddUriRpcMethod m;
  198. {
  199. auto req = createReq(AddUriRpcMethod::getMethodName());
  200. auto urisParam = List::g();
  201. urisParam->append("http://localhost/");
  202. req.params->append(std::move(urisParam));
  203. auto res = m.execute(std::move(req), e_.get());
  204. CPPUNIT_ASSERT_EQUAL(0, res.code);
  205. const RequestGroupList& rgs =
  206. e_->getRequestGroupMan()->getReservedGroups();
  207. CPPUNIT_ASSERT_EQUAL((size_t)1, rgs.size());
  208. CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/"),
  209. (*rgs.begin())->getDownloadContext()->
  210. getFirstFileEntry()->getRemainingUris().front());
  211. }
  212. {
  213. auto req = createReq(AddUriRpcMethod::getMethodName());
  214. auto urisParam = List::g();
  215. urisParam->append("http://localhost/");
  216. req.params->append(std::move(urisParam));
  217. // with options
  218. auto opt = Dict::g();
  219. opt->put(PREF_DIR->k, "/sink");
  220. req.params->append(std::move(opt));
  221. auto res = m.execute(std::move(req), e_.get());
  222. CPPUNIT_ASSERT_EQUAL(0, res.code);
  223. a2_gid_t gid;
  224. CPPUNIT_ASSERT_EQUAL(0, GroupId::toNumericId
  225. (gid, downcast<String>(res.param)->s().c_str()));
  226. CPPUNIT_ASSERT_EQUAL(std::string("/sink"),
  227. findReservedGroup(e_->getRequestGroupMan().get(),
  228. gid)->
  229. getOption()->get(PREF_DIR));
  230. }
  231. }
  232. void RpcMethodTest::testAddUri_withoutUri()
  233. {
  234. AddUriRpcMethod m;
  235. auto res = m.execute(createReq(AddUriRpcMethod::getMethodName()), e_.get());
  236. CPPUNIT_ASSERT_EQUAL(1, res.code);
  237. }
  238. void RpcMethodTest::testAddUri_notUri()
  239. {
  240. AddUriRpcMethod m;
  241. auto req = createReq(AddUriRpcMethod::getMethodName());
  242. auto urisParam = List::g();
  243. urisParam->append("not uri");
  244. req.params->append(std::move(urisParam));
  245. auto res = m.execute(std::move(req), e_.get());
  246. CPPUNIT_ASSERT_EQUAL(1, res.code);
  247. }
  248. void RpcMethodTest::testAddUri_withBadOption()
  249. {
  250. AddUriRpcMethod m;
  251. auto req = createReq(AddUriRpcMethod::getMethodName());
  252. auto urisParam = List::g();
  253. urisParam->append("http://localhost");
  254. req.params->append(std::move(urisParam));
  255. auto opt = Dict::g();
  256. opt->put(PREF_FILE_ALLOCATION->k, "badvalue");
  257. req.params->append(std::move(opt));
  258. auto res = m.execute(std::move(req), e_.get());
  259. CPPUNIT_ASSERT_EQUAL(1, res.code);
  260. }
  261. void RpcMethodTest::testAddUri_withPosition()
  262. {
  263. AddUriRpcMethod m;
  264. auto req1 = createReq(AddUriRpcMethod::getMethodName());
  265. auto urisParam1 = List::g();
  266. urisParam1->append("http://uri1");
  267. req1.params->append(std::move(urisParam1));
  268. auto res1 = m.execute(std::move(req1), e_.get());
  269. CPPUNIT_ASSERT_EQUAL(0, res1.code);
  270. auto req2 = createReq(AddUriRpcMethod::getMethodName());
  271. auto urisParam2 = List::g();
  272. urisParam2->append("http://uri2");
  273. req2.params->append(std::move(urisParam2));
  274. req2.params->append(Dict::g());
  275. req2.params->append(Integer::g(0));
  276. m.execute(std::move(req2), e_.get());
  277. std::string uri =
  278. getReservedGroup(e_->getRequestGroupMan().get(), 0)->
  279. getDownloadContext()->getFirstFileEntry()->getRemainingUris()[0];
  280. CPPUNIT_ASSERT_EQUAL(std::string("http://uri2"), uri);
  281. }
  282. void RpcMethodTest::testAddUri_withBadPosition()
  283. {
  284. AddUriRpcMethod m;
  285. auto req = createReq(AddUriRpcMethod::getMethodName());
  286. auto urisParam = List::g();
  287. urisParam->append("http://localhost/");
  288. req.params->append(std::move(urisParam));
  289. req.params->append(Dict::g());
  290. req.params->append(Integer::g(-1));
  291. auto res = m.execute(std::move(req), e_.get());
  292. CPPUNIT_ASSERT_EQUAL(1, res.code);
  293. }
  294. #ifdef ENABLE_BITTORRENT
  295. namespace {
  296. RpcRequest createAddTorrentReq()
  297. {
  298. auto req = createReq(AddTorrentRpcMethod::getMethodName());
  299. req.params->append(readFile(A2_TEST_DIR"/single.torrent"));
  300. auto uris = List::g();
  301. uris->append("http://localhost/aria2-0.8.2.tar.bz2");
  302. req.params->append(std::move(uris));
  303. return req;
  304. }
  305. } // namespace
  306. void RpcMethodTest::testAddTorrent()
  307. {
  308. File(e_->getOption()->get(PREF_DIR)+
  309. "/0a3893293e27ac0490424c06de4d09242215f0a6.torrent").remove();
  310. AddTorrentRpcMethod m;
  311. {
  312. // Saving upload metadata is disabled by option.
  313. auto res = m.execute(createAddTorrentReq(), e_.get());
  314. CPPUNIT_ASSERT
  315. (!File(e_->getOption()->get(PREF_DIR)+
  316. "/0a3893293e27ac0490424c06de4d09242215f0a6.torrent").exists());
  317. CPPUNIT_ASSERT_EQUAL(0, res.code);
  318. CPPUNIT_ASSERT_EQUAL(sizeof(a2_gid_t)*2,
  319. downcast<String>(res.param)->s().size());
  320. }
  321. e_->getOption()->put(PREF_RPC_SAVE_UPLOAD_METADATA, A2_V_TRUE);
  322. {
  323. auto res = m.execute(createAddTorrentReq(), e_.get());
  324. CPPUNIT_ASSERT
  325. (File(e_->getOption()->get(PREF_DIR)+
  326. "/0a3893293e27ac0490424c06de4d09242215f0a6.torrent").exists());
  327. CPPUNIT_ASSERT_EQUAL(0, res.code);
  328. a2_gid_t gid;
  329. CPPUNIT_ASSERT_EQUAL(0, GroupId::toNumericId
  330. (gid, downcast<String>(res.param)->s().c_str()));
  331. auto group = findReservedGroup(e_->getRequestGroupMan().get(), gid);
  332. CPPUNIT_ASSERT(group);
  333. CPPUNIT_ASSERT_EQUAL(e_->getOption()->get(PREF_DIR)+"/aria2-0.8.2.tar.bz2",
  334. group->getFirstFilePath());
  335. CPPUNIT_ASSERT_EQUAL((size_t)1,
  336. group->getDownloadContext()->getFirstFileEntry()->
  337. getRemainingUris().size());
  338. CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/aria2-0.8.2.tar.bz2"),
  339. group->getDownloadContext()->getFirstFileEntry()->
  340. getRemainingUris()[0]);
  341. }
  342. {
  343. auto req = createAddTorrentReq();
  344. // with options
  345. std::string dir = A2_TEST_OUT_DIR"/aria2_RpcMethodTest_testAddTorrent";
  346. File(dir).mkdirs();
  347. auto opt = Dict::g();
  348. opt->put(PREF_DIR->k, dir);
  349. File(dir+"/0a3893293e27ac0490424c06de4d09242215f0a6.torrent").remove();
  350. req.params->append(std::move(opt));
  351. auto res = m.execute(std::move(req), e_.get());
  352. CPPUNIT_ASSERT_EQUAL(0, res.code);
  353. a2_gid_t gid;
  354. CPPUNIT_ASSERT_EQUAL(0, GroupId::toNumericId
  355. (gid, downcast<String>(res.param)->s().c_str()));
  356. CPPUNIT_ASSERT_EQUAL
  357. (dir+"/aria2-0.8.2.tar.bz2",
  358. findReservedGroup(e_->getRequestGroupMan().get(), gid)
  359. ->getFirstFilePath());
  360. CPPUNIT_ASSERT
  361. (File(dir+"/0a3893293e27ac0490424c06de4d09242215f0a6.torrent").exists());
  362. }
  363. }
  364. void RpcMethodTest::testAddTorrent_withoutTorrent()
  365. {
  366. AddTorrentRpcMethod m;
  367. auto res = m.execute(createReq(AddTorrentRpcMethod::getMethodName()),
  368. e_.get());
  369. CPPUNIT_ASSERT_EQUAL(1, res.code);
  370. }
  371. void RpcMethodTest::testAddTorrent_notBase64Torrent()
  372. {
  373. AddTorrentRpcMethod m;
  374. auto req = createReq(AddTorrentRpcMethod::getMethodName());
  375. req.params->append("not torrent");
  376. auto res = m.execute(std::move(req), e_.get());
  377. CPPUNIT_ASSERT_EQUAL(1, res.code);
  378. }
  379. void RpcMethodTest::testAddTorrent_withPosition()
  380. {
  381. AddTorrentRpcMethod m;
  382. auto req1 = createReq(AddTorrentRpcMethod::getMethodName());
  383. req1.params->append(readFile(A2_TEST_DIR"/test.torrent"));
  384. req1.params->append(List::g());
  385. req1.params->append(Dict::g());
  386. auto res1 = m.execute(std::move(req1), e_.get());
  387. CPPUNIT_ASSERT_EQUAL(0, res1.code);
  388. auto req2 = createReq(AddTorrentRpcMethod::getMethodName());
  389. req2.params->append(readFile(A2_TEST_DIR"/single.torrent"));
  390. req2.params->append(List::g());
  391. req2.params->append(Dict::g());
  392. req2.params->append(Integer::g(0));
  393. m.execute(std::move(req2), e_.get());
  394. CPPUNIT_ASSERT_EQUAL((size_t)1,
  395. getReservedGroup(e_->getRequestGroupMan().get(), 0)->
  396. getDownloadContext()->getFileEntries().size());
  397. }
  398. #endif // ENABLE_BITTORRENT
  399. #ifdef ENABLE_METALINK
  400. namespace {
  401. RpcRequest createAddMetalinkReq()
  402. {
  403. auto req = createReq(AddMetalinkRpcMethod::getMethodName());
  404. req.params->append(readFile(A2_TEST_DIR"/2files.metalink"));
  405. return req;
  406. }
  407. } // namespace
  408. void RpcMethodTest::testAddMetalink()
  409. {
  410. File(e_->getOption()->get(PREF_DIR)+
  411. "/c908634fbc257fd56f0114912c2772aeeb4064f4.meta4").remove();
  412. AddMetalinkRpcMethod m;
  413. {
  414. // Saving upload metadata is disabled by option.
  415. auto res = m.execute(createAddMetalinkReq(), e_.get());
  416. CPPUNIT_ASSERT_EQUAL(0, res.code);
  417. const List* resParams = downcast<List>(res.param);
  418. CPPUNIT_ASSERT_EQUAL((size_t)2, resParams->size());
  419. a2_gid_t gid1, gid2;
  420. CPPUNIT_ASSERT_EQUAL
  421. (0, GroupId::toNumericId
  422. (gid1, downcast<String>(resParams->get(0))->s().c_str()));
  423. CPPUNIT_ASSERT_EQUAL
  424. (0, GroupId::toNumericId
  425. (gid2, downcast<String>(resParams->get(1))->s().c_str()));
  426. CPPUNIT_ASSERT
  427. (!File(e_->getOption()->get(PREF_DIR)+
  428. "/c908634fbc257fd56f0114912c2772aeeb4064f4.meta4").exists());
  429. }
  430. e_->getOption()->put(PREF_RPC_SAVE_UPLOAD_METADATA, A2_V_TRUE);
  431. {
  432. auto res = m.execute(createAddMetalinkReq(), e_.get());
  433. CPPUNIT_ASSERT_EQUAL(0, res.code);
  434. const List* resParams = downcast<List>(res.param);
  435. CPPUNIT_ASSERT_EQUAL((size_t)2, resParams->size());
  436. a2_gid_t gid3, gid4;
  437. CPPUNIT_ASSERT_EQUAL
  438. (0, GroupId::toNumericId
  439. (gid3, downcast<String>(resParams->get(0))->s().c_str()));
  440. CPPUNIT_ASSERT_EQUAL
  441. (0, GroupId::toNumericId
  442. (gid4, downcast<String>(resParams->get(1))->s().c_str()));
  443. CPPUNIT_ASSERT
  444. (File(e_->getOption()->get(PREF_DIR)+
  445. "/c908634fbc257fd56f0114912c2772aeeb4064f4.meta4").exists());
  446. auto tar = findReservedGroup(e_->getRequestGroupMan().get(), gid3);
  447. CPPUNIT_ASSERT(tar);
  448. CPPUNIT_ASSERT_EQUAL(e_->getOption()->get(PREF_DIR)+"/aria2-5.0.0.tar.bz2",
  449. tar->getFirstFilePath());
  450. auto deb = findReservedGroup(e_->getRequestGroupMan().get(), gid4);
  451. CPPUNIT_ASSERT(deb);
  452. CPPUNIT_ASSERT_EQUAL(e_->getOption()->get(PREF_DIR)+"/aria2-5.0.0.deb",
  453. deb->getFirstFilePath());
  454. }
  455. {
  456. auto req = createAddMetalinkReq();
  457. // with options
  458. std::string dir = A2_TEST_OUT_DIR"/aria2_RpcMethodTest_testAddMetalink";
  459. File(dir).mkdirs();
  460. auto opt = Dict::g();
  461. opt->put(PREF_DIR->k, dir);
  462. File(dir+"/c908634fbc257fd56f0114912c2772aeeb4064f4.meta4").remove();
  463. req.params->append(std::move(opt));
  464. auto res = m.execute(std::move(req), e_.get());
  465. CPPUNIT_ASSERT_EQUAL(0, res.code);
  466. const List* resParams = downcast<List>(res.param);
  467. CPPUNIT_ASSERT_EQUAL((size_t)2, resParams->size());
  468. a2_gid_t gid5;
  469. CPPUNIT_ASSERT_EQUAL
  470. (0, GroupId::toNumericId
  471. (gid5, downcast<String>(resParams->get(0))->s().c_str()));
  472. CPPUNIT_ASSERT_EQUAL(dir+"/aria2-5.0.0.tar.bz2",
  473. findReservedGroup
  474. (e_->getRequestGroupMan().get(), gid5)->
  475. getFirstFilePath());
  476. CPPUNIT_ASSERT
  477. (File(dir+"/c908634fbc257fd56f0114912c2772aeeb4064f4.meta4").exists());
  478. }
  479. }
  480. void RpcMethodTest::testAddMetalink_withoutMetalink()
  481. {
  482. AddMetalinkRpcMethod m;
  483. auto res = m.execute(createReq(AddMetalinkRpcMethod::getMethodName()),
  484. e_.get());
  485. CPPUNIT_ASSERT_EQUAL(1, res.code);
  486. }
  487. void RpcMethodTest::testAddMetalink_notBase64Metalink()
  488. {
  489. AddMetalinkRpcMethod m;
  490. auto req = createReq(AddMetalinkRpcMethod::getMethodName());
  491. req.params->append("not metalink");
  492. auto res = m.execute(std::move(req), e_.get());
  493. CPPUNIT_ASSERT_EQUAL(1, res.code);
  494. }
  495. void RpcMethodTest::testAddMetalink_withPosition()
  496. {
  497. AddUriRpcMethod m1;
  498. auto req1 = createReq(AddUriRpcMethod::getMethodName());
  499. auto urisParam1 = List::g();
  500. urisParam1->append("http://uri");
  501. req1.params->append(std::move(urisParam1));
  502. auto res1 = m1.execute(std::move(req1), e_.get());
  503. CPPUNIT_ASSERT_EQUAL(0, res1.code);
  504. AddMetalinkRpcMethod m2;
  505. auto req2 = createReq(AddMetalinkRpcMethod::getMethodName());
  506. req2.params->append(readFile(A2_TEST_DIR"/2files.metalink"));
  507. req2.params->append(Dict::g());
  508. req2.params->append(Integer::g(0));
  509. auto res2 = m2.execute(std::move(req2), e_.get());
  510. CPPUNIT_ASSERT_EQUAL(0, res2.code);
  511. CPPUNIT_ASSERT_EQUAL(e_->getOption()->get(PREF_DIR)+"/aria2-5.0.0.tar.bz2",
  512. getReservedGroup(e_->getRequestGroupMan().get(), 0)->
  513. getFirstFilePath());
  514. }
  515. #endif // ENABLE_METALINK
  516. void RpcMethodTest::testGetOption()
  517. {
  518. auto group = std::make_shared<RequestGroup>(GroupId::create(), option_);
  519. group->getOption()->put(PREF_DIR, "alpha");
  520. e_->getRequestGroupMan()->addReservedGroup(group);
  521. auto dr = createDownloadResult(error_code::FINISHED, "http://host/fin");
  522. dr->option->put(PREF_DIR, "bravo");
  523. e_->getRequestGroupMan()->addDownloadResult(dr);
  524. GetOptionRpcMethod m;
  525. auto req = createReq(GetOptionRpcMethod::getMethodName());
  526. req.params->append(GroupId::toHex(group->getGID()));
  527. auto res = m.execute(std::move(req), e_.get());
  528. CPPUNIT_ASSERT_EQUAL(0, res.code);
  529. const Dict* resopt = downcast<Dict>(res.param);
  530. CPPUNIT_ASSERT_EQUAL(std::string("alpha"),
  531. downcast<String>(resopt->get(PREF_DIR->k))->s());
  532. req = createReq(GetOptionRpcMethod::getMethodName());
  533. req.params->append(dr->gid->toHex());
  534. res = m.execute(std::move(req), e_.get());
  535. CPPUNIT_ASSERT_EQUAL(0, res.code);
  536. resopt = downcast<Dict>(res.param);
  537. CPPUNIT_ASSERT_EQUAL(std::string("bravo"),
  538. downcast<String>(resopt->get(PREF_DIR->k))->s());
  539. // Invalid GID
  540. req = createReq(GetOptionRpcMethod::getMethodName());
  541. req.params->append(GroupId::create()->toHex());
  542. res = m.execute(std::move(req), e_.get());
  543. CPPUNIT_ASSERT_EQUAL(1, res.code);
  544. }
  545. void RpcMethodTest::testChangeOption()
  546. {
  547. auto group = std::make_shared<RequestGroup>(GroupId::create(), option_);
  548. e_->getRequestGroupMan()->addReservedGroup(group);
  549. ChangeOptionRpcMethod m;
  550. auto req = createReq(ChangeOptionRpcMethod::getMethodName());
  551. req.params->append(GroupId::toHex(group->getGID()));
  552. auto opt = Dict::g();
  553. opt->put(PREF_MAX_DOWNLOAD_LIMIT->k, "100K");
  554. #ifdef ENABLE_BITTORRENT
  555. opt->put(PREF_BT_MAX_PEERS->k, "100");
  556. opt->put(PREF_BT_REQUEST_PEER_SPEED_LIMIT->k, "300K");
  557. opt->put(PREF_MAX_UPLOAD_LIMIT->k, "50K");
  558. {
  559. auto btObject = make_unique<BtObject>();
  560. btObject->btRuntime = std::make_shared<BtRuntime>();
  561. e_->getBtRegistry()->put(group->getGID(), std::move(btObject));
  562. }
  563. #endif // ENABLE_BITTORRENT
  564. req.params->append(std::move(opt));
  565. auto res = m.execute(std::move(req), e_.get());
  566. auto option = group->getOption();
  567. CPPUNIT_ASSERT_EQUAL(0, res.code);
  568. CPPUNIT_ASSERT_EQUAL((int)100_k, group->getMaxDownloadSpeedLimit());
  569. CPPUNIT_ASSERT_EQUAL(std::string("102400"),
  570. option->get(PREF_MAX_DOWNLOAD_LIMIT));
  571. #ifdef ENABLE_BITTORRENT
  572. CPPUNIT_ASSERT_EQUAL(std::string("307200"),
  573. option->get(PREF_BT_REQUEST_PEER_SPEED_LIMIT));
  574. CPPUNIT_ASSERT_EQUAL(std::string("100"), option->get(PREF_BT_MAX_PEERS));
  575. CPPUNIT_ASSERT_EQUAL(100,
  576. e_->getBtRegistry()->get(group->getGID())
  577. ->btRuntime->getMaxPeers());
  578. CPPUNIT_ASSERT_EQUAL((int)50_k, group->getMaxUploadSpeedLimit());
  579. CPPUNIT_ASSERT_EQUAL(std::string("51200"),
  580. option->get(PREF_MAX_UPLOAD_LIMIT));
  581. #endif // ENABLE_BITTORRENT
  582. }
  583. void RpcMethodTest::testChangeOption_withBadOption()
  584. {
  585. auto group = std::make_shared<RequestGroup>(GroupId::create(), option_);
  586. e_->getRequestGroupMan()->addReservedGroup(group);
  587. ChangeOptionRpcMethod m;
  588. auto req = createReq(ChangeOptionRpcMethod::getMethodName());
  589. req.params->append(GroupId::toHex(group->getGID()));
  590. auto opt = Dict::g();
  591. opt->put(PREF_MAX_DOWNLOAD_LIMIT->k, "badvalue");
  592. req.params->append(std::move(opt));
  593. auto res = m.execute(std::move(req), e_.get());
  594. CPPUNIT_ASSERT_EQUAL(1, res.code);
  595. }
  596. void RpcMethodTest::testChangeOption_withNotAllowedOption()
  597. {
  598. auto group = std::make_shared<RequestGroup>(GroupId::create(), option_);
  599. e_->getRequestGroupMan()->addReservedGroup(group);
  600. ChangeOptionRpcMethod m;
  601. auto req = createReq(ChangeOptionRpcMethod::getMethodName());
  602. req.params->append(GroupId::toHex(group->getGID()));
  603. auto opt = Dict::g();
  604. opt->put(PREF_MAX_OVERALL_DOWNLOAD_LIMIT->k, "100K");
  605. req.params->append(std::move(opt));
  606. auto res = m.execute(std::move(req), e_.get());
  607. // The unacceptable options are just ignored.
  608. CPPUNIT_ASSERT_EQUAL(0, res.code);
  609. }
  610. void RpcMethodTest::testChangeOption_withoutGid()
  611. {
  612. ChangeOptionRpcMethod m;
  613. auto res = m.execute
  614. (createReq(ChangeOptionRpcMethod::getMethodName()), e_.get());
  615. CPPUNIT_ASSERT_EQUAL(1, res.code);
  616. }
  617. void RpcMethodTest::testChangeGlobalOption()
  618. {
  619. ChangeGlobalOptionRpcMethod m;
  620. auto req = createReq(ChangeGlobalOptionRpcMethod::getMethodName());
  621. auto opt = Dict::g();
  622. opt->put(PREF_MAX_OVERALL_DOWNLOAD_LIMIT->k, "100K");
  623. #ifdef ENABLE_BITTORRENT
  624. opt->put(PREF_MAX_OVERALL_UPLOAD_LIMIT->k, "50K");
  625. #endif // ENABLE_BITTORRENT
  626. req.params->append(std::move(opt));
  627. auto res = m.execute(std::move(req), e_.get());
  628. CPPUNIT_ASSERT_EQUAL(0, res.code);
  629. CPPUNIT_ASSERT_EQUAL(
  630. (int)100_k, e_->getRequestGroupMan()->getMaxOverallDownloadSpeedLimit());
  631. CPPUNIT_ASSERT_EQUAL(std::string("102400"),
  632. e_->getOption()->get(PREF_MAX_OVERALL_DOWNLOAD_LIMIT));
  633. #ifdef ENABLE_BITTORRENT
  634. CPPUNIT_ASSERT_EQUAL(
  635. (int)50_k, e_->getRequestGroupMan()->getMaxOverallUploadSpeedLimit());
  636. CPPUNIT_ASSERT_EQUAL(std::string("51200"),
  637. e_->getOption()->get(PREF_MAX_OVERALL_UPLOAD_LIMIT));
  638. #endif // ENABLE_BITTORRENT
  639. }
  640. void RpcMethodTest::testChangeGlobalOption_withBadOption()
  641. {
  642. ChangeGlobalOptionRpcMethod m;
  643. auto req = createReq(ChangeGlobalOptionRpcMethod::getMethodName());
  644. auto opt = Dict::g();
  645. opt->put(PREF_MAX_OVERALL_DOWNLOAD_LIMIT->k, "badvalue");
  646. req.params->append(std::move(opt));
  647. auto res = m.execute(std::move(req), e_.get());
  648. CPPUNIT_ASSERT_EQUAL(1, res.code);
  649. }
  650. void RpcMethodTest::testChangeGlobalOption_withNotAllowedOption()
  651. {
  652. ChangeGlobalOptionRpcMethod m;
  653. auto req = createReq(ChangeGlobalOptionRpcMethod::getMethodName());
  654. auto opt = Dict::g();
  655. opt->put(PREF_ENABLE_RPC->k, "100K");
  656. req.params->append(std::move(opt));
  657. auto res = m.execute(std::move(req), e_.get());
  658. // The unacceptable options are just ignored.
  659. CPPUNIT_ASSERT_EQUAL(0, res.code);
  660. }
  661. void RpcMethodTest::testNoSuchMethod()
  662. {
  663. NoSuchMethodRpcMethod m;
  664. auto res = m.execute(createReq("make.hamburger"), e_.get());
  665. CPPUNIT_ASSERT_EQUAL(1, res.code);
  666. CPPUNIT_ASSERT_EQUAL(std::string("No such method: make.hamburger"),
  667. getString(downcast<Dict>(res.param), "faultString"));
  668. }
  669. void RpcMethodTest::testTellStatus_withoutGid()
  670. {
  671. TellStatusRpcMethod m;
  672. auto res = m.execute
  673. (createReq(TellStatusRpcMethod::getMethodName()), e_.get());
  674. CPPUNIT_ASSERT_EQUAL(1, res.code);
  675. }
  676. namespace {
  677. void addUri(const std::string& uri, const std::shared_ptr<DownloadEngine>& e)
  678. {
  679. AddUriRpcMethod m;
  680. auto req = createReq(AddUriRpcMethod::getMethodName());
  681. auto urisParam = List::g();
  682. urisParam->append(uri);
  683. req.params->append(std::move(urisParam));
  684. CPPUNIT_ASSERT_EQUAL(0, m.execute(std::move(req), e.get()).code);
  685. }
  686. } // namespace
  687. #ifdef ENABLE_BITTORRENT
  688. namespace {
  689. void addTorrent
  690. (const std::string& torrentFile, const std::shared_ptr<DownloadEngine>& e)
  691. {
  692. AddTorrentRpcMethod m;
  693. auto req = createReq(AddTorrentRpcMethod::getMethodName());
  694. req.params->append(readFile(torrentFile));
  695. auto res = m.execute(std::move(req), e.get());
  696. }
  697. } // namespace
  698. #endif // ENABLE_BITTORRENT
  699. void RpcMethodTest::testTellWaiting()
  700. {
  701. addUri("http://1/", e_);
  702. addUri("http://2/", e_);
  703. addUri("http://3/", e_);
  704. #ifdef ENABLE_BITTORRENT
  705. addTorrent(A2_TEST_DIR"/single.torrent", e_);
  706. #else // !ENABLE_BITTORRENT
  707. addUri("http://4/", e_);
  708. #endif // !ENABLE_BITTORRENT
  709. auto& rgman = e_->getRequestGroupMan();
  710. TellWaitingRpcMethod m;
  711. auto req = createReq(TellWaitingRpcMethod::getMethodName());
  712. req.params->append(Integer::g(1));
  713. req.params->append(Integer::g(2));
  714. auto res = m.execute(std::move(req), e_.get());
  715. CPPUNIT_ASSERT_EQUAL(0, res.code);
  716. const List* resParams = downcast<List>(res.param);
  717. CPPUNIT_ASSERT_EQUAL((size_t)2, resParams->size());
  718. CPPUNIT_ASSERT_EQUAL(GroupId::toHex(getReservedGroup(rgman.get(), 1)
  719. ->getGID()),
  720. getString(downcast<Dict>(resParams->get(0)), "gid"));
  721. CPPUNIT_ASSERT_EQUAL(GroupId::toHex(getReservedGroup(rgman.get(), 2)
  722. ->getGID()),
  723. getString(downcast<Dict>(resParams->get(1)), "gid"));
  724. // waiting.size() == offset+num
  725. req = createReq(TellWaitingRpcMethod::getMethodName());
  726. req.params->append(Integer::g(1));
  727. req.params->append(Integer::g(3));
  728. res = m.execute(std::move(req), e_.get());
  729. CPPUNIT_ASSERT_EQUAL(0, res.code);
  730. resParams = downcast<List>(res.param);
  731. CPPUNIT_ASSERT_EQUAL((size_t)3, resParams->size());
  732. // waiting.size() < offset+num
  733. req = createReq(TellWaitingRpcMethod::getMethodName());
  734. req.params->append(Integer::g(1));
  735. req.params->append(Integer::g(4));
  736. res = m.execute(std::move(req), e_.get());
  737. CPPUNIT_ASSERT_EQUAL(0, res.code);
  738. resParams = downcast<List>(res.param);
  739. CPPUNIT_ASSERT_EQUAL((size_t)3, resParams->size());
  740. // offset = INT32_MAX
  741. req = createReq(TellWaitingRpcMethod::getMethodName());
  742. req.params->append(Integer::g(INT32_MAX));
  743. req.params->append(Integer::g(1));
  744. res = m.execute(std::move(req), e_.get());
  745. CPPUNIT_ASSERT_EQUAL(0, res.code);
  746. resParams = downcast<List>(res.param);
  747. CPPUNIT_ASSERT_EQUAL((size_t)0, resParams->size());
  748. // num = INT32_MAX
  749. req = createReq(TellWaitingRpcMethod::getMethodName());
  750. req.params->append(Integer::g(1));
  751. req.params->append(Integer::g(INT32_MAX));
  752. res = m.execute(std::move(req), e_.get());
  753. CPPUNIT_ASSERT_EQUAL(0, res.code);
  754. resParams = downcast<List>(res.param);
  755. CPPUNIT_ASSERT_EQUAL((size_t)3, resParams->size());
  756. // offset=INT32_MAX and num = INT32_MAX
  757. req = createReq(TellWaitingRpcMethod::getMethodName());
  758. req.params->append(Integer::g(INT32_MAX));
  759. req.params->append(Integer::g(INT32_MAX));
  760. res = m.execute(std::move(req), e_.get());
  761. CPPUNIT_ASSERT_EQUAL(0, res.code);
  762. resParams = downcast<List>(res.param);
  763. CPPUNIT_ASSERT_EQUAL((size_t)0, resParams->size());
  764. // offset=INT32_MIN and num = INT32_MAX
  765. req = createReq(TellWaitingRpcMethod::getMethodName());
  766. req.params->append(Integer::g(INT32_MIN));
  767. req.params->append(Integer::g(INT32_MAX));
  768. res = m.execute(std::move(req), e_.get());
  769. CPPUNIT_ASSERT_EQUAL(0, res.code);
  770. resParams = downcast<List>(res.param);
  771. CPPUNIT_ASSERT_EQUAL((size_t)0, resParams->size());
  772. // negative offset
  773. req = createReq(TellWaitingRpcMethod::getMethodName());
  774. req.params->append(Integer::g(-1));
  775. req.params->append(Integer::g(2));
  776. res = m.execute(std::move(req), e_.get());
  777. CPPUNIT_ASSERT_EQUAL(0, res.code);
  778. resParams = downcast<List>(res.param);
  779. CPPUNIT_ASSERT_EQUAL((size_t)2, resParams->size());
  780. CPPUNIT_ASSERT_EQUAL(GroupId::toHex(getReservedGroup(rgman.get(),
  781. 3)->getGID()),
  782. getString(downcast<Dict>(resParams->get(0)), "gid"));
  783. CPPUNIT_ASSERT_EQUAL(GroupId::toHex(getReservedGroup(rgman.get(),
  784. 2)->getGID()),
  785. getString(downcast<Dict>(resParams->get(1)), "gid"));
  786. // negative offset and size < num
  787. req = RpcRequest(TellWaitingRpcMethod::getMethodName(), List::g());
  788. req.params->append(Integer::g(-1));
  789. req.params->append(Integer::g(100));
  790. res = m.execute(std::move(req), e_.get());
  791. CPPUNIT_ASSERT_EQUAL(0, res.code);
  792. resParams = downcast<List>(res.param);
  793. CPPUNIT_ASSERT_EQUAL((size_t)4, resParams->size());
  794. // nagative offset and normalized offset < 0
  795. req = RpcRequest(TellWaitingRpcMethod::getMethodName(), List::g());
  796. req.params->append(Integer::g(-5));
  797. req.params->append(Integer::g(100));
  798. res = m.execute(std::move(req), e_.get());
  799. CPPUNIT_ASSERT_EQUAL(0, res.code);
  800. resParams = downcast<List>(res.param);
  801. CPPUNIT_ASSERT_EQUAL((size_t)0, resParams->size());
  802. // nagative offset and normalized offset == 0
  803. req = RpcRequest(TellWaitingRpcMethod::getMethodName(), List::g());
  804. req.params->append(Integer::g(-4));
  805. req.params->append(Integer::g(100));
  806. res = m.execute(std::move(req), e_.get());
  807. CPPUNIT_ASSERT_EQUAL(0, res.code);
  808. resParams = downcast<List>(res.param);
  809. CPPUNIT_ASSERT_EQUAL((size_t)1, resParams->size());
  810. }
  811. void RpcMethodTest::testTellWaiting_fail()
  812. {
  813. TellWaitingRpcMethod m;
  814. auto res = m.execute(createReq(TellWaitingRpcMethod::getMethodName()),
  815. e_.get());
  816. CPPUNIT_ASSERT_EQUAL(1, res.code);
  817. }
  818. void RpcMethodTest::testGetVersion()
  819. {
  820. GetVersionRpcMethod m;
  821. auto res = m.execute(createReq(GetVersionRpcMethod::getMethodName()),
  822. e_.get());
  823. CPPUNIT_ASSERT_EQUAL(0, res.code);
  824. const Dict* resParams = downcast<Dict>(res.param);
  825. CPPUNIT_ASSERT_EQUAL(std::string(PACKAGE_VERSION),
  826. getString(resParams, "version"));
  827. const List* featureList = downcast<List>(resParams->get("enabledFeatures"));
  828. std::string features;
  829. for(auto i = featureList->begin(); i != featureList->end(); ++i) {
  830. const String* s = downcast<String>(*i);
  831. features += s->s();
  832. features += ", ";
  833. }
  834. CPPUNIT_ASSERT_EQUAL(featureSummary()+", ", features);
  835. }
  836. void RpcMethodTest::testGatherStoppedDownload()
  837. {
  838. std::vector<std::shared_ptr<FileEntry>> fileEntries;
  839. std::vector<a2_gid_t> followedBy;
  840. followedBy.push_back(3);
  841. followedBy.push_back(4);
  842. auto d = std::make_shared<DownloadResult>();
  843. d->gid = GroupId::create();
  844. d->fileEntries = fileEntries;
  845. d->inMemoryDownload = false;
  846. d->sessionDownloadLength = UINT64_MAX;
  847. d->sessionTime = 1_s;
  848. d->result = error_code::FINISHED;
  849. d->followedBy = followedBy;
  850. d->belongsTo = 2;
  851. auto entry = Dict::g();
  852. std::vector<std::string> keys;
  853. gatherStoppedDownload(entry.get(), d, keys);
  854. const List* followedByRes = downcast<List>(entry->get("followedBy"));
  855. CPPUNIT_ASSERT_EQUAL(GroupId::toHex(3),
  856. downcast<String>(followedByRes->get(0))->s());
  857. CPPUNIT_ASSERT_EQUAL(GroupId::toHex(4),
  858. downcast<String>(followedByRes->get(1))->s());
  859. CPPUNIT_ASSERT_EQUAL(GroupId::toHex(2),
  860. downcast<String>(entry->get("belongsTo"))->s());
  861. keys.push_back("gid");
  862. entry = Dict::g();
  863. gatherStoppedDownload(entry.get(), d, keys);
  864. CPPUNIT_ASSERT_EQUAL((size_t)1, entry->size());
  865. CPPUNIT_ASSERT(entry->containsKey("gid"));
  866. }
  867. void RpcMethodTest::testGatherProgressCommon()
  868. {
  869. auto dctx = std::make_shared<DownloadContext>(0, 0,"aria2.tar.bz2");
  870. std::string uris[] = { "http://localhost/aria2.tar.bz2" };
  871. dctx->getFirstFileEntry()->addUris(std::begin(uris), std::end(uris));
  872. auto group = std::make_shared<RequestGroup>(GroupId::create(),
  873. util::copy(option_));
  874. group->setDownloadContext(dctx);
  875. std::vector<std::shared_ptr<RequestGroup>> followedBy;
  876. for(int i = 0; i < 2; ++i) {
  877. followedBy.push_back(std::make_shared<RequestGroup>(GroupId::create(),
  878. util::copy(option_)));
  879. }
  880. group->followedBy(followedBy.begin(), followedBy.end());
  881. auto parent = GroupId::create();
  882. group->belongsTo(parent->getNumericId());
  883. auto entry = Dict::g();
  884. std::vector<std::string> keys;
  885. gatherProgressCommon(entry.get(), group, keys);
  886. const List* followedByRes = downcast<List>(entry->get("followedBy"));
  887. CPPUNIT_ASSERT_EQUAL(GroupId::toHex(followedBy[0]->getGID()),
  888. downcast<String>(followedByRes->get(0))->s());
  889. CPPUNIT_ASSERT_EQUAL(GroupId::toHex(followedBy[1]->getGID()),
  890. downcast<String>(followedByRes->get(1))->s());
  891. CPPUNIT_ASSERT_EQUAL(parent->toHex(),
  892. downcast<String>(entry->get("belongsTo"))->s());
  893. const List* files = downcast<List>(entry->get("files"));
  894. CPPUNIT_ASSERT_EQUAL((size_t)1, files->size());
  895. const Dict* file = downcast<Dict>(files->get(0));
  896. CPPUNIT_ASSERT_EQUAL(std::string("aria2.tar.bz2"),
  897. downcast<String>(file->get("path"))->s());
  898. CPPUNIT_ASSERT_EQUAL(uris[0],
  899. downcast<String>
  900. (downcast<Dict>
  901. (downcast<List>(file->get("uris"))->get(0))
  902. ->get("uri"))
  903. ->s());
  904. CPPUNIT_ASSERT_EQUAL(e_->getOption()->get(PREF_DIR),
  905. downcast<String>(entry->get("dir"))->s());
  906. keys.push_back("gid");
  907. entry = Dict::g();
  908. gatherProgressCommon(entry.get(), group, keys);
  909. CPPUNIT_ASSERT_EQUAL((size_t)1, entry->size());
  910. CPPUNIT_ASSERT(entry->containsKey("gid"));
  911. }
  912. #ifdef ENABLE_BITTORRENT
  913. void RpcMethodTest::testGatherBitTorrentMetadata()
  914. {
  915. auto option = std::make_shared<Option>();
  916. option->put(PREF_DIR, ".");
  917. auto dctx = std::make_shared<DownloadContext>();
  918. bittorrent::load(A2_TEST_DIR"/test.torrent", dctx, option);
  919. auto btDict = Dict::g();
  920. gatherBitTorrentMetadata(btDict.get(), bittorrent::getTorrentAttrs(dctx));
  921. CPPUNIT_ASSERT_EQUAL(std::string("REDNOAH.COM RULES"),
  922. downcast<String>(btDict->get("comment"))->s());
  923. CPPUNIT_ASSERT_EQUAL((int64_t)1123456789,
  924. downcast<Integer>(btDict->get("creationDate"))->i());
  925. CPPUNIT_ASSERT_EQUAL(std::string("multi"),
  926. downcast<String>(btDict->get("mode"))->s());
  927. CPPUNIT_ASSERT_EQUAL(std::string("aria2-test"),
  928. downcast<String>
  929. (downcast<Dict>
  930. (btDict->get("info"))
  931. ->get("name"))
  932. ->s());
  933. const List* announceList = downcast<List>(btDict->get("announceList"));
  934. CPPUNIT_ASSERT_EQUAL((size_t)3, announceList->size());
  935. CPPUNIT_ASSERT_EQUAL(std::string("http://tracker1"),
  936. downcast<String>(downcast<List>(announceList->get(0))->get(0))->s());
  937. CPPUNIT_ASSERT_EQUAL(std::string("http://tracker2"),
  938. downcast<String>(downcast<List>(announceList->get(1))->get(0))->s());
  939. CPPUNIT_ASSERT_EQUAL(std::string("http://tracker3"),
  940. downcast<String>(downcast<List>(announceList->get(2))->get(0))->s());
  941. // Remove some keys
  942. auto modBtAttrs = bittorrent::getTorrentAttrs(dctx);
  943. modBtAttrs->comment.clear();
  944. modBtAttrs->creationDate = 0;
  945. modBtAttrs->mode = BT_FILE_MODE_NONE;
  946. modBtAttrs->metadata.clear();
  947. btDict = Dict::g();
  948. gatherBitTorrentMetadata(btDict.get(), modBtAttrs);
  949. CPPUNIT_ASSERT(!btDict->containsKey("comment"));
  950. CPPUNIT_ASSERT(!btDict->containsKey("creationDate"));
  951. CPPUNIT_ASSERT(!btDict->containsKey("mode"));
  952. CPPUNIT_ASSERT(!btDict->containsKey("info"));
  953. CPPUNIT_ASSERT(btDict->containsKey("announceList"));
  954. }
  955. #endif // ENABLE_BITTORRENT
  956. void RpcMethodTest::testChangePosition()
  957. {
  958. e_->getRequestGroupMan()->addReservedGroup
  959. (std::make_shared<RequestGroup>(GroupId::create(), util::copy(option_)));
  960. e_->getRequestGroupMan()->addReservedGroup
  961. (std::make_shared<RequestGroup>(GroupId::create(), util::copy(option_)));
  962. a2_gid_t gid = getReservedGroup(e_->getRequestGroupMan().get(), 0)->getGID();
  963. ChangePositionRpcMethod m;
  964. auto req = createReq(ChangePositionRpcMethod::getMethodName());
  965. req.params->append(GroupId::toHex(gid));
  966. req.params->append(Integer::g(1));
  967. req.params->append("POS_SET");
  968. auto res = m.execute(std::move(req), e_.get());
  969. CPPUNIT_ASSERT_EQUAL(0, res.code);
  970. CPPUNIT_ASSERT_EQUAL((int64_t)1, downcast<Integer>(res.param)->i());
  971. CPPUNIT_ASSERT_EQUAL
  972. (gid, getReservedGroup(e_->getRequestGroupMan().get(), 1)->getGID());
  973. }
  974. void RpcMethodTest::testChangePosition_fail()
  975. {
  976. ChangePositionRpcMethod m;
  977. auto res = m.execute
  978. (createReq(ChangePositionRpcMethod::getMethodName()), e_.get());
  979. CPPUNIT_ASSERT_EQUAL(1, res.code);
  980. auto req = createReq(ChangePositionRpcMethod::getMethodName());
  981. req.params->append("1");
  982. req.params->append(Integer::g(2));
  983. req.params->append("bad keyword");
  984. res = m.execute(std::move(req), e_.get());
  985. CPPUNIT_ASSERT_EQUAL(1, res.code);
  986. }
  987. namespace {
  988. RpcRequest createChangeUriReq(a2_gid_t gid, size_t fileIndex)
  989. {
  990. auto req = createReq(ChangeUriRpcMethod::getMethodName());
  991. req.params->append(GroupId::toHex(gid)); // GID
  992. req.params->append(Integer::g(fileIndex)); // index of FileEntry
  993. auto removeuris = List::g();
  994. removeuris->append("http://example.org/mustremove1");
  995. removeuris->append("http://example.org/mustremove2");
  996. removeuris->append("http://example.org/notexist");
  997. req.params->append(std::move(removeuris));
  998. return req;
  999. }
  1000. } // namespace
  1001. void RpcMethodTest::testChangeUri()
  1002. {
  1003. std::shared_ptr<FileEntry> files[3];
  1004. for(int i = 0; i < 3; ++i) {
  1005. files[i].reset(new FileEntry());
  1006. }
  1007. files[1]->addUri("http://example.org/aria2.tar.bz2");
  1008. files[1]->addUri("http://example.org/mustremove1");
  1009. files[1]->addUri("http://example.org/mustremove2");
  1010. auto dctx = std::make_shared<DownloadContext>();
  1011. dctx->setFileEntries(&files[0], &files[3]);
  1012. auto group = std::make_shared<RequestGroup>(GroupId::create(), option_);
  1013. group->setDownloadContext(dctx);
  1014. e_->getRequestGroupMan()->addReservedGroup(group);
  1015. ChangeUriRpcMethod m;
  1016. auto req = createChangeUriReq(group->getGID(), 2);
  1017. auto adduris = List::g();
  1018. adduris->append("http://example.org/added1");
  1019. adduris->append("http://example.org/added2");
  1020. adduris->append("baduri");
  1021. adduris->append("http://example.org/added3");
  1022. req.params->append(std::move(adduris));
  1023. auto res = m.execute(std::move(req), e_.get());
  1024. CPPUNIT_ASSERT_EQUAL(0, res.code);
  1025. CPPUNIT_ASSERT_EQUAL((int64_t)2, downcast<Integer>(downcast<List>(res.param)->get(0))->i());
  1026. CPPUNIT_ASSERT_EQUAL((int64_t)3, downcast<Integer>(downcast<List>(res.param)->get(1))->i());
  1027. CPPUNIT_ASSERT_EQUAL((size_t)0, files[0]->getRemainingUris().size());
  1028. CPPUNIT_ASSERT_EQUAL((size_t)0, files[2]->getRemainingUris().size());
  1029. std::deque<std::string> uris = files[1]->getRemainingUris();
  1030. CPPUNIT_ASSERT_EQUAL((size_t)4, uris.size());
  1031. CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/aria2.tar.bz2"),uris[0]);
  1032. CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/added1"), uris[1]);
  1033. CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/added2"), uris[2]);
  1034. CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/added3"), uris[3]);
  1035. req = createChangeUriReq(group->getGID(), 2);
  1036. // Change adduris
  1037. adduris = List::g();
  1038. adduris->append("http://example.org/added1-1");
  1039. adduris->append("http://example.org/added1-2");
  1040. req.params->append(std::move(adduris));
  1041. // Set position parameter
  1042. req.params->append(Integer::g(2));
  1043. res = m.execute(std::move(req), e_.get());
  1044. CPPUNIT_ASSERT_EQUAL(0, res.code);
  1045. CPPUNIT_ASSERT_EQUAL((int64_t)0, downcast<Integer>(downcast<List>(res.param)->get(0))->i());
  1046. CPPUNIT_ASSERT_EQUAL((int64_t)2, downcast<Integer>(downcast<List>(res.param)->get(1))->i());
  1047. uris = files[1]->getRemainingUris();
  1048. CPPUNIT_ASSERT_EQUAL((size_t)6, uris.size());
  1049. CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/added1-1"), uris[2]);
  1050. CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/added1-2"), uris[3]);
  1051. // Change index of FileEntry
  1052. req = createChangeUriReq(group->getGID(), 1);
  1053. adduris = List::g();
  1054. adduris->append("http://example.org/added1-1");
  1055. adduris->append("http://example.org/added1-2");
  1056. req.params->append(std::move(adduris));
  1057. // Set position far beyond the size of uris in FileEntry.
  1058. req.params->append(Integer::g(1000));
  1059. res = m.execute(std::move(req), e_.get());
  1060. CPPUNIT_ASSERT_EQUAL(0, res.code);
  1061. CPPUNIT_ASSERT_EQUAL((int64_t)0, downcast<Integer>(downcast<List>(res.param)->get(0))->i());
  1062. CPPUNIT_ASSERT_EQUAL((int64_t)2, downcast<Integer>(downcast<List>(res.param)->get(1))->i());
  1063. uris = files[0]->getRemainingUris();
  1064. CPPUNIT_ASSERT_EQUAL((size_t)2, uris.size());
  1065. CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/added1-1"), uris[0]);
  1066. CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/added1-2"), uris[1]);
  1067. }
  1068. namespace {
  1069. RpcRequest createChangeUriEmptyReq(a2_gid_t gid, size_t fileIndex)
  1070. {
  1071. auto req = createReq(ChangeUriRpcMethod::getMethodName());
  1072. req.params->append(GroupId::toHex(gid)); // GID
  1073. req.params->append(Integer::g(fileIndex)); // index of FileEntry
  1074. req.params->append(List::g()); // remove uris
  1075. req.params->append(List::g()); // append uris
  1076. return req;
  1077. }
  1078. } // namespace
  1079. void RpcMethodTest::testChangeUri_fail()
  1080. {
  1081. std::shared_ptr<FileEntry> files[3];
  1082. for(int i = 0; i < 3; ++i) {
  1083. files[i] = std::make_shared<FileEntry>();
  1084. }
  1085. auto dctx = std::make_shared<DownloadContext>();
  1086. dctx->setFileEntries(&files[0], &files[3]);
  1087. auto group = std::make_shared<RequestGroup>(GroupId::create(), option_);
  1088. group->setDownloadContext(dctx);
  1089. e_->getRequestGroupMan()->addReservedGroup(group);
  1090. ChangeUriRpcMethod m;
  1091. auto req = createChangeUriEmptyReq(group->getGID(), 1);
  1092. auto res = m.execute(std::move(req), e_.get());
  1093. CPPUNIT_ASSERT_EQUAL(0, res.code);
  1094. req = createChangeUriEmptyReq(group->getGID(), 0);
  1095. res = m.execute(std::move(req), e_.get());
  1096. // RPC request fails because 2nd argument is less than 1.
  1097. CPPUNIT_ASSERT_EQUAL(1, res.code);
  1098. req = createChangeUriEmptyReq(GroupId::create()->getNumericId(), 1);
  1099. res = m.execute(std::move(req), e_.get());
  1100. // RPC request fails because the given GID does not exist.
  1101. CPPUNIT_ASSERT_EQUAL(1, res.code);
  1102. req = createChangeUriEmptyReq(group->getGID(), 4);
  1103. res = m.execute(std::move(req), e_.get());
  1104. // RPC request fails because FileEntry#3 does not exist.
  1105. CPPUNIT_ASSERT_EQUAL(1, res.code);
  1106. req = createChangeUriEmptyReq(group->getGID(), 1);
  1107. req.params->set(1, String::g("0"));
  1108. res = m.execute(std::move(req), e_.get());
  1109. // RPC request fails because index of FileEntry is string.
  1110. CPPUNIT_ASSERT_EQUAL(1, res.code);
  1111. req = createChangeUriEmptyReq(group->getGID(), 1);
  1112. req.params->set(2, String::g("http://url"));
  1113. res = m.execute(std::move(req), e_.get());
  1114. // RPC request fails because 3rd param is not list.
  1115. CPPUNIT_ASSERT_EQUAL(1, res.code);
  1116. req = createChangeUriEmptyReq(group->getGID(), 1);
  1117. req.params->set(2, List::g());
  1118. req.params->set(3, String::g("http://url"));
  1119. res = m.execute(std::move(req), e_.get());
  1120. // RPC request fails because 4th param is not list.
  1121. CPPUNIT_ASSERT_EQUAL(1, res.code);
  1122. }
  1123. void RpcMethodTest::testGetSessionInfo()
  1124. {
  1125. GetSessionInfoRpcMethod m;
  1126. auto res = m.execute
  1127. (createReq(GetSessionInfoRpcMethod::getMethodName()), e_.get());
  1128. CPPUNIT_ASSERT_EQUAL(0, res.code);
  1129. CPPUNIT_ASSERT_EQUAL(util::toHex(e_->getSessionId()),
  1130. getString(downcast<Dict>(res.param), "sessionId"));
  1131. }
  1132. void RpcMethodTest::testPause()
  1133. {
  1134. std::vector<std::string> uris {
  1135. "http://url1",
  1136. "http://url2",
  1137. "http://url3",
  1138. };
  1139. option_->put(PREF_FORCE_SEQUENTIAL, A2_V_TRUE);
  1140. std::vector<std::shared_ptr<RequestGroup>> groups;
  1141. createRequestGroupForUri(groups, option_, uris);
  1142. CPPUNIT_ASSERT_EQUAL((size_t)3, groups.size());
  1143. e_->getRequestGroupMan()->addReservedGroup(groups);
  1144. {
  1145. PauseRpcMethod m;
  1146. auto req = createReq(PauseRpcMethod::getMethodName());
  1147. req.params->append(GroupId::toHex(groups[0]->getGID()));
  1148. auto res = m.execute(std::move(req), e_.get());
  1149. CPPUNIT_ASSERT_EQUAL(0, res.code);
  1150. }
  1151. CPPUNIT_ASSERT(groups[0]->isPauseRequested());
  1152. {
  1153. UnpauseRpcMethod m;
  1154. auto req = createReq(UnpauseRpcMethod::getMethodName());
  1155. req.params->append(GroupId::toHex(groups[0]->getGID()));
  1156. auto res = m.execute(std::move(req), e_.get());
  1157. CPPUNIT_ASSERT_EQUAL(0, res.code);
  1158. }
  1159. CPPUNIT_ASSERT(!groups[0]->isPauseRequested());
  1160. {
  1161. PauseAllRpcMethod m;
  1162. auto req = createReq(PauseAllRpcMethod::getMethodName());
  1163. auto res = m.execute(std::move(req), e_.get());
  1164. CPPUNIT_ASSERT_EQUAL(0, res.code);
  1165. }
  1166. for(size_t i = 0; i < groups.size(); ++i) {
  1167. CPPUNIT_ASSERT(groups[i]->isPauseRequested());
  1168. }
  1169. {
  1170. UnpauseAllRpcMethod m;
  1171. auto req = createReq(UnpauseAllRpcMethod::getMethodName());
  1172. auto res = m.execute(std::move(req), e_.get());
  1173. CPPUNIT_ASSERT_EQUAL(0, res.code);
  1174. }
  1175. for(size_t i = 0; i < groups.size(); ++i) {
  1176. CPPUNIT_ASSERT(!groups[i]->isPauseRequested());
  1177. }
  1178. {
  1179. ForcePauseAllRpcMethod m;
  1180. auto req = createReq(ForcePauseAllRpcMethod::getMethodName());
  1181. auto res = m.execute(std::move(req), e_.get());
  1182. CPPUNIT_ASSERT_EQUAL(0, res.code);
  1183. }
  1184. for(size_t i = 0; i < groups.size(); ++i) {
  1185. CPPUNIT_ASSERT(groups[i]->isPauseRequested());
  1186. }
  1187. }
  1188. void RpcMethodTest::testSystemMulticall()
  1189. {
  1190. SystemMulticallRpcMethod m;
  1191. auto req = createReq("system.multicall");
  1192. auto reqparams = List::g();
  1193. for(int i = 0; i < 2; ++i) {
  1194. auto dict = Dict::g();
  1195. dict->put("methodName", AddUriRpcMethod::getMethodName());
  1196. auto params = List::g();
  1197. auto urisParam = List::g();
  1198. urisParam->append("http://localhost/"+util::itos(i));
  1199. params->append(std::move(urisParam));
  1200. dict->put("params", std::move(params));
  1201. reqparams->append(std::move(dict));
  1202. }
  1203. {
  1204. auto dict = Dict::g();
  1205. dict->put("methodName", "not exists");
  1206. dict->put("params", List::g());
  1207. reqparams->append(std::move(dict));
  1208. }
  1209. {
  1210. reqparams->append("not struct");
  1211. }
  1212. {
  1213. auto dict = Dict::g();
  1214. dict->put("methodName", "system.multicall");
  1215. dict->put("params", List::g());
  1216. reqparams->append(std::move(dict));
  1217. }
  1218. {
  1219. // missing params
  1220. auto dict = Dict::g();
  1221. dict->put("methodName", GetVersionRpcMethod::getMethodName());
  1222. reqparams->append(std::move(dict));
  1223. }
  1224. {
  1225. auto dict = Dict::g();
  1226. dict->put("methodName", GetVersionRpcMethod::getMethodName());
  1227. dict->put("params", List::g());
  1228. reqparams->append(std::move(dict));
  1229. }
  1230. req.params->append(std::move(reqparams));
  1231. auto res = m.execute(std::move(req), e_.get());
  1232. CPPUNIT_ASSERT_EQUAL(0, res.code);
  1233. const List* resParams = downcast<List>(res.param);
  1234. CPPUNIT_ASSERT_EQUAL((size_t)7, resParams->size());
  1235. auto& rgman = e_->getRequestGroupMan();
  1236. CPPUNIT_ASSERT_EQUAL(GroupId::toHex(getReservedGroup(rgman.get(), 0)
  1237. ->getGID()),
  1238. downcast<String>(downcast<List>(resParams->get(0))->get(0))->s());
  1239. CPPUNIT_ASSERT_EQUAL(GroupId::toHex(getReservedGroup(rgman.get(), 1)
  1240. ->getGID()),
  1241. downcast<String>(downcast<List>(resParams->get(1))->get(0))->s());
  1242. CPPUNIT_ASSERT_EQUAL((int64_t)1,
  1243. downcast<Integer>
  1244. (downcast<Dict>(resParams->get(2))->get("faultCode"))
  1245. ->i());
  1246. CPPUNIT_ASSERT_EQUAL((int64_t)1,
  1247. downcast<Integer>
  1248. (downcast<Dict>(resParams->get(3))->get("faultCode"))
  1249. ->i());
  1250. CPPUNIT_ASSERT_EQUAL((int64_t)1,
  1251. downcast<Integer>
  1252. (downcast<Dict>(resParams->get(4))->get("faultCode"))
  1253. ->i());
  1254. CPPUNIT_ASSERT(downcast<List>(resParams->get(5)));
  1255. CPPUNIT_ASSERT(downcast<List>(resParams->get(6)));
  1256. }
  1257. void RpcMethodTest::testSystemMulticall_fail()
  1258. {
  1259. SystemMulticallRpcMethod m;
  1260. auto res = m.execute(createReq("system.multicall"), e_.get());
  1261. CPPUNIT_ASSERT_EQUAL(1, res.code);
  1262. }
  1263. void RpcMethodTest::testSystemListMethods()
  1264. {
  1265. SystemListMethodsRpcMethod m;
  1266. auto res = m.execute(createReq("system.listMethods"), e_.get());
  1267. CPPUNIT_ASSERT_EQUAL(0, res.code);
  1268. const auto resParams = downcast<List>(res.param);
  1269. auto &allNames = allMethodNames();
  1270. CPPUNIT_ASSERT_EQUAL(allNames.size(), resParams->size());
  1271. for (size_t i = 0; i < allNames.size(); ++i) {
  1272. const auto s = downcast<String>(resParams->get(i));
  1273. CPPUNIT_ASSERT(s);
  1274. CPPUNIT_ASSERT_EQUAL(allNames[i], s->s());
  1275. }
  1276. }
  1277. } // namespace rpc
  1278. } // namespace aria2