RpcMethodTest.cc 50 KB

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