DefaultPieceStorageTest.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. #include "DefaultPieceStorage.h"
  2. #include <cppunit/extensions/HelperMacros.h>
  3. #include "util.h"
  4. #include "Exception.h"
  5. #include "Piece.h"
  6. #include "Peer.h"
  7. #include "Option.h"
  8. #include "FileEntry.h"
  9. #include "RarestPieceSelector.h"
  10. #include "InorderPieceSelector.h"
  11. #include "DownloadContext.h"
  12. #include "bittorrent_helper.h"
  13. #include "DiskAdaptor.h"
  14. #include "DiskWriterFactory.h"
  15. #include "PieceStatMan.h"
  16. #include "prefs.h"
  17. namespace aria2 {
  18. class DefaultPieceStorageTest : public CppUnit::TestFixture {
  19. CPPUNIT_TEST_SUITE(DefaultPieceStorageTest);
  20. CPPUNIT_TEST(testGetTotalLength);
  21. CPPUNIT_TEST(testGetMissingPiece);
  22. CPPUNIT_TEST(testGetMissingPiece_many);
  23. CPPUNIT_TEST(testGetMissingPiece_excludedIndexes);
  24. CPPUNIT_TEST(testGetMissingPiece_manyWithExcludedIndexes);
  25. CPPUNIT_TEST(testGetMissingFastPiece);
  26. CPPUNIT_TEST(testGetMissingFastPiece_excludedIndexes);
  27. CPPUNIT_TEST(testHasMissingPiece);
  28. CPPUNIT_TEST(testCompletePiece);
  29. CPPUNIT_TEST(testGetPiece);
  30. CPPUNIT_TEST(testGetPieceInUsedPieces);
  31. CPPUNIT_TEST(testGetPieceCompletedPiece);
  32. CPPUNIT_TEST(testCancelPiece);
  33. CPPUNIT_TEST(testMarkPiecesDone);
  34. CPPUNIT_TEST(testGetCompletedLength);
  35. CPPUNIT_TEST(testGetFilteredCompletedLength);
  36. CPPUNIT_TEST(testGetNextUsedIndex);
  37. CPPUNIT_TEST_SUITE_END();
  38. private:
  39. std::shared_ptr<DownloadContext> dctx_;
  40. std::shared_ptr<Peer> peer;
  41. std::shared_ptr<Option> option_;
  42. std::unique_ptr<PieceSelector> pieceSelector_;
  43. public:
  44. void setUp()
  45. {
  46. option_ = std::make_shared<Option>();
  47. option_->put(PREF_DIR, ".");
  48. dctx_ = std::make_shared<DownloadContext>();
  49. bittorrent::load(A2_TEST_DIR "/test.torrent", dctx_, option_);
  50. peer = std::make_shared<Peer>("192.168.0.1", 6889);
  51. peer->allocateSessionResource(dctx_->getPieceLength(),
  52. dctx_->getTotalLength());
  53. pieceSelector_ = make_unique<InorderPieceSelector>();
  54. }
  55. void testGetTotalLength();
  56. void testGetMissingPiece();
  57. void testGetMissingPiece_many();
  58. void testGetMissingPiece_excludedIndexes();
  59. void testGetMissingPiece_manyWithExcludedIndexes();
  60. void testGetMissingFastPiece();
  61. void testGetMissingFastPiece_excludedIndexes();
  62. void testHasMissingPiece();
  63. void testCompletePiece();
  64. void testGetPiece();
  65. void testGetPieceInUsedPieces();
  66. void testGetPieceCompletedPiece();
  67. void testCancelPiece();
  68. void testMarkPiecesDone();
  69. void testGetCompletedLength();
  70. void testGetFilteredCompletedLength();
  71. void testGetNextUsedIndex();
  72. };
  73. CPPUNIT_TEST_SUITE_REGISTRATION(DefaultPieceStorageTest);
  74. void DefaultPieceStorageTest::testGetTotalLength()
  75. {
  76. DefaultPieceStorage pss(dctx_, option_.get());
  77. CPPUNIT_ASSERT_EQUAL((int64_t)384LL, pss.getTotalLength());
  78. }
  79. void DefaultPieceStorageTest::testGetMissingPiece()
  80. {
  81. DefaultPieceStorage pss(dctx_, option_.get());
  82. pss.setPieceSelector(std::move(pieceSelector_));
  83. peer->setAllBitfield();
  84. auto piece = pss.getMissingPiece(peer, 1);
  85. CPPUNIT_ASSERT_EQUAL(std::string("piece: index=0, length=128"),
  86. piece->toString());
  87. CPPUNIT_ASSERT(piece->usedBy(1));
  88. piece = pss.getMissingPiece(peer, 1);
  89. CPPUNIT_ASSERT_EQUAL(std::string("piece: index=1, length=128"),
  90. piece->toString());
  91. piece = pss.getMissingPiece(peer, 1);
  92. CPPUNIT_ASSERT_EQUAL(std::string("piece: index=2, length=128"),
  93. piece->toString());
  94. piece = pss.getMissingPiece(peer, 1);
  95. CPPUNIT_ASSERT(!piece);
  96. }
  97. void DefaultPieceStorageTest::testGetMissingPiece_many()
  98. {
  99. DefaultPieceStorage pss(dctx_, option_.get());
  100. pss.setPieceSelector(std::move(pieceSelector_));
  101. peer->setAllBitfield();
  102. std::vector<std::shared_ptr<Piece>> pieces;
  103. pss.getMissingPiece(pieces, 2, peer, 1);
  104. CPPUNIT_ASSERT_EQUAL((size_t)2, pieces.size());
  105. CPPUNIT_ASSERT_EQUAL(std::string("piece: index=0, length=128"),
  106. pieces[0]->toString());
  107. CPPUNIT_ASSERT(pieces[0]->usedBy(1));
  108. CPPUNIT_ASSERT_EQUAL(std::string("piece: index=1, length=128"),
  109. pieces[1]->toString());
  110. pieces.clear();
  111. pss.getMissingPiece(pieces, 2, peer, 1);
  112. CPPUNIT_ASSERT_EQUAL((size_t)1, pieces.size());
  113. CPPUNIT_ASSERT_EQUAL(std::string("piece: index=2, length=128"),
  114. pieces[0]->toString());
  115. }
  116. void DefaultPieceStorageTest::testGetMissingPiece_excludedIndexes()
  117. {
  118. DefaultPieceStorage pss(dctx_, option_.get());
  119. pss.setPieceSelector(std::move(pieceSelector_));
  120. pss.setEndGamePieceNum(0);
  121. peer->setAllBitfield();
  122. std::vector<size_t> excludedIndexes;
  123. excludedIndexes.push_back(1);
  124. auto piece = pss.getMissingPiece(peer, excludedIndexes, 1);
  125. CPPUNIT_ASSERT_EQUAL(std::string("piece: index=0, length=128"),
  126. piece->toString());
  127. piece = pss.getMissingPiece(peer, excludedIndexes, 1);
  128. CPPUNIT_ASSERT_EQUAL(std::string("piece: index=2, length=128"),
  129. piece->toString());
  130. piece = pss.getMissingPiece(peer, excludedIndexes, 1);
  131. CPPUNIT_ASSERT(!piece);
  132. }
  133. void DefaultPieceStorageTest::testGetMissingPiece_manyWithExcludedIndexes()
  134. {
  135. DefaultPieceStorage pss(dctx_, option_.get());
  136. pss.setPieceSelector(std::move(pieceSelector_));
  137. peer->setAllBitfield();
  138. std::vector<size_t> excludedIndexes;
  139. excludedIndexes.push_back(1);
  140. std::vector<std::shared_ptr<Piece>> pieces;
  141. pss.getMissingPiece(pieces, 2, peer, excludedIndexes, 1);
  142. CPPUNIT_ASSERT_EQUAL((size_t)2, pieces.size());
  143. CPPUNIT_ASSERT_EQUAL(std::string("piece: index=0, length=128"),
  144. pieces[0]->toString());
  145. CPPUNIT_ASSERT_EQUAL(std::string("piece: index=2, length=128"),
  146. pieces[1]->toString());
  147. pieces.clear();
  148. pss.getMissingPiece(pieces, 2, peer, excludedIndexes, 1);
  149. CPPUNIT_ASSERT(pieces.empty());
  150. }
  151. void DefaultPieceStorageTest::testGetMissingFastPiece()
  152. {
  153. DefaultPieceStorage pss(dctx_, option_.get());
  154. pss.setPieceSelector(std::move(pieceSelector_));
  155. pss.setEndGamePieceNum(0);
  156. peer->setAllBitfield();
  157. peer->setFastExtensionEnabled(true);
  158. peer->addPeerAllowedIndex(2);
  159. auto piece = pss.getMissingFastPiece(peer, 1);
  160. CPPUNIT_ASSERT_EQUAL(std::string("piece: index=2, length=128"),
  161. piece->toString());
  162. CPPUNIT_ASSERT(!pss.getMissingFastPiece(peer, 1));
  163. }
  164. void DefaultPieceStorageTest::testGetMissingFastPiece_excludedIndexes()
  165. {
  166. DefaultPieceStorage pss(dctx_, option_.get());
  167. pss.setPieceSelector(std::move(pieceSelector_));
  168. pss.setEndGamePieceNum(0);
  169. peer->setAllBitfield();
  170. peer->setFastExtensionEnabled(true);
  171. peer->addPeerAllowedIndex(1);
  172. peer->addPeerAllowedIndex(2);
  173. std::vector<size_t> excludedIndexes;
  174. excludedIndexes.push_back(2);
  175. auto piece = pss.getMissingFastPiece(peer, excludedIndexes, 1);
  176. CPPUNIT_ASSERT_EQUAL(std::string("piece: index=1, length=128"),
  177. piece->toString());
  178. CPPUNIT_ASSERT(!pss.getMissingFastPiece(peer, excludedIndexes, 1));
  179. }
  180. void DefaultPieceStorageTest::testHasMissingPiece()
  181. {
  182. DefaultPieceStorage pss(dctx_, option_.get());
  183. CPPUNIT_ASSERT(!pss.hasMissingPiece(peer));
  184. peer->setAllBitfield();
  185. CPPUNIT_ASSERT(pss.hasMissingPiece(peer));
  186. }
  187. void DefaultPieceStorageTest::testCompletePiece()
  188. {
  189. DefaultPieceStorage pss(dctx_, option_.get());
  190. pss.setPieceSelector(std::move(pieceSelector_));
  191. pss.setEndGamePieceNum(0);
  192. peer->setAllBitfield();
  193. auto piece = pss.getMissingPiece(peer, 1);
  194. CPPUNIT_ASSERT_EQUAL(std::string("piece: index=0, length=128"),
  195. piece->toString());
  196. CPPUNIT_ASSERT_EQUAL((int64_t)0LL, pss.getCompletedLength());
  197. pss.completePiece(piece);
  198. CPPUNIT_ASSERT_EQUAL((int64_t)128LL, pss.getCompletedLength());
  199. auto incompletePiece = pss.getMissingPiece(peer, 1);
  200. incompletePiece->completeBlock(0);
  201. CPPUNIT_ASSERT_EQUAL((int64_t)256LL, pss.getCompletedLength());
  202. }
  203. void DefaultPieceStorageTest::testGetPiece()
  204. {
  205. DefaultPieceStorage pss(dctx_, option_.get());
  206. auto pieceGot = pss.getPiece(0);
  207. CPPUNIT_ASSERT_EQUAL((size_t)0, pieceGot->getIndex());
  208. CPPUNIT_ASSERT_EQUAL((int64_t)128, pieceGot->getLength());
  209. CPPUNIT_ASSERT_EQUAL(false, pieceGot->pieceComplete());
  210. }
  211. void DefaultPieceStorageTest::testGetPieceInUsedPieces()
  212. {
  213. DefaultPieceStorage pss(dctx_, option_.get());
  214. auto piece = std::make_shared<Piece>(0, 128);
  215. piece->completeBlock(0);
  216. pss.addUsedPiece(piece);
  217. auto pieceGot = pss.getPiece(0);
  218. CPPUNIT_ASSERT_EQUAL((size_t)0, pieceGot->getIndex());
  219. CPPUNIT_ASSERT_EQUAL((int64_t)128, pieceGot->getLength());
  220. CPPUNIT_ASSERT_EQUAL((size_t)1, pieceGot->countCompleteBlock());
  221. }
  222. void DefaultPieceStorageTest::testGetPieceCompletedPiece()
  223. {
  224. DefaultPieceStorage pss(dctx_, option_.get());
  225. auto piece = std::make_shared<Piece>(0, 128);
  226. pss.completePiece(piece);
  227. auto pieceGot = pss.getPiece(0);
  228. CPPUNIT_ASSERT_EQUAL((size_t)0, pieceGot->getIndex());
  229. CPPUNIT_ASSERT_EQUAL((int64_t)128, pieceGot->getLength());
  230. CPPUNIT_ASSERT_EQUAL(true, pieceGot->pieceComplete());
  231. }
  232. void DefaultPieceStorageTest::testCancelPiece()
  233. {
  234. size_t pieceLength = 256_k;
  235. int64_t totalLength = 32 * pieceLength; // <-- make the number of piece
  236. // greater than END_GAME_PIECE_NUM
  237. std::deque<std::string> uris1;
  238. uris1.push_back("http://localhost/src/file1.txt");
  239. auto file1 =
  240. std::make_shared<FileEntry>("src/file1.txt", totalLength, 0 /*, uris1*/);
  241. auto dctx = std::make_shared<DownloadContext>(pieceLength, totalLength,
  242. "src/file1.txt");
  243. DefaultPieceStorage ps{dctx, option_.get()};
  244. auto p = ps.getMissingPiece(0, 1);
  245. p->completeBlock(0);
  246. ps.cancelPiece(p, 1);
  247. auto p2 = ps.getMissingPiece(0, 2);
  248. CPPUNIT_ASSERT(p2->hasBlock(0));
  249. CPPUNIT_ASSERT(p2->usedBy(2));
  250. CPPUNIT_ASSERT(!p2->usedBy(1));
  251. }
  252. void DefaultPieceStorageTest::testMarkPiecesDone()
  253. {
  254. size_t pieceLength = 256_k;
  255. int64_t totalLength = 4_m;
  256. auto dctx = std::make_shared<DownloadContext>(pieceLength, totalLength);
  257. DefaultPieceStorage ps(dctx, option_.get());
  258. ps.markPiecesDone(pieceLength * 10 + 32_k + 1);
  259. for (size_t i = 0; i < 10; ++i) {
  260. CPPUNIT_ASSERT(ps.hasPiece(i));
  261. }
  262. for (size_t i = 10; i < (totalLength + pieceLength - 1) / pieceLength; ++i) {
  263. CPPUNIT_ASSERT(!ps.hasPiece(i));
  264. }
  265. CPPUNIT_ASSERT_EQUAL((int64_t)pieceLength * 10 + (int64_t)32_k,
  266. ps.getCompletedLength());
  267. ps.markPiecesDone(totalLength);
  268. for (size_t i = 0; i < (totalLength + pieceLength - 1) / pieceLength; ++i) {
  269. CPPUNIT_ASSERT(ps.hasPiece(i));
  270. }
  271. ps.markPiecesDone(0);
  272. CPPUNIT_ASSERT_EQUAL((int64_t)0, ps.getCompletedLength());
  273. }
  274. void DefaultPieceStorageTest::testGetCompletedLength()
  275. {
  276. auto dctx = std::make_shared<DownloadContext>(1_m, 256_m);
  277. DefaultPieceStorage ps(dctx, option_.get());
  278. CPPUNIT_ASSERT_EQUAL((int64_t)0, ps.getCompletedLength());
  279. ps.markPiecesDone(250_m);
  280. CPPUNIT_ASSERT_EQUAL((int64_t)250_m, ps.getCompletedLength());
  281. std::vector<std::shared_ptr<Piece>> inFlightPieces;
  282. for (int i = 0; i < 2; ++i) {
  283. auto p = std::make_shared<Piece>(250 + i, 1_m);
  284. for (int j = 0; j < 32; ++j) {
  285. p->completeBlock(j);
  286. }
  287. inFlightPieces.push_back(p);
  288. CPPUNIT_ASSERT_EQUAL((int64_t)512_k, p->getCompletedLength());
  289. }
  290. ps.addInFlightPiece(inFlightPieces);
  291. CPPUNIT_ASSERT_EQUAL((int64_t)251_m, ps.getCompletedLength());
  292. ps.markPiecesDone(256_m);
  293. CPPUNIT_ASSERT_EQUAL((int64_t)256_m, ps.getCompletedLength());
  294. }
  295. void DefaultPieceStorageTest::testGetFilteredCompletedLength()
  296. {
  297. const size_t pieceLength = 1_m;
  298. auto dctx = std::make_shared<DownloadContext>();
  299. dctx->setPieceLength(pieceLength);
  300. auto files = std::vector<std::shared_ptr<FileEntry>>{
  301. std::make_shared<FileEntry>("foo", 2 * pieceLength, 0),
  302. std::make_shared<FileEntry>("bar", 4 * pieceLength, 2 * pieceLength)};
  303. files[1]->setRequested(false);
  304. dctx->setFileEntries(std::begin(files), std::end(files));
  305. DefaultPieceStorage ps(dctx, option_.get());
  306. std::vector<std::shared_ptr<Piece>> inflightPieces(2);
  307. inflightPieces[0] = std::make_shared<Piece>(1, pieceLength);
  308. inflightPieces[0]->completeBlock(0);
  309. inflightPieces[1] = std::make_shared<Piece>(2, pieceLength);
  310. inflightPieces[1]->completeBlock(1);
  311. inflightPieces[1]->completeBlock(2);
  312. ps.addInFlightPiece(inflightPieces);
  313. ps.setupFileFilter();
  314. auto piece = ps.getMissingPiece(0, 1);
  315. ps.completePiece(piece);
  316. CPPUNIT_ASSERT_EQUAL((int64_t)pieceLength + (int64_t)16_k,
  317. ps.getFilteredCompletedLength());
  318. }
  319. void DefaultPieceStorageTest::testGetNextUsedIndex()
  320. {
  321. DefaultPieceStorage pss(dctx_, option_.get());
  322. CPPUNIT_ASSERT_EQUAL((size_t)3, pss.getNextUsedIndex(0));
  323. auto piece = pss.getMissingPiece(2, 1);
  324. CPPUNIT_ASSERT_EQUAL((size_t)2, pss.getNextUsedIndex(0));
  325. pss.completePiece(piece);
  326. CPPUNIT_ASSERT_EQUAL((size_t)2, pss.getNextUsedIndex(0));
  327. piece = pss.getMissingPiece(0, 1);
  328. CPPUNIT_ASSERT_EQUAL((size_t)2, pss.getNextUsedIndex(0));
  329. }
  330. } // namespace aria2