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>
|
2007-10-18 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||||
|
|
||||||
Added HTTP/1.1 keep alive and pipelining support.
|
Added HTTP/1.1 keep alive and pipelining support.
|
||||||
|
|
9
TODO
9
TODO
|
@ -49,8 +49,13 @@
|
||||||
* Rewrite MetaFileUtil
|
* Rewrite MetaFileUtil
|
||||||
* Reconsider the use of RecoverableException and FatalException
|
* Reconsider the use of RecoverableException and FatalException
|
||||||
* Limit the number of opening file to,say,100 in MultiDiskAdaptor.
|
* 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
|
* 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.
|
* 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
|
* Use content-type for PostDownloadHandler
|
||||||
|
* Torrent information
|
||||||
|
|
|
@ -236,7 +236,7 @@ void DefaultBtInteractive::addRequests() {
|
||||||
if(pieceStorage->isEndGame()) {
|
if(pieceStorage->isEndGame()) {
|
||||||
pieceNum = 1;
|
pieceNum = 1;
|
||||||
} else {
|
} 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);
|
pieceNum = DIV_FLOOR(MAX_PENDING_REQUEST, blocks);
|
||||||
}
|
}
|
||||||
fillPiece(pieceNum);
|
fillPiece(pieceNum);
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
#include "DefaultDiskWriterFactory.h"
|
#include "DefaultDiskWriterFactory.h"
|
||||||
#include "DlAbortEx.h"
|
#include "DlAbortEx.h"
|
||||||
|
#include "Util.h"
|
||||||
|
|
||||||
DefaultPieceStorage::DefaultPieceStorage(const DownloadContextHandle& downloadContext, const Option* option):
|
DefaultPieceStorage::DefaultPieceStorage(const DownloadContextHandle& downloadContext, const Option* option):
|
||||||
downloadContext(downloadContext),
|
downloadContext(downloadContext),
|
||||||
|
@ -194,6 +195,36 @@ PieceHandle DefaultPieceStorage::getMissingPiece()
|
||||||
return checkOutPiece(bitfieldMan->getSparseMissingUnusedIndex());
|
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)
|
PieceHandle DefaultPieceStorage::getMissingPiece(int32_t index)
|
||||||
{
|
{
|
||||||
if(hasPiece(index) || isPieceUsed(index)) {
|
if(hasPiece(index) || isPieceUsed(index)) {
|
||||||
|
@ -299,7 +330,7 @@ void DefaultPieceStorage::cancelPiece(const PieceHandle& piece)
|
||||||
}
|
}
|
||||||
bitfieldMan->unsetUseBit(piece->getIndex());
|
bitfieldMan->unsetUseBit(piece->getIndex());
|
||||||
if(!isEndGame()) {
|
if(!isEndGame()) {
|
||||||
if(piece->countCompleteBlock() == 0) {
|
if(piece->getCompletedLength() == 0) {
|
||||||
deleteUsedPiece(piece);
|
deleteUsedPiece(piece);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -376,6 +407,7 @@ void DefaultPieceStorage::clearFileFilter()
|
||||||
// not unittested
|
// not unittested
|
||||||
bool DefaultPieceStorage::downloadFinished()
|
bool DefaultPieceStorage::downloadFinished()
|
||||||
{
|
{
|
||||||
|
// TODO iterate all requested FileEntry and Call bitfieldMan->isBitSetOffsetRange()
|
||||||
return bitfieldMan->isFilteredAllBitSet();
|
return bitfieldMan->isFilteredAllBitSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,8 @@ class Option;
|
||||||
extern typedef deque<PieceHandle> Pieces;
|
extern typedef deque<PieceHandle> Pieces;
|
||||||
class DiskWriterFactory;
|
class DiskWriterFactory;
|
||||||
extern typedef SharedHandle<DiskWriterFactory> DiskWriterFactoryHandle;
|
extern typedef SharedHandle<DiskWriterFactory> DiskWriterFactoryHandle;
|
||||||
|
class FileEntry;
|
||||||
|
extern typedef SharedHandle<FileEntry> FileEntryHandle;
|
||||||
|
|
||||||
#define END_GAME_PIECE_NUM 20
|
#define END_GAME_PIECE_NUM 20
|
||||||
|
|
||||||
|
@ -97,6 +99,7 @@ public:
|
||||||
virtual PieceHandle getMissingFastPiece(const PeerHandle& peer);
|
virtual PieceHandle getMissingFastPiece(const PeerHandle& peer);
|
||||||
|
|
||||||
virtual PieceHandle getMissingPiece();
|
virtual PieceHandle getMissingPiece();
|
||||||
|
virtual PieceHandle getMissingPiece(const FileEntryHandle& fileEntry);
|
||||||
|
|
||||||
virtual PieceHandle getMissingPiece(int32_t index);
|
virtual PieceHandle getMissingPiece(int32_t index);
|
||||||
|
|
||||||
|
|
104
src/Piece.cc
104
src/Piece.cc
|
@ -36,16 +36,17 @@
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "BitfieldManFactory.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 =
|
bitfield =
|
||||||
BitfieldManFactory::getFactoryInstance()->createBitfieldMan(BLOCK_LENGTH, length);
|
BitfieldManFactory::getFactoryInstance()->createBitfieldMan(_blockLength, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
Piece::Piece(const Piece& piece) {
|
Piece::Piece(const Piece& piece) {
|
||||||
index = piece.index;
|
index = piece.index;
|
||||||
length = piece.length;
|
length = piece.length;
|
||||||
|
_blockLength = piece._blockLength;
|
||||||
if(piece.bitfield == 0) {
|
if(piece.bitfield == 0) {
|
||||||
bitfield = 0;
|
bitfield = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -53,10 +54,10 @@ Piece::Piece(const Piece& piece) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Piece::completeBlock(int32_t blockIndex) {
|
void Piece::completeBlock(int32_t blockIndex) {
|
||||||
bitfield->setBit(blockIndex);
|
bitfield->setBit(blockIndex);
|
||||||
bitfield->unsetUseBit(blockIndex);
|
bitfield->unsetUseBit(blockIndex);
|
||||||
|
removeSubPiece(blockIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Piece::clearAllBlock() {
|
void Piece::clearAllBlock() {
|
||||||
|
@ -106,7 +107,7 @@ void Piece::reconfigure(int32_t length)
|
||||||
{
|
{
|
||||||
this->length = length;
|
this->length = length;
|
||||||
bitfield =
|
bitfield =
|
||||||
BitfieldManFactory::getFactoryInstance()->createBitfieldMan(BLOCK_LENGTH, length);
|
BitfieldManFactory::getFactoryInstance()->createBitfieldMan(_blockLength, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Piece::setBitfield(const unsigned char* bitfield, int32_t len)
|
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);
|
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 "BitfieldMan.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#define BLOCK_LENGTH (16*1024)
|
class Piece;
|
||||||
|
typedef SharedHandle<Piece> PieceHandle;
|
||||||
|
typedef deque<PieceHandle> Pieces;
|
||||||
|
|
||||||
class Piece {
|
class Piece {
|
||||||
private:
|
private:
|
||||||
int32_t index;
|
int32_t index;
|
||||||
int32_t length;
|
int32_t length;
|
||||||
|
int32_t _blockLength;
|
||||||
BitfieldMan* bitfield;
|
BitfieldMan* bitfield;
|
||||||
|
|
||||||
|
Pieces _subPieces;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
static const int32_t BLOCK_LENGTH = 16*1024;
|
||||||
|
|
||||||
Piece();
|
Piece();
|
||||||
|
|
||||||
Piece(int32_t index, int32_t length);
|
Piece(int32_t index, int32_t length, int32_t blockLength = BLOCK_LENGTH);
|
||||||
|
|
||||||
Piece(const Piece& piece);
|
Piece(const Piece& piece);
|
||||||
|
|
||||||
|
@ -118,6 +126,19 @@ public:
|
||||||
return bitfield->isUseBitSet(index);
|
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.
|
* Loses current bitfield state.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
PiecedSegment::PiecedSegment(int32_t pieceLength, const PieceHandle& piece):
|
PiecedSegment::PiecedSegment(int32_t pieceLength, const PieceHandle& piece):
|
||||||
_pieceLength(pieceLength), _overflowLength(0), _piece(piece)
|
_pieceLength(pieceLength), _overflowLength(0), _piece(piece)
|
||||||
{
|
{
|
||||||
_writtenLength = _piece->getAllMissingBlockIndexes().front()*BLOCK_LENGTH;
|
_writtenLength = _piece->getAllMissingBlockIndexes().front()*_piece->getBlockLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
PiecedSegment::~PiecedSegment() {}
|
PiecedSegment::~PiecedSegment() {}
|
||||||
|
@ -75,7 +75,7 @@ void PiecedSegment::updateWrittenLength(int32_t bytes)
|
||||||
_overflowLength = newWrittenLength-_piece->getLength();
|
_overflowLength = newWrittenLength-_piece->getLength();
|
||||||
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);
|
_piece->completeBlock(i);
|
||||||
}
|
}
|
||||||
if(newWrittenLength == _piece->getLength()) {
|
if(newWrittenLength == _piece->getLength()) {
|
||||||
|
|
|
@ -42,7 +42,7 @@ ostream& operator<<(ostream& o, const Segment& segment) {
|
||||||
if(segment.complete()) {
|
if(segment.complete()) {
|
||||||
o << "writtenLength = " << segment._piece->getLength();
|
o << "writtenLength = " << segment._piece->getLength();
|
||||||
} else {
|
} else {
|
||||||
o << "writtenLength = " << (segment._piece->getMissingUnusedBlockIndex()-1)*BLOCK_LENGTH;
|
o << "writtenLength = " << (segment._piece->getMissingUnusedBlockIndex()-1)*segment._piece->getBlockLength();
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,10 @@
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <ostream>
|
#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 {
|
class Util {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "Piece.h"
|
#include "Piece.h"
|
||||||
#include "Peer.h"
|
#include "Peer.h"
|
||||||
#include "Option.h"
|
#include "Option.h"
|
||||||
|
#include "MockBtContext.h"
|
||||||
#include <cppunit/extensions/HelperMacros.h>
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -22,6 +23,8 @@ class DefaultPieceStorageTest:public CppUnit::TestFixture {
|
||||||
CPPUNIT_TEST(testGetPiece);
|
CPPUNIT_TEST(testGetPiece);
|
||||||
CPPUNIT_TEST(testGetPieceInUsedPieces);
|
CPPUNIT_TEST(testGetPieceInUsedPieces);
|
||||||
CPPUNIT_TEST(testGetPieceCompletedPiece);
|
CPPUNIT_TEST(testGetPieceCompletedPiece);
|
||||||
|
CPPUNIT_TEST(testGetMissingPiece_fileEntry);
|
||||||
|
CPPUNIT_TEST(testCancelPiece);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
private:
|
private:
|
||||||
BtContextHandle btContext;
|
BtContextHandle btContext;
|
||||||
|
@ -43,6 +46,12 @@ public:
|
||||||
option = new Option();
|
option = new Option();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tearDown()
|
||||||
|
{
|
||||||
|
delete option;
|
||||||
|
option = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void testGetTotalLength();
|
void testGetTotalLength();
|
||||||
void testGetMissingPiece();
|
void testGetMissingPiece();
|
||||||
void testGetMissingFastPiece();
|
void testGetMissingFastPiece();
|
||||||
|
@ -51,6 +60,8 @@ public:
|
||||||
void testGetPiece();
|
void testGetPiece();
|
||||||
void testGetPieceInUsedPieces();
|
void testGetPieceInUsedPieces();
|
||||||
void testGetPieceCompletedPiece();
|
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((int32_t)128, pieceGot->getLength());
|
||||||
CPPUNIT_ASSERT_EQUAL(true, pieceGot->pieceComplete());
|
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
|
TESTS = aria2c
|
||||||
check_PROGRAMS = $(TESTS)
|
check_PROGRAMS = $(TESTS)
|
||||||
aria2c_SOURCES = AllTest.cc\
|
aria2c_SOURCES = AllTest.cc\
|
||||||
|
PieceTest.cc\
|
||||||
|
DefaultPieceStorageTest.cc\
|
||||||
SegmentTest.cc\
|
SegmentTest.cc\
|
||||||
GrowSegmentTest.cc\
|
GrowSegmentTest.cc\
|
||||||
SingleFileAllocationIteratorTest.cc\
|
SingleFileAllocationIteratorTest.cc\
|
||||||
|
@ -67,7 +69,6 @@ aria2c_SOURCES += BtAllowedFastMessageTest.cc\
|
||||||
DefaultBtContextTest.cc\
|
DefaultBtContextTest.cc\
|
||||||
DefaultBtMessageDispatcherTest.cc\
|
DefaultBtMessageDispatcherTest.cc\
|
||||||
DefaultBtRequestFactoryTest.cc\
|
DefaultBtRequestFactoryTest.cc\
|
||||||
DefaultPieceStorageTest.cc\
|
|
||||||
MockBtMessage.h\
|
MockBtMessage.h\
|
||||||
MockBtMessageDispatcher.h\
|
MockBtMessageDispatcher.h\
|
||||||
MockBtMessageFactory.h\
|
MockBtMessageFactory.h\
|
||||||
|
|
|
@ -61,7 +61,6 @@ check_PROGRAMS = $(am__EXEEXT_1)
|
||||||
@ENABLE_BITTORRENT_TRUE@ DefaultBtContextTest.cc\
|
@ENABLE_BITTORRENT_TRUE@ DefaultBtContextTest.cc\
|
||||||
@ENABLE_BITTORRENT_TRUE@ DefaultBtMessageDispatcherTest.cc\
|
@ENABLE_BITTORRENT_TRUE@ DefaultBtMessageDispatcherTest.cc\
|
||||||
@ENABLE_BITTORRENT_TRUE@ DefaultBtRequestFactoryTest.cc\
|
@ENABLE_BITTORRENT_TRUE@ DefaultBtRequestFactoryTest.cc\
|
||||||
@ENABLE_BITTORRENT_TRUE@ DefaultPieceStorageTest.cc\
|
|
||||||
@ENABLE_BITTORRENT_TRUE@ MockBtMessage.h\
|
@ENABLE_BITTORRENT_TRUE@ MockBtMessage.h\
|
||||||
@ENABLE_BITTORRENT_TRUE@ MockBtMessageDispatcher.h\
|
@ENABLE_BITTORRENT_TRUE@ MockBtMessageDispatcher.h\
|
||||||
@ENABLE_BITTORRENT_TRUE@ MockBtMessageFactory.h\
|
@ENABLE_BITTORRENT_TRUE@ MockBtMessageFactory.h\
|
||||||
|
@ -112,7 +111,8 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||||
CONFIG_HEADER = $(top_builddir)/config.h
|
CONFIG_HEADER = $(top_builddir)/config.h
|
||||||
CONFIG_CLEAN_FILES =
|
CONFIG_CLEAN_FILES =
|
||||||
am__EXEEXT_1 = aria2c$(EXEEXT)
|
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 \
|
SingleFileAllocationIteratorTest.cc \
|
||||||
DefaultBtProgressInfoFileTest.cc \
|
DefaultBtProgressInfoFileTest.cc \
|
||||||
SingleFileDownloadContextTest.cc RequestGroupTest.cc \
|
SingleFileDownloadContextTest.cc RequestGroupTest.cc \
|
||||||
|
@ -140,17 +140,17 @@ am__aria2c_SOURCES_DIST = AllTest.cc SegmentTest.cc GrowSegmentTest.cc \
|
||||||
BtRequestMessageTest.cc BtSuggestPieceMessageTest.cc \
|
BtRequestMessageTest.cc BtSuggestPieceMessageTest.cc \
|
||||||
BtUnchokeMessageTest.cc DefaultBtAnnounceTest.cc \
|
BtUnchokeMessageTest.cc DefaultBtAnnounceTest.cc \
|
||||||
DefaultBtContextTest.cc DefaultBtMessageDispatcherTest.cc \
|
DefaultBtContextTest.cc DefaultBtMessageDispatcherTest.cc \
|
||||||
DefaultBtRequestFactoryTest.cc DefaultPieceStorageTest.cc \
|
DefaultBtRequestFactoryTest.cc MockBtMessage.h \
|
||||||
MockBtMessage.h MockBtMessageDispatcher.h \
|
MockBtMessageDispatcher.h MockBtMessageFactory.h \
|
||||||
MockBtMessageFactory.h ShaVisitorTest.cc \
|
ShaVisitorTest.cc DefaultPeerListProcessorTest.cc \
|
||||||
DefaultPeerListProcessorTest.cc AnnounceListTest.cc \
|
AnnounceListTest.cc DefaultPeerStorageTest.cc \
|
||||||
DefaultPeerStorageTest.cc MockPeerStorage.h DataTest.cc \
|
MockPeerStorage.h DataTest.cc DictionaryTest.cc ListTest.cc \
|
||||||
DictionaryTest.cc ListTest.cc MetaFileUtilTest.cc \
|
MetaFileUtilTest.cc MultiDiskAdaptorTest.cc \
|
||||||
MultiDiskAdaptorTest.cc ByteArrayDiskWriterTest.cc PeerTest.cc \
|
ByteArrayDiskWriterTest.cc PeerTest.cc PeerMessageUtilTest.cc \
|
||||||
PeerMessageUtilTest.cc ShareRatioSeedCriteriaTest.cc \
|
ShareRatioSeedCriteriaTest.cc BtRegistryTest.cc \
|
||||||
BtRegistryTest.cc MultiFileAllocationIteratorTest.cc \
|
MultiFileAllocationIteratorTest.cc BtDependencyTest.cc \
|
||||||
BtDependencyTest.cc BtPostDownloadHandlerTest.cc \
|
BtPostDownloadHandlerTest.cc TimeSeedCriteriaTest.cc \
|
||||||
TimeSeedCriteriaTest.cc MetalinkerTest.cc MetalinkEntryTest.cc \
|
MetalinkerTest.cc MetalinkEntryTest.cc \
|
||||||
Xml2MetalinkProcessorTest.cc Metalink2RequestGroupTest.cc \
|
Xml2MetalinkProcessorTest.cc Metalink2RequestGroupTest.cc \
|
||||||
MetalinkPostDownloadHandlerTest.cc
|
MetalinkPostDownloadHandlerTest.cc
|
||||||
@ENABLE_MESSAGE_DIGEST_TRUE@am__objects_1 = \
|
@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@ DefaultBtContextTest.$(OBJEXT) \
|
||||||
@ENABLE_BITTORRENT_TRUE@ DefaultBtMessageDispatcherTest.$(OBJEXT) \
|
@ENABLE_BITTORRENT_TRUE@ DefaultBtMessageDispatcherTest.$(OBJEXT) \
|
||||||
@ENABLE_BITTORRENT_TRUE@ DefaultBtRequestFactoryTest.$(OBJEXT) \
|
@ENABLE_BITTORRENT_TRUE@ DefaultBtRequestFactoryTest.$(OBJEXT) \
|
||||||
@ENABLE_BITTORRENT_TRUE@ DefaultPieceStorageTest.$(OBJEXT) \
|
|
||||||
@ENABLE_BITTORRENT_TRUE@ ShaVisitorTest.$(OBJEXT) \
|
@ENABLE_BITTORRENT_TRUE@ ShaVisitorTest.$(OBJEXT) \
|
||||||
@ENABLE_BITTORRENT_TRUE@ DefaultPeerListProcessorTest.$(OBJEXT) \
|
@ENABLE_BITTORRENT_TRUE@ DefaultPeerListProcessorTest.$(OBJEXT) \
|
||||||
@ENABLE_BITTORRENT_TRUE@ AnnounceListTest.$(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@ Xml2MetalinkProcessorTest.$(OBJEXT) \
|
||||||
@ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.$(OBJEXT) \
|
@ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.$(OBJEXT) \
|
||||||
@ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandlerTest.$(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) \
|
GrowSegmentTest.$(OBJEXT) \
|
||||||
SingleFileAllocationIteratorTest.$(OBJEXT) \
|
SingleFileAllocationIteratorTest.$(OBJEXT) \
|
||||||
DefaultBtProgressInfoFileTest.$(OBJEXT) \
|
DefaultBtProgressInfoFileTest.$(OBJEXT) \
|
||||||
|
@ -412,7 +412,8 @@ target_cpu = @target_cpu@
|
||||||
target_os = @target_os@
|
target_os = @target_os@
|
||||||
target_vendor = @target_vendor@
|
target_vendor = @target_vendor@
|
||||||
TESTS = aria2c
|
TESTS = aria2c
|
||||||
aria2c_SOURCES = AllTest.cc SegmentTest.cc GrowSegmentTest.cc \
|
aria2c_SOURCES = AllTest.cc PieceTest.cc DefaultPieceStorageTest.cc \
|
||||||
|
SegmentTest.cc GrowSegmentTest.cc \
|
||||||
SingleFileAllocationIteratorTest.cc \
|
SingleFileAllocationIteratorTest.cc \
|
||||||
DefaultBtProgressInfoFileTest.cc \
|
DefaultBtProgressInfoFileTest.cc \
|
||||||
SingleFileDownloadContextTest.cc RequestGroupTest.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)/ParameterizedStringParserTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerMessageUtilTest.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)/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)/RequestFactoryTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestGroupManTest.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@
|
@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