mirror of https://github.com/aria2/aria2
2007-10-24 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
* src/Piece.{h, cc}: Added SubPiece infrastructure to track down the data smaller than block length. A block length can be specified by constructor's argument. * src/DefaultPieceStorage.{h, cc} (getMissingPiece): Get a missing piece in the range of given FileEntry. This function is not used in the program yet. * src/Util.h: Added some macros.pull/1/head
parent
884a139e72
commit
3ab9fe706d
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
2007-10-24 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||
|
||||
* src/Piece.{h, cc}: Added SubPiece infrastructure to track down
|
||||
the data smaller than block length.
|
||||
A block length can be specified by constructor's argument.
|
||||
* src/DefaultPieceStorage.{h, cc} (getMissingPiece):
|
||||
Get a missing piece in the range of given FileEntry. This function is
|
||||
not used in the program yet.
|
||||
* src/Util.h: Added some macros.
|
||||
|
||||
2007-10-18 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||
|
||||
Added HTTP/1.1 keep alive and pipelining support.
|
||||
|
|
9
TODO
9
TODO
|
@ -49,8 +49,13 @@
|
|||
* Rewrite MetaFileUtil
|
||||
* Reconsider the use of RecoverableException and FatalException
|
||||
* Limit the number of opening file to,say,100 in MultiDiskAdaptor.
|
||||
|
||||
* Implement duplicate download checking in Bt
|
||||
* Implement the feature to treat http/ftp as auxuality download method for BitTorrent
|
||||
|
||||
-- remaining features to be implemented for 0.12.0 release
|
||||
* Reimplement ChecksumCommand(validation using 1 checksum for 1 file)
|
||||
* Implement duplicate download checking in Bt
|
||||
* Add PeerListenCommand to DownloadEngine only when it is really necessary.
|
||||
* ftp://USER:PASSWD@Servername automatic parsing
|
||||
* improve --metalink-location field
|
||||
* Use content-type for PostDownloadHandler
|
||||
* Torrent information
|
||||
|
|
|
@ -236,7 +236,7 @@ void DefaultBtInteractive::addRequests() {
|
|||
if(pieceStorage->isEndGame()) {
|
||||
pieceNum = 1;
|
||||
} else {
|
||||
int32_t blocks = DIV_FLOOR(btContext->getPieceLength(), BLOCK_LENGTH);
|
||||
int32_t blocks = DIV_FLOOR(btContext->getPieceLength(), Piece::BLOCK_LENGTH);
|
||||
pieceNum = DIV_FLOOR(MAX_PENDING_REQUEST, blocks);
|
||||
}
|
||||
fillPiece(pieceNum);
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "message.h"
|
||||
#include "DefaultDiskWriterFactory.h"
|
||||
#include "DlAbortEx.h"
|
||||
#include "Util.h"
|
||||
|
||||
DefaultPieceStorage::DefaultPieceStorage(const DownloadContextHandle& downloadContext, const Option* option):
|
||||
downloadContext(downloadContext),
|
||||
|
@ -194,6 +195,36 @@ PieceHandle DefaultPieceStorage::getMissingPiece()
|
|||
return checkOutPiece(bitfieldMan->getSparseMissingUnusedIndex());
|
||||
}
|
||||
|
||||
PieceHandle DefaultPieceStorage::getMissingPiece(const FileEntryHandle& fileEntry)
|
||||
{
|
||||
BitfieldMan temp(*bitfieldMan);
|
||||
temp.clearFilter();
|
||||
temp.addFilter(fileEntry->getOffset(), fileEntry->getLength());
|
||||
temp.enableFilter();
|
||||
|
||||
int32_t firstPieceIndex = START_INDEX(fileEntry->getOffset(), downloadContext->getPieceLength());
|
||||
int32_t endPieceIndex = END_INDEX(fileEntry->getOffset(), fileEntry->getLength(), downloadContext->getPieceLength());
|
||||
if(!temp.isBitSet(firstPieceIndex) && !temp.isUseBitSet(firstPieceIndex)) {
|
||||
PieceHandle piece = findUsedPiece(firstPieceIndex);
|
||||
if(!piece.isNull()) {
|
||||
if(piece->isRangeComplete(fileEntry->getOffset()-firstPieceIndex*downloadContext->getPieceLength(),
|
||||
fileEntry->getLength() > downloadContext->getPieceLength() ?
|
||||
downloadContext->getPieceLength():fileEntry->getLength())) {
|
||||
temp.setBit(firstPieceIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(firstPieceIndex != endPieceIndex && !temp.isBitSet(endPieceIndex) && !temp.isUseBitSet(endPieceIndex)) {
|
||||
PieceHandle piece = findUsedPiece(endPieceIndex);
|
||||
if(!piece.isNull()) {
|
||||
if(piece->isRangeComplete(0, fileEntry->getOffset()+fileEntry->getLength()-endPieceIndex*downloadContext->getPieceLength())) {
|
||||
temp.setBit(endPieceIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
return checkOutPiece(temp.getSparseMissingUnusedIndex());
|
||||
}
|
||||
|
||||
PieceHandle DefaultPieceStorage::getMissingPiece(int32_t index)
|
||||
{
|
||||
if(hasPiece(index) || isPieceUsed(index)) {
|
||||
|
@ -299,7 +330,7 @@ void DefaultPieceStorage::cancelPiece(const PieceHandle& piece)
|
|||
}
|
||||
bitfieldMan->unsetUseBit(piece->getIndex());
|
||||
if(!isEndGame()) {
|
||||
if(piece->countCompleteBlock() == 0) {
|
||||
if(piece->getCompletedLength() == 0) {
|
||||
deleteUsedPiece(piece);
|
||||
}
|
||||
}
|
||||
|
@ -376,6 +407,7 @@ void DefaultPieceStorage::clearFileFilter()
|
|||
// not unittested
|
||||
bool DefaultPieceStorage::downloadFinished()
|
||||
{
|
||||
// TODO iterate all requested FileEntry and Call bitfieldMan->isBitSetOffsetRange()
|
||||
return bitfieldMan->isFilteredAllBitSet();
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,8 @@ class Option;
|
|||
extern typedef deque<PieceHandle> Pieces;
|
||||
class DiskWriterFactory;
|
||||
extern typedef SharedHandle<DiskWriterFactory> DiskWriterFactoryHandle;
|
||||
class FileEntry;
|
||||
extern typedef SharedHandle<FileEntry> FileEntryHandle;
|
||||
|
||||
#define END_GAME_PIECE_NUM 20
|
||||
|
||||
|
@ -97,6 +99,7 @@ public:
|
|||
virtual PieceHandle getMissingFastPiece(const PeerHandle& peer);
|
||||
|
||||
virtual PieceHandle getMissingPiece();
|
||||
virtual PieceHandle getMissingPiece(const FileEntryHandle& fileEntry);
|
||||
|
||||
virtual PieceHandle getMissingPiece(int32_t index);
|
||||
|
||||
|
|
104
src/Piece.cc
104
src/Piece.cc
|
@ -36,16 +36,17 @@
|
|||
#include "Util.h"
|
||||
#include "BitfieldManFactory.h"
|
||||
|
||||
Piece::Piece():index(0), length(0), bitfield(0) {}
|
||||
Piece::Piece():index(0), length(0), _blockLength(BLOCK_LENGTH), bitfield(0) {}
|
||||
|
||||
Piece::Piece(int32_t index, int32_t length):index(index), length(length) {
|
||||
Piece::Piece(int32_t index, int32_t length, int32_t blockLength):index(index), length(length), _blockLength(blockLength) {
|
||||
bitfield =
|
||||
BitfieldManFactory::getFactoryInstance()->createBitfieldMan(BLOCK_LENGTH, length);
|
||||
BitfieldManFactory::getFactoryInstance()->createBitfieldMan(_blockLength, length);
|
||||
}
|
||||
|
||||
Piece::Piece(const Piece& piece) {
|
||||
index = piece.index;
|
||||
length = piece.length;
|
||||
_blockLength = piece._blockLength;
|
||||
if(piece.bitfield == 0) {
|
||||
bitfield = 0;
|
||||
} else {
|
||||
|
@ -53,10 +54,10 @@ Piece::Piece(const Piece& piece) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void Piece::completeBlock(int32_t blockIndex) {
|
||||
bitfield->setBit(blockIndex);
|
||||
bitfield->unsetUseBit(blockIndex);
|
||||
removeSubPiece(blockIndex);
|
||||
}
|
||||
|
||||
void Piece::clearAllBlock() {
|
||||
|
@ -106,7 +107,7 @@ void Piece::reconfigure(int32_t length)
|
|||
{
|
||||
this->length = length;
|
||||
bitfield =
|
||||
BitfieldManFactory::getFactoryInstance()->createBitfieldMan(BLOCK_LENGTH, length);
|
||||
BitfieldManFactory::getFactoryInstance()->createBitfieldMan(_blockLength, length);
|
||||
}
|
||||
|
||||
void Piece::setBitfield(const unsigned char* bitfield, int32_t len)
|
||||
|
@ -114,3 +115,96 @@ void Piece::setBitfield(const unsigned char* bitfield, int32_t len)
|
|||
this->bitfield->setBitfield(bitfield, len);
|
||||
}
|
||||
|
||||
void Piece::addSubPiece(const PieceHandle& subPiece)
|
||||
{
|
||||
_subPieces.push_back(subPiece);
|
||||
}
|
||||
|
||||
PieceHandle Piece::getSubPiece(int32_t blockIndex)
|
||||
{
|
||||
Pieces::iterator itr = getSubPieceIterator(blockIndex);
|
||||
if(itr == _subPieces.end()) {
|
||||
return 0;
|
||||
} else {
|
||||
return *itr;
|
||||
}
|
||||
}
|
||||
|
||||
void Piece::removeSubPiece(int32_t blockIndex)
|
||||
{
|
||||
Pieces::iterator itr = getSubPieceIterator(blockIndex);
|
||||
if(itr != _subPieces.end()) {
|
||||
_subPieces.erase(itr);
|
||||
}
|
||||
}
|
||||
|
||||
Pieces::iterator Piece::getSubPieceIterator(int32_t blockIndex)
|
||||
{
|
||||
for(Pieces::iterator itr = _subPieces.begin(); itr != _subPieces.end(); ++itr) {
|
||||
if((*itr)->getIndex() == blockIndex) {
|
||||
return itr;
|
||||
}
|
||||
}
|
||||
return _subPieces.end();
|
||||
}
|
||||
|
||||
bool Piece::isRangeComplete(int32_t offset, int32_t length)
|
||||
{
|
||||
int32_t startIndex = START_INDEX(offset, _blockLength);
|
||||
int32_t endIndex = END_INDEX(offset, length, _blockLength);
|
||||
if(countBlock() <= endIndex) {
|
||||
endIndex = countBlock()-1;
|
||||
}
|
||||
if(startIndex+1 < endIndex) {
|
||||
if(!bitfield->isBitRangeSet(startIndex+1, endIndex-1)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(startIndex == endIndex) {
|
||||
if(hasBlock(startIndex)) {
|
||||
return true;
|
||||
}
|
||||
PieceHandle subPiece = getSubPiece(startIndex);
|
||||
if(subPiece.isNull()) {
|
||||
return false;
|
||||
}
|
||||
return subPiece->isRangeComplete(offset, length);
|
||||
} else {
|
||||
if(!hasBlock(startIndex)) {
|
||||
PieceHandle subPiece = getSubPiece(startIndex);
|
||||
if(subPiece.isNull()) {
|
||||
return false;
|
||||
}
|
||||
if(!subPiece->isRangeComplete(offset-startIndex*_blockLength, length)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!hasBlock(endIndex)) {
|
||||
PieceHandle subPiece = getSubPiece(endIndex);
|
||||
if(subPiece.isNull()) {
|
||||
return false;
|
||||
}
|
||||
if(!subPiece->isRangeComplete(0, offset+length-endIndex*_blockLength)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t Piece::getCompletedLength()
|
||||
{
|
||||
int32_t length = 0;
|
||||
for(int32_t i = 0; i < countBlock(); ++i) {
|
||||
if(hasBlock(i)) {
|
||||
length += getBlockLength(i);
|
||||
} else {
|
||||
PieceHandle subPiece = getSubPiece(i);
|
||||
if(!subPiece.isNull()) {
|
||||
length += subPiece->getCompletedLength();
|
||||
}
|
||||
}
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
|
|
25
src/Piece.h
25
src/Piece.h
|
@ -38,17 +38,25 @@
|
|||
#include "BitfieldMan.h"
|
||||
#include "common.h"
|
||||
|
||||
#define BLOCK_LENGTH (16*1024)
|
||||
class Piece;
|
||||
typedef SharedHandle<Piece> PieceHandle;
|
||||
typedef deque<PieceHandle> Pieces;
|
||||
|
||||
class Piece {
|
||||
private:
|
||||
int32_t index;
|
||||
int32_t length;
|
||||
int32_t _blockLength;
|
||||
BitfieldMan* bitfield;
|
||||
|
||||
Pieces _subPieces;
|
||||
public:
|
||||
|
||||
static const int32_t BLOCK_LENGTH = 16*1024;
|
||||
|
||||
Piece();
|
||||
|
||||
Piece(int32_t index, int32_t length);
|
||||
Piece(int32_t index, int32_t length, int32_t blockLength = BLOCK_LENGTH);
|
||||
|
||||
Piece(const Piece& piece);
|
||||
|
||||
|
@ -118,6 +126,19 @@ public:
|
|||
return bitfield->isUseBitSet(index);
|
||||
}
|
||||
|
||||
void addSubPiece(const PieceHandle& subPiece);
|
||||
|
||||
PieceHandle getSubPiece(int32_t blockIndex);
|
||||
|
||||
void removeSubPiece(int32_t blockIndex);
|
||||
|
||||
Pieces::iterator getSubPieceIterator(int32_t blockIndex);
|
||||
|
||||
bool isRangeComplete(int32_t offset, int32_t length);
|
||||
|
||||
// Calculates completed length, taking into account SubPieces
|
||||
int32_t getCompletedLength();
|
||||
|
||||
/**
|
||||
* Loses current bitfield state.
|
||||
*/
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
PiecedSegment::PiecedSegment(int32_t pieceLength, const PieceHandle& piece):
|
||||
_pieceLength(pieceLength), _overflowLength(0), _piece(piece)
|
||||
{
|
||||
_writtenLength = _piece->getAllMissingBlockIndexes().front()*BLOCK_LENGTH;
|
||||
_writtenLength = _piece->getAllMissingBlockIndexes().front()*_piece->getBlockLength();
|
||||
}
|
||||
|
||||
PiecedSegment::~PiecedSegment() {}
|
||||
|
@ -75,7 +75,7 @@ void PiecedSegment::updateWrittenLength(int32_t bytes)
|
|||
_overflowLength = newWrittenLength-_piece->getLength();
|
||||
newWrittenLength = _piece->getLength();
|
||||
}
|
||||
for(int32_t i = _writtenLength/BLOCK_LENGTH; i < newWrittenLength/BLOCK_LENGTH; ++i) {
|
||||
for(int32_t i = _writtenLength/_piece->getBlockLength(); i < newWrittenLength/_piece->getBlockLength(); ++i) {
|
||||
_piece->completeBlock(i);
|
||||
}
|
||||
if(newWrittenLength == _piece->getLength()) {
|
||||
|
|
|
@ -42,7 +42,7 @@ ostream& operator<<(ostream& o, const Segment& segment) {
|
|||
if(segment.complete()) {
|
||||
o << "writtenLength = " << segment._piece->getLength();
|
||||
} else {
|
||||
o << "writtenLength = " << (segment._piece->getMissingUnusedBlockIndex()-1)*BLOCK_LENGTH;
|
||||
o << "writtenLength = " << (segment._piece->getMissingUnusedBlockIndex()-1)*segment._piece->getBlockLength();
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,10 @@
|
|||
#include <deque>
|
||||
#include <ostream>
|
||||
|
||||
#define STRTOLL(X) strtoll(X, (char**)NULL, 10);
|
||||
#define STRTOLL(X) strtoll(X, (char**)NULL, 10)
|
||||
|
||||
#define START_INDEX(OFFSET, PIECE_LENGTH) ((OFFSET)/(PIECE_LENGTH))
|
||||
#define END_INDEX(OFFSET, LENGTH, PIECE_LENGTH) (((OFFSET)+(LENGTH)-1)/(PIECE_LENGTH))
|
||||
|
||||
class Util {
|
||||
public:
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "Piece.h"
|
||||
#include "Peer.h"
|
||||
#include "Option.h"
|
||||
#include "MockBtContext.h"
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
using namespace std;
|
||||
|
@ -22,6 +23,8 @@ class DefaultPieceStorageTest:public CppUnit::TestFixture {
|
|||
CPPUNIT_TEST(testGetPiece);
|
||||
CPPUNIT_TEST(testGetPieceInUsedPieces);
|
||||
CPPUNIT_TEST(testGetPieceCompletedPiece);
|
||||
CPPUNIT_TEST(testGetMissingPiece_fileEntry);
|
||||
CPPUNIT_TEST(testCancelPiece);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
private:
|
||||
BtContextHandle btContext;
|
||||
|
@ -43,6 +46,12 @@ public:
|
|||
option = new Option();
|
||||
}
|
||||
|
||||
void tearDown()
|
||||
{
|
||||
delete option;
|
||||
option = 0;
|
||||
}
|
||||
|
||||
void testGetTotalLength();
|
||||
void testGetMissingPiece();
|
||||
void testGetMissingFastPiece();
|
||||
|
@ -51,6 +60,8 @@ public:
|
|||
void testGetPiece();
|
||||
void testGetPieceInUsedPieces();
|
||||
void testGetPieceCompletedPiece();
|
||||
void testGetMissingPiece_fileEntry();
|
||||
void testCancelPiece();
|
||||
};
|
||||
|
||||
|
||||
|
@ -153,3 +164,102 @@ void DefaultPieceStorageTest::testGetPieceCompletedPiece() {
|
|||
CPPUNIT_ASSERT_EQUAL((int32_t)128, pieceGot->getLength());
|
||||
CPPUNIT_ASSERT_EQUAL(true, pieceGot->pieceComplete());
|
||||
}
|
||||
|
||||
void DefaultPieceStorageTest::testGetMissingPiece_fileEntry()
|
||||
{
|
||||
// - 32KB
|
||||
// +--------+
|
||||
// |11111222|
|
||||
int32_t pieceLength = 256*1024;
|
||||
int64_t totalLength = 1*pieceLength;
|
||||
int32_t blockLength = 16*1024;
|
||||
Strings uris1;
|
||||
uris1.push_back("http://localhost/src/file1.txt");
|
||||
Strings uris2;
|
||||
uris2.push_back("http://localhost/src/file2.txt");
|
||||
FileEntryHandle file1 = new FileEntry("src/file1.txt", 150*1024, 0/*, uris1*/);
|
||||
FileEntryHandle file2 = new FileEntry("src/file2.txt", 106*1024, file1->getLength() /*, uris2*/);
|
||||
|
||||
MockBtContextHandle dctx = new MockBtContext();
|
||||
dctx->setPieceLength(pieceLength);
|
||||
dctx->setTotalLength(totalLength);
|
||||
dctx->addFileEntry(file1);
|
||||
dctx->addFileEntry(file2);
|
||||
|
||||
DefaultPieceStorageHandle ps = new DefaultPieceStorage(dctx, option);
|
||||
|
||||
PieceHandle p = ps->getMissingPiece(file1);
|
||||
CPPUNIT_ASSERT(!p.isNull());
|
||||
CPPUNIT_ASSERT_EQUAL((int32_t)0, p->getIndex());
|
||||
|
||||
for(int32_t i = 0; i < 9; ++i) {
|
||||
p->completeBlock(i);
|
||||
}
|
||||
PieceHandle subPiece = new Piece(9, blockLength, 1);
|
||||
p->addSubPiece(subPiece);
|
||||
|
||||
ps->cancelPiece(p);
|
||||
|
||||
// Piece index = 0 should be retrieved again because the part of file1 is
|
||||
// not complete
|
||||
PieceHandle p2 = ps->getMissingPiece(file1);
|
||||
CPPUNIT_ASSERT(!p2.isNull());
|
||||
CPPUNIT_ASSERT_EQUAL((int32_t)0, p2->getIndex());
|
||||
|
||||
// Make the part of file1 complete
|
||||
for(int32_t i = 0; i < 6*1024; ++i) {
|
||||
p2->getSubPiece(9)->completeBlock(i);
|
||||
}
|
||||
ps->cancelPiece(p2);
|
||||
|
||||
// Null Piece should be retrieved
|
||||
CPPUNIT_ASSERT(ps->getMissingPiece(file1).isNull());
|
||||
|
||||
// Next, I retrive the piece giving file2
|
||||
PieceHandle p3 = ps->getMissingPiece(file2);
|
||||
CPPUNIT_ASSERT(!p3.isNull());
|
||||
CPPUNIT_ASSERT_EQUAL((int32_t)0, p3->getIndex());
|
||||
|
||||
// Make the part of file2 complete
|
||||
for(int32_t i = 6*1024; i < 16*1024; ++i) {
|
||||
p3->getSubPiece(9)->completeBlock(i);
|
||||
}
|
||||
for(int32_t i = 10; i < 16; ++i) {
|
||||
p3->completeBlock(i);
|
||||
}
|
||||
ps->cancelPiece(p3);
|
||||
|
||||
// Null Piece should be retrieved
|
||||
CPPUNIT_ASSERT(ps->getMissingPiece(file2).isNull());
|
||||
}
|
||||
|
||||
void DefaultPieceStorageTest::testCancelPiece()
|
||||
{
|
||||
int32_t pieceLength = 256*1024;
|
||||
int64_t totalLength = 32*pieceLength; // <-- make the number of piece greater than END_GAME_PIECE_NUM
|
||||
int32_t blockLength = 16*1024;
|
||||
Strings uris1;
|
||||
uris1.push_back("http://localhost/src/file1.txt");
|
||||
FileEntryHandle file1 = new FileEntry("src/file1.txt", totalLength, 0 /*, uris1*/);
|
||||
|
||||
MockBtContextHandle dctx = new MockBtContext();
|
||||
dctx->setPieceLength(pieceLength);
|
||||
dctx->setTotalLength(totalLength);
|
||||
dctx->addFileEntry(file1);
|
||||
|
||||
DefaultPieceStorageHandle ps = new DefaultPieceStorage(dctx, option);
|
||||
|
||||
PieceHandle p = ps->getMissingPiece(file1);
|
||||
|
||||
PieceHandle subPiece = new Piece(0, blockLength, 1);
|
||||
subPiece->completeBlock(0);
|
||||
p->addSubPiece(subPiece);
|
||||
|
||||
ps->cancelPiece(p);
|
||||
|
||||
// See the sub piece is also hibernated...
|
||||
PieceHandle p2 = ps->getMissingPiece(file1);
|
||||
|
||||
CPPUNIT_ASSERT(!p2->getSubPiece(0).isNull());
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
TESTS = aria2c
|
||||
check_PROGRAMS = $(TESTS)
|
||||
aria2c_SOURCES = AllTest.cc\
|
||||
PieceTest.cc\
|
||||
DefaultPieceStorageTest.cc\
|
||||
SegmentTest.cc\
|
||||
GrowSegmentTest.cc\
|
||||
SingleFileAllocationIteratorTest.cc\
|
||||
|
@ -67,7 +69,6 @@ aria2c_SOURCES += BtAllowedFastMessageTest.cc\
|
|||
DefaultBtContextTest.cc\
|
||||
DefaultBtMessageDispatcherTest.cc\
|
||||
DefaultBtRequestFactoryTest.cc\
|
||||
DefaultPieceStorageTest.cc\
|
||||
MockBtMessage.h\
|
||||
MockBtMessageDispatcher.h\
|
||||
MockBtMessageFactory.h\
|
||||
|
|
|
@ -61,7 +61,6 @@ check_PROGRAMS = $(am__EXEEXT_1)
|
|||
@ENABLE_BITTORRENT_TRUE@ DefaultBtContextTest.cc\
|
||||
@ENABLE_BITTORRENT_TRUE@ DefaultBtMessageDispatcherTest.cc\
|
||||
@ENABLE_BITTORRENT_TRUE@ DefaultBtRequestFactoryTest.cc\
|
||||
@ENABLE_BITTORRENT_TRUE@ DefaultPieceStorageTest.cc\
|
||||
@ENABLE_BITTORRENT_TRUE@ MockBtMessage.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ MockBtMessageDispatcher.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ MockBtMessageFactory.h\
|
||||
|
@ -112,7 +111,8 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
|||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
am__EXEEXT_1 = aria2c$(EXEEXT)
|
||||
am__aria2c_SOURCES_DIST = AllTest.cc SegmentTest.cc GrowSegmentTest.cc \
|
||||
am__aria2c_SOURCES_DIST = AllTest.cc PieceTest.cc \
|
||||
DefaultPieceStorageTest.cc SegmentTest.cc GrowSegmentTest.cc \
|
||||
SingleFileAllocationIteratorTest.cc \
|
||||
DefaultBtProgressInfoFileTest.cc \
|
||||
SingleFileDownloadContextTest.cc RequestGroupTest.cc \
|
||||
|
@ -140,17 +140,17 @@ am__aria2c_SOURCES_DIST = AllTest.cc SegmentTest.cc GrowSegmentTest.cc \
|
|||
BtRequestMessageTest.cc BtSuggestPieceMessageTest.cc \
|
||||
BtUnchokeMessageTest.cc DefaultBtAnnounceTest.cc \
|
||||
DefaultBtContextTest.cc DefaultBtMessageDispatcherTest.cc \
|
||||
DefaultBtRequestFactoryTest.cc DefaultPieceStorageTest.cc \
|
||||
MockBtMessage.h MockBtMessageDispatcher.h \
|
||||
MockBtMessageFactory.h ShaVisitorTest.cc \
|
||||
DefaultPeerListProcessorTest.cc AnnounceListTest.cc \
|
||||
DefaultPeerStorageTest.cc MockPeerStorage.h DataTest.cc \
|
||||
DictionaryTest.cc ListTest.cc MetaFileUtilTest.cc \
|
||||
MultiDiskAdaptorTest.cc ByteArrayDiskWriterTest.cc PeerTest.cc \
|
||||
PeerMessageUtilTest.cc ShareRatioSeedCriteriaTest.cc \
|
||||
BtRegistryTest.cc MultiFileAllocationIteratorTest.cc \
|
||||
BtDependencyTest.cc BtPostDownloadHandlerTest.cc \
|
||||
TimeSeedCriteriaTest.cc MetalinkerTest.cc MetalinkEntryTest.cc \
|
||||
DefaultBtRequestFactoryTest.cc MockBtMessage.h \
|
||||
MockBtMessageDispatcher.h MockBtMessageFactory.h \
|
||||
ShaVisitorTest.cc DefaultPeerListProcessorTest.cc \
|
||||
AnnounceListTest.cc DefaultPeerStorageTest.cc \
|
||||
MockPeerStorage.h DataTest.cc DictionaryTest.cc ListTest.cc \
|
||||
MetaFileUtilTest.cc MultiDiskAdaptorTest.cc \
|
||||
ByteArrayDiskWriterTest.cc PeerTest.cc PeerMessageUtilTest.cc \
|
||||
ShareRatioSeedCriteriaTest.cc BtRegistryTest.cc \
|
||||
MultiFileAllocationIteratorTest.cc BtDependencyTest.cc \
|
||||
BtPostDownloadHandlerTest.cc TimeSeedCriteriaTest.cc \
|
||||
MetalinkerTest.cc MetalinkEntryTest.cc \
|
||||
Xml2MetalinkProcessorTest.cc Metalink2RequestGroupTest.cc \
|
||||
MetalinkPostDownloadHandlerTest.cc
|
||||
@ENABLE_MESSAGE_DIGEST_TRUE@am__objects_1 = \
|
||||
|
@ -178,7 +178,6 @@ am__aria2c_SOURCES_DIST = AllTest.cc SegmentTest.cc GrowSegmentTest.cc \
|
|||
@ENABLE_BITTORRENT_TRUE@ DefaultBtContextTest.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ DefaultBtMessageDispatcherTest.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ DefaultBtRequestFactoryTest.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ DefaultPieceStorageTest.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ ShaVisitorTest.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ DefaultPeerListProcessorTest.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ AnnounceListTest.$(OBJEXT) \
|
||||
|
@ -202,7 +201,8 @@ am__aria2c_SOURCES_DIST = AllTest.cc SegmentTest.cc GrowSegmentTest.cc \
|
|||
@ENABLE_METALINK_TRUE@ Xml2MetalinkProcessorTest.$(OBJEXT) \
|
||||
@ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.$(OBJEXT) \
|
||||
@ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandlerTest.$(OBJEXT)
|
||||
am_aria2c_OBJECTS = AllTest.$(OBJEXT) SegmentTest.$(OBJEXT) \
|
||||
am_aria2c_OBJECTS = AllTest.$(OBJEXT) PieceTest.$(OBJEXT) \
|
||||
DefaultPieceStorageTest.$(OBJEXT) SegmentTest.$(OBJEXT) \
|
||||
GrowSegmentTest.$(OBJEXT) \
|
||||
SingleFileAllocationIteratorTest.$(OBJEXT) \
|
||||
DefaultBtProgressInfoFileTest.$(OBJEXT) \
|
||||
|
@ -412,7 +412,8 @@ target_cpu = @target_cpu@
|
|||
target_os = @target_os@
|
||||
target_vendor = @target_vendor@
|
||||
TESTS = aria2c
|
||||
aria2c_SOURCES = AllTest.cc SegmentTest.cc GrowSegmentTest.cc \
|
||||
aria2c_SOURCES = AllTest.cc PieceTest.cc DefaultPieceStorageTest.cc \
|
||||
SegmentTest.cc GrowSegmentTest.cc \
|
||||
SingleFileAllocationIteratorTest.cc \
|
||||
DefaultBtProgressInfoFileTest.cc \
|
||||
SingleFileDownloadContextTest.cc RequestGroupTest.cc \
|
||||
|
@ -561,6 +562,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ParameterizedStringParserTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerMessageUtilTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PieceTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestFactoryTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestGroupManTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestGroupTest.Po@am__quote@
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
#include "Piece.h"
|
||||
#include <string>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class PieceTest:public CppUnit::TestFixture {
|
||||
|
||||
CPPUNIT_TEST_SUITE(PieceTest);
|
||||
CPPUNIT_TEST(testCompleteBlock);
|
||||
CPPUNIT_TEST(testIsRangeComplete);
|
||||
CPPUNIT_TEST(testIsRangeComplete_subPiece);
|
||||
CPPUNIT_TEST(testGetCompletedLength);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
private:
|
||||
|
||||
public:
|
||||
void setUp() {}
|
||||
|
||||
void testCompleteBlock();
|
||||
void testIsRangeComplete();
|
||||
void testIsRangeComplete_subPiece();
|
||||
void testGetCompletedLength();
|
||||
};
|
||||
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION( PieceTest );
|
||||
|
||||
void PieceTest::testCompleteBlock()
|
||||
{
|
||||
int32_t blockLength = 32*1024;
|
||||
Piece p(0, blockLength*10, blockLength);
|
||||
|
||||
// 5 is a block index inside the Piece p.
|
||||
PieceHandle subPiece = new Piece(5, blockLength, 1);
|
||||
p.addSubPiece(subPiece);
|
||||
|
||||
CPPUNIT_ASSERT(!p.getSubPiece(5).isNull());
|
||||
|
||||
// When block is complete, then its associated sub piece must be deleted.
|
||||
p.completeBlock(5);
|
||||
|
||||
CPPUNIT_ASSERT(p.getSubPiece(5).isNull());
|
||||
}
|
||||
|
||||
void PieceTest::testIsRangeComplete()
|
||||
{
|
||||
int32_t blockLength = 16*1024;
|
||||
Piece p(0, blockLength*10, blockLength);
|
||||
|
||||
CPPUNIT_ASSERT(!p.isRangeComplete(8*1024, 16*1024));
|
||||
|
||||
p.completeBlock(0);
|
||||
CPPUNIT_ASSERT(!p.isRangeComplete(8*1024, 16*1024));
|
||||
CPPUNIT_ASSERT(p.isRangeComplete(8*1024, 8*1024));
|
||||
|
||||
p.completeBlock(1);
|
||||
CPPUNIT_ASSERT(p.isRangeComplete(8*1024, 16*1024));
|
||||
}
|
||||
|
||||
void PieceTest::testIsRangeComplete_subPiece()
|
||||
{
|
||||
int32_t blockLength = 16*1024;
|
||||
Piece p(0, blockLength*10, blockLength);
|
||||
|
||||
CPPUNIT_ASSERT(!p.isRangeComplete(8*1024, 32*1024));
|
||||
|
||||
PieceHandle startSubPiece = new Piece(0, blockLength, 1);
|
||||
p.addSubPiece(startSubPiece);
|
||||
|
||||
PieceHandle endSubPiece = new Piece(2, blockLength, 1);
|
||||
p.addSubPiece(endSubPiece);
|
||||
|
||||
p.completeBlock(1);
|
||||
|
||||
CPPUNIT_ASSERT(!p.isRangeComplete(8*1024, 32*1024));
|
||||
|
||||
for(int32_t i = 8*1024; i < blockLength; ++i) {
|
||||
startSubPiece->completeBlock(i);
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT(!p.isRangeComplete(8*1024, 32*1024));
|
||||
|
||||
for(int32_t i = 0; i < 8*1024; ++i) {
|
||||
endSubPiece->completeBlock(i);
|
||||
}
|
||||
CPPUNIT_ASSERT(p.isRangeComplete(8*1024, 32*1024));
|
||||
}
|
||||
|
||||
void PieceTest::testGetCompletedLength()
|
||||
{
|
||||
int32_t blockLength = 16*1024;
|
||||
Piece p(0, blockLength*10, blockLength);
|
||||
|
||||
PieceHandle subPiece = new Piece(0, blockLength, 1);
|
||||
for(int32_t i = 0; i < blockLength-1; ++i) {
|
||||
subPiece->completeBlock(i);
|
||||
}
|
||||
p.addSubPiece(subPiece);
|
||||
|
||||
p.completeBlock(1);
|
||||
p.completeBlock(2);
|
||||
p.completeBlock(9);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(blockLength*3+blockLength-1, p.getCompletedLength());
|
||||
}
|
Loading…
Reference in New Issue