Merge branch 'master' into dynamic-select-file

dynamic-select-file
Tatsuhiro Tsujikawa 2016-05-16 12:27:14 +09:00
commit 9727b5b256
21 changed files with 217 additions and 241 deletions

View File

@ -16,13 +16,17 @@ ITriskTI
Igor Khomyakov
Jarda Snajdr
Kcchouette
Kurt Kartaltepe
Mingye Wang
Nils Maier
ORiON-
ReadmeCritic
Ross Smith II
Ryan Steinmetz
Ryo ONODERA
Sarim Khan
Sergey Zolotarev
Sonny Piers
Tatsuhiro Tsujikawa
Vasilij Schneidermann
Zoltan Toth-Czifra
@ -36,6 +40,6 @@ luokar
mozillazg
multisnow
oliviercommelarbre
Sonny Piers
rotor
[1] https://gist.github.com/tatsuhiro-t/deaffeb064652104ad11

84
NEWS
View File

@ -1,37 +1,79 @@
aria2 1.22.0
aria2 1.23.0
============
Release Note
------------
This release adds new feature that manages the number of concurrent
downloads dynamically. --stream-piece-selector option gets new value
"random" which randomizes the piece selection for HTTP/FTP downloads.
This effectively randomizes the order of files on multi-file Web
Seeding. Now all contributor's names are in AUTHORS file.
Previously, aria2 shows error when it sees floating point number in a
torrent file because torrent file specification does not allow
floating point number. In this release, they are just ignored, and
aria2 continues to parse the rest of the torrent file as if there is
nothing wrong.
This release fixes several bugs reported by users, and adds several
new features. Read the following section for details.
Changes
-------
* Add description about possible fragmentation with
--file-allocation=trunc
* Simplify cache write
* Make single-entry metalink download with multi-file torrent work
The previous cache write routine was too complex. I'm sure I can
rewrite it to more elegantly. But the primary motivation of this
complex logic is for disk activity reduction on Windows 7, and I
observed it on my old IDE disk. I checked it again recently, and
there is no difference between with and without this complex logic.
For this reason, it was removed. Will revert this change if many of
users are not happy with this.
* Add all contributor's names in AUTHORS
* Allow subsecond value in ns cookie.txt file's expiry time field
* Ignore floating number in torrent file
Fixes GH-655
* Added support for a dynamic management of the number of concurrent
downloads as a function of the overall bandwidth observed
* Adjust chromium cookie time
This change adds --optimize-concurrent-downloads option.
* import-po: iterate on glob, not ls output
Patch from oliviercommelarbre
Patch from Mingye Wang
* Add --stream-piece-selector=random
* Add --stderr option to redirect all stdout log output to stderr
Fixes GH-638
* Add "hide" to --download-result option
Fixes GH-639
* Fix downloaded metaurl torrent filename
* Add a little bit of color to have a better visual of important
informations
Patch from rotor
* Update README URLs based on HTTP redirects
Patch from ReadmeCritic
* Relocate from github.com/tatsuhiro-t/aria2 to github.com/aria2/aria2
Fixes GH-602
* mingw: Defer the falloc warning until falloc is specified by option
Fixes GH-594
* Add bittorrent key to aria2.tellStopped status
Fixes GH-612
* Addsystem.listNotifications RPC method
Merges GH-620
Patch from Sonny Piers
* Report CheckIntegrity info in tellStatus
- Adds verifiedLength to tellStatus. Reports the length of data that
has been verified of the current RequestGroup being verified.
- Adds verifyPending to tellStatus. Reports if the RequestGroup has
a verification of integrity pending.
Closes GH-561
Patch from Kurt Kartaltepe

View File

@ -42,7 +42,7 @@ aria2c executable was generated using android-ndk-r10d.
The following libraries were statically linked.
* openssl 1.0.2g
* openssl 1.0.2h
* expat 2.1.0
* c-ares 1.11.0
* libssh2 1.7.0

View File

