BittorrentHelperTest.cc 39 KB

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