aria2/test/DefaultPieceStorageTest.cc
Tatsuhiro Tsujikawa c064a2cd9e 2008-02-10 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Extract the Peer class's member variables, which are only needed 
after
	PeerInteractionCommand, into PeerSessionResource class.
	This class is instantiated in PeerInteractionCommand class's 
ctor and
	released in its dtor.
	This will make Peer class lightweight and uses less memory for 
peers
	which are not connected and wait in the queue.
	* src/PeerChokeCommand.cc
	* src/PeerSessionResource.{h, cc}
	* src/PeerInteractionCommand.cc
	* src/PeerAbstractCommand.cc: Note: 0 is given to onAbort() 
function.
	* src/DefaultBtInteractive.cc
	* src/BtPieceMessage.cc
	* src/BtInterestedMessage.cc
	* src/BtUnchokeMessage.cc
	* src/DefaultPeerStorage.{h, cc}
	* src/PeerInitiateConnectionCommand.cc
	* src/ActivePeerConnectionCommand.cc
	* src/BtNotInterestedMessage.cc
	* src/DefaultBtMessageDispatcher.cc
	* src/BtChokeMessage.cc
	* src/BtRequestMessage.cc
	* src/Peer.{h, cc}
	* src/BtRegistry.h
	* src/TrackerWatcherCommand.cc
	* src/PeerReceiveHandshakeCommand.cc
	* test/BtExtendedMessageTest.cc
	* test/BtAllowedFastMessageTest.cc
	* test/BtCancelMessageTest.cc
	* test/DefaultPieceStorageTest.cc
	* test/BtBitfieldMessageTest.cc
	* test/BtHaveMessageTest.cc
	* test/BtNotInterestedMessageTest.cc
	* test/BtRequestMessageTest.cc
	* test/PeerSessionResourceTest.cc
	* test/DefaultBtMessageDispatcherTest.cc
	* test/PeerTest.cc
	* test/BtInterestedMessageTest.cc
	* test/BtRejectMessageTest.cc
	* test/BtChokeMessageTest.cc
	* test/DefaultPeerStorageTest.cc
	* test/BtHaveNoneMessageTest.cc
	* test/BtHaveAllMessageTest.cc
	* test/DefaultExtensionMessageFactoryTest.cc
	* test/BtUnchokeMessageTest.cc
	* test/DefaultBtMessageFactoryTest.cc
	* test/HandshakeExtensionMessageTest.cc
	* test/UTPexExtensionMessageTest.cc
	* test/DefaultBtRequestFactoryTest.cc
	* test/BtPieceMessageTest.cc
	
	Removed typedef PeerStats.
	* src/PeerStat.h
	* src/SegmentMan.cc
2008-02-09 17:14:40 +00:00

300 lines
9 KiB
C++

#include "DefaultPieceStorage.h"
#include "DefaultBtContext.h"
#include "Util.h"
#include "Exception.h"
#include "FixedNumberRandomizer.h"
#include "BitfieldManFactory.h"
#include "Piece.h"
#include "Peer.h"
#include "Option.h"
#include "FileEntry.h"
#include "MockBtContext.h"
#include <cppunit/extensions/HelperMacros.h>
namespace aria2 {
class DefaultPieceStorageTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(DefaultPieceStorageTest);
CPPUNIT_TEST(testGetTotalLength);
CPPUNIT_TEST(testGetMissingPiece);
CPPUNIT_TEST(testGetMissingFastPiece);
CPPUNIT_TEST(testHasMissingPiece);
CPPUNIT_TEST(testCompletePiece);
CPPUNIT_TEST(testGetPiece);
CPPUNIT_TEST(testGetPieceInUsedPieces);
CPPUNIT_TEST(testGetPieceCompletedPiece);
CPPUNIT_TEST(testGetMissingPiece_fileEntry);
CPPUNIT_TEST(testCancelPiece);
CPPUNIT_TEST(testMarkPiecesDone);
CPPUNIT_TEST_SUITE_END();
private:
SharedHandle<BtContext> btContext;
SharedHandle<Peer> peer;
Option* option;
public:
DefaultPieceStorageTest():btContext(0), peer(0) {
FixedNumberRandomizer* randomizer = new FixedNumberRandomizer();
randomizer->setFixedNumber(0);
BitfieldManFactory::setDefaultRandomizer(randomizer);
}
void setUp() {
btContext = new DefaultBtContext();
btContext->load("test.torrent");
peer = new Peer("192.168.0.1", 6889);
peer->allocateSessionResource(btContext->getPieceLength(),
btContext->getTotalLength());
option = new Option();
}
void tearDown()
{
delete option;
option = 0;
}
void testGetTotalLength();
void testGetMissingPiece();
void testGetMissingFastPiece();
void testHasMissingPiece();
void testCompletePiece();
void testGetPiece();
void testGetPieceInUsedPieces();
void testGetPieceCompletedPiece();
void testGetMissingPiece_fileEntry();
void testCancelPiece();
void testMarkPiecesDone();
};
CPPUNIT_TEST_SUITE_REGISTRATION(DefaultPieceStorageTest);
void DefaultPieceStorageTest::testGetTotalLength() {
DefaultPieceStorage pss(btContext, option);
CPPUNIT_ASSERT_EQUAL((long long int)384,
pss.getTotalLength());
}
void DefaultPieceStorageTest::testGetMissingPiece() {
DefaultPieceStorage pss(btContext, option);
pss.setEndGamePieceNum(0);
peer->setAllBitfield();
SharedHandle<Piece> piece = pss.getMissingPiece(peer);
CPPUNIT_ASSERT_EQUAL(std::string("piece: index=0, length=128"),
piece->toString());
piece = pss.getMissingPiece(peer);
CPPUNIT_ASSERT_EQUAL(std::string("piece: index=1, length=128"),
piece->toString());
piece = pss.getMissingPiece(peer);
CPPUNIT_ASSERT_EQUAL(std::string("piece: index=2, length=128"),
piece->toString());
piece = pss.getMissingPiece(peer);
CPPUNIT_ASSERT(piece.isNull());
}
void DefaultPieceStorageTest::testGetMissingFastPiece() {
DefaultPieceStorage pss(btContext, option);
pss.setEndGamePieceNum(0);
peer->setAllBitfield();
peer->setFastExtensionEnabled(true);
peer->addPeerAllowedIndex(2);
SharedHandle<Piece> piece = pss.getMissingFastPiece(peer);
CPPUNIT_ASSERT_EQUAL(std::string("piece: index=2, length=128"),
piece->toString());
}
void DefaultPieceStorageTest::testHasMissingPiece() {
DefaultPieceStorage pss(btContext, option);
CPPUNIT_ASSERT(!pss.hasMissingPiece(peer));
peer->setAllBitfield();
CPPUNIT_ASSERT(pss.hasMissingPiece(peer));
}
void DefaultPieceStorageTest::testCompletePiece() {
DefaultPieceStorage pss(btContext, option);
pss.setEndGamePieceNum(0);
peer->setAllBitfield();
SharedHandle<Piece> piece = pss.getMissingPiece(peer);
CPPUNIT_ASSERT_EQUAL(std::string("piece: index=0, length=128"),
piece->toString());
CPPUNIT_ASSERT_EQUAL((int64_t)0,
pss.getCompletedLength());
pss.completePiece(piece);
CPPUNIT_ASSERT_EQUAL((int64_t)128,
pss.getCompletedLength());
SharedHandle<Piece> incompletePiece = pss.getMissingPiece(peer);
incompletePiece->completeBlock(0);
CPPUNIT_ASSERT_EQUAL((int64_t)256,
pss.getCompletedLength());
}
void DefaultPieceStorageTest::testGetPiece() {
DefaultPieceStorage pss(btContext, option);
SharedHandle<Piece> pieceGot = pss.getPiece(0);
CPPUNIT_ASSERT_EQUAL((int32_t)0, pieceGot->getIndex());
CPPUNIT_ASSERT_EQUAL((int32_t)128, pieceGot->getLength());
CPPUNIT_ASSERT_EQUAL(false, pieceGot->pieceComplete());
}
void DefaultPieceStorageTest::testGetPieceInUsedPieces() {
DefaultPieceStorage pss(btContext, option);
SharedHandle<Piece> piece = SharedHandle<Piece>(new Piece(0, 128));
piece->completeBlock(0);
pss.addUsedPiece(piece);
SharedHandle<Piece> pieceGot = pss.getPiece(0);
CPPUNIT_ASSERT_EQUAL((int32_t)0, pieceGot->getIndex());
CPPUNIT_ASSERT_EQUAL((int32_t)128, pieceGot->getLength());
CPPUNIT_ASSERT_EQUAL((int32_t)1, pieceGot->countCompleteBlock());
}
void DefaultPieceStorageTest::testGetPieceCompletedPiece() {
DefaultPieceStorage pss(btContext, option);
SharedHandle<Piece> piece = SharedHandle<Piece>(new Piece(0, 128));
pss.completePiece(piece);
SharedHandle<Piece> pieceGot = pss.getPiece(0);
CPPUNIT_ASSERT_EQUAL((int32_t)0, pieceGot->getIndex());
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;
std::deque<std::string> uris1;
uris1.push_back("http://localhost/src/file1.txt");
std::deque<std::string> uris2;
uris2.push_back("http://localhost/src/file2.txt");
SharedHandle<FileEntry> file1 = new FileEntry("src/file1.txt", 150*1024, 0/*, uris1*/);
SharedHandle<FileEntry> file2 = new FileEntry("src/file2.txt", 106*1024, file1->getLength() /*, uris2*/);
SharedHandle<MockBtContext> dctx = new MockBtContext();
dctx->setPieceLength(pieceLength);
dctx->setTotalLength(totalLength);
dctx->addFileEntry(file1);
dctx->addFileEntry(file2);
SharedHandle<DefaultPieceStorage> ps = new DefaultPieceStorage(dctx, option);
SharedHandle<Piece> 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);
}
SharedHandle<Piece> 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
SharedHandle<Piece> 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
SharedHandle<Piece> 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;
std::deque<std::string> uris1;
uris1.push_back("http://localhost/src/file1.txt");
SharedHandle<FileEntry> file1 = new FileEntry("src/file1.txt", totalLength, 0 /*, uris1*/);
SharedHandle<MockBtContext> dctx = new MockBtContext();
dctx->setPieceLength(pieceLength);
dctx->setTotalLength(totalLength);
dctx->addFileEntry(file1);
SharedHandle<DefaultPieceStorage> ps = new DefaultPieceStorage(dctx, option);
SharedHandle<Piece> p = ps->getMissingPiece(file1);
SharedHandle<Piece> subPiece = new Piece(0, blockLength, 1);
subPiece->completeBlock(0);
p->addSubPiece(subPiece);
ps->cancelPiece(p);
// See the sub piece is also hibernated...
SharedHandle<Piece> p2 = ps->getMissingPiece(file1);
CPPUNIT_ASSERT(!p2->getSubPiece(0).isNull());
}
void DefaultPieceStorageTest::testMarkPiecesDone()
{
int32_t pieceLength = 256*1024;
int64_t totalLength = 4*1024*1024;
SharedHandle<MockBtContext> dctx = new MockBtContext();
dctx->setPieceLength(pieceLength);
dctx->setTotalLength(totalLength);
DefaultPieceStorage ps(dctx, option);
ps.markPiecesDone(pieceLength*10+16*1024*2+1);
for(int32_t i = 0; i < 10; ++i) {
CPPUNIT_ASSERT(ps.hasPiece(i));
}
for(int32_t i = 10; i < (totalLength+pieceLength-1)/pieceLength; ++i) {
CPPUNIT_ASSERT(!ps.hasPiece(i));
}
CPPUNIT_ASSERT_EQUAL((int64_t)pieceLength*10+16*1024*2, ps.getCompletedLength());
ps.markPiecesDone(totalLength);
for(int32_t i = 0; i < (totalLength+pieceLength-1)/pieceLength; ++i) {
CPPUNIT_ASSERT(ps.hasPiece(i));
}
}
} // namespace aria2