@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
#
AC_PREREQ([2.67])
AC_INIT([aria2],[1.22.0],[https://github.com/aria2/aria2/issues],[aria2],[https://aria2.github.io/])
AC_INIT([aria2],[1.23.0],[https://github.com/aria2/aria2/issues],[aria2],[https://aria2.github.io/])
AC_CANONICAL_HOST
AC_CANONICAL_TARGET

File diff suppressed because one or more lines are too long

View File

@ -30,7 +30,7 @@ echo "Renaming po files..."
mv "$WORK_DIR"/aria2/*.po "$WORK_DIR"
echo -n "en@quot en@boldquot" > "$PO_DIR"/LINGUAS
for file in `ls "$WORK_DIR"/*.po`; do
for file in "$WORK_DIR"/*.po; do
# First remove useless '\r' in messages
sed -i -e 's/\\r//' "$file"
bn=`basename "$file"`

View File

@ -21,5 +21,5 @@ Importing PO files from launchpad-export.tar.gz
The downloaded file is named as launchpad-export.tar.gz at the time of
this writing. It includes all PO files translated at launchpad. To
import those files, use ``import-po`` script in the top directory. It
will deflate the tar.gz file and rename PO files and move them to po
will inflate the tar.gz file and rename PO files and move them to po
directory and run ``make update-po``.

View File

@ -96,49 +96,10 @@ ssize_t AbstractSingleDiskAdaptor::readDataDropCache(unsigned char* data,
void AbstractSingleDiskAdaptor::writeCache(const WrDiskCacheEntry* entry)
{
// Write cached data in 4KiB aligned offset. This reduces disk
// activity especially on Windows 7 NTFS. In this code, we assume
// that maximum length of DataCell data is 16KiB to simplify the
// code.
unsigned char buf[16_k];
int64_t start = 0;
size_t buflen = 0;
size_t buffoffset = 0;
const WrDiskCacheEntry::DataCellSet& dataSet = entry->getDataSet();
for (auto& d : dataSet) {
if (start + static_cast<ssize_t>(buflen) < d->goff) {
A2_LOG_DEBUG(fmt("Cache flush goff=%" PRId64 ", len=%lu", start,
static_cast<unsigned long>(buflen)));
writeData(buf + buffoffset, buflen - buffoffset, start);
start = d->goff;
buflen = buffoffset = 0;
}
if (buflen == 0 && (d->goff & 0xfff) == 0 && (d->len & 0xfff) == 0) {
// Already aligned. Write it without copy.
A2_LOG_DEBUG(fmt("Cache flush goff=%" PRId64 ", len=%lu", start,
static_cast<unsigned long>(d->len)));
writeData(d->data + d->offset, d->len, start);
start += d->len;
}
else {
if (buflen == 0) {
buflen = buffoffset = d->goff & 0xfff;
}
size_t wlen = std::min(sizeof(buf) - buflen, d->len);
memcpy(buf + buflen, d->data + d->offset, wlen);
buflen += wlen;
if (buflen == sizeof(buf)) {
A2_LOG_DEBUG(fmt("Cache flush goff=%" PRId64 ", len=%lu", start,
static_cast<unsigned long>(buflen)));
writeData(buf + buffoffset, buflen - buffoffset, start);
memcpy(buf, d->data + d->offset + wlen, d->len - wlen);
start += sizeof(buf) - buffoffset;
buflen = d->len - wlen;
buffoffset = 0;
}
}
for (auto& d : entry->getDataSet()) {
A2_LOG_DEBUG(fmt("Cache flush goff=%" PRId64 ", len=%lu", d->goff, d->len));
writeData(d->data + d->offset, d->len, d->goff);
}
writeData(buf + buffoffset, buflen - buffoffset, start);
}
bool AbstractSingleDiskAdaptor::fileExists()

View File

@ -37,16 +37,13 @@
#include <cstring>
#include "util.h"
#include "BtConstants.h"
#include "a2functional.h"
namespace aria2 {
const unsigned char BtHandshakeMessage::BT_PSTR[] = "BitTorrent protocol";
const char BtHandshakeMessage::NAME[] = "handshake";
const unsigned char* BtHandshakeMessage::BT_PSTR =
reinterpret_cast<const unsigned char*>("BitTorrent protocol");
BtHandshakeMessage::BtHandshakeMessage() : SimpleBtMessage(ID, NAME) { init(); }
BtHandshakeMessage::BtHandshakeMessage(const unsigned char* infoHash,
@ -54,19 +51,17 @@ BtHandshakeMessage::BtHandshakeMessage(const unsigned char* infoHash,
: SimpleBtMessage(ID, NAME)
{
init();
memcpy(infoHash_, infoHash, INFO_HASH_LENGTH);
memcpy(peerId_, peerId, PEER_ID_LENGTH);
std::copy_n(infoHash, infoHash_.size(), std::begin(infoHash_));
std::copy_n(peerId, peerId_.size(), std::begin(peerId_));
}
BtHandshakeMessage::~BtHandshakeMessage() {}
void BtHandshakeMessage::init()
{
pstrlen_ = 19;
pstr_ = new unsigned char[PSTR_LENGTH];
reserved_ = new unsigned char[RESERVED_LENGTH];
infoHash_ = new unsigned char[INFO_HASH_LENGTH];
peerId_ = new unsigned char[PEER_ID_LENGTH];
memcpy(pstr_, BT_PSTR, PSTR_LENGTH);
memset(reserved_, 0, RESERVED_LENGTH);
std::copy_n(BT_PSTR, pstr_.size(), std::begin(pstr_));
std::fill(std::begin(reserved_), std::end(reserved_), 0);
// fast extension
reserved_[7] |= 0x04u;
// extended messaging
@ -76,23 +71,25 @@ void BtHandshakeMessage::init()
std::unique_ptr<BtHandshakeMessage>
BtHandshakeMessage::create(const unsigned char* data, size_t dataLength)
{
auto message = make_unique<BtHandshakeMessage>();
message->pstrlen_ = data[0];
memcpy(message->pstr_, &data[1], PSTR_LENGTH);
memcpy(message->reserved_, &data[20], RESERVED_LENGTH);
memcpy(message->infoHash_, &data[28], INFO_HASH_LENGTH);
memcpy(message->peerId_, &data[48], PEER_ID_LENGTH);
return message;
auto msg = make_unique<BtHandshakeMessage>();
msg->pstrlen_ = data[0];
std::copy_n(&data[1], msg->pstr_.size(), std::begin(msg->pstr_));
std::copy_n(&data[20], msg->reserved_.size(), std::begin(msg->reserved_));
std::copy_n(&data[28], msg->infoHash_.size(), std::begin(msg->infoHash_));
std::copy_n(&data[48], msg->peerId_.size(), std::begin(msg->peerId_));
return msg;
}
unsigned char* BtHandshakeMessage::createMessage()
{
auto msg = new unsigned char[MESSAGE_LENGTH];
msg[0] = pstrlen_;
memcpy(msg + 1, pstr_, PSTR_LENGTH);
memcpy(msg + 20, reserved_, RESERVED_LENGTH);
memcpy(msg + 28, infoHash_, INFO_HASH_LENGTH);
memcpy(msg + 48, peerId_, PEER_ID_LENGTH);
auto dst = msg;
*dst++ = pstrlen_;
dst = std::copy(std::begin(pstr_), std::end(pstr_), dst);
dst = std::copy(std::begin(reserved_), std::end(reserved_), dst);
dst = std::copy(std::begin(infoHash_), std::end(infoHash_), dst);
std::copy(std::begin(peerId_), std::end(peerId_), dst);
return msg;
}
@ -101,8 +98,8 @@ size_t BtHandshakeMessage::getMessageLength() { return MESSAGE_LENGTH; }
std::string BtHandshakeMessage::toString() const
{
return fmt("%s peerId=%s, reserved=%s", NAME,
util::percentEncode(peerId_, PEER_ID_LENGTH).c_str(),
util::toHex(reserved_, RESERVED_LENGTH).c_str());
util::percentEncode(peerId_.data(), peerId_.size()).c_str(),
util::toHex(reserved_.data(), reserved_.size()).c_str());
}
bool BtHandshakeMessage::isFastExtensionSupported() const
@ -119,12 +116,12 @@ bool BtHandshakeMessage::isDHTEnabled() const { return reserved_[7] & 0x01u; }
void BtHandshakeMessage::setInfoHash(const unsigned char* infoHash)
{
memcpy(infoHash_, infoHash, INFO_HASH_LENGTH);
std::copy_n(infoHash, infoHash_.size(), std::begin(infoHash_));
}
void BtHandshakeMessage::setPeerId(const unsigned char* peerId)
{
memcpy(peerId_, peerId, PEER_ID_LENGTH);
std::copy_n(peerId, peerId_.size(), std::begin(peerId_));
}
} // namespace aria2

View File

@ -37,21 +37,26 @@
#include "SimpleBtMessage.h"
#include <array>
#include "BtConstants.h"
namespace aria2 {
class BtHandshakeMessage : public SimpleBtMessage {
public:
static const size_t PSTR_LENGTH = 19;
static const unsigned char* BT_PSTR;
static const size_t RESERVED_LENGTH = 8;
static const size_t MESSAGE_LENGTH = 68;
constexpr static size_t PSTR_LENGTH = 19;
constexpr static size_t RESERVED_LENGTH = 8;
constexpr static size_t MESSAGE_LENGTH = 68;
const static unsigned char BT_PSTR[];
private:
uint8_t pstrlen_;
unsigned char* pstr_;
unsigned char* reserved_;
unsigned char* infoHash_;
unsigned char* peerId_;
std::array<unsigned char, PSTR_LENGTH> pstr_;
std::array<unsigned char, RESERVED_LENGTH> reserved_;
std::array<unsigned char, INFO_HASH_LENGTH> infoHash_;
std::array<unsigned char, PEER_ID_LENGTH> peerId_;
void init();
public:
@ -66,17 +71,11 @@ public:
static std::unique_ptr<BtHandshakeMessage> create(const unsigned char* data,
size_t dataLength);
virtual ~BtHandshakeMessage()
{
delete[] pstr_;
delete[] reserved_;
delete[] infoHash_;
delete[] peerId_;
}
virtual ~BtHandshakeMessage();
static const uint8_t ID = INT8_MAX;
static const char NAME[];
const static char NAME[];
virtual void doReceivedAction() CXX11_OVERRIDE{};
@ -104,15 +103,15 @@ public:
uint8_t getPstrlen() const { return pstrlen_; }
const unsigned char* getPstr() const { return pstr_; }
const unsigned char* getPstr() const { return pstr_.data(); }
const unsigned char* getReserved() const { return reserved_; }
const unsigned char* getReserved() const { return reserved_.data(); }
const unsigned char* getInfoHash() const { return infoHash_; }
const unsigned char* getInfoHash() const { return infoHash_.data(); }
void setInfoHash(const unsigned char* infoHash);
const unsigned char* getPeerId() const { return peerId_; }
const unsigned char* getPeerId() const { return peerId_.data(); }
void setPeerId(const unsigned char* peerId);
};

View File

@ -35,6 +35,7 @@
#include "DHTGetPeersReplyMessage.h"
#include <cstring>
#include <array>
#include "DHTNode.h"
#include "DHTBucket.h"
@ -81,24 +82,24 @@ std::unique_ptr<Dict> DHTGetPeersReplyMessage::getResponse()
rDict->put(TOKEN, token_);
// TODO want parameter
if (!closestKNodes_.empty()) {
unsigned char buffer[DHTBucket::K * 38];
const int clen = bittorrent::getCompactLength(family_);
const int unit = clen + 20;
size_t offset = 0;
std::array<unsigned char, DHTBucket::K * 38> buffer;
const auto clen = bittorrent::getCompactLength(family_);
const auto unit = clen + DHT_ID_LENGTH;
auto last = std::begin(buffer);
size_t k = 0;
for (auto i = std::begin(closestKNodes_), eoi = std::end(closestKNodes_);
i != eoi && k < DHTBucket::K; ++i) {
memcpy(buffer + offset, (*i)->getID(), DHT_ID_LENGTH);
unsigned char compact[COMPACT_LEN_IPV6];
int compactlen = bittorrent::packcompact(compact, (*i)->getIPAddress(),
(*i)->getPort());
for (auto i = std::begin(closestKNodes_);
i != std::end(closestKNodes_) && k < DHTBucket::K; ++i) {
std::array<unsigned char, COMPACT_LEN_IPV6> compact;
auto compactlen = bittorrent::packcompact(
compact.data(), (*i)->getIPAddress(), (*i)->getPort());
if (compactlen == clen) {
memcpy(buffer + 20 + offset, compact, compactlen);
offset += unit;
last = std::copy_n((*i)->getID(), DHT_ID_LENGTH, last);
last = std::copy_n(std::begin(compact), compactlen, last);
++k;
}
}
rDict->put(family_ == AF_INET ? NODES : NODES6, String::g(buffer, offset));
rDict->put(family_ == AF_INET ? NODES : NODES6,
String::g(std::begin(buffer), last));
}
if (!values_.empty()) {
// Limit the size of values list. The maximum size of UDP datagram
@ -123,16 +124,16 @@ std::unique_ptr<Dict> DHTGetPeersReplyMessage::getResponse()
// doesn't specify the maximum size of token, reply message
// template may get bigger than 395 bytes. So we use 25 as maximum
// number of peer info that a message can carry.
static const size_t MAX_VALUES_SIZE = 25;
constexpr size_t MAX_VALUES_SIZE = 25;
auto valuesList = List::g();
for (auto i = std::begin(values_), eoi = std::end(values_);
i != eoi && valuesList->size() < MAX_VALUES_SIZE; ++i) {
unsigned char compact[COMPACT_LEN_IPV6];
const int clen = bittorrent::getCompactLength(family_);
int compactlen = bittorrent::packcompact(compact, (*i)->getIPAddress(),
(*i)->getPort());
for (auto i = std::begin(values_);
i != std::end(values_) && valuesList->size() < MAX_VALUES_SIZE; ++i) {
std::array<unsigned char, COMPACT_LEN_IPV6> compact;
const auto clen = bittorrent::getCompactLength(family_);
auto compactlen = bittorrent::packcompact(
compact.data(), (*i)->getIPAddress(), (*i)->getPort());
if (compactlen == clen) {
valuesList->append(String::g(compact, compactlen));
valuesList->append(String::g(compact.data(), compactlen));
}
}
rDict->put(VALUES, std::move(valuesList));

View File

@ -412,98 +412,10 @@ ssize_t MultiDiskAdaptor::readData(unsigned char* data, size_t len,
void MultiDiskAdaptor::writeCache(const WrDiskCacheEntry* entry)
{
// Write cached data in 4KiB aligned offset. This reduces disk
// activity especially on Windows 7 NTFS.
unsigned char buf[16_k];
size_t buflen = 0;
size_t buffoffset = 0;
auto& dataSet = entry->getDataSet();
if (dataSet.empty()) {
return;
for (auto& d : entry->getDataSet()) {
A2_LOG_DEBUG(fmt("Cache flush goff=%" PRId64 ", len=%lu", d->goff, d->len));
writeData(d->data + d->offset, d->len, d->goff);
}
auto dent =
findFirstDiskWriterEntry(diskWriterEntries_, (*dataSet.begin())->goff),
eod = diskWriterEntries_.cend();
auto i = std::begin(dataSet), eoi = std::end(dataSet);
size_t celloff = 0;
for (; dent != eod; ++dent) {
int64_t lstart = 0, lp = 0;
auto& fent = (*dent)->getFileEntry();
if (fent->getLength() == 0) {
continue;
}
for (; i != eoi;) {
if (std::max(fent->getOffset(),
static_cast<int64_t>((*i)->goff + celloff)) <
std::min(fent->getLastOffset(),
static_cast<int64_t>((*i)->goff + (*i)->len))) {
openIfNot((*dent).get(), &DiskWriterEntry::openFile);
if (!(*dent)->isOpen()) {
throwOnDiskWriterNotOpened((*dent).get(), (*i)->goff + celloff);
}
}
else {
A2_LOG_DEBUG(fmt("%s Cache flush loff=%" PRId64 ", len=%lu",
fent->getPath().c_str(), lstart,
static_cast<unsigned long>(buflen - buffoffset)));
(*dent)->getDiskWriter()->writeData(buf + buffoffset,
buflen - buffoffset, lstart);
buflen = buffoffset = 0;
break;
}
int64_t loff = fent->gtoloff((*i)->goff + celloff);
if (static_cast<int64_t>(lstart + buflen) < loff) {
A2_LOG_DEBUG(fmt("%s Cache flush loff=%" PRId64 ", len=%lu",
fent->getPath().c_str(), lstart,
static_cast<unsigned long>(buflen - buffoffset)));
(*dent)->getDiskWriter()->writeData(buf + buffoffset,
buflen - buffoffset, lstart);
lstart = lp = loff;
buflen = buffoffset = 0;
}
// If the position of the cache data is not aligned, offset
// buffer so that next write can be aligned.
if (buflen == 0) {
buflen = buffoffset = loff & 0xfff;
}
assert((*i)->len > celloff);
for (;;) {
size_t wlen = std::min(static_cast<int64_t>((*i)->len - celloff),
fent->getLength() - lp);
wlen = std::min(wlen, sizeof(buf) - buflen);
memcpy(buf + buflen, (*i)->data + (*i)->offset + celloff, wlen);
buflen += wlen;
celloff += wlen;
lp += wlen;
if (lp == fent->getLength() || buflen == sizeof(buf)) {
A2_LOG_DEBUG(fmt("%s Cache flush loff=%" PRId64 ", len=%lu",
fent->getPath().c_str(), lstart,
static_cast<unsigned long>(buflen - buffoffset)));
(*dent)->getDiskWriter()->writeData(buf + buffoffset,
buflen - buffoffset, lstart);
lstart += buflen - buffoffset;
lp = lstart;
buflen = buffoffset = 0;
}
if (lp == fent->getLength() || celloff == (*i)->len) {
break;
}
}
if (celloff == (*i)->len) {
++i;
celloff = 0;
}
}
if (i == eoi) {
A2_LOG_DEBUG(fmt("%s Cache flush loff=%" PRId64 ", len=%lu",
fent->getPath().c_str(), lstart,
static_cast<unsigned long>(buflen - buffoffset)));
(*dent)->getDiskWriter()->writeData(buf + buffoffset, buflen - buffoffset,
lstart);
break;
}
}
assert(i == eoi);
}
bool MultiDiskAdaptor::fileExists()

View File

@ -69,9 +69,14 @@ std::unique_ptr<Cookie> parseNsCookie(const std::string& cookieStr,
return nullptr;
}
int64_t expiryTime;
if (!util::parseLLIntNoThrow(expiryTime,
std::string(vs[4].first, vs[4].second))) {
return nullptr;
{
// chrome extension uses subsecond resolution for expiry time.
double expiryTimeDouble;
if (!util::parseDoubleNoThrow(expiryTimeDouble,
std::string(vs[4].first, vs[4].second))) {
return nullptr;
}
expiryTime = static_cast<int64_t>(expiryTimeDouble);
}
if (std::numeric_limits<time_t>::max() < expiryTime) {
expiryTime = std::numeric_limits<time_t>::max();

View File

@ -59,8 +59,13 @@ Sqlite3ChromiumCookieParser::~Sqlite3ChromiumCookieParser() {}
const char* Sqlite3ChromiumCookieParser::getQuery() const
{
return "SELECT host_key, path, secure, expires_utc, name, value, "
"last_access_utc"
// chrome's time is microsecond resolution, and its epoc is Jan 1
// 00:00:00 +0000 1601, so we have to convert it to second from UNIX
// epoc. 11644473600 is the second between chrome's epoc and UNIX
// epoc. e.g., date +%s -d 'Jan 1 00:00:00 +0000 1601'
return "SELECT host_key, path, secure, expires_utc / 1000000 - 11644473600 "
"as expires_utc, name, value, "
"last_access_utc / 1000000 - 11644473600 as last_access_utc"
" FROM cookies";
}

View File

@ -596,6 +596,33 @@ bool parseLLIntNoThrow(int64_t& res, const std::string& s, int base)
}
}
bool parseDoubleNoThrow(double& res, const std::string& s)
{
if (s.empty()) {
return false;
}
errno = 0;
char* endptr;
auto d = strtod(s.c_str(), &endptr);
if (errno == ERANGE) {
return false;
}
if (endptr != s.c_str() + s.size()) {
for (auto i = std::begin(s) + (endptr - s.c_str()); i != std::end(s); ++i) {
if (!isspace(*i)) {
return false;
}
}
}
res = d;
return true;
}
SegList<int> parseIntSegments(const std::string& src)
{
SegList<int> sgl;

View File

@ -280,6 +280,10 @@ bool parseUIntNoThrow(uint32_t& res, const std::string& s, int base = 10);
bool parseLLIntNoThrow(int64_t& res, const std::string& s, int base = 10);
// Parses |s| as floating point number, and stores the result into
// |res|. This function returns true if it succeeds.
bool parseDoubleNoThrow(double& res, const std::string& s);
SegList<int> parseIntSegments(const std::string& src);
// Parses string which specifies the range of piece index for higher

View File

@ -328,10 +328,10 @@ void CookieStorageTest::testLoad()
c = cookies[3];
CPPUNIT_ASSERT_EQUAL(std::string("TAX"), c->getName());
CPPUNIT_ASSERT_EQUAL(std::string("1000"), c->getValue());
CPPUNIT_ASSERT((time_t)INT32_MAX <= c->getExpiryTime());
CPPUNIT_ASSERT_EQUAL((time_t)1463304912, c->getExpiryTime());
CPPUNIT_ASSERT(c->getPersistent());
CPPUNIT_ASSERT_EQUAL(std::string("/"), c->getPath());
CPPUNIT_ASSERT_EQUAL(std::string("overflow"), c->getDomain());
CPPUNIT_ASSERT_EQUAL(std::string("something"), c->getDomain());
CPPUNIT_ASSERT(!c->getSecure());
}

View File

@ -69,9 +69,9 @@ void NsCookieParserTest::testParse()
c = cookies[3].get();
CPPUNIT_ASSERT_EQUAL(std::string("TAX"), c->getName());
CPPUNIT_ASSERT_EQUAL(std::string("1000"), c->getValue());
CPPUNIT_ASSERT((time_t)INT32_MAX <= c->getExpiryTime());
CPPUNIT_ASSERT_EQUAL((time_t)1463304912, c->getExpiryTime());
CPPUNIT_ASSERT(c->getPersistent());
CPPUNIT_ASSERT_EQUAL(std::string("overflow"), c->getDomain());
CPPUNIT_ASSERT_EQUAL(std::string("something"), c->getDomain());
CPPUNIT_ASSERT(c->getHostOnly());
CPPUNIT_ASSERT_EQUAL(std::string("/"), c->getPath());
CPPUNIT_ASSERT(!c->getSecure());

View File

@ -66,6 +66,7 @@ class UtilTest2 : public CppUnit::TestFixture {
CPPUNIT_TEST(testInPrivateAddress);
CPPUNIT_TEST(testSecfmt);
CPPUNIT_TEST(testTlsHostnameMatch);
CPPUNIT_TEST(testParseDoubleNoThrow);
CPPUNIT_TEST_SUITE_END();
private:
@ -115,6 +116,7 @@ public:
void testInPrivateAddress();
void testSecfmt();
void testTlsHostnameMatch();
void testParseDoubleNoThrow();
};
CPPUNIT_TEST_SUITE_REGISTRATION(UtilTest2);
@ -978,4 +980,21 @@ void UtilTest2::testTlsHostnameMatch()
CPPUNIT_ASSERT(!util::tlsHostnameMatch("xn--*.a.b", "xn--c.a.b"));
}
void UtilTest2::testParseDoubleNoThrow()
{
double n;
CPPUNIT_ASSERT(util::parseDoubleNoThrow(n, " 123 "));
CPPUNIT_ASSERT_EQUAL(123., n);
CPPUNIT_ASSERT(util::parseDoubleNoThrow(n, "3.14"));
CPPUNIT_ASSERT_EQUAL(3.14, n);
CPPUNIT_ASSERT(util::parseDoubleNoThrow(n, "-3.14"));
CPPUNIT_ASSERT_EQUAL(-3.14, n);
CPPUNIT_ASSERT(!util::parseDoubleNoThrow(n, ""));
CPPUNIT_ASSERT(!util::parseDoubleNoThrow(n, "123x"));
}
} // namespace aria2

Binary file not shown.

View File

@ -5,5 +5,5 @@ expired FALSE / FALSE 1000 user me
192.168.0.1 TRUE /cgi-bin FALSE 0 passwd secret
badformat
overflow FALSE / FALSE 9223372036854775807 TAX 1000
.example.org TRUE / FALSE 2147483647 novalue
something FALSE / FALSE 1463304912.5 TAX 1000
.example.org TRUE / FALSE 2147483647.123 novalue