MetalinkProcessorTest.cc 35 KB

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