mirror of
https://github.com/aria2/aria2.git
synced 2025-02-26 08:22:11 +00:00
Added --always-resume and --max-resume-failure-tries option. If --always-resume=false is given, when all given URIs does not support resume or aria2 encounters N URIs which does not support resume (N is the value specified using --max-resume-failure-tries option), aria2 download file from scratch. The default behavior is --always-resume=true, which means if all URIs do not support resume, download fails. I think this is OK because user normally don't like to see that partially downloaded file is overwritten(this is particularly true if file size is big). This option is useful when aria2 is used as download backend and graceful falling back to overwritten behavior is preferable. Added exit status value 8, which means download failed because server did not support resume. * src/AbstractCommand.cc * src/DefaultPieceStorage.cc * src/DownloadCommand.cc * src/DownloadResultCode.h * src/FileEntry.h * src/FtpNegotiationCommand.cc * src/HttpResponse.cc * src/HttpResponseCommand.cc * src/OptionHandlerFactory.cc * src/RequestGroup.cc * src/RequestGroup.h * src/SegmentMan.cc * src/SegmentMan.h * src/prefs.cc * src/prefs.h * src/usage_text.h * test/DefaultPieceStorageTest.cc * test/SegmentManTest.cc
209 lines
7.0 KiB
C++
209 lines
7.0 KiB
C++
#include "SegmentMan.h"
|
|
|
|
#include <cppunit/extensions/HelperMacros.h>
|
|
|
|
#include "DownloadContext.h"
|
|
#include "UnknownLengthPieceStorage.h"
|
|
#include "DefaultPieceStorage.h"
|
|
#include "Segment.h"
|
|
#include "Option.h"
|
|
#include "PieceSelector.h"
|
|
|
|
namespace aria2 {
|
|
|
|
class SegmentManTest:public CppUnit::TestFixture {
|
|
|
|
CPPUNIT_TEST_SUITE(SegmentManTest);
|
|
CPPUNIT_TEST(testNullBitfield);
|
|
CPPUNIT_TEST(testCompleteSegment);
|
|
CPPUNIT_TEST(testGetSegment_sameFileEntry);
|
|
CPPUNIT_TEST(testRegisterPeerStat);
|
|
CPPUNIT_TEST(testCancelAllSegments);
|
|
CPPUNIT_TEST(testGetPeerStat);
|
|
CPPUNIT_TEST(testGetCleanSegmentIfOwnerIsIdle);
|
|
CPPUNIT_TEST_SUITE_END();
|
|
private:
|
|
SharedHandle<Option> _option;
|
|
SharedHandle<DownloadContext> _dctx;
|
|
SharedHandle<DefaultPieceStorage> _pieceStorage;
|
|
SharedHandle<SegmentMan> _segmentMan;
|
|
public:
|
|
void setUp()
|
|
{
|
|
size_t pieceLength = 1024*1024;
|
|
uint64_t totalLength = 64*1024*1024;
|
|
_option.reset(new Option());
|
|
_dctx.reset
|
|
(new DownloadContext(pieceLength, totalLength, "aria2.tar.bz2"));
|
|
_pieceStorage.reset(new DefaultPieceStorage(_dctx, _option.get()));
|
|
_segmentMan.reset(new SegmentMan(_option.get(), _dctx, _pieceStorage));
|
|
}
|
|
|
|
void testNullBitfield();
|
|
void testCompleteSegment();
|
|
void testGetSegment_sameFileEntry();
|
|
void testRegisterPeerStat();
|
|
void testCancelAllSegments();
|
|
void testGetPeerStat();
|
|
void testGetCleanSegmentIfOwnerIsIdle();
|
|
};
|
|
|
|
|
|
CPPUNIT_TEST_SUITE_REGISTRATION( SegmentManTest );
|
|
|
|
void SegmentManTest::testNullBitfield()
|
|
{
|
|
Option op;
|
|
SharedHandle<DownloadContext> dctx
|
|
(new DownloadContext(0, 0, "aria2.tar.bz2"));
|
|
SharedHandle<UnknownLengthPieceStorage> ps
|
|
(new UnknownLengthPieceStorage(dctx, &op));
|
|
SegmentMan segmentMan(&op, dctx, ps);
|
|
|
|
SharedHandle<Segment> segment = segmentMan.getSegment(1);
|
|
CPPUNIT_ASSERT(!segment.isNull());
|
|
CPPUNIT_ASSERT_EQUAL((size_t)0, segment->getIndex());
|
|
CPPUNIT_ASSERT_EQUAL((size_t)0, segment->getLength());
|
|
CPPUNIT_ASSERT_EQUAL((size_t)0, segment->getSegmentLength());
|
|
CPPUNIT_ASSERT_EQUAL((size_t)0, segment->getWrittenLength());
|
|
|
|
SharedHandle<Segment> segment2 = segmentMan.getSegment(2);
|
|
CPPUNIT_ASSERT(segment2.isNull());
|
|
|
|
segmentMan.cancelSegment(1);
|
|
CPPUNIT_ASSERT(!segmentMan.getSegment(2).isNull());
|
|
}
|
|
|
|
void SegmentManTest::testCompleteSegment()
|
|
{
|
|
Option op;
|
|
size_t pieceLength = 1024*1024;
|
|
uint64_t totalLength = 64*1024*1024;
|
|
SharedHandle<DownloadContext> dctx
|
|
(new DownloadContext(pieceLength, totalLength, "aria2.tar.bz2"));
|
|
SharedHandle<DefaultPieceStorage> ps(new DefaultPieceStorage(dctx, &op));
|
|
|
|
SegmentMan segmentMan(&op, dctx, ps);
|
|
|
|
CPPUNIT_ASSERT(!segmentMan.getSegment(1, 0).isNull());
|
|
SharedHandle<Segment> seg = segmentMan.getSegment(1, 1);
|
|
CPPUNIT_ASSERT(!seg.isNull());
|
|
CPPUNIT_ASSERT(!segmentMan.getSegment(1, 2).isNull());
|
|
|
|
seg->updateWrittenLength(pieceLength);
|
|
segmentMan.completeSegment(1, seg);
|
|
|
|
std::vector<SharedHandle<Segment> > segments;
|
|
segmentMan.getInFlightSegment(segments, 1);
|
|
CPPUNIT_ASSERT_EQUAL((size_t)2, segments.size());
|
|
CPPUNIT_ASSERT_EQUAL((size_t)0, segments[0]->getIndex());
|
|
CPPUNIT_ASSERT_EQUAL((size_t)2, segments[1]->getIndex());
|
|
}
|
|
|
|
void SegmentManTest::testGetSegment_sameFileEntry()
|
|
{
|
|
Option op;
|
|
SharedHandle<DownloadContext> dctx(new DownloadContext());
|
|
dctx->setPieceLength(2);
|
|
SharedHandle<FileEntry> fileEntries[] = {
|
|
SharedHandle<FileEntry>(new FileEntry("file1", 3, 0)),
|
|
SharedHandle<FileEntry>(new FileEntry("file2", 6, 3)),
|
|
SharedHandle<FileEntry>(new FileEntry("file3", 1, 9))
|
|
};
|
|
dctx->setFileEntries(&fileEntries[0], &fileEntries[3]);
|
|
SharedHandle<DefaultPieceStorage> ps(new DefaultPieceStorage(dctx, &op));
|
|
SegmentMan segman(&op, dctx, ps);
|
|
|
|
std::vector<SharedHandle<Segment> > segments;
|
|
segman.getSegment(segments, 1, fileEntries[1], 4);
|
|
// See 3 segments are returned, not 4 because the part of file1 is
|
|
// not filled in segment#1
|
|
CPPUNIT_ASSERT_EQUAL((size_t)3, segments.size());
|
|
|
|
SharedHandle<Segment> segmentNo1 = segman.getSegment(2, 1);
|
|
// Fill the part of file1 in segment#1
|
|
segmentNo1->updateWrittenLength(1);
|
|
segman.cancelSegment(2);
|
|
|
|
segman.cancelSegment(1);
|
|
segments.clear();
|
|
segman.getSegment(segments, 1, fileEntries[1], 4);
|
|
CPPUNIT_ASSERT_EQUAL((size_t)4, segments.size());
|
|
|
|
segman.cancelSegment(1);
|
|
SharedHandle<Segment> segmentNo4 = segman.getSegment(1, 4);
|
|
// Fill the part of file2 in segment#4
|
|
segmentNo4->updateWrittenLength(1);
|
|
segman.cancelSegment(1);
|
|
|
|
segments.clear();
|
|
segman.getSegment(segments, 1, fileEntries[1], 4);
|
|
// segment#4 is not returned because the part of file2 is filled.
|
|
CPPUNIT_ASSERT_EQUAL((size_t)3, segments.size());
|
|
}
|
|
|
|
void SegmentManTest::testRegisterPeerStat()
|
|
{
|
|
Option op;
|
|
SharedHandle<DownloadContext> dctx(new DownloadContext());
|
|
SharedHandle<DefaultPieceStorage> ps(new DefaultPieceStorage(dctx, &op));
|
|
SegmentMan segman(&op, dctx, ps);
|
|
|
|
SharedHandle<PeerStat> p1(new PeerStat(0, "host1", "http"));
|
|
segman.registerPeerStat(p1);
|
|
CPPUNIT_ASSERT_EQUAL((size_t)1, segman.getPeerStats().size());
|
|
SharedHandle<PeerStat> p2(new PeerStat(0, "host2", "http"));
|
|
segman.registerPeerStat(p2);
|
|
CPPUNIT_ASSERT_EQUAL((size_t)1, segman.getPeerStats().size());
|
|
p2->downloadStart();
|
|
segman.registerPeerStat(p1);
|
|
CPPUNIT_ASSERT_EQUAL((size_t)2, segman.getPeerStats().size());
|
|
}
|
|
|
|
void SegmentManTest::testCancelAllSegments()
|
|
{
|
|
_segmentMan->getSegment(1, 0);
|
|
_segmentMan->getSegment(2, 1);
|
|
CPPUNIT_ASSERT(_segmentMan->getSegment(3, 0).isNull());
|
|
CPPUNIT_ASSERT(_segmentMan->getSegment(4, 1).isNull());
|
|
_segmentMan->cancelAllSegments();
|
|
CPPUNIT_ASSERT(!_segmentMan->getSegment(3, 0).isNull());
|
|
CPPUNIT_ASSERT(!_segmentMan->getSegment(4, 1).isNull());
|
|
}
|
|
|
|
void SegmentManTest::testGetPeerStat()
|
|
{
|
|
SharedHandle<PeerStat> peerStat1(new PeerStat(1));
|
|
_segmentMan->registerPeerStat(peerStat1);
|
|
CPPUNIT_ASSERT_EQUAL((cuid_t)1, _segmentMan->getPeerStat(1)->getCuid());
|
|
}
|
|
|
|
void SegmentManTest::testGetCleanSegmentIfOwnerIsIdle()
|
|
{
|
|
SharedHandle<Segment> seg1 = _segmentMan->getSegment(1, 0);
|
|
SharedHandle<Segment> seg2 = _segmentMan->getSegment(2, 1);
|
|
seg2->updateWrittenLength(100);
|
|
CPPUNIT_ASSERT(!_segmentMan->getCleanSegmentIfOwnerIsIdle(3, 0).isNull());
|
|
SharedHandle<PeerStat> peerStat3(new PeerStat(3));
|
|
_segmentMan->registerPeerStat(peerStat3);
|
|
CPPUNIT_ASSERT(!_segmentMan->getCleanSegmentIfOwnerIsIdle(4, 0).isNull());
|
|
SharedHandle<PeerStat> peerStat4(new PeerStat(4));
|
|
peerStat4->downloadStart();
|
|
_segmentMan->registerPeerStat(peerStat4);
|
|
// Owner PeerStat is not IDLE
|
|
CPPUNIT_ASSERT(_segmentMan->getCleanSegmentIfOwnerIsIdle(5, 0).isNull());
|
|
// Segment::updateWrittenLength != 0
|
|
CPPUNIT_ASSERT(_segmentMan->getCleanSegmentIfOwnerIsIdle(5, 1).isNull());
|
|
|
|
// Test with UnknownLengthPieceStorage
|
|
SharedHandle<DownloadContext> dctx(new DownloadContext(1024, 0, "aria2"));
|
|
SharedHandle<UnknownLengthPieceStorage> ps
|
|
(new UnknownLengthPieceStorage(dctx, _option.get()));
|
|
_segmentMan.reset(new SegmentMan(_option.get(), dctx, ps));
|
|
|
|
CPPUNIT_ASSERT(!_segmentMan->getCleanSegmentIfOwnerIsIdle(1, 0).isNull());
|
|
|
|
}
|
|
|
|
} // namespace aria2
|