mirror of https://github.com/aria2/aria2
2007-11-07 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Reflect the download length of in-flight pieces. It makes the download length readout more precise. * src/DefaultPieceStorage.{h, cc} * test/DefaultPieceStorageTest.cc * src/a2functional.h * test/a2functionalTest.cc Lower CPU load when --max-download-limit is used. There is up and down in speed indicator when enabling http-pipelining but a download goes well. I think the problem is that because http-pipelining is enabled, DownloadCommand is created for each segment and in its constructor, PeerStat::downloadStart() is called. In PeerStat::downloadStart(), speed calculation object is reseted, which makes download speed zero. * src/DownloadCommand.cc Rewritten using accumulate. * src/RequestGroupMan.cc (calculateStat) Code clearnup. * src/FtpNegotiationCommand.cc * src/HttpResponseCommand.ccpull/1/head
parent
dfd40dff54
commit
b4f7588ba2
25
ChangeLog
25
ChangeLog
|
@ -1,3 +1,28 @@
|
||||||
|
2007-11-07 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||||
|
|
||||||
|
Reflect the download length of in-flight pieces.
|
||||||
|
It makes the download length readout more precise.
|
||||||
|
* src/DefaultPieceStorage.{h, cc}
|
||||||
|
* test/DefaultPieceStorageTest.cc
|
||||||
|
* src/a2functional.h
|
||||||
|
* test/a2functionalTest.cc
|
||||||
|
|
||||||
|
Lower CPU load when --max-download-limit is used.
|
||||||
|
There is up and down in speed indicator when enabling
|
||||||
|
http-pipelining but a download goes well. I think the problem is that
|
||||||
|
because http-pipelining is enabled, DownloadCommand is created for
|
||||||
|
each segment and in its constructor, PeerStat::downloadStart() is
|
||||||
|
called. In PeerStat::downloadStart(), speed calculation object is
|
||||||
|
reseted, which makes download speed zero.
|
||||||
|
* src/DownloadCommand.cc
|
||||||
|
|
||||||
|
Rewritten using accumulate.
|
||||||
|
* src/RequestGroupMan.cc (calculateStat)
|
||||||
|
|
||||||
|
Code clearnup.
|
||||||
|
* src/FtpNegotiationCommand.cc
|
||||||
|
* src/HttpResponseCommand.cc
|
||||||
|
|
||||||
2007-11-06 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
2007-11-06 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||||
|
|
||||||
Fixed: Can not resume: aria2 reports download already finished.
|
Fixed: Can not resume: aria2 reports download already finished.
|
||||||
|
|
|
@ -47,6 +47,8 @@
|
||||||
#include "DefaultDiskWriterFactory.h"
|
#include "DefaultDiskWriterFactory.h"
|
||||||
#include "DlAbortEx.h"
|
#include "DlAbortEx.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
#include "a2functional.h"
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
DefaultPieceStorage::DefaultPieceStorage(const DownloadContextHandle& downloadContext, const Option* option):
|
DefaultPieceStorage::DefaultPieceStorage(const DownloadContextHandle& downloadContext, const Option* option):
|
||||||
downloadContext(downloadContext),
|
downloadContext(downloadContext),
|
||||||
|
@ -358,12 +360,17 @@ int64_t DefaultPieceStorage::getFilteredTotalLength()
|
||||||
|
|
||||||
int64_t DefaultPieceStorage::getCompletedLength()
|
int64_t DefaultPieceStorage::getCompletedLength()
|
||||||
{
|
{
|
||||||
return bitfieldMan->getCompletedLength();
|
return bitfieldMan->getCompletedLength()+getInFlightPieceCompletedLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t DefaultPieceStorage::getFilteredCompletedLength()
|
int64_t DefaultPieceStorage::getFilteredCompletedLength()
|
||||||
{
|
{
|
||||||
return bitfieldMan->getFilteredCompletedLength();
|
return bitfieldMan->getFilteredCompletedLength()+getInFlightPieceCompletedLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t DefaultPieceStorage::getInFlightPieceCompletedLength() const
|
||||||
|
{
|
||||||
|
return accumulate(usedPieces.begin(), usedPieces.end(), 0, adopt2nd(plus<int32_t>(), mem_fun_sh(&Piece::getCompletedLength)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// not unittested
|
// not unittested
|
||||||
|
|
|
@ -88,6 +88,9 @@ private:
|
||||||
void reduceUsedPieces(int32_t delMax);
|
void reduceUsedPieces(int32_t delMax);
|
||||||
void deleteUsedPiece(const PieceHandle& piece);
|
void deleteUsedPiece(const PieceHandle& piece);
|
||||||
PieceHandle findUsedPiece(int32_t index) const;
|
PieceHandle findUsedPiece(int32_t index) const;
|
||||||
|
|
||||||
|
int32_t getInFlightPieceCompletedLength() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DefaultPieceStorage(const DownloadContextHandle& downloadContext, const Option* option);
|
DefaultPieceStorage(const DownloadContextHandle& downloadContext, const Option* option);
|
||||||
virtual ~DefaultPieceStorage();
|
virtual ~DefaultPieceStorage();
|
||||||
|
|
|
@ -79,10 +79,11 @@ bool DownloadCommand::executeInternal() {
|
||||||
// TODO we need to specify the sum of all segmentMan's download speed here.
|
// TODO we need to specify the sum of all segmentMan's download speed here.
|
||||||
if(maxDownloadSpeedLimit > 0 &&
|
if(maxDownloadSpeedLimit > 0 &&
|
||||||
maxDownloadSpeedLimit < _requestGroup->getSegmentMan()->calculateDownloadSpeed()) {
|
maxDownloadSpeedLimit < _requestGroup->getSegmentMan()->calculateDownloadSpeed()) {
|
||||||
Util::usleep(1);
|
|
||||||
e->commands.push_back(this);
|
e->commands.push_back(this);
|
||||||
|
disableReadCheckSocket();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
setReadCheckSocket(socket);
|
||||||
SegmentHandle segment = _segments.front();
|
SegmentHandle segment = _segments.front();
|
||||||
|
|
||||||
int32_t BUFSIZE = 16*1024;
|
int32_t BUFSIZE = 16*1024;
|
||||||
|
|
|
@ -200,10 +200,11 @@ bool FtpNegotiationCommand::recvSize() {
|
||||||
|
|
||||||
initPieceStorage();
|
initPieceStorage();
|
||||||
|
|
||||||
// TODO validate filename and totalsize against hintFilename and hintTotalSize if these are provided.
|
// TODO validate totalsize against hintTotalSize if it is provided.
|
||||||
_requestGroup->validateTotalLengthByHint(size);
|
_requestGroup->validateTotalLengthByHint(size);
|
||||||
|
// TODO Is this really necessary?
|
||||||
if(req->getMethod() == Request::METHOD_HEAD) {
|
if(req->getMethod() == Request::METHOD_HEAD) {
|
||||||
//_requestGroup->getSegmentMan()->isSplittable = false; // TODO because we don't want segment file to be saved.
|
// TODO because we don't want segment file to be saved.
|
||||||
sequence = SEQ_HEAD_OK;
|
sequence = SEQ_HEAD_OK;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,12 +75,6 @@ bool HttpResponseCommand::executeInternal()
|
||||||
// check HTTP status number
|
// check HTTP status number
|
||||||
httpResponse->validateResponse();
|
httpResponse->validateResponse();
|
||||||
httpResponse->retrieveCookie();
|
httpResponse->retrieveCookie();
|
||||||
// check whether the server supports persistent connections.
|
|
||||||
/*
|
|
||||||
if(Util::toLower(headers.getFirst("Connection")).find("close") != string::npos) {
|
|
||||||
req->setKeepAlive(false);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// check whether Location header exists. If it does, update request object
|
// check whether Location header exists. If it does, update request object
|
||||||
// with redirected URL.
|
// with redirected URL.
|
||||||
// then establish a connection to the new host and port
|
// then establish a connection to the new host and port
|
||||||
|
@ -116,18 +110,13 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpResponseHandle& httpRe
|
||||||
if(size == INT64_MAX || size < 0) {
|
if(size == INT64_MAX || size < 0) {
|
||||||
throw new DlAbortEx(EX_TOO_LARGE_FILE, Util::llitos(size, true).c_str());
|
throw new DlAbortEx(EX_TOO_LARGE_FILE, Util::llitos(size, true).c_str());
|
||||||
}
|
}
|
||||||
//_requestGroup->getSegmentMan()->isSplittable = !(size == 0);
|
|
||||||
//_requestGroup->getSegmentMan()->totalSize = size;
|
|
||||||
//_requestGroup->getSegmentMan()->initDownloadContext(size);
|
|
||||||
|
|
||||||
SingleFileDownloadContextHandle(_requestGroup->getDownloadContext())->setTotalLength(size);
|
SingleFileDownloadContextHandle(_requestGroup->getDownloadContext())->setTotalLength(size);
|
||||||
|
|
||||||
initPieceStorage();
|
initPieceStorage();
|
||||||
|
|
||||||
// quick hack for method 'head'
|
// quick hack for method 'head',, is it necessary?
|
||||||
if(httpRequest->getMethod() == Request::METHOD_HEAD) {
|
if(httpRequest->getMethod() == Request::METHOD_HEAD) {
|
||||||
// TODO because we don't want segment file to be saved.
|
// TODO because we don't want segment file to be saved.
|
||||||
//_requestGroup->getSegmentMan()->isSplittable = false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,11 +145,9 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpResponseHandle& httpRe
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HttpResponseCommand::handleOtherEncoding(const HttpResponseHandle& httpResponse) {
|
bool HttpResponseCommand::handleOtherEncoding(const HttpResponseHandle& httpResponse) {
|
||||||
HttpRequestHandle httpRequest = httpResponse->getHttpRequest();
|
|
||||||
// we ignore content-length when transfer-encoding is set
|
// we ignore content-length when transfer-encoding is set
|
||||||
//_requestGroup->getSegmentMan()->isSplittable = false;
|
HttpRequestHandle httpRequest = httpResponse->getHttpRequest();
|
||||||
//_requestGroup->getSegmentMan()->totalSize = 0;
|
// quick hack for method 'head',, is it necessary?
|
||||||
// quick hack for method 'head'
|
|
||||||
if(httpRequest->getMethod() == Request::METHOD_HEAD) {
|
if(httpRequest->getMethod() == Request::METHOD_HEAD) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -169,11 +156,9 @@ bool HttpResponseCommand::handleOtherEncoding(const HttpResponseHandle& httpResp
|
||||||
|
|
||||||
initPieceStorage();
|
initPieceStorage();
|
||||||
|
|
||||||
//segment = _requestGroup->getSegmentMan()->getSegment(cuid);
|
|
||||||
|
|
||||||
shouldCancelDownloadForSafety();
|
shouldCancelDownloadForSafety();
|
||||||
// TODO handle file-size unknown case
|
// TODO handle file-size unknown case
|
||||||
_requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile();//_requestGroup->getFilePath());
|
_requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile();
|
||||||
e->commands.push_back(createHttpDownloadCommand(httpResponse));
|
e->commands.push_back(createHttpDownloadCommand(httpResponse));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,10 @@
|
||||||
#include "LogFactory.h"
|
#include "LogFactory.h"
|
||||||
#include "DownloadEngine.h"
|
#include "DownloadEngine.h"
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
|
#include "a2functional.h"
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
RequestGroupMan::RequestGroupMan(const RequestGroups& requestGroups,
|
RequestGroupMan::RequestGroupMan(const RequestGroups& requestGroups,
|
||||||
int32_t maxSimultaneousDownloads):
|
int32_t maxSimultaneousDownloads):
|
||||||
|
@ -277,10 +279,6 @@ void RequestGroupMan::halt()
|
||||||
|
|
||||||
TransferStat RequestGroupMan::calculateStat()
|
TransferStat RequestGroupMan::calculateStat()
|
||||||
{
|
{
|
||||||
TransferStat stat;
|
return accumulate(_requestGroups.begin(), _requestGroups.end(), TransferStat(),
|
||||||
for(RequestGroups::const_iterator itr = _requestGroups.begin();
|
adopt2nd(plus<TransferStat>(), mem_fun_sh(&RequestGroup::calculateStat)));
|
||||||
itr != _requestGroups.end(); ++itr) {
|
|
||||||
stat = stat+(*itr)->calculateStat();
|
|
||||||
}
|
|
||||||
return stat;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
/* <!-- copyright */
|
||||||
|
/*
|
||||||
|
* aria2 - The high speed download utility
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give
|
||||||
|
* permission to link the code of portions of this program with the
|
||||||
|
* OpenSSL library under certain conditions as described in each
|
||||||
|
* individual source file, and distribute linked combinations
|
||||||
|
* including the two.
|
||||||
|
* You must obey the GNU General Public License in all respects
|
||||||
|
* for all of the code used other than OpenSSL. If you modify
|
||||||
|
* file(s) with this exception, you may extend this exception to your
|
||||||
|
* version of the file(s), but you are not obligated to do so. If you
|
||||||
|
* do not wish to do so, delete this exception statement from your
|
||||||
|
* version. If you delete this exception statement from all source
|
||||||
|
* files in the program, then also delete it here.
|
||||||
|
*/
|
||||||
|
/* copyright --> */
|
||||||
|
#include <functional>
|
||||||
|
#include "SharedHandle.h"
|
||||||
|
|
||||||
|
// mem_fun_t for SharedHandle
|
||||||
|
template <class ReturnType, typename ClassType>
|
||||||
|
class mem_fun_sh_t:public std::unary_function< SharedHandle<ClassType>, ReturnType>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ReturnType (ClassType::*f)();
|
||||||
|
|
||||||
|
public:
|
||||||
|
mem_fun_sh_t(ReturnType (ClassType::*f)()):f(f) {}
|
||||||
|
|
||||||
|
ReturnType operator()(const SharedHandle<ClassType>& x) const
|
||||||
|
{
|
||||||
|
return (x.get()->*f)();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// const_mem_fun_t for SharedHandle
|
||||||
|
template <class ReturnType, typename ClassType>
|
||||||
|
class const_mem_fun_sh_t:public std::unary_function< SharedHandle<ClassType>, ReturnType>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ReturnType (ClassType::*f)() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
const_mem_fun_sh_t(ReturnType (ClassType::*f)() const):f(f) {}
|
||||||
|
|
||||||
|
ReturnType operator()(const SharedHandle<ClassType>& x) const
|
||||||
|
{
|
||||||
|
return (x.get()->*f)();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ReturnType, typename ClassType>
|
||||||
|
mem_fun_sh_t<ReturnType, ClassType>
|
||||||
|
mem_fun_sh(ReturnType (ClassType::*f)())
|
||||||
|
{
|
||||||
|
return mem_fun_sh_t<ReturnType, ClassType>(f);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class ReturnType, typename ClassType>
|
||||||
|
const_mem_fun_sh_t<ReturnType, ClassType>
|
||||||
|
mem_fun_sh(ReturnType (ClassType::*f)() const)
|
||||||
|
{
|
||||||
|
return const_mem_fun_sh_t<ReturnType, ClassType>(f);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class BinaryOp, class UnaryOp>
|
||||||
|
class adopt2nd_t:public std::binary_function<typename BinaryOp::first_argument_type,
|
||||||
|
typename UnaryOp::argument_type,
|
||||||
|
typename BinaryOp::result_type> {
|
||||||
|
private:
|
||||||
|
BinaryOp _binaryOp;
|
||||||
|
UnaryOp _unaryOp;
|
||||||
|
public:
|
||||||
|
adopt2nd_t(const BinaryOp& b, const UnaryOp& u):
|
||||||
|
_binaryOp(b), _unaryOp(u) {}
|
||||||
|
|
||||||
|
typename BinaryOp::result_type
|
||||||
|
operator()(const typename BinaryOp::first_argument_type& x,
|
||||||
|
const typename UnaryOp::argument_type& y)
|
||||||
|
{
|
||||||
|
return _binaryOp(x, _unaryOp(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class BinaryOp, class UnaryOp>
|
||||||
|
inline adopt2nd_t<BinaryOp, UnaryOp>
|
||||||
|
adopt2nd(const BinaryOp& binaryOp, const UnaryOp& unaryOp)
|
||||||
|
{
|
||||||
|
return adopt2nd_t<BinaryOp, UnaryOp>(binaryOp, unaryOp);
|
||||||
|
};
|
|
@ -119,20 +119,24 @@ void DefaultPieceStorageTest::testCompletePiece() {
|
||||||
DefaultPieceStorage pss(btContext, option);
|
DefaultPieceStorage pss(btContext, option);
|
||||||
pss.setEndGamePieceNum(0);
|
pss.setEndGamePieceNum(0);
|
||||||
|
|
||||||
peer->setAllBitfield();
|
peer->setAllBitfield();
|
||||||
|
|
||||||
PieceHandle piece = pss.getMissingPiece(peer);
|
PieceHandle piece = pss.getMissingPiece(peer);
|
||||||
CPPUNIT_ASSERT_EQUAL(string("piece: index=0, length=128"),
|
CPPUNIT_ASSERT_EQUAL(string("piece: index=0, length=128"),
|
||||||
piece->toString());
|
piece->toString());
|
||||||
|
|
||||||
CPPUNIT_ASSERT_EQUAL((long long int)0,
|
CPPUNIT_ASSERT_EQUAL((int64_t)0,
|
||||||
pss.getCompletedLength());
|
pss.getCompletedLength());
|
||||||
|
|
||||||
pss.completePiece(piece);
|
pss.completePiece(piece);
|
||||||
|
|
||||||
CPPUNIT_ASSERT_EQUAL((long long int)128,
|
CPPUNIT_ASSERT_EQUAL((int64_t)128,
|
||||||
pss.getCompletedLength());
|
pss.getCompletedLength());
|
||||||
|
|
||||||
|
PieceHandle incompletePiece = pss.getMissingPiece(peer);
|
||||||
|
incompletePiece->completeBlock(0);
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int64_t)256,
|
||||||
|
pss.getCompletedLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefaultPieceStorageTest::testGetPiece() {
|
void DefaultPieceStorageTest::testGetPiece() {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
TESTS = aria2c
|
TESTS = aria2c
|
||||||
check_PROGRAMS = $(TESTS)
|
check_PROGRAMS = $(TESTS)
|
||||||
aria2c_SOURCES = AllTest.cc\
|
aria2c_SOURCES = AllTest.cc\
|
||||||
|
a2functionalTest.cc\
|
||||||
FileEntryTest.cc\
|
FileEntryTest.cc\
|
||||||
PieceTest.cc\
|
PieceTest.cc\
|
||||||
DefaultPieceStorageTest.cc\
|
DefaultPieceStorageTest.cc\
|
||||||
|
|
|
@ -112,8 +112,9 @@ 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 FileEntryTest.cc PieceTest.cc \
|
am__aria2c_SOURCES_DIST = AllTest.cc a2functionalTest.cc \
|
||||||
DefaultPieceStorageTest.cc SegmentTest.cc GrowSegmentTest.cc \
|
FileEntryTest.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 \
|
||||||
|
@ -203,9 +204,10 @@ am__aria2c_SOURCES_DIST = AllTest.cc FileEntryTest.cc PieceTest.cc \
|
||||||
@ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.$(OBJEXT) \
|
@ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.$(OBJEXT) \
|
||||||
@ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandlerTest.$(OBJEXT) \
|
@ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandlerTest.$(OBJEXT) \
|
||||||
@ENABLE_METALINK_TRUE@ MetalinkHelperTest.$(OBJEXT)
|
@ENABLE_METALINK_TRUE@ MetalinkHelperTest.$(OBJEXT)
|
||||||
am_aria2c_OBJECTS = AllTest.$(OBJEXT) FileEntryTest.$(OBJEXT) \
|
am_aria2c_OBJECTS = AllTest.$(OBJEXT) a2functionalTest.$(OBJEXT) \
|
||||||
PieceTest.$(OBJEXT) DefaultPieceStorageTest.$(OBJEXT) \
|
FileEntryTest.$(OBJEXT) PieceTest.$(OBJEXT) \
|
||||||
SegmentTest.$(OBJEXT) GrowSegmentTest.$(OBJEXT) \
|
DefaultPieceStorageTest.$(OBJEXT) SegmentTest.$(OBJEXT) \
|
||||||
|
GrowSegmentTest.$(OBJEXT) \
|
||||||
SingleFileAllocationIteratorTest.$(OBJEXT) \
|
SingleFileAllocationIteratorTest.$(OBJEXT) \
|
||||||
DefaultBtProgressInfoFileTest.$(OBJEXT) \
|
DefaultBtProgressInfoFileTest.$(OBJEXT) \
|
||||||
SingleFileDownloadContextTest.$(OBJEXT) \
|
SingleFileDownloadContextTest.$(OBJEXT) \
|
||||||
|
@ -414,9 +416,9 @@ 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 FileEntryTest.cc PieceTest.cc \
|
aria2c_SOURCES = AllTest.cc a2functionalTest.cc FileEntryTest.cc \
|
||||||
DefaultPieceStorageTest.cc SegmentTest.cc GrowSegmentTest.cc \
|
PieceTest.cc DefaultPieceStorageTest.cc SegmentTest.cc \
|
||||||
SingleFileAllocationIteratorTest.cc \
|
GrowSegmentTest.cc SingleFileAllocationIteratorTest.cc \
|
||||||
DefaultBtProgressInfoFileTest.cc \
|
DefaultBtProgressInfoFileTest.cc \
|
||||||
SingleFileDownloadContextTest.cc RequestGroupTest.cc \
|
SingleFileDownloadContextTest.cc RequestGroupTest.cc \
|
||||||
PStringBuildVisitorTest.cc ParameterizedStringParserTest.cc \
|
PStringBuildVisitorTest.cc ParameterizedStringParserTest.cc \
|
||||||
|
@ -584,6 +586,7 @@ distclean-compile:
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeSeedCriteriaTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeSeedCriteriaTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UtilTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UtilTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xml2MetalinkProcessorTest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xml2MetalinkProcessorTest.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/a2functionalTest.Po@am__quote@
|
||||||
|
|
||||||
.cc.o:
|
.cc.o:
|
||||||
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
#include "a2functional.h"
|
||||||
|
#include <string>
|
||||||
|
#include <numeric>
|
||||||
|
#include <cppunit/extensions/HelperMacros.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class a2functionalTest:public CppUnit::TestFixture {
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE(a2functionalTest);
|
||||||
|
CPPUNIT_TEST(testMemFunSh);
|
||||||
|
CPPUNIT_TEST(testAdopt2nd);
|
||||||
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
public:
|
||||||
|
void testMemFunSh();
|
||||||
|
void testAdopt2nd();
|
||||||
|
|
||||||
|
class Greeting {
|
||||||
|
public:
|
||||||
|
virtual ~Greeting() {}
|
||||||
|
|
||||||
|
virtual string sayGreeting() = 0;
|
||||||
|
|
||||||
|
virtual string sayGreetingConst() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef SharedHandle<Greeting> GreetingHandle;
|
||||||
|
|
||||||
|
class JapaneseGreeting:public Greeting
|
||||||
|
{
|
||||||
|
virtual string sayGreeting()
|
||||||
|
{
|
||||||
|
return "HAROO WAARUDO";
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual string sayGreetingConst() const
|
||||||
|
{
|
||||||
|
return "HAROO WAARUDO";
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE_REGISTRATION(a2functionalTest);
|
||||||
|
|
||||||
|
void a2functionalTest::testMemFunSh()
|
||||||
|
{
|
||||||
|
GreetingHandle greeting = new JapaneseGreeting();
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(string("HAROO WAARUDO"), mem_fun_sh(&Greeting::sayGreeting)(greeting));
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(string("HAROO WAARUDO"), mem_fun_sh(&Greeting::sayGreetingConst)(greeting));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void a2functionalTest::testAdopt2nd()
|
||||||
|
{
|
||||||
|
GreetingHandle greeting = new JapaneseGreeting();
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(string("A Japanese said:HAROO WAARUDO"),
|
||||||
|
adopt2nd(plus<string>(), mem_fun_sh(&Greeting::sayGreeting))("A Japanese said:", greeting));
|
||||||
|
}
|
Loading…
Reference in New Issue