MetalinkProcessorTest.cc 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055
  1. #include "metalink_helper.h"
  2. #include <iostream>
  3. #include <cppunit/extensions/HelperMacros.h>
  4. #include "MetalinkParserStateMachine.h"
  5. #include "Exception.h"
  6. #include "DefaultDiskWriter.h"
  7. #include "ByteArrayDiskWriter.h"
  8. #include "Metalinker.h"
  9. #include "MetalinkEntry.h"
  10. #include "MetalinkResource.h"
  11. #include "MetalinkMetaurl.h"
  12. #include "MessageDigest.h"
  13. #include "ChunkChecksum.h"
  14. #include "Checksum.h"
  15. #include "Signature.h"
  16. #include "fmt.h"
  17. #include "RecoverableException.h"
  18. #include "util.h"
  19. namespace aria2 {
  20. class MetalinkProcessorTest : public CppUnit::TestFixture {
  21. CPPUNIT_TEST_SUITE(MetalinkProcessorTest);
  22. CPPUNIT_TEST(testParseFileV4);
  23. CPPUNIT_TEST(testParseFileV4_attrs);
  24. CPPUNIT_TEST(testParseFile);
  25. CPPUNIT_TEST(testParseFile_dirtraversal);
  26. CPPUNIT_TEST(testParseBinaryStream);
  27. CPPUNIT_TEST(testMalformedXML);
  28. CPPUNIT_TEST(testMalformedXML2);
  29. CPPUNIT_TEST(testBadSize);
  30. CPPUNIT_TEST(testBadSizeV4);
  31. CPPUNIT_TEST(testBadMaxConn);
  32. CPPUNIT_TEST(testNoName);
  33. CPPUNIT_TEST(testBadURLPrefs);
  34. CPPUNIT_TEST(testBadURLMaxConn);
  35. CPPUNIT_TEST(testUnsupportedType);
  36. CPPUNIT_TEST(testMultiplePieces);
  37. CPPUNIT_TEST(testBadPieceNo);
  38. CPPUNIT_TEST(testBadPieceLength);
  39. CPPUNIT_TEST(testUnsupportedType_piece);
  40. CPPUNIT_TEST(testLargeFileSize);
  41. CPPUNIT_TEST(testXmlPrefixV3);
  42. CPPUNIT_TEST_SUITE_END();
  43. private:
  44. public:
  45. void testParseFileV4();
  46. void testParseFileV4_attrs();
  47. void testParseFile();
  48. void testParseFile_dirtraversal();
  49. void testParseBinaryStream();
  50. void testMalformedXML();
  51. void testMalformedXML2();
  52. void testBadSize();
  53. void testBadSizeV4();
  54. void testBadMaxConn();
  55. void testNoName();
  56. void testBadURLPrefs();
  57. void testBadURLMaxConn();
  58. void testUnsupportedType();
  59. void testMultiplePieces();
  60. void testBadPieceNo();
  61. void testBadPieceLength();
  62. void testUnsupportedType_piece();
  63. void testLargeFileSize();
  64. void testXmlPrefixV3();
  65. };
  66. CPPUNIT_TEST_SUITE_REGISTRATION(MetalinkProcessorTest);
  67. void MetalinkProcessorTest::testParseFileV4()
  68. {
  69. auto m = metalink::parseFile(A2_TEST_DIR "/metalink4.xml");
  70. CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
  71. auto& e = m->getEntries()[0];
  72. CPPUNIT_ASSERT_EQUAL(std::string("example.ext"), e->getPath());
  73. CPPUNIT_ASSERT_EQUAL((int64_t)786430LL, e->getLength());
  74. CPPUNIT_ASSERT_EQUAL(-1, e->maxConnections);
  75. CPPUNIT_ASSERT_EQUAL(std::string("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"),
  76. util::toHex(e->checksum->getDigest()));
  77. CPPUNIT_ASSERT(e->checksum);
  78. CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), e->checksum->getHashType());
  79. CPPUNIT_ASSERT(e->chunkChecksum);
  80. if (MessageDigest::supports("sha-256")) {
  81. CPPUNIT_ASSERT_EQUAL(std::string("sha-256"),
  82. e->chunkChecksum->getHashType());
  83. CPPUNIT_ASSERT_EQUAL(262144, e->chunkChecksum->getPieceLength());
  84. CPPUNIT_ASSERT_EQUAL((size_t)3, e->chunkChecksum->countPieceHash());
  85. CPPUNIT_ASSERT_EQUAL(
  86. std::string(
  87. "0245178074fd042e19b7c3885b360fc21064b30e73f5626c7e3b005d048069c5"),
  88. util::toHex(e->chunkChecksum->getPieceHash(0)));
  89. CPPUNIT_ASSERT_EQUAL(
  90. std::string(
  91. "487ba2299be7f759d7c7bf6a4ac3a32cee81f1bb9332fc485947e32918864fb2"),
  92. util::toHex(e->chunkChecksum->getPieceHash(1)));
  93. CPPUNIT_ASSERT_EQUAL(
  94. std::string(
  95. "37290d74ac4d186e3a8e5785d259d2ec04fac91ae28092e7620ec8bc99e830aa"),
  96. util::toHex(e->chunkChecksum->getPieceHash(2)));
  97. }
  98. else {
  99. CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), e->chunkChecksum->getHashType());
  100. CPPUNIT_ASSERT_EQUAL(262144, e->chunkChecksum->getPieceLength());
  101. CPPUNIT_ASSERT_EQUAL((size_t)3, e->chunkChecksum->countPieceHash());
  102. CPPUNIT_ASSERT_EQUAL(
  103. std::string("5bd9f7248df0f3a6a86ab6c95f48787d546efa14"),
  104. util::toHex(e->chunkChecksum->getPieceHash(0)));
  105. CPPUNIT_ASSERT_EQUAL(
  106. std::string("9413ee70957a09d55704123687478e07f18c7b29"),
  107. util::toHex(e->chunkChecksum->getPieceHash(1)));
  108. CPPUNIT_ASSERT_EQUAL(
  109. std::string("44213f9f4d59b557314fadcd233232eebcac8012"),
  110. util::toHex(e->chunkChecksum->getPieceHash(2)));
  111. }
  112. CPPUNIT_ASSERT(e->getSignature());
  113. CPPUNIT_ASSERT_EQUAL(std::string("application/pgp-signature"),
  114. e->getSignature()->getType());
  115. CPPUNIT_ASSERT_EQUAL(std::string("a signature"),
  116. e->getSignature()->getBody());
  117. CPPUNIT_ASSERT_EQUAL((size_t)2, e->resources.size());
  118. auto& r = e->resources[0];
  119. CPPUNIT_ASSERT_EQUAL(std::string("ftp://ftp.example.com/example.ext"),
  120. r->url);
  121. CPPUNIT_ASSERT_EQUAL(std::string("de"), r->location);
  122. CPPUNIT_ASSERT_EQUAL(1, r->priority);
  123. CPPUNIT_ASSERT_EQUAL(std::string("ftp"),
  124. MetalinkResource::getTypeString(r->type));
  125. CPPUNIT_ASSERT_EQUAL(-1, r->maxConnections);
  126. #ifdef ENABLE_BITTORRENT
  127. CPPUNIT_ASSERT_EQUAL((size_t)1, e->metaurls.size());
  128. auto& mu = e->metaurls[0];
  129. CPPUNIT_ASSERT_EQUAL(std::string("http://example.com/example.ext.torrent"),
  130. mu->url);
  131. CPPUNIT_ASSERT_EQUAL(2, mu->priority);
  132. CPPUNIT_ASSERT_EQUAL(std::string("torrent"), mu->mediatype);
  133. #else // !ENABLE_BITTORRENT
  134. CPPUNIT_ASSERT_EQUAL((size_t)0, e->metaurls.size());
  135. #endif // !ENABLE_BITTORRENT
  136. }
  137. void MetalinkProcessorTest::testParseFileV4_attrs()
  138. {
  139. std::unique_ptr<Metalinker> m;
  140. ByteArrayDiskWriter dw;
  141. {
  142. // Testing file@name
  143. const char* tmpl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  144. "<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
  145. "<file name=\"%s\">"
  146. "<url>http://example.org</url>"
  147. "</file>"
  148. "</metalink>";
  149. dw.setString(fmt(tmpl, "foo"));
  150. m = metalink::parseBinaryStream(&dw);
  151. CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
  152. // empty name
  153. dw.setString(fmt(tmpl, ""));
  154. try {
  155. metalink::parseBinaryStream(&dw);
  156. CPPUNIT_FAIL("exception must be thrown.");
  157. }
  158. catch (RecoverableException& e) {
  159. // success
  160. }
  161. // dir traversing
  162. dw.setString(fmt(tmpl, "../doughnuts"));
  163. try {
  164. m = metalink::parseBinaryStream(&dw);
  165. CPPUNIT_FAIL("exception must be thrown.");
  166. }
  167. catch (RecoverableException& e) {
  168. // success
  169. }
  170. }
  171. {
  172. // Testing url@priority
  173. const char* tmpl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  174. "<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
  175. "<file name=\"example.ext\">"
  176. "<url priority=\"%s\">http://example.org</url>"
  177. "</file>"
  178. "</metalink>";
  179. dw.setString(fmt(tmpl, "0"));
  180. try {
  181. metalink::parseBinaryStream(&dw);
  182. CPPUNIT_FAIL("exception must be thrown.");
  183. }
  184. catch (RecoverableException& e) {
  185. // success
  186. }
  187. dw.setString(fmt(tmpl, "1"));
  188. m = metalink::parseBinaryStream(&dw);
  189. CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
  190. dw.setString(fmt(tmpl, "100"));
  191. m = metalink::parseBinaryStream(&dw);
  192. CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
  193. dw.setString(fmt(tmpl, "999999"));
  194. m = metalink::parseBinaryStream(&dw);
  195. CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
  196. dw.setString(fmt(tmpl, "1000000"));
  197. try {
  198. m = metalink::parseBinaryStream(&dw);
  199. CPPUNIT_FAIL("exception must be thrown.");
  200. }
  201. catch (RecoverableException& e) {
  202. // success
  203. }
  204. dw.setString(fmt(tmpl, "A"));
  205. try {
  206. m = metalink::parseBinaryStream(&dw);
  207. CPPUNIT_FAIL("exception must be thrown.");
  208. }
  209. catch (RecoverableException& e) {
  210. }
  211. }
  212. {
  213. // Testing metaurl@priority
  214. const char* tmpl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  215. "<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
  216. "<file name=\"example.ext\">"
  217. "<metaurl priority=\"%s\" "
  218. "mediatype=\"torrent\">http://example.org</metaurl>"
  219. "</file>"
  220. "</metalink>";
  221. dw.setString(fmt(tmpl, "0"));
  222. try {
  223. m = metalink::parseBinaryStream(&dw);
  224. CPPUNIT_FAIL("exception must be thrown.");
  225. }
  226. catch (RecoverableException& e) {
  227. // success
  228. }
  229. dw.setString(fmt(tmpl, "1"));
  230. m = metalink::parseBinaryStream(&dw);
  231. CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
  232. dw.setString(fmt(tmpl, "100"));
  233. m = metalink::parseBinaryStream(&dw);
  234. CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
  235. dw.setString(fmt(tmpl, "999999"));
  236. m = metalink::parseBinaryStream(&dw);
  237. CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
  238. dw.setString(fmt(tmpl, "1000000"));
  239. try {
  240. m = metalink::parseBinaryStream(&dw);
  241. CPPUNIT_FAIL("exception must be thrown.");
  242. }
  243. catch (RecoverableException& e) {
  244. // success
  245. }
  246. dw.setString(fmt(tmpl, "A"));
  247. try {
  248. m = metalink::parseBinaryStream(&dw);
  249. CPPUNIT_FAIL("exception must be thrown.");
  250. }
  251. catch (RecoverableException& e) {
  252. }
  253. }
  254. {
  255. // Testing metaurl@mediatype
  256. // no mediatype
  257. dw.setString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  258. "<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
  259. "<file name=\"example.ext\">"
  260. "<metaurl>http://example.org</metaurl>"
  261. "</file>"
  262. "</metalink>");
  263. try {
  264. m = metalink::parseBinaryStream(&dw);
  265. CPPUNIT_FAIL("exception must be thrown.");
  266. }
  267. catch (RecoverableException& e) {
  268. // success
  269. }
  270. const char* tmpl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  271. "<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
  272. "<file name=\"example.ext\">"
  273. "<metaurl mediatype=\"%s\">http://example.org</metaurl>"
  274. "</file>"
  275. "</metalink>";
  276. dw.setString(fmt(tmpl, "torrent"));
  277. m = metalink::parseBinaryStream(&dw);
  278. CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
  279. // empty mediatype
  280. dw.setString(fmt(tmpl, ""));
  281. try {
  282. m = metalink::parseBinaryStream(&dw);
  283. CPPUNIT_FAIL("exception must be thrown.");
  284. }
  285. catch (RecoverableException& e) {
  286. // success
  287. }
  288. }
  289. {
  290. // Testing metaurl@name
  291. const char* tmpl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  292. "<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
  293. "<file name=\"example.ext\">"
  294. "<metaurl mediatype=\"torrent\" "
  295. "name=\"%s\">http://example.org</metaurl>"
  296. "</file>"
  297. "</metalink>";
  298. dw.setString(fmt(tmpl, "foo"));
  299. m = metalink::parseBinaryStream(&dw);
  300. CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
  301. // dir traversing
  302. dw.setString(fmt(tmpl, "../doughnuts"));
  303. try {
  304. m = metalink::parseBinaryStream(&dw);
  305. CPPUNIT_FAIL("exception must be thrown.");
  306. }
  307. catch (RecoverableException& e) {
  308. // success
  309. }
  310. // empty name
  311. dw.setString(fmt(tmpl, ""));
  312. try {
  313. m = metalink::parseBinaryStream(&dw);
  314. CPPUNIT_FAIL("exception must be thrown.");
  315. }
  316. catch (RecoverableException& e) {
  317. // success
  318. }
  319. }
  320. {
  321. // Testing pieces@length
  322. // No pieces@length
  323. dw.setString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  324. "<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
  325. "<file name=\"example.ext\">"
  326. "<url>http://example.org</url>"
  327. "<pieces type=\"sha-1\">"
  328. "<hash>0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33</hash>"
  329. "</pieces>"
  330. "</file>"
  331. "</metalink>");
  332. try {
  333. m = metalink::parseBinaryStream(&dw);
  334. CPPUNIT_FAIL("exception must be thrown.");
  335. }
  336. catch (RecoverableException& e) {
  337. }
  338. const char* tmpl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  339. "<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
  340. "<file name=\"example.ext\">"
  341. "<url>http://example.org</url>"
  342. "<pieces length=\"%s\" type=\"sha-1\">"
  343. "<hash>0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33</hash>"
  344. "</pieces>"
  345. "</file>"
  346. "</metalink>";
  347. dw.setString(fmt(tmpl, "262144"));
  348. m = metalink::parseBinaryStream(&dw);
  349. // empty
  350. try {
  351. dw.setString(fmt(tmpl, ""));
  352. m = metalink::parseBinaryStream(&dw);
  353. CPPUNIT_FAIL("exception must be thrown.");
  354. }
  355. catch (RecoverableException& e) {
  356. }
  357. // not a number
  358. try {
  359. dw.setString(fmt(tmpl, "A"));
  360. m = metalink::parseBinaryStream(&dw);
  361. CPPUNIT_FAIL("exception must be thrown.");
  362. }
  363. catch (RecoverableException& e) {
  364. }
  365. }
  366. {
  367. // Testing pieces@type
  368. // No pieces@type
  369. dw.setString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  370. "<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
  371. "<file name=\"example.ext\">"
  372. "<url>http://example.org</url>"
  373. "<pieces length=\"262144\">"
  374. "<hash>0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33</hash>"
  375. "</pieces>"
  376. "</file>"
  377. "</metalink>");
  378. try {
  379. m = metalink::parseBinaryStream(&dw);
  380. CPPUNIT_FAIL("exception must be thrown.");
  381. }
  382. catch (RecoverableException& e) {
  383. }
  384. const char* tmpl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  385. "<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
  386. "<file name=\"example.ext\">"
  387. "<url>http://example.org</url>"
  388. "<pieces length=\"262144\" type=\"%s\">"
  389. "<hash>0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33</hash>"
  390. "</pieces>"
  391. "</file>"
  392. "</metalink>";
  393. dw.setString(fmt(tmpl, "sha-1"));
  394. m = metalink::parseBinaryStream(&dw);
  395. // empty
  396. try {
  397. dw.setString(fmt(tmpl, ""));
  398. m = metalink::parseBinaryStream(&dw);
  399. CPPUNIT_FAIL("exception must be thrown.");
  400. }
  401. catch (RecoverableException& e) {
  402. }
  403. }
  404. {
  405. // Testing hash@type
  406. // No hash@type
  407. dw.setString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  408. "<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
  409. "<file name=\"example.ext\">"
  410. "<url>http://example.org</url>"
  411. "<hash>0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33</hash>"
  412. "</file>"
  413. "</metalink>");
  414. try {
  415. m = metalink::parseBinaryStream(&dw);
  416. CPPUNIT_FAIL("exception must be thrown.");
  417. }
  418. catch (RecoverableException& e) {
  419. }
  420. const char* tmpl =
  421. "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  422. "<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
  423. "<file name=\"example.ext\">"
  424. "<url>http://example.org</url>"
  425. "<hash type=\"%s\">0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33</hash>"
  426. "</file>"
  427. "</metalink>";
  428. dw.setString(fmt(tmpl, "sha-1"));
  429. m = metalink::parseBinaryStream(&dw);
  430. // empty
  431. try {
  432. dw.setString(fmt(tmpl, ""));
  433. m = metalink::parseBinaryStream(&dw);
  434. CPPUNIT_FAIL("exception must be thrown.");
  435. }
  436. catch (RecoverableException& e) {
  437. }
  438. }
  439. {
  440. // Testing signature@mediatype
  441. // No hash@type
  442. dw.setString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  443. "<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
  444. "<file name=\"example.ext\">"
  445. "<url>http://example.org</url>"
  446. "<signature>sig</signature>"
  447. "</file>"
  448. "</metalink>");
  449. try {
  450. m = metalink::parseBinaryStream(&dw);
  451. CPPUNIT_FAIL("exception must be thrown.");
  452. }
  453. catch (RecoverableException& e) {
  454. }
  455. const char* tmpl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  456. "<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
  457. "<file name=\"example.ext\">"
  458. "<url>http://example.org</url>"
  459. "<signature mediatype=\"%s\">sig</signature>"
  460. "</file>"
  461. "</metalink>";
  462. dw.setString(fmt(tmpl, "application/pgp-signature"));
  463. m = metalink::parseBinaryStream(&dw);
  464. // empty
  465. try {
  466. dw.setString(fmt(tmpl, ""));
  467. m = metalink::parseBinaryStream(&dw);
  468. CPPUNIT_FAIL("exception must be thrown.");
  469. }
  470. catch (RecoverableException& e) {
  471. }
  472. }
  473. }
  474. void MetalinkProcessorTest::testParseFile()
  475. {
  476. try {
  477. auto metalinker = metalink::parseFile(A2_TEST_DIR "/test.xml");
  478. auto entryItr = std::begin(metalinker->getEntries());
  479. auto& entry1 = *entryItr;
  480. CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.5.2.tar.bz2"), entry1->getPath());
  481. CPPUNIT_ASSERT_EQUAL((int64_t)0LL, entry1->getLength());
  482. CPPUNIT_ASSERT_EQUAL(std::string("0.5.2"), entry1->version);
  483. CPPUNIT_ASSERT_EQUAL(std::string("en-US"), entry1->languages[0]);
  484. CPPUNIT_ASSERT_EQUAL(std::string("Linux-x86"), entry1->oses[0]);
  485. CPPUNIT_ASSERT_EQUAL(1, entry1->maxConnections);
  486. CPPUNIT_ASSERT_EQUAL(
  487. std::string("a96cf3f0266b91d87d5124cf94326422800b627d"),
  488. util::toHex(entry1->checksum->getDigest()));
  489. CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), entry1->checksum->getHashType());
  490. CPPUNIT_ASSERT(entry1->getSignature());
  491. CPPUNIT_ASSERT_EQUAL(std::string("pgp"), entry1->getSignature()->getType());
  492. CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.5.2.tar.bz2.sig"),
  493. entry1->getSignature()->getFile());
  494. // Note that we don't strip anything
  495. CPPUNIT_ASSERT_EQUAL(
  496. std::string(
  497. "\n-----BEGIN PGP SIGNATURE-----\n"
  498. "Version: GnuPG v1.4.9 (GNU/Linux)\n"
  499. "\n"
  500. "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
  501. "ffffffffffffffffffffffff\n"
  502. "fffff\n"
  503. "-----END PGP SIGNATURE-----\n"
  504. "\t"),
  505. entry1->getSignature()->getBody());
  506. auto resourceItr1 = std::begin(entry1->resources);
  507. auto& resource1 = *resourceItr1;
  508. CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_FTP, resource1->type);
  509. CPPUNIT_ASSERT_EQUAL(std::string("jp"), resource1->location);
  510. CPPUNIT_ASSERT_EQUAL(1, resource1->priority);
  511. CPPUNIT_ASSERT_EQUAL(std::string("ftp://ftphost/aria2-0.5.2.tar.bz2"),
  512. resource1->url);
  513. CPPUNIT_ASSERT_EQUAL(1, resource1->maxConnections);
  514. ++resourceItr1;
  515. auto& resource2 = *resourceItr1;
  516. CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_HTTP, resource2->type);
  517. CPPUNIT_ASSERT_EQUAL(std::string("us"), resource2->location);
  518. CPPUNIT_ASSERT_EQUAL(1, resource2->priority);
  519. CPPUNIT_ASSERT_EQUAL(std::string("http://httphost/aria2-0.5.2.tar.bz2"),
  520. resource2->url);
  521. CPPUNIT_ASSERT_EQUAL(-1, resource2->maxConnections);
  522. ++entryItr;
  523. auto& entry2 = *entryItr;
  524. CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.5.1.tar.bz2"), entry2->getPath());
  525. CPPUNIT_ASSERT_EQUAL((int64_t)345689LL, entry2->getLength());
  526. CPPUNIT_ASSERT_EQUAL(std::string("0.5.1"), entry2->version);
  527. CPPUNIT_ASSERT_EQUAL(std::string("ja-JP"), entry2->languages[0]);
  528. CPPUNIT_ASSERT_EQUAL(std::string("Linux-m68k"), entry2->oses[0]);
  529. CPPUNIT_ASSERT_EQUAL(-1, entry2->maxConnections);
  530. CPPUNIT_ASSERT_EQUAL(
  531. std::string("4c255b0ed130f5ea880f0aa061c3da0487e251cc"),
  532. util::toHex(entry2->checksum->getDigest()));
  533. CPPUNIT_ASSERT_EQUAL((size_t)2, entry2->chunkChecksum->countPieceHash());
  534. CPPUNIT_ASSERT_EQUAL(262144, entry2->chunkChecksum->getPieceLength());
  535. CPPUNIT_ASSERT_EQUAL(
  536. std::string("179463a88d79cbf0b1923991708aead914f26142"),
  537. util::toHex(entry2->chunkChecksum->getPieceHash(0)));
  538. CPPUNIT_ASSERT_EQUAL(
  539. std::string("fecf8bc9a1647505fe16746f94e97a477597dbf3"),
  540. util::toHex(entry2->chunkChecksum->getPieceHash(1)));
  541. CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), entry2->checksum->getHashType());
  542. // See that signature is null
  543. CPPUNIT_ASSERT(!entry2->getSignature());
  544. ++entryItr;
  545. // test case: verification hash is not provided
  546. auto& entry3 = *entryItr;
  547. CPPUNIT_ASSERT_EQUAL(std::string("NoVerificationHash"), entry3->getPath());
  548. CPPUNIT_ASSERT(!entry3->checksum);
  549. CPPUNIT_ASSERT(!entry3->chunkChecksum);
  550. ++entryItr;
  551. // test case: unsupported verification hash is included
  552. auto& entry4 = *entryItr;
  553. CPPUNIT_ASSERT_EQUAL(std::string("UnsupportedVerificationHashTypeIncluded"),
  554. entry4->getPath());
  555. CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), entry4->checksum->getHashType());
  556. CPPUNIT_ASSERT_EQUAL(
  557. std::string("4c255b0ed130f5ea880f0aa061c3da0487e251cc"),
  558. util::toHex(entry4->checksum->getDigest()));
  559. CPPUNIT_ASSERT_EQUAL(std::string("sha-1"),
  560. entry4->chunkChecksum->getHashType());
  561. }
  562. catch (Exception& e) {
  563. CPPUNIT_FAIL(e.stackTrace());
  564. }
  565. }
  566. void MetalinkProcessorTest::testParseFile_dirtraversal()
  567. {
  568. auto metalinker =
  569. metalink::parseFile(A2_TEST_DIR "/metalink3-dirtraversal.xml");
  570. CPPUNIT_ASSERT_EQUAL((size_t)1, metalinker->getEntries().size());
  571. auto& e = metalinker->getEntries()[0];
  572. CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.5.3.tar.bz2"), e->getPath());
  573. CPPUNIT_ASSERT(e->getSignature());
  574. CPPUNIT_ASSERT_EQUAL(std::string(""), e->getSignature()->getFile());
  575. }
  576. void MetalinkProcessorTest::testParseBinaryStream()
  577. {
  578. DefaultDiskWriter dw(A2_TEST_DIR "/test.xml");
  579. dw.enableReadOnly();
  580. dw.openExistingFile();
  581. try {
  582. auto m = metalink::parseBinaryStream(&dw);
  583. auto& entry1 = m->getEntries()[0];
  584. CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.5.2.tar.bz2"), entry1->getPath());
  585. }
  586. catch (Exception& e) {
  587. CPPUNIT_FAIL(e.stackTrace());
  588. }
  589. }
  590. void MetalinkProcessorTest::testMalformedXML()
  591. {
  592. ByteArrayDiskWriter dw;
  593. dw.setString("<metalink version=\"3.0\" "
  594. "xmlns=\"http://www.metalinker.org/\"><files></file></"
  595. "metalink>");
  596. try {
  597. metalink::parseBinaryStream(&dw);
  598. CPPUNIT_FAIL("exception must be thrown.");
  599. }
  600. catch (Exception& e) {
  601. std::cerr << e.stackTrace() << std::endl;
  602. }
  603. }
  604. void MetalinkProcessorTest::testMalformedXML2()
  605. {
  606. ByteArrayDiskWriter dw;
  607. dw.setString("<metalink version=\"3.0\" "
  608. "xmlns=\"http://www.metalinker.org/\"><files></files>");
  609. try {
  610. metalink::parseBinaryStream(&dw);
  611. CPPUNIT_FAIL("exception must be thrown.");
  612. }
  613. catch (Exception& e) {
  614. std::cerr << e.stackTrace() << std::endl;
  615. }
  616. }
  617. void MetalinkProcessorTest::testBadSizeV4()
  618. {
  619. ByteArrayDiskWriter dw;
  620. const char* tmpl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  621. "<metalink xmlns=\"urn:ietf:params:xml:ns:metalink\">"
  622. "<file name=\"foo\">"
  623. "<size>%s</size>"
  624. "<url>http://example.org</url>"
  625. "</file>"
  626. "</metalink>";
  627. dw.setString(fmt(tmpl, "9223372036854775807"));
  628. metalink::parseBinaryStream(&dw);
  629. dw.setString(fmt(tmpl, "-1"));
  630. try {
  631. metalink::parseBinaryStream(&dw);
  632. CPPUNIT_FAIL("exception must be thrown.");
  633. }
  634. catch (RecoverableException& e) {
  635. }
  636. }
  637. void MetalinkProcessorTest::testBadSize()
  638. {
  639. ByteArrayDiskWriter dw;
  640. dw.setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
  641. "<files>"
  642. "<file name=\"aria2-0.5.2.tar.bz2\">"
  643. " <size>abc</size>"
  644. " <version>0.5.2</version>"
  645. " <language>en-US</language>"
  646. " <os>Linux-x86</os>"
  647. "</file>"
  648. "</files>"
  649. "</metalink>");
  650. try {
  651. auto m = metalink::parseBinaryStream(&dw);
  652. auto& e = m->getEntries()[0];
  653. CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.5.2.tar.bz2"), e->getPath());
  654. CPPUNIT_ASSERT_EQUAL((int64_t)0LL, e->getLength());
  655. CPPUNIT_ASSERT_EQUAL(std::string("0.5.2"), e->version);
  656. CPPUNIT_ASSERT_EQUAL(std::string("en-US"), e->languages[0]);
  657. CPPUNIT_ASSERT_EQUAL(std::string("Linux-x86"), e->oses[0]);
  658. }
  659. catch (Exception& e) {
  660. CPPUNIT_FAIL(e.stackTrace());
  661. }
  662. }
  663. void MetalinkProcessorTest::testBadMaxConn()
  664. {
  665. ByteArrayDiskWriter dw;
  666. dw.setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
  667. "<files>"
  668. "<file name=\"aria2-0.5.2.tar.bz2\">"
  669. " <size>43743838</size>"
  670. " <version>0.5.2</version>"
  671. " <language>en-US</language>"
  672. " <os>Linux-x86</os>"
  673. " <resources maxconnections=\"abc\"/>"
  674. "</file>"
  675. "</files>"
  676. "</metalink>");
  677. try {
  678. auto m = metalink::parseBinaryStream(&dw);
  679. auto& e = m->getEntries()[0];
  680. CPPUNIT_ASSERT_EQUAL((int64_t)43743838LL, e->getLength());
  681. }
  682. catch (Exception& e) {
  683. CPPUNIT_FAIL(e.stackTrace());
  684. }
  685. }
  686. void MetalinkProcessorTest::testNoName()
  687. {
  688. ByteArrayDiskWriter dw;
  689. dw.setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
  690. "<files>"
  691. "<file>"
  692. " <size>1024</size>"
  693. " <version>0.0.1</version>"
  694. " <language>GB</language>"
  695. " <os>Linux-x64</os>"
  696. "</file>"
  697. "<file name=\"aria2-0.5.2.tar.bz2\">"
  698. " <size>43743838</size>"
  699. " <version>0.5.2</version>"
  700. " <language>en-US</language>"
  701. " <os>Linux-x86</os>"
  702. "</file>"
  703. "</files>"
  704. "</metalink>");
  705. try {
  706. auto m = metalink::parseBinaryStream(&dw);
  707. CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
  708. auto& e = m->getEntries()[0];
  709. CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.5.2.tar.bz2"), e->getPath());
  710. }
  711. catch (Exception& e) {
  712. CPPUNIT_FAIL(e.stackTrace());
  713. }
  714. }
  715. void MetalinkProcessorTest::testBadURLPrefs()
  716. {
  717. ByteArrayDiskWriter dw;
  718. dw.setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
  719. "<files>"
  720. "<file name=\"aria2-0.5.2.tar.bz2\">"
  721. " <size>43743838</size>"
  722. " <version>0.5.2</version>"
  723. " <language>en-US</language>"
  724. " <os>Linux-x86</os>"
  725. " <resources>"
  726. " <url type=\"ftp\" maxconnections=\"1\" preference=\"xyz\""
  727. " location=\"jp\">ftp://mirror/</url>"
  728. " </resources>"
  729. "</file>"
  730. "</files>"
  731. "</metalink>");
  732. try {
  733. auto m = metalink::parseBinaryStream(&dw);
  734. auto& e = m->getEntries()[0];
  735. auto& r = e->resources[0];
  736. CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_FTP, r->type);
  737. CPPUNIT_ASSERT_EQUAL(MetalinkResource::getLowestPriority(), r->priority);
  738. CPPUNIT_ASSERT_EQUAL(1, r->maxConnections);
  739. CPPUNIT_ASSERT_EQUAL(std::string("jp"), r->location);
  740. }
  741. catch (Exception& e) {
  742. CPPUNIT_FAIL(e.stackTrace());
  743. }
  744. }
  745. void MetalinkProcessorTest::testBadURLMaxConn()
  746. {
  747. ByteArrayDiskWriter dw;
  748. dw.setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
  749. "<files>"
  750. "<file name=\"aria2-0.5.2.tar.bz2\">"
  751. " <size>43743838</size>"
  752. " <version>0.5.2</version>"
  753. " <language>en-US</language>"
  754. " <os>Linux-x86</os>"
  755. " <resources>"
  756. " <url maxconnections=\"xyz\" type=\"ftp\""
  757. " preference=\"100\""
  758. " location=\"jp\">ftp://mirror/</url>"
  759. " </resources>"
  760. "</file>"
  761. "</files>"
  762. "</metalink>");
  763. try {
  764. auto m = metalink::parseBinaryStream(&dw);
  765. auto& e = m->getEntries()[0];
  766. auto& r = e->resources[0];
  767. CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_FTP, r->type);
  768. CPPUNIT_ASSERT_EQUAL(1, r->priority);
  769. CPPUNIT_ASSERT_EQUAL(-1, r->maxConnections);
  770. CPPUNIT_ASSERT_EQUAL(std::string("jp"), r->location);
  771. }
  772. catch (Exception& e) {
  773. CPPUNIT_FAIL(e.stackTrace());
  774. }
  775. }
  776. void MetalinkProcessorTest::testUnsupportedType()
  777. {
  778. ByteArrayDiskWriter dw;
  779. dw.setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
  780. "<files>"
  781. "<file name=\"aria2-0.5.2.tar.bz2\">"
  782. " <size>43743838</size>"
  783. " <version>0.5.2</version>"
  784. " <language>en-US</language>"
  785. " <os>Linux-x86</os>"
  786. " <resources>"
  787. " <url type=\"ftp\">ftp://mirror/</url>"
  788. " <url type=\"magnet\">magnet:xt=XYZ</url>"
  789. " <url type=\"http\">http://mirror/</url>"
  790. " </resources>"
  791. "</file>"
  792. "</files>"
  793. "</metalink>");
  794. try {
  795. auto m = metalink::parseBinaryStream(&dw);
  796. auto& e = m->getEntries()[0];
  797. CPPUNIT_ASSERT_EQUAL((size_t)3, e->resources.size());
  798. auto& r1 = e->resources[0];
  799. CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_FTP, r1->type);
  800. auto& r2 = e->resources[1];
  801. CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_NOT_SUPPORTED, r2->type);
  802. auto& r3 = e->resources[2];
  803. CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_HTTP, r3->type);
  804. }
  805. catch (Exception& e) {
  806. CPPUNIT_FAIL(e.stackTrace());
  807. }
  808. }
  809. void MetalinkProcessorTest::testMultiplePieces()
  810. {
  811. ByteArrayDiskWriter dw;
  812. dw.setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
  813. "<files>"
  814. "<file name=\"aria2.tar.bz2\">"
  815. " <verification>"
  816. " <pieces length=\"1024\" type=\"sha1\">"
  817. " </pieces>"
  818. " <pieces length=\"512\" type=\"md5\">"
  819. " </pieces>"
  820. " </verification>"
  821. "</file>"
  822. "</files>"
  823. "</metalink>");
  824. try {
  825. // aria2 prefers sha1
  826. auto m = metalink::parseBinaryStream(&dw);
  827. auto& e = m->getEntries()[0];
  828. auto& c = e->chunkChecksum;
  829. CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), c->getHashType());
  830. CPPUNIT_ASSERT_EQUAL((int32_t)1_k, c->getPieceLength());
  831. }
  832. catch (Exception& e) {
  833. CPPUNIT_FAIL(e.stackTrace());
  834. }
  835. }
  836. void MetalinkProcessorTest::testBadPieceNo()
  837. {
  838. ByteArrayDiskWriter dw;
  839. dw.setString(
  840. "<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
  841. "<files>"
  842. "<file name=\"aria2.tar.bz2\">"
  843. " <verification>"
  844. " <pieces length=\"512\" type=\"sha1\">"
  845. " <hash piece=\"0\">44213f9f4d59b557314fadcd233232eebcac8012</hash>"
  846. " <hash "
  847. "piece=\"xyz\">44213f9f4d59b557314fadcd233232eebcac8012</hash>"
  848. " </pieces>"
  849. " <pieces length=\"1024\" type=\"sha1\">"
  850. " <hash piece=\"0\">44213f9f4d59b557314fadcd233232eebcac8012</hash>"
  851. " </pieces>"
  852. " </verification>"
  853. "</file>"
  854. "</files>"
  855. "</metalink>");
  856. try {
  857. auto m = metalink::parseBinaryStream(&dw);
  858. auto& e = m->getEntries()[0];
  859. auto& c = e->chunkChecksum;
  860. CPPUNIT_ASSERT(c);
  861. CPPUNIT_ASSERT_EQUAL((int32_t)1_k, c->getPieceLength());
  862. CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), c->getHashType());
  863. }
  864. catch (Exception& e) {
  865. CPPUNIT_FAIL(e.stackTrace());
  866. }
  867. }
  868. void MetalinkProcessorTest::testBadPieceLength()
  869. {
  870. ByteArrayDiskWriter dw;
  871. dw.setString(
  872. "<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
  873. "<files>"
  874. "<file name=\"aria2.tar.bz2\">"
  875. " <verification>"
  876. " <pieces length=\"xyz\" type=\"sha1\">"
  877. " <hash piece=\"0\">44213f9f4d59b557314fadcd233232eebcac8012</hash>"
  878. " </pieces>"
  879. " <pieces length=\"1024\" type=\"sha1\">"
  880. " <hash piece=\"0\">44213f9f4d59b557314fadcd233232eebcac8012</hash>"
  881. " </pieces>"
  882. " </verification>"
  883. "</file>"
  884. "</files>"
  885. "</metalink>");
  886. try {
  887. auto m = metalink::parseBinaryStream(&dw);
  888. CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
  889. auto& e = m->getEntries()[0];
  890. auto& c = e->chunkChecksum;
  891. CPPUNIT_ASSERT(c);
  892. CPPUNIT_ASSERT_EQUAL((int32_t)1_k, c->getPieceLength());
  893. CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), c->getHashType());
  894. }
  895. catch (Exception& e) {
  896. CPPUNIT_FAIL(e.stackTrace());
  897. }
  898. }
  899. void MetalinkProcessorTest::testUnsupportedType_piece()
  900. {
  901. ByteArrayDiskWriter dw;
  902. dw.setString(
  903. "<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
  904. "<files>"
  905. "<file name=\"aria2.tar.bz2\">"
  906. " <verification>"
  907. " <pieces length=\"512\" type=\"ARIA2\">"
  908. " <hash piece=\"0\">44213f9f4d59b557314fadcd233232eebcac8012</hash>"
  909. " </pieces>"
  910. " <pieces length=\"1024\" type=\"sha1\">"
  911. " <hash piece=\"0\">44213f9f4d59b557314fadcd233232eebcac8012</hash>"
  912. " </pieces>"
  913. " </verification>"
  914. "</file>"
  915. "</files>"
  916. "</metalink>");
  917. try {
  918. auto m = metalink::parseBinaryStream(&dw);
  919. auto& e = m->getEntries()[0];
  920. auto& c = e->chunkChecksum;
  921. CPPUNIT_ASSERT(c);
  922. CPPUNIT_ASSERT_EQUAL((int32_t)1_k, c->getPieceLength());
  923. CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), c->getHashType());
  924. }
  925. catch (Exception& e) {
  926. CPPUNIT_FAIL(e.stackTrace());
  927. }
  928. }
  929. void MetalinkProcessorTest::testLargeFileSize()
  930. {
  931. ByteArrayDiskWriter dw;
  932. dw.setString("<metalink version=\"3.0\" xmlns=\"http://www.metalinker.org/\">"
  933. "<files>"
  934. "<file name=\"dvd.iso\">"
  935. " <size>9223372036854775807</size>"
  936. " <resources>"
  937. " <url type=\"http\">ftp://mirror/</url>"
  938. " </resources>"
  939. "</file>"
  940. "</files>"
  941. "</metalink>");
  942. try {
  943. auto m = metalink::parseBinaryStream(&dw);
  944. auto& e = m->getEntries()[0];
  945. CPPUNIT_ASSERT_EQUAL((int64_t)9223372036854775807LL, e->getLength());
  946. }
  947. catch (Exception& e) {
  948. CPPUNIT_FAIL(e.stackTrace());
  949. }
  950. }
  951. void MetalinkProcessorTest::testXmlPrefixV3()
  952. {
  953. ByteArrayDiskWriter dw;
  954. dw.setString(
  955. "<m:metalink version=\"3.0\" xmlns:m=\"http://www.metalinker.org/\">"
  956. "<m:files>"
  957. "<m:file name=\"dvd.iso\">"
  958. " <m:size>9223372036854775807</m:size>"
  959. " <m:resources>"
  960. " <m:url type=\"http\">ftp://mirror/</m:url>"
  961. " </m:resources>"
  962. "</m:file>"
  963. "</m:files>"
  964. "</m:metalink>");
  965. try {
  966. auto m = metalink::parseBinaryStream(&dw);
  967. CPPUNIT_ASSERT_EQUAL((size_t)1, m->getEntries().size());
  968. auto& e = m->getEntries()[0];
  969. CPPUNIT_ASSERT_EQUAL((int64_t)9223372036854775807LL, e->getLength());
  970. }
  971. catch (Exception& e) {
  972. CPPUNIT_FAIL(e.stackTrace());
  973. }
  974. }
  975. } // namespace aria2