BittorrentHelperTest.cc 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036
  1. #include "bittorrent_helper.h"
  2. #include <cstring>
  3. #include <iostream>
  4. #include <cppunit/extensions/HelperMacros.h>
  5. #include "DownloadContext.h"
  6. #include "util.h"
  7. #include "RecoverableException.h"
  8. #include "AnnounceTier.h"
  9. #include "FixedNumberRandomizer.h"
  10. #include "FileEntry.h"
  11. #include "array_fun.h"
  12. #include "a2netcompat.h"
  13. #include "bencode2.h"
  14. #include "TestUtil.h"
  15. #include "base32.h"
  16. #include "Option.h"
  17. #include "prefs.h"
  18. namespace aria2 {
  19. namespace bittorrent {
  20. class BittorrentHelperTest : public CppUnit::TestFixture {
  21. CPPUNIT_TEST_SUITE(BittorrentHelperTest);
  22. CPPUNIT_TEST(testGetInfoHash);
  23. CPPUNIT_TEST(testGetPieceHash);
  24. CPPUNIT_TEST(testGetFileEntries);
  25. CPPUNIT_TEST(testGetTotalLength);
  26. CPPUNIT_TEST(testGetFileEntriesSingle);
  27. CPPUNIT_TEST(testGetTotalLengthSingle);
  28. CPPUNIT_TEST(testGetFileModeMulti);
  29. CPPUNIT_TEST(testGetFileModeSingle);
  30. CPPUNIT_TEST(testGetNameMulti);
  31. CPPUNIT_TEST(testGetNameSingle);
  32. CPPUNIT_TEST(testOverrideName);
  33. CPPUNIT_TEST(testGetAnnounceTier);
  34. CPPUNIT_TEST(testGetAnnounceTierAnnounceList);
  35. CPPUNIT_TEST(testGetPieceLength);
  36. CPPUNIT_TEST(testGetInfoHashAsString);
  37. CPPUNIT_TEST(testGetPeerId);
  38. CPPUNIT_TEST(testComputeFastSet);
  39. CPPUNIT_TEST(testGetFileEntries_multiFileUrlList);
  40. CPPUNIT_TEST(testGetFileEntries_singleFileUrlList);
  41. CPPUNIT_TEST(testGetFileEntries_singleFileUrlListEndsWithSlash);
  42. CPPUNIT_TEST(testLoadFromMemory);
  43. CPPUNIT_TEST(testLoadFromMemory_somethingMissing);
  44. CPPUNIT_TEST(testLoadFromMemory_overrideName);
  45. CPPUNIT_TEST(testLoadFromMemory_multiFileDirTraversal);
  46. CPPUNIT_TEST(testLoadFromMemory_singleFileDirTraversal);
  47. CPPUNIT_TEST(testLoadFromMemory_multiFileNonUtf8Path);
  48. CPPUNIT_TEST(testLoadFromMemory_singleFileNonUtf8Path);
  49. CPPUNIT_TEST(testGetNodes);
  50. CPPUNIT_TEST(testGetBasePath);
  51. CPPUNIT_TEST(testSetFileFilter_single);
  52. CPPUNIT_TEST(testSetFileFilter_multi);
  53. CPPUNIT_TEST(testUTF8Torrent);
  54. CPPUNIT_TEST(testEtc);
  55. CPPUNIT_TEST(testCheckBitfield);
  56. CPPUNIT_TEST(testMetadata);
  57. CPPUNIT_TEST(testParseMagnet);
  58. CPPUNIT_TEST(testParseMagnet_base32);
  59. CPPUNIT_TEST(testMetadata2Torrent);
  60. CPPUNIT_TEST(testTorrent2Magnet);
  61. CPPUNIT_TEST(testExtractPeerFromString);
  62. CPPUNIT_TEST(testExtractPeerFromList);
  63. CPPUNIT_TEST(testExtract2PeersFromList);
  64. CPPUNIT_TEST(testPackcompact);
  65. CPPUNIT_TEST(testUnpackcompact);
  66. CPPUNIT_TEST(testRemoveAnnounceUri);
  67. CPPUNIT_TEST(testAddAnnounceUri);
  68. CPPUNIT_TEST(testAdjustAnnounceUri);
  69. CPPUNIT_TEST_SUITE_END();
  70. public:
  71. std::shared_ptr<Option> option_;
  72. void setUp()
  73. {
  74. option_.reset(new Option());
  75. option_->put(PREF_DIR, ".");
  76. }
  77. void testGetInfoHash();
  78. void testGetPieceHash();
  79. void testGetFileEntries();
  80. void testGetTotalLength();
  81. void testGetFileEntriesSingle();
  82. void testGetTotalLengthSingle();
  83. void testGetFileModeMulti();
  84. void testGetFileModeSingle();
  85. void testGetNameMulti();
  86. void testGetNameSingle();
  87. void testOverrideName();
  88. void testGetAnnounceTier();
  89. void testGetAnnounceTierAnnounceList();
  90. void testGetPieceLength();
  91. void testGetInfoHashAsString();
  92. void testGetPeerId();
  93. void testComputeFastSet();
  94. void testGetFileEntries_multiFileUrlList();
  95. void testGetFileEntries_singleFileUrlList();
  96. void testGetFileEntries_singleFileUrlListEndsWithSlash();
  97. void testLoadFromMemory();
  98. void testLoadFromMemory_somethingMissing();
  99. void testLoadFromMemory_overrideName();
  100. void testLoadFromMemory_multiFileDirTraversal();
  101. void testLoadFromMemory_singleFileDirTraversal();
  102. void testLoadFromMemory_multiFileNonUtf8Path();
  103. void testLoadFromMemory_singleFileNonUtf8Path();
  104. void testGetNodes();
  105. void testGetBasePath();
  106. void testSetFileFilter_single();
  107. void testSetFileFilter_multi();
  108. void testUTF8Torrent();
  109. void testEtc();
  110. void testCheckBitfield();
  111. void testMetadata();
  112. void testParseMagnet();
  113. void testParseMagnet_base32();
  114. void testMetadata2Torrent();
  115. void testTorrent2Magnet();
  116. void testExtractPeerFromString();
  117. void testExtractPeerFromList();
  118. void testExtract2PeersFromList();
  119. void testPackcompact();
  120. void testUnpackcompact();
  121. void testRemoveAnnounceUri();
  122. void testAddAnnounceUri();
  123. void testAdjustAnnounceUri();
  124. };
  125. CPPUNIT_TEST_SUITE_REGISTRATION(BittorrentHelperTest);
  126. void BittorrentHelperTest::testGetInfoHash()
  127. {
  128. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  129. load(A2_TEST_DIR "/test.torrent", dctx, option_);
  130. std::string correctHash = "248d0a1cd08284299de78d5c1ed359bb46717d8c";
  131. CPPUNIT_ASSERT_EQUAL(correctHash, bittorrent::getInfoHashString(dctx));
  132. }
  133. void BittorrentHelperTest::testGetPieceHash()
  134. {
  135. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  136. load(A2_TEST_DIR "/test.torrent", dctx, option_);
  137. CPPUNIT_ASSERT_EQUAL(std::string("AAAAAAAAAAAAAAAAAAAA"),
  138. dctx->getPieceHash(0));
  139. CPPUNIT_ASSERT_EQUAL(std::string("BBBBBBBBBBBBBBBBBBBB"),
  140. dctx->getPieceHash(1));
  141. CPPUNIT_ASSERT_EQUAL(std::string("CCCCCCCCCCCCCCCCCCCC"),
  142. dctx->getPieceHash(2));
  143. CPPUNIT_ASSERT_EQUAL(std::string(""), dctx->getPieceHash(3));
  144. CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), dctx->getPieceHashType());
  145. }
  146. void BittorrentHelperTest::testGetFileEntries()
  147. {
  148. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  149. option_->put(PREF_MAX_CONNECTION_PER_SERVER, "10");
  150. load(A2_TEST_DIR "/test.torrent", dctx, option_);
  151. // This is multi-file torrent.
  152. std::vector<std::shared_ptr<FileEntry>> fileEntries = dctx->getFileEntries();
  153. // There are 2 file entries.
  154. CPPUNIT_ASSERT_EQUAL((size_t)2, fileEntries.size());
  155. std::vector<std::shared_ptr<FileEntry>>::iterator itr = fileEntries.begin();
  156. std::shared_ptr<FileEntry> fileEntry1 = *itr;
  157. CPPUNIT_ASSERT_EQUAL(std::string("./aria2-test/aria2/src/aria2c"),
  158. fileEntry1->getPath());
  159. CPPUNIT_ASSERT_EQUAL(std::string("aria2-test/aria2/src/aria2c"),
  160. fileEntry1->getOriginalName());
  161. CPPUNIT_ASSERT_EQUAL(10, fileEntry1->getMaxConnectionPerServer());
  162. itr++;
  163. std::shared_ptr<FileEntry> fileEntry2 = *itr;
  164. CPPUNIT_ASSERT_EQUAL(std::string("./aria2-test/aria2-0.2.2.tar.bz2"),
  165. fileEntry2->getPath());
  166. CPPUNIT_ASSERT_EQUAL(10, fileEntry2->getMaxConnectionPerServer());
  167. }
  168. void BittorrentHelperTest::testGetFileEntriesSingle()
  169. {
  170. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  171. option_->put(PREF_MAX_CONNECTION_PER_SERVER, "10");
  172. load(A2_TEST_DIR "/single.torrent", dctx, option_);
  173. // This is multi-file torrent.
  174. std::vector<std::shared_ptr<FileEntry>> fileEntries = dctx->getFileEntries();
  175. // There is 1 file entry.
  176. CPPUNIT_ASSERT_EQUAL((size_t)1, fileEntries.size());
  177. std::vector<std::shared_ptr<FileEntry>>::iterator itr = fileEntries.begin();
  178. std::shared_ptr<FileEntry> fileEntry1 = *itr;
  179. CPPUNIT_ASSERT_EQUAL(std::string("./aria2-0.8.2.tar.bz2"),
  180. fileEntry1->getPath());
  181. CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.8.2.tar.bz2"),
  182. fileEntry1->getOriginalName());
  183. CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.8.2.tar.bz2"),
  184. fileEntry1->getSuffixPath());
  185. CPPUNIT_ASSERT_EQUAL(10, fileEntry1->getMaxConnectionPerServer());
  186. }
  187. void BittorrentHelperTest::testGetTotalLength()
  188. {
  189. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  190. load(A2_TEST_DIR "/test.torrent", dctx, option_);
  191. CPPUNIT_ASSERT_EQUAL((int64_t)384LL, dctx->getTotalLength());
  192. }
  193. void BittorrentHelperTest::testGetTotalLengthSingle()
  194. {
  195. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  196. load(A2_TEST_DIR "/single.torrent", dctx, option_);
  197. CPPUNIT_ASSERT_EQUAL((int64_t)384LL, dctx->getTotalLength());
  198. }
  199. void BittorrentHelperTest::testGetFileModeMulti()
  200. {
  201. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  202. load(A2_TEST_DIR "/test.torrent", dctx, option_);
  203. CPPUNIT_ASSERT_EQUAL(BT_FILE_MODE_MULTI, getTorrentAttrs(dctx)->mode);
  204. }
  205. void BittorrentHelperTest::testGetFileModeSingle()
  206. {
  207. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  208. load(A2_TEST_DIR "/single.torrent", dctx, option_);
  209. CPPUNIT_ASSERT_EQUAL(BT_FILE_MODE_SINGLE, getTorrentAttrs(dctx)->mode);
  210. }
  211. void BittorrentHelperTest::testGetNameMulti()
  212. {
  213. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  214. load(A2_TEST_DIR "/test.torrent", dctx, option_);
  215. CPPUNIT_ASSERT_EQUAL(std::string("aria2-test"), getTorrentAttrs(dctx)->name);
  216. }
  217. void BittorrentHelperTest::testGetNameSingle()
  218. {
  219. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  220. load(A2_TEST_DIR "/single.torrent", dctx, option_);
  221. CPPUNIT_ASSERT_EQUAL(std::string("./aria2-0.8.2.tar.bz2"),
  222. dctx->getBasePath());
  223. CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.8.2.tar.bz2"),
  224. getTorrentAttrs(dctx)->name);
  225. }
  226. void BittorrentHelperTest::testOverrideName()
  227. {
  228. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  229. load(A2_TEST_DIR "/test.torrent", dctx, option_, "aria2-override.name");
  230. CPPUNIT_ASSERT_EQUAL(std::string("./aria2-override.name"),
  231. dctx->getBasePath());
  232. CPPUNIT_ASSERT_EQUAL(std::string("aria2-override.name"),
  233. getTorrentAttrs(dctx)->name);
  234. }
  235. void BittorrentHelperTest::testGetAnnounceTier()
  236. {
  237. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  238. load(A2_TEST_DIR "/single.torrent", dctx, option_);
  239. auto attrs = getTorrentAttrs(dctx);
  240. // There is 1 tier.
  241. CPPUNIT_ASSERT_EQUAL((size_t)1, attrs->announceList.size());
  242. CPPUNIT_ASSERT_EQUAL((size_t)1, attrs->announceList[0].size());
  243. CPPUNIT_ASSERT_EQUAL(std::string("http://aria.rednoah.com/announce.php"),
  244. attrs->announceList[0][0]);
  245. }
  246. void BittorrentHelperTest::testGetAnnounceTierAnnounceList()
  247. {
  248. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  249. load(A2_TEST_DIR "/test.torrent", dctx, option_);
  250. auto attrs = getTorrentAttrs(dctx);
  251. // There are 3 tiers.
  252. CPPUNIT_ASSERT_EQUAL((size_t)3, attrs->announceList.size());
  253. CPPUNIT_ASSERT_EQUAL((size_t)1, attrs->announceList[0].size());
  254. CPPUNIT_ASSERT_EQUAL(std::string("http://tracker1"),
  255. attrs->announceList[0][0]);
  256. CPPUNIT_ASSERT_EQUAL((size_t)1, attrs->announceList[1].size());
  257. CPPUNIT_ASSERT_EQUAL(std::string("http://tracker2"),
  258. attrs->announceList[1][0]);
  259. CPPUNIT_ASSERT_EQUAL((size_t)1, attrs->announceList[2].size());
  260. CPPUNIT_ASSERT_EQUAL(std::string("http://tracker3"),
  261. attrs->announceList[2][0]);
  262. }
  263. void BittorrentHelperTest::testGetPieceLength()
  264. {
  265. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  266. load(A2_TEST_DIR "/test.torrent", dctx, option_);
  267. CPPUNIT_ASSERT_EQUAL(128, dctx->getPieceLength());
  268. }
  269. void BittorrentHelperTest::testGetInfoHashAsString()
  270. {
  271. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  272. load(A2_TEST_DIR "/test.torrent", dctx, option_);
  273. CPPUNIT_ASSERT_EQUAL(std::string("248d0a1cd08284299de78d5c1ed359bb46717d8c"),
  274. getInfoHashString(dctx));
  275. }
  276. void BittorrentHelperTest::testGetPeerId()
  277. {
  278. std::string peerId = generatePeerId("aria2-");
  279. CPPUNIT_ASSERT(peerId.find("aria2-") == 0);
  280. CPPUNIT_ASSERT_EQUAL((size_t)20, peerId.size());
  281. }
  282. void BittorrentHelperTest::testComputeFastSet()
  283. {
  284. std::string ipaddr = "192.168.0.1";
  285. unsigned char infoHash[20];
  286. memset(infoHash, 0, sizeof(infoHash));
  287. infoHash[0] = 0xff;
  288. int fastSetSize = 10;
  289. size_t numPieces = 1000;
  290. {
  291. auto fastSet = computeFastSet(ipaddr, numPieces, infoHash, fastSetSize);
  292. size_t ans[] = {686, 459, 278, 200, 404, 834, 64, 203, 760, 950};
  293. CPPUNIT_ASSERT(std::equal(fastSet.begin(), fastSet.end(), std::begin(ans)));
  294. }
  295. ipaddr = "10.0.0.1";
  296. {
  297. auto fastSet = computeFastSet(ipaddr, numPieces, infoHash, fastSetSize);
  298. size_t ans[] = {568, 188, 466, 452, 550, 662, 109, 226, 398, 11};
  299. CPPUNIT_ASSERT(std::equal(fastSet.begin(), fastSet.end(), std::begin(ans)));
  300. }
  301. // See when pieces < fastSetSize
  302. numPieces = 9;
  303. {
  304. auto fastSet = computeFastSet(ipaddr, numPieces, infoHash, fastSetSize);
  305. size_t ans[] = {8, 6, 7, 5, 1, 4, 0, 2, 3};
  306. CPPUNIT_ASSERT(std::equal(fastSet.begin(), fastSet.end(), std::begin(ans)));
  307. }
  308. }
  309. void BittorrentHelperTest::testGetFileEntries_multiFileUrlList()
  310. {
  311. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  312. load(A2_TEST_DIR "/url-list-multiFile.torrent", dctx, option_);
  313. // This is multi-file torrent.
  314. const std::vector<std::shared_ptr<FileEntry>>& fileEntries =
  315. dctx->getFileEntries();
  316. // There are 2 file entries.
  317. CPPUNIT_ASSERT_EQUAL((size_t)2, fileEntries.size());
  318. std::vector<std::shared_ptr<FileEntry>>::const_iterator itr =
  319. fileEntries.begin();
  320. const std::shared_ptr<FileEntry>& fileEntry1 = *itr;
  321. CPPUNIT_ASSERT_EQUAL(std::string("./aria2-test@/aria2@/src@/aria2c@"),
  322. fileEntry1->getPath());
  323. CPPUNIT_ASSERT_EQUAL(std::string("aria2-test@/aria2@/src@/aria2c@"),
  324. fileEntry1->getSuffixPath());
  325. const std::deque<std::string>& uris1 = fileEntry1->getRemainingUris();
  326. CPPUNIT_ASSERT_EQUAL((size_t)2, uris1.size());
  327. CPPUNIT_ASSERT_EQUAL(
  328. std::string(
  329. "http://localhost/dist/aria2-test%40/aria2%40/src%40/aria2c%40"),
  330. uris1[0]);
  331. CPPUNIT_ASSERT_EQUAL(
  332. std::string("http://mirror/dist/aria2-test%40/aria2%40/src%40/aria2c%40"),
  333. uris1[1]);
  334. ++itr;
  335. const std::shared_ptr<FileEntry>& fileEntry2 = *itr;
  336. CPPUNIT_ASSERT_EQUAL(std::string("./aria2-test@/aria2-0.2.2.tar.bz2"),
  337. fileEntry2->getPath());
  338. const std::deque<std::string>& uris2 = fileEntry2->getRemainingUris();
  339. CPPUNIT_ASSERT_EQUAL((size_t)2, uris2.size());
  340. CPPUNIT_ASSERT_EQUAL(
  341. std::string("http://localhost/dist/aria2-test%40/aria2-0.2.2.tar.bz2"),
  342. uris2[0]);
  343. CPPUNIT_ASSERT_EQUAL(
  344. std::string("http://mirror/dist/aria2-test%40/aria2-0.2.2.tar.bz2"),
  345. uris2[1]);
  346. }
  347. void BittorrentHelperTest::testGetFileEntries_singleFileUrlList()
  348. {
  349. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  350. load(A2_TEST_DIR "/url-list-singleFile.torrent", dctx, option_);
  351. // This is single-file torrent.
  352. const std::vector<std::shared_ptr<FileEntry>>& fileEntries =
  353. dctx->getFileEntries();
  354. // There are 1 file entries.
  355. CPPUNIT_ASSERT_EQUAL((size_t)1, fileEntries.size());
  356. const std::shared_ptr<FileEntry>& fileEntry1 = fileEntries.front();
  357. CPPUNIT_ASSERT_EQUAL(std::string("./aria2.tar.bz2"), fileEntry1->getPath());
  358. const std::deque<std::string>& uris1 = fileEntry1->getRemainingUris();
  359. CPPUNIT_ASSERT_EQUAL((size_t)1, uris1.size());
  360. CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/dist/aria2.tar.bz2"),
  361. uris1[0]);
  362. }
  363. void BittorrentHelperTest::testGetFileEntries_singleFileUrlListEndsWithSlash()
  364. {
  365. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  366. load(A2_TEST_DIR "/url-list-singleFileEndsWithSlash.torrent", dctx, option_);
  367. // This is single-file torrent.
  368. const std::vector<std::shared_ptr<FileEntry>>& fileEntries =
  369. dctx->getFileEntries();
  370. // There are 1 file entries.
  371. CPPUNIT_ASSERT_EQUAL((size_t)1, fileEntries.size());
  372. const std::shared_ptr<FileEntry>& fileEntry1 = fileEntries.front();
  373. CPPUNIT_ASSERT_EQUAL(std::string("./aria2@.tar.bz2"), fileEntry1->getPath());
  374. const std::deque<std::string>& uris1 = fileEntry1->getRemainingUris();
  375. CPPUNIT_ASSERT_EQUAL((size_t)1, uris1.size());
  376. CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/dist/aria2%40.tar.bz2"),
  377. uris1[0]);
  378. }
  379. void BittorrentHelperTest::testLoadFromMemory_multiFileNonUtf8Path()
  380. {
  381. auto path = List::g();
  382. path->append("path");
  383. path->append(fromHex("90a28a") + "E");
  384. auto file = Dict::g();
  385. file->put("length", Integer::g(1_k));
  386. file->put("path", std::move(path));
  387. auto files = List::g();
  388. files->append(std::move(file));
  389. auto info = Dict::g();
  390. info->put("files", std::move(files));
  391. info->put("piece length", Integer::g(1_k));
  392. info->put("pieces", "01234567890123456789");
  393. info->put("name", fromHex("1b") + "$B%O%m!<" + fromHex("1b") + "(B");
  394. Dict dict;
  395. dict.put("info", std::move(info));
  396. auto dctx = std::make_shared<DownloadContext>();
  397. loadFromMemory(bencode2::encode(&dict), dctx, option_, "default");
  398. auto& fe = dctx->getFirstFileEntry();
  399. CPPUNIT_ASSERT_EQUAL(
  400. std::string("./%1B%24B%25O%25m%21%3C%1B%28B/path/%90%A2%8AE"),
  401. fe->getPath());
  402. CPPUNIT_ASSERT_EQUAL(
  403. std::string("%1B%24B%25O%25m%21%3C%1B%28B/path/%90%A2%8AE"),
  404. fe->getSuffixPath());
  405. CPPUNIT_ASSERT_EQUAL(std::string("./%1B%24B%25O%25m%21%3C%1B%28B"),
  406. dctx->getBasePath());
  407. }
  408. void BittorrentHelperTest::testLoadFromMemory_singleFileNonUtf8Path()
  409. {
  410. auto info = Dict::g();
  411. info->put("piece length", Integer::g(1_k));
  412. info->put("pieces", "01234567890123456789");
  413. info->put("name", fromHex("90a28a") + "E");
  414. info->put("length", Integer::g(1_k));
  415. Dict dict;
  416. dict.put("info", std::move(info));
  417. auto dctx = std::make_shared<DownloadContext>();
  418. loadFromMemory(bencode2::encode(&dict), dctx, option_, "default");
  419. const std::shared_ptr<FileEntry>& fe = dctx->getFirstFileEntry();
  420. CPPUNIT_ASSERT_EQUAL(std::string("./%90%A2%8AE"), fe->getPath());
  421. CPPUNIT_ASSERT_EQUAL(std::string("%90%A2%8AE"), fe->getSuffixPath());
  422. }
  423. void BittorrentHelperTest::testLoadFromMemory()
  424. {
  425. std::string memory = "d8:announce36:http://aria.rednoah.com/"
  426. "announce.php13:announce-listll16:http://tracker1 "
  427. "el15:http://tracker2el15:http://"
  428. "tracker3ee7:comment17:REDNOAH.COM RULES13:creation "
  429. "datei1123456789e4:infod5:filesld6:lengthi284e4:pathl5:"
  430. "aria23:src6:aria2ceed6:lengthi100e4:pathl19:aria2-0.2."
  431. "2.tar.bz2eee4:name10:aria2-test12:piece "
  432. "lengthi128e6:pieces60:"
  433. "AAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCC"
  434. "CCCCCee";
  435. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  436. loadFromMemory(memory, dctx, option_, "default");
  437. std::string correctHash = "248d0a1cd08284299de78d5c1ed359bb46717d8c";
  438. CPPUNIT_ASSERT_EQUAL(correctHash, getInfoHashString(dctx));
  439. }
  440. void BittorrentHelperTest::testLoadFromMemory_somethingMissing()
  441. {
  442. // pieces missing
  443. try {
  444. std::string memory = "d8:announce36:http://aria.rednoah.com/"
  445. "announce.php4:infod4:name13:aria2.tar.bz26:"
  446. "lengthi262144eee";
  447. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  448. loadFromMemory(memory, dctx, option_, "default");
  449. CPPUNIT_FAIL("exception must be thrown.");
  450. }
  451. catch (Exception& e) {
  452. // OK
  453. }
  454. }
  455. void BittorrentHelperTest::testLoadFromMemory_overrideName()
  456. {
  457. std::string memory = "d8:announce36:http://aria.rednoah.com/"
  458. "announce.php13:announce-listll16:http://tracker1 "
  459. "el15:http://tracker2el15:http://"
  460. "tracker3ee7:comment17:REDNOAH.COM RULES13:creation "
  461. "datei1123456789e4:infod5:filesld6:lengthi284e4:pathl5:"
  462. "aria23:src6:aria2ceed6:lengthi100e4:pathl19:aria2-0.2."
  463. "2.tar.bz2eee4:name10:aria2-test12:piece "
  464. "lengthi128e6:pieces60:"
  465. "AAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCC"
  466. "CCCCCee";
  467. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  468. loadFromMemory(memory, dctx, option_, "default", "aria2-override.name");
  469. CPPUNIT_ASSERT_EQUAL(std::string("aria2-override.name"),
  470. getTorrentAttrs(dctx)->name);
  471. }
  472. void BittorrentHelperTest::testLoadFromMemory_multiFileDirTraversal()
  473. {
  474. std::string memory = "d8:announce27:http://example.com/"
  475. "announce4:infod5:filesld6:lengthi262144e4:pathl7:../"
  476. "dir14:dir28:file.imgeee4:name14:../name1/name212:piece "
  477. "lengthi262144e6:pieces20:00000000000000000000ee";
  478. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  479. try {
  480. loadFromMemory(memory, dctx, option_, "default");
  481. CPPUNIT_FAIL("Exception must be thrown.");
  482. }
  483. catch (RecoverableException& e) {
  484. // success
  485. }
  486. }
  487. void BittorrentHelperTest::testLoadFromMemory_singleFileDirTraversal()
  488. {
  489. std::string memory = "d8:announce27:http://example.com/"
  490. "announce4:infod4:name14:../name1/"
  491. "name26:lengthi262144e12:piece "
  492. "lengthi262144e6:pieces20:00000000000000000000ee";
  493. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  494. try {
  495. loadFromMemory(memory, dctx, option_, "default");
  496. }
  497. catch (RecoverableException& e) {
  498. // success
  499. }
  500. }
  501. void BittorrentHelperTest::testGetNodes()
  502. {
  503. {
  504. std::string memory = "d5:nodesl"
  505. "l11:192.168.0.1i6881ee"
  506. "l11:192.168.0.2i6882ee"
  507. "e4:infod4:name13:aria2.tar.bz26:lengthi262144e"
  508. "12:piece lengthi262144e"
  509. "6:pieces20:AAAAAAAAAAAAAAAAAAAA"
  510. "ee";
  511. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  512. loadFromMemory(memory, dctx, option_, "default");
  513. auto attrs = getTorrentAttrs(dctx);
  514. CPPUNIT_ASSERT_EQUAL((size_t)2, attrs->nodes.size());
  515. CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), attrs->nodes[0].first);
  516. CPPUNIT_ASSERT_EQUAL((uint16_t)6881, attrs->nodes[0].second);
  517. CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.2"), attrs->nodes[1].first);
  518. CPPUNIT_ASSERT_EQUAL((uint16_t)6882, attrs->nodes[1].second);
  519. }
  520. {
  521. // empty hostname
  522. std::string memory = "d5:nodesl"
  523. "l1: i6881ee"
  524. "l11:192.168.0.2i6882ee"
  525. "e4:infod4:name13:aria2.tar.bz26:lengthi262144e"
  526. "12:piece lengthi262144e"
  527. "6:pieces20:AAAAAAAAAAAAAAAAAAAA"
  528. "ee";
  529. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  530. loadFromMemory(memory, dctx, option_, "default");
  531. auto attrs = getTorrentAttrs(dctx);
  532. CPPUNIT_ASSERT_EQUAL((size_t)1, attrs->nodes.size());
  533. CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.2"), attrs->nodes[0].first);
  534. CPPUNIT_ASSERT_EQUAL((uint16_t)6882, attrs->nodes[0].second);
  535. }
  536. {
  537. // bad port
  538. std::string memory = "d5:nodesl"
  539. "l11:192.168.0.11:xe"
  540. "l11:192.168.0.2i6882ee"
  541. "e4:infod4:name13:aria2.tar.bz26:lengthi262144e"
  542. "12:piece lengthi262144e"
  543. "6:pieces20:AAAAAAAAAAAAAAAAAAAA"
  544. "ee";
  545. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  546. loadFromMemory(memory, dctx, option_, "default");
  547. auto attrs = getTorrentAttrs(dctx);
  548. CPPUNIT_ASSERT_EQUAL((size_t)1, attrs->nodes.size());
  549. CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.2"), attrs->nodes[0].first);
  550. CPPUNIT_ASSERT_EQUAL((uint16_t)6882, attrs->nodes[0].second);
  551. }
  552. {
  553. // port missing
  554. std::string memory = "d5:nodesl"
  555. "l11:192.168.0.1e"
  556. "l11:192.168.0.2i6882ee"
  557. "e4:infod4:name13:aria2.tar.bz26:lengthi262144e"
  558. "12:piece lengthi262144e"
  559. "6:pieces20:AAAAAAAAAAAAAAAAAAAA"
  560. "ee";
  561. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  562. loadFromMemory(memory, dctx, option_, "default");
  563. auto attrs = getTorrentAttrs(dctx);
  564. CPPUNIT_ASSERT_EQUAL((size_t)1, attrs->nodes.size());
  565. CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.2"), attrs->nodes[0].first);
  566. CPPUNIT_ASSERT_EQUAL((uint16_t)6882, attrs->nodes[0].second);
  567. }
  568. {
  569. // nodes is not a list
  570. std::string memory = "d5:nodes"
  571. "l11:192.168.0.1e"
  572. "4:infod4:name13:aria2.tar.bz26:lengthi262144e"
  573. "12:piece lengthi262144e"
  574. "6:pieces20:AAAAAAAAAAAAAAAAAAAA"
  575. "ee";
  576. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  577. loadFromMemory(memory, dctx, option_, "default");
  578. auto attrs = getTorrentAttrs(dctx);
  579. CPPUNIT_ASSERT_EQUAL((size_t)0, attrs->nodes.size());
  580. }
  581. {
  582. // the element of node is not Data
  583. std::string memory = "d5:nodesl"
  584. "ll11:192.168.0.1i6881eee"
  585. "l11:192.168.0.2i6882ee"
  586. "e4:infod4:name13:aria2.tar.bz26:lengthi262144e"
  587. "12:piece lengthi262144e"
  588. "6:pieces20:AAAAAAAAAAAAAAAAAAAA"
  589. "ee";
  590. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  591. loadFromMemory(memory, dctx, option_, "default");
  592. auto attrs = getTorrentAttrs(dctx);
  593. CPPUNIT_ASSERT_EQUAL((size_t)1, attrs->nodes.size());
  594. CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.2"), attrs->nodes[0].first);
  595. CPPUNIT_ASSERT_EQUAL((uint16_t)6882, attrs->nodes[0].second);
  596. }
  597. }
  598. void BittorrentHelperTest::testGetBasePath()
  599. {
  600. std::shared_ptr<DownloadContext> singleCtx(new DownloadContext());
  601. load(A2_TEST_DIR "/single.torrent", singleCtx, option_);
  602. singleCtx->setFilePathWithIndex(1, "new-path");
  603. CPPUNIT_ASSERT_EQUAL(std::string("new-path"), singleCtx->getBasePath());
  604. option_->put(PREF_DIR, "downloads");
  605. std::shared_ptr<DownloadContext> multiCtx(new DownloadContext());
  606. load(A2_TEST_DIR "/test.torrent", multiCtx, option_);
  607. CPPUNIT_ASSERT_EQUAL(std::string("downloads/aria2-test"),
  608. multiCtx->getBasePath());
  609. }
  610. void BittorrentHelperTest::testSetFileFilter_single()
  611. {
  612. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  613. load(A2_TEST_DIR "/single.torrent", dctx, option_);
  614. CPPUNIT_ASSERT(dctx->getFirstFileEntry()->isRequested());
  615. dctx->setFileFilter(SegList<int>());
  616. CPPUNIT_ASSERT(dctx->getFirstFileEntry()->isRequested());
  617. dctx->setFileFilter(util::parseIntSegments("1,2"));
  618. CPPUNIT_ASSERT(dctx->getFirstFileEntry()->isRequested());
  619. // For single file torrent, file is always selected whatever range
  620. // is passed.
  621. dctx->setFileFilter(util::parseIntSegments("2,3"));
  622. CPPUNIT_ASSERT(dctx->getFirstFileEntry()->isRequested());
  623. }
  624. void BittorrentHelperTest::testSetFileFilter_multi()
  625. {
  626. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  627. load(A2_TEST_DIR "/test.torrent", dctx, option_);
  628. CPPUNIT_ASSERT(dctx->getFileEntries()[0]->isRequested());
  629. CPPUNIT_ASSERT(dctx->getFileEntries()[1]->isRequested());
  630. dctx->setFileFilter(SegList<int>());
  631. CPPUNIT_ASSERT(dctx->getFileEntries()[0]->isRequested());
  632. CPPUNIT_ASSERT(dctx->getFileEntries()[1]->isRequested());
  633. dctx->setFileFilter(util::parseIntSegments("2,3"));
  634. CPPUNIT_ASSERT(!dctx->getFileEntries()[0]->isRequested());
  635. CPPUNIT_ASSERT(dctx->getFileEntries()[1]->isRequested());
  636. dctx->setFileFilter(util::parseIntSegments("3,4"));
  637. CPPUNIT_ASSERT(!dctx->getFileEntries()[0]->isRequested());
  638. CPPUNIT_ASSERT(!dctx->getFileEntries()[1]->isRequested());
  639. dctx->setFileFilter(util::parseIntSegments("1,2"));
  640. CPPUNIT_ASSERT(dctx->getFileEntries()[0]->isRequested());
  641. CPPUNIT_ASSERT(dctx->getFileEntries()[1]->isRequested());
  642. }
  643. void BittorrentHelperTest::testUTF8Torrent()
  644. {
  645. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  646. load(A2_TEST_DIR "/utf8.torrent", dctx, option_);
  647. CPPUNIT_ASSERT_EQUAL(std::string("name in utf-8"),
  648. getTorrentAttrs(dctx)->name);
  649. CPPUNIT_ASSERT_EQUAL(std::string("./name in utf-8/path in utf-8"),
  650. dctx->getFirstFileEntry()->getPath());
  651. CPPUNIT_ASSERT_EQUAL(std::string("This is utf8 comment."),
  652. getTorrentAttrs(dctx)->comment);
  653. }
  654. void BittorrentHelperTest::testEtc()
  655. {
  656. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  657. load(A2_TEST_DIR "/test.torrent", dctx, option_);
  658. CPPUNIT_ASSERT_EQUAL(std::string("REDNOAH.COM RULES"),
  659. getTorrentAttrs(dctx)->comment);
  660. CPPUNIT_ASSERT_EQUAL(std::string("aria2"), getTorrentAttrs(dctx)->createdBy);
  661. CPPUNIT_ASSERT_EQUAL((time_t)1123456789, getTorrentAttrs(dctx)->creationDate);
  662. }
  663. void BittorrentHelperTest::testCheckBitfield()
  664. {
  665. unsigned char bitfield[] = {0xff, 0xe0};
  666. checkBitfield(bitfield, sizeof(bitfield), 11);
  667. try {
  668. checkBitfield(bitfield, sizeof(bitfield), 17);
  669. CPPUNIT_FAIL("exception must be thrown.");
  670. }
  671. catch (RecoverableException& e) {
  672. // success
  673. }
  674. // Change last byte
  675. bitfield[1] = 0xf0;
  676. try {
  677. checkBitfield(bitfield, sizeof(bitfield), 11);
  678. CPPUNIT_FAIL("exception must be thrown.");
  679. }
  680. catch (RecoverableException& e) {
  681. // success
  682. }
  683. }
  684. void BittorrentHelperTest::testMetadata()
  685. {
  686. auto dctx = std::make_shared<DownloadContext>();
  687. load(A2_TEST_DIR "/test.torrent", dctx, option_);
  688. std::string torrentData = readFile(A2_TEST_DIR "/test.torrent");
  689. auto tr = bencode2::decode(torrentData);
  690. auto infoDic = downcast<Dict>(tr)->get("info");
  691. std::string metadata = bencode2::encode(infoDic);
  692. auto attrs = getTorrentAttrs(dctx);
  693. CPPUNIT_ASSERT(metadata == attrs->metadata);
  694. CPPUNIT_ASSERT_EQUAL(metadata.size(), attrs->metadataSize);
  695. }
  696. void BittorrentHelperTest::testParseMagnet()
  697. {
  698. std::string magnet =
  699. "magnet:?xt=urn:btih:248d0a1cd08284299de78d5c1ed359bb46717d8c&dn=aria2"
  700. "&tr=http://tracker1&tr=http://tracker2";
  701. auto attrs = bittorrent::parseMagnet(magnet);
  702. CPPUNIT_ASSERT_EQUAL(std::string("248d0a1cd08284299de78d5c1ed359bb46717d8c"),
  703. util::toHex(attrs->infoHash));
  704. CPPUNIT_ASSERT_EQUAL(std::string("[METADATA]aria2"), attrs->name);
  705. CPPUNIT_ASSERT_EQUAL((size_t)2, attrs->announceList.size());
  706. CPPUNIT_ASSERT_EQUAL(std::string("http://tracker1"),
  707. attrs->announceList[0][0]);
  708. CPPUNIT_ASSERT_EQUAL(std::string("http://tracker2"),
  709. attrs->announceList[1][0]);
  710. magnet = "magnet:?xt=urn:btih:248d0a1cd08284299de78d5c1ed359bb46717d8c";
  711. attrs = bittorrent::parseMagnet(magnet);
  712. CPPUNIT_ASSERT_EQUAL(
  713. std::string("[METADATA]248d0a1cd08284299de78d5c1ed359bb46717d8c"),
  714. attrs->name);
  715. CPPUNIT_ASSERT(attrs->announceList.empty());
  716. magnet = "magnet:?xt=urn:sha1:7899bdb90a026c746f3cbc10839dd9b2a2a3e985&"
  717. "xt=urn:btih:248d0a1cd08284299de78d5c1ed359bb46717d8c";
  718. attrs = bittorrent::parseMagnet(magnet);
  719. CPPUNIT_ASSERT_EQUAL(std::string("248d0a1cd08284299de78d5c1ed359bb46717d8c"),
  720. util::toHex(attrs->infoHash));
  721. }
  722. void BittorrentHelperTest::testParseMagnet_base32()
  723. {
  724. std::string infoHash = "248d0a1cd08284299de78d5c1ed359bb46717d8c";
  725. std::string base32InfoHash = base32::encode(fromHex(infoHash));
  726. std::string magnet = "magnet:?xt=urn:btih:" + base32InfoHash + "&dn=aria2";
  727. auto attrs = bittorrent::parseMagnet(magnet);
  728. CPPUNIT_ASSERT_EQUAL(std::string("248d0a1cd08284299de78d5c1ed359bb46717d8c"),
  729. util::toHex(attrs->infoHash));
  730. }
  731. void BittorrentHelperTest::testMetadata2Torrent()
  732. {
  733. TorrentAttribute attrs;
  734. std::string metadata = "METADATA";
  735. CPPUNIT_ASSERT_EQUAL(std::string("d4:infoMETADATAe"),
  736. metadata2Torrent(metadata, &attrs));
  737. attrs.announceList.push_back(std::vector<std::string>());
  738. attrs.announceList[0].push_back("http://localhost/announce");
  739. CPPUNIT_ASSERT_EQUAL(std::string("d"
  740. "13:announce-list"
  741. "ll25:http://localhost/announceee"
  742. "4:infoMETADATA"
  743. "e"),
  744. metadata2Torrent(metadata, &attrs));
  745. }
  746. void BittorrentHelperTest::testTorrent2Magnet()
  747. {
  748. std::shared_ptr<DownloadContext> dctx(new DownloadContext());
  749. load(A2_TEST_DIR "/test.torrent", dctx, option_);
  750. CPPUNIT_ASSERT_EQUAL(
  751. std::string("magnet:?xt=urn:btih:248D0A1CD08284299DE78D5C1ED359BB46717D8C"
  752. "&dn=aria2-test"
  753. "&tr=http%3A%2F%2Ftracker1"
  754. "&tr=http%3A%2F%2Ftracker2"
  755. "&tr=http%3A%2F%2Ftracker3"),
  756. torrent2Magnet(getTorrentAttrs(dctx)));
  757. }
  758. void BittorrentHelperTest::testExtractPeerFromString()
  759. {
  760. std::string hextext = "100210354527354678541237324732171ae1";
  761. hextext += "20010db8bd0501d2288a1fc0000110ee1ae2";
  762. std::string peersstr = "36:" + fromHex(hextext);
  763. auto str = bencode2::decode(peersstr);
  764. std::deque<std::shared_ptr<Peer>> peers;
  765. extractPeer(str.get(), AF_INET6, std::back_inserter(peers));
  766. CPPUNIT_ASSERT_EQUAL((size_t)2, peers.size());
  767. CPPUNIT_ASSERT_EQUAL(std::string("1002:1035:4527:3546:7854:1237:3247:3217"),
  768. peers[0]->getIPAddress());
  769. CPPUNIT_ASSERT_EQUAL((uint16_t)6881, peers[0]->getPort());
  770. CPPUNIT_ASSERT_EQUAL(std::string("2001:db8:bd05:1d2:288a:1fc0:1:10ee"),
  771. peers[1]->getIPAddress());
  772. CPPUNIT_ASSERT_EQUAL((uint16_t)6882, peers[1]->getPort());
  773. hextext = "c0a800011ae1";
  774. hextext += "c0a800021ae2";
  775. peersstr = "12:" + fromHex(hextext);
  776. str = bencode2::decode(peersstr);
  777. peers.clear();
  778. extractPeer(str.get(), AF_INET, std::back_inserter(peers));
  779. CPPUNIT_ASSERT_EQUAL((size_t)2, peers.size());
  780. CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), peers[0]->getIPAddress());
  781. CPPUNIT_ASSERT_EQUAL((uint16_t)6881, peers[0]->getPort());
  782. CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.2"), peers[1]->getIPAddress());
  783. CPPUNIT_ASSERT_EQUAL((uint16_t)6882, peers[1]->getPort());
  784. }
  785. void BittorrentHelperTest::testExtractPeerFromList()
  786. {
  787. std::string peersString =
  788. "d5:peersld2:ip11:192.168.0.17:peer id20:aria2-00000000000000"
  789. "4:porti2006eeee";
  790. auto dict = bencode2::decode(peersString);
  791. std::deque<std::shared_ptr<Peer>> peers;
  792. extractPeer(downcast<Dict>(dict)->get("peers"), AF_INET,
  793. std::back_inserter(peers));
  794. CPPUNIT_ASSERT_EQUAL((size_t)1, peers.size());
  795. auto& peer = *peers.begin();
  796. CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), peer->getIPAddress());
  797. CPPUNIT_ASSERT_EQUAL((uint16_t)2006, peer->getPort());
  798. }
  799. void BittorrentHelperTest::testExtract2PeersFromList()
  800. {
  801. std::string peersString =
  802. "d5:peersld2:ip11:192.168.0.17:peer id20:aria2-00000000000000"
  803. "4:porti65535eed2:ip11:192.168.0.27:peer id20:aria2-00000000000000"
  804. "4:porti2007eeee";
  805. auto dict = bencode2::decode(peersString);
  806. std::deque<std::shared_ptr<Peer>> peers;
  807. extractPeer(downcast<Dict>(dict)->get("peers"), AF_INET,
  808. std::back_inserter(peers));
  809. CPPUNIT_ASSERT_EQUAL((size_t)2, peers.size());
  810. auto& peer = *peers.begin();
  811. CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), peer->getIPAddress());
  812. CPPUNIT_ASSERT_EQUAL((uint16_t)65535, peer->getPort());
  813. peer = *(peers.begin() + 1);
  814. CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.2"), peer->getIPAddress());
  815. CPPUNIT_ASSERT_EQUAL((uint16_t)2007, peer->getPort());
  816. }
  817. void BittorrentHelperTest::testPackcompact()
  818. {
  819. unsigned char compact[COMPACT_LEN_IPV6];
  820. CPPUNIT_ASSERT_EQUAL(
  821. (size_t)18,
  822. packcompact(compact, "1002:1035:4527:3546:7854:1237:3247:3217", 6881));
  823. CPPUNIT_ASSERT_EQUAL(std::string("100210354527354678541237324732171ae1"),
  824. util::toHex(compact, 18));
  825. CPPUNIT_ASSERT_EQUAL((size_t)6, packcompact(compact, "192.168.0.1", 6881));
  826. CPPUNIT_ASSERT_EQUAL(std::string("c0a800011ae1"), util::toHex(compact, 6));
  827. CPPUNIT_ASSERT_EQUAL((size_t)0, packcompact(compact, "badaddr", 6881));
  828. }
  829. void BittorrentHelperTest::testUnpackcompact()
  830. {
  831. unsigned char compact6[] = {0x10, 0x02, 0x10, 0x35, 0x45, 0x27,
  832. 0x35, 0x46, 0x78, 0x54, 0x12, 0x37,
  833. 0x32, 0x47, 0x32, 0x17, 0x1A, 0xE1};
  834. std::pair<std::string, uint16_t> p = unpackcompact(compact6, AF_INET6);
  835. CPPUNIT_ASSERT_EQUAL(std::string("1002:1035:4527:3546:7854:1237:3247:3217"),
  836. p.first);
  837. CPPUNIT_ASSERT_EQUAL((uint16_t)6881, p.second);
  838. unsigned char compact[] = {0xC0, 0xa8, 0x00, 0x01, 0x1A, 0xE1};
  839. p = unpackcompact(compact, AF_INET);
  840. CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), p.first);
  841. CPPUNIT_ASSERT_EQUAL((uint16_t)6881, p.second);
  842. }
  843. void BittorrentHelperTest::testRemoveAnnounceUri()
  844. {
  845. TorrentAttribute attrs;
  846. std::vector<std::string> tier1;
  847. tier1.push_back("http://host1/announce");
  848. std::vector<std::string> tier2;
  849. tier2.push_back("http://host2/announce");
  850. tier2.push_back("http://host3/announce");
  851. attrs.announceList.push_back(tier1);
  852. attrs.announceList.push_back(tier2);
  853. std::vector<std::string> removeUris;
  854. removeUris.push_back(tier1[0]);
  855. removeUris.push_back(tier2[0]);
  856. removeAnnounceUri(&attrs, removeUris);
  857. CPPUNIT_ASSERT_EQUAL((size_t)1, attrs.announceList.size());
  858. CPPUNIT_ASSERT_EQUAL(std::string("http://host3/announce"),
  859. attrs.announceList[0][0]);
  860. removeUris.clear();
  861. removeUris.push_back("*");
  862. removeAnnounceUri(&attrs, removeUris);
  863. CPPUNIT_ASSERT(attrs.announceList.empty());
  864. }
  865. void BittorrentHelperTest::testAddAnnounceUri()
  866. {
  867. TorrentAttribute attrs;
  868. std::vector<std::string> addUris;
  869. addUris.push_back("http://host1/announce");
  870. addUris.push_back("http://host2/announce");
  871. addAnnounceUri(&attrs, addUris);
  872. CPPUNIT_ASSERT_EQUAL((size_t)2, attrs.announceList.size());
  873. CPPUNIT_ASSERT_EQUAL((size_t)1, attrs.announceList[0].size());
  874. CPPUNIT_ASSERT_EQUAL(std::string("http://host1/announce"),
  875. attrs.announceList[0][0]);
  876. CPPUNIT_ASSERT_EQUAL((size_t)1, attrs.announceList[1].size());
  877. CPPUNIT_ASSERT_EQUAL(std::string("http://host2/announce"),
  878. attrs.announceList[1][0]);
  879. }
  880. void BittorrentHelperTest::testAdjustAnnounceUri()
  881. {
  882. TorrentAttribute attrs;
  883. std::vector<std::string> tier1;
  884. tier1.push_back("http://host1/announce");
  885. std::vector<std::string> tier2;
  886. tier2.push_back("http://host2/announce");
  887. tier2.push_back("http://host3/announce");
  888. attrs.announceList.push_back(tier1);
  889. attrs.announceList.push_back(tier2);
  890. std::shared_ptr<Option> option(new Option());
  891. option->put(PREF_BT_TRACKER, "http://host1/announce,http://host4/announce");
  892. option->put(PREF_BT_EXCLUDE_TRACKER,
  893. "http://host1/announce,http://host2/announce");
  894. adjustAnnounceUri(&attrs, option);
  895. CPPUNIT_ASSERT_EQUAL((size_t)3, attrs.announceList.size());
  896. CPPUNIT_ASSERT_EQUAL((size_t)1, attrs.announceList[0].size());
  897. CPPUNIT_ASSERT_EQUAL(std::string("http://host3/announce"),
  898. attrs.announceList[0][0]);
  899. CPPUNIT_ASSERT_EQUAL((size_t)1, attrs.announceList[1].size());
  900. CPPUNIT_ASSERT_EQUAL(std::string("http://host1/announce"),
  901. attrs.announceList[1][0]);
  902. CPPUNIT_ASSERT_EQUAL((size_t)1, attrs.announceList[2].size());
  903. CPPUNIT_ASSERT_EQUAL(std::string("http://host4/announce"),
  904. attrs.announceList[2][0]);
  905. }
  906. } // namespace bittorrent
  907. } // namespace aria2