diff --git a/ChangeLog b/ChangeLog index 986c2d6a..91c607cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +2009-03-07 Tatsuhiro Tsujikawa + + Added --index-out option to specify each file path for torrent. + Here index shown in --show-files option is used to specify which + file path should be altered. For example, to change the file path + with index=2, use --index-out=2=aria2.tar.bz2. You can use this + option multiple times: --index-out=1=aria2.tar.bz2 + --index-out=2=aria2-opt.tar.bz2. The short hand form -O is also + available. This option can be specified in -i list. + * src/DefaultBtContext.cc + * src/DefaultBtContext.h + * src/MultiDiskAdaptor.cc + * src/MultiDiskAdaptor.h + * src/MultiFileAllocationIterator.cc + * src/OptionHandlerFactory.cc + * src/OptionHandlerImpl.h + * src/Util.cc + * src/Util.h + * src/download_helper.cc + * src/prefs.cc + * src/prefs.h + * src/usage_text.h + * test/DefaultBtContextTest.cc + * test/MultiDiskAdaptorTest.cc + * test/MultiFileAllocationIteratorTest.cc + * test/UtilTest.cc + 2009-03-05 Tatsuhiro Tsujikawa Use Util::pathJoin() diff --git a/src/DefaultBtContext.cc b/src/DefaultBtContext.cc index aede7d07..79976621 100644 --- a/src/DefaultBtContext.cc +++ b/src/DefaultBtContext.cc @@ -151,14 +151,20 @@ void DefaultBtContext::extractFileEntries(const bencode::BDE& infoDict, throw DlAbortEx("Path is empty."); } - std::vector elements(pathList.size()); - std::transform(pathList.listBegin(), pathList.listEnd(), elements.begin(), + std::vector pathelem(pathList.size()); + std::transform(pathList.listBegin(), pathList.listEnd(), pathelem.begin(), std::mem_fun_ref(&bencode::BDE::s)); - std::string path = Util::joinPath(elements.begin(), elements.end()); + std::string path = Util::joinPath(pathelem.begin(), pathelem.end()); + // Split path with '/' again because each pathList element can + // contain "/" inside. + std::deque elements; + Util::slice(elements, path, '/'); + elements.push_front(name); + path = Util::joinPath(elements.begin(), elements.end()); std::deque uris; std::transform(urlList.begin(), urlList.end(), std::back_inserter(uris), - std::bind2nd(std::plus(), "/"+name+"/"+path)); + std::bind2nd(std::plus(), "/"+path)); FileEntryHandle fileEntry(new FileEntry(path, fileLengthData.i(), offset, uris)); fileEntries.push_back(fileEntry); @@ -475,4 +481,15 @@ void DefaultBtContext::setInfoHash(const unsigned char* infoHash) memcpy(this->infoHash, infoHash, sizeof(this->infoHash)); } +void DefaultBtContext::setFilePathWithIndex +(size_t index, const std::string& path) +{ + if(0 < index && index <= fileEntries.size()) { + fileEntries[index-1]->setPath(path); + } else { + throw DlAbortEx(StringFormat("No such file with index=%u", + static_cast(index)).str()); + } +} + } // namespace aria2 diff --git a/src/DefaultBtContext.h b/src/DefaultBtContext.h index d736edb7..3a1bec86 100644 --- a/src/DefaultBtContext.h +++ b/src/DefaultBtContext.h @@ -182,6 +182,12 @@ private: void setRandomizer(const SharedHandle& randomizer); + // Sets file path for spcified index. index starts from 1. The index + // is the same used in BtContext::setFileFilter(). Please note that + // path is not the actual file path. The actual file path is + // getDir()+"/"+path. + void setFilePathWithIndex(size_t index, const std::string& path); + friend std::ostream& operator<<(std::ostream& o, const DefaultBtContext& ctx); static const std::string DEFAULT_PEER_ID_PREFIX; diff --git a/src/MultiDiskAdaptor.cc b/src/MultiDiskAdaptor.cc index b7ab9b53..c7da07ff 100644 --- a/src/MultiDiskAdaptor.cc +++ b/src/MultiDiskAdaptor.cc @@ -58,15 +58,15 @@ DiskWriterEntry::DiskWriterEntry(const SharedHandle& fileEntry): DiskWriterEntry::~DiskWriterEntry() {} -std::string DiskWriterEntry::getFilePath(const std::string& topDir) const +std::string DiskWriterEntry::getFilePath(const std::string& storeDir) const { - return topDir+"/"+fileEntry->getPath(); + return storeDir+"/"+fileEntry->getPath(); } -void DiskWriterEntry::initAndOpenFile(const std::string& topDir) +void DiskWriterEntry::initAndOpenFile(const std::string& storeDir) { if(!diskWriter.isNull()) { - diskWriter->initAndOpenFile(getFilePath(topDir), fileEntry->getLength()); + diskWriter->initAndOpenFile(getFilePath(storeDir), fileEntry->getLength()); if(_directIO) { diskWriter->enableDirectIO(); } @@ -74,10 +74,10 @@ void DiskWriterEntry::initAndOpenFile(const std::string& topDir) } } -void DiskWriterEntry::openFile(const std::string& topDir) +void DiskWriterEntry::openFile(const std::string& storeDir) { if(!diskWriter.isNull()) { - diskWriter->openFile(getFilePath(topDir), fileEntry->getLength()); + diskWriter->openFile(getFilePath(storeDir), fileEntry->getLength()); if(_directIO) { diskWriter->enableDirectIO(); } @@ -85,10 +85,10 @@ void DiskWriterEntry::openFile(const std::string& topDir) } } -void DiskWriterEntry::openExistingFile(const std::string& topDir) +void DiskWriterEntry::openExistingFile(const std::string& storeDir) { if(!diskWriter.isNull()) { - diskWriter->openExistingFile(getFilePath(topDir), fileEntry->getLength()); + diskWriter->openExistingFile(getFilePath(storeDir), fileEntry->getLength()); if(_directIO) { diskWriter->enableDirectIO(); } @@ -109,9 +109,9 @@ void DiskWriterEntry::closeFile() } } -bool DiskWriterEntry::fileExists(const std::string& topDir) +bool DiskWriterEntry::fileExists(const std::string& storeDir) { - return File(getFilePath(topDir)).exists(); + return File(getFilePath(storeDir)).exists(); } uint64_t DiskWriterEntry::size() const @@ -270,9 +270,9 @@ void MultiDiskAdaptor::resetDiskWriterEntries() diskWriterEntries.begin(); i != diskWriterEntries.end(); ++i) { if((*i)->needsFileAllocation() || dwreq.find((*i)->getFileEntry()->getPath()) != dwreq.end() || - (*i)->fileExists(getTopDirPath())) { + (*i)->fileExists(storeDir)) { logger->debug("Creating DiskWriter for filename=%s", - (*i)->getFilePath(getTopDirPath()).c_str()); + (*i)->getFilePath(storeDir).c_str()); (*i)->setDiskWriter(dwFactory.newDiskWriter()); (*i)->getDiskWriter()->setDirectIOAllowed(_directIOAllowed); if(_readOnly) { @@ -287,25 +287,25 @@ std::string MultiDiskAdaptor::getTopDirPath() const return storeDir+"/"+topDir; } -void MultiDiskAdaptor::mkdir(const std::string& topDirPath) const +void MultiDiskAdaptor::mkdir(const std::string& storeDir) const { for(std::deque >::const_iterator i = diskWriterEntries.begin(); i != diskWriterEntries.end(); ++i) { - (*i)->getFileEntry()->setupDir(topDirPath); + (*i)->getFileEntry()->setupDir(storeDir); } } void MultiDiskAdaptor::openIfNot (const SharedHandle& entry, void (DiskWriterEntry::*open)(const std::string&), - const std::string& topDirPath) + const std::string& storeDir) { if(!entry->isOpen()) { // logger->debug("DiskWriterEntry: Cache MISS. offset=%s", // Util::itos(entry->getFileEntry()->getOffset()).c_str()); size_t numOpened = _openedDiskWriterEntries.size(); - (entry.get()->*open)(topDirPath); + (entry.get()->*open)(storeDir); if(numOpened >= _maxOpenFiles) { // Cache is full. // Choose one DiskWriterEntry randomly and close it. @@ -326,32 +326,29 @@ void MultiDiskAdaptor::openIfNot void MultiDiskAdaptor::openFile() { - _cachedTopDirPath = getTopDirPath(); resetDiskWriterEntries(); - mkdir(_cachedTopDirPath); + mkdir(storeDir); // Call DiskWriterEntry::openFile to make sure that zero-length files are // created. for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end(); ++itr) { - openIfNot(*itr, &DiskWriterEntry::openFile, _cachedTopDirPath); + openIfNot(*itr, &DiskWriterEntry::openFile, storeDir); } } void MultiDiskAdaptor::initAndOpenFile() { - _cachedTopDirPath = getTopDirPath(); resetDiskWriterEntries(); - mkdir(_cachedTopDirPath); + mkdir(storeDir); // Call DiskWriterEntry::initAndOpenFile to make files truncated. for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end(); ++itr) { - openIfNot(*itr, &DiskWriterEntry::initAndOpenFile, _cachedTopDirPath); + openIfNot(*itr, &DiskWriterEntry::initAndOpenFile, storeDir); } } void MultiDiskAdaptor::openExistingFile() { - _cachedTopDirPath = getTopDirPath(); resetDiskWriterEntries(); // Not need to call openIfNot here. } @@ -416,12 +413,12 @@ findFirstDiskWriterEntry(const DiskWriterEntries& diskWriterEntries, off_t offse static void throwOnDiskWriterNotOpened(const SharedHandle& e, off_t offset, - const std::string& topDirPath) + const std::string& storeDir) { throw DlAbortEx (StringFormat("DiskWriter for offset=%s, filename=%s is not opened.", Util::itos(offset).c_str(), - e->getFilePath(topDirPath).c_str()).str()); + e->getFilePath(storeDir).c_str()).str()); } void MultiDiskAdaptor::writeData(const unsigned char* data, size_t len, @@ -434,10 +431,10 @@ void MultiDiskAdaptor::writeData(const unsigned char* data, size_t len, for(DiskWriterEntries::const_iterator i = first; i != diskWriterEntries.end(); ++i) { size_t writeLength = calculateLength(*i, fileOffset, rem); - openIfNot(*i, &DiskWriterEntry::openFile, _cachedTopDirPath); + openIfNot(*i, &DiskWriterEntry::openFile, storeDir); if(!(*i)->isOpen()) { - throwOnDiskWriterNotOpened(*i, offset+(len-rem), _cachedTopDirPath); + throwOnDiskWriterNotOpened(*i, offset+(len-rem), storeDir); } (*i)->getDiskWriter()->writeData(data+(len-rem), writeLength, fileOffset); @@ -459,10 +456,10 @@ ssize_t MultiDiskAdaptor::readData(unsigned char* data, size_t len, off_t offset for(DiskWriterEntries::const_iterator i = first; i != diskWriterEntries.end(); ++i) { size_t readLength = calculateLength(*i, fileOffset, rem); - openIfNot(*i, &DiskWriterEntry::openFile, _cachedTopDirPath); + openIfNot(*i, &DiskWriterEntry::openFile, storeDir); if(!(*i)->isOpen()) { - throwOnDiskWriterNotOpened(*i, offset+(len-rem), _cachedTopDirPath); + throwOnDiskWriterNotOpened(*i, offset+(len-rem), storeDir); } totalReadLength += @@ -478,12 +475,13 @@ ssize_t MultiDiskAdaptor::readData(unsigned char* data, size_t len, off_t offset bool MultiDiskAdaptor::fileExists() { + // TODO Use FileEntry::fileExists() here. + // Don't use _cachedTopDirPath because they are initialized after opening files. // This method could be called before opening files. - std::string topDirPath = getTopDirPath(); for(std::deque >::iterator i = fileEntries.begin(); i != fileEntries.end(); ++i) { - if(File(topDirPath+"/"+(*i)->getPath()).exists()) { + if(File(storeDir+"/"+(*i)->getPath()).exists()) { return true; } } @@ -496,7 +494,7 @@ uint64_t MultiDiskAdaptor::size() uint64_t size = 0; for(DiskWriterEntries::const_iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end(); ++itr) { - openIfNot(*itr, &DiskWriterEntry::openFile, _cachedTopDirPath); + openIfNot(*itr, &DiskWriterEntry::openFile, storeDir); size += (*itr)->size(); } return size; @@ -538,9 +536,9 @@ void MultiDiskAdaptor::cutTrailingGarbage() for(std::deque >::const_iterator i = diskWriterEntries.begin(); i != diskWriterEntries.end(); ++i) { uint64_t length = (*i)->getFileEntry()->getLength(); - if(File((*i)->getFilePath(_cachedTopDirPath)).size() > length) { + if(File((*i)->getFilePath(storeDir)).size() > length) { // We need open file before calling DiskWriter::truncate(uint64_t) - openIfNot(*i, &DiskWriterEntry::openFile, _cachedTopDirPath); + openIfNot(*i, &DiskWriterEntry::openFile, storeDir); (*i)->getDiskWriter()->truncate(length); } } @@ -557,7 +555,7 @@ size_t MultiDiskAdaptor::utime(const Time& actime, const Time& modtime) for(std::deque >::const_iterator i = fileEntries.begin(); i != fileEntries.end(); ++i) { if((*i)->isRequested()) { - File f(getTopDirPath()+"/"+(*i)->getPath()); + File f(storeDir+"/"+(*i)->getPath()); if(f.isFile() && f.utime(actime, modtime)) { ++numOK; } @@ -572,4 +570,9 @@ MultiDiskAdaptor::getDiskWriterEntries() const return diskWriterEntries; } +const std::string& MultiDiskAdaptor::getStoreDir() const +{ + return storeDir; +} + } // namespace aria2 diff --git a/src/MultiDiskAdaptor.h b/src/MultiDiskAdaptor.h index a52e8b1e..686ef694 100644 --- a/src/MultiDiskAdaptor.h +++ b/src/MultiDiskAdaptor.h @@ -55,19 +55,19 @@ public: ~DiskWriterEntry(); - std::string getFilePath(const std::string& topDir) const; + std::string getFilePath(const std::string& storeDir) const; - void initAndOpenFile(const std::string& topDir); + void initAndOpenFile(const std::string& storeDir); - void openFile(const std::string& topDir); + void openFile(const std::string& storeDir); - void openExistingFile(const std::string& topDir); + void openExistingFile(const std::string& storeDir); void closeFile(); bool isOpen() const; - bool fileExists(const std::string& topDir); + bool fileExists(const std::string& storeDir); uint64_t size() const; @@ -105,8 +105,6 @@ private: size_t pieceLength; DiskWriterEntries diskWriterEntries; - std::string _cachedTopDirPath; - std::deque > _openedDiskWriterEntries; size_t _maxOpenFiles; @@ -117,13 +115,13 @@ private: void resetDiskWriterEntries(); - void mkdir(const std::string& topDirPath) const; + void mkdir(const std::string& storeDir) const; std::string getTopDirPath() const; void openIfNot(const SharedHandle& entry, void (DiskWriterEntry::*f)(const std::string&), - const std::string& topDirPath); + const std::string& storeDir); static const size_t DEFAULT_MAX_OPEN_FILES = 100; @@ -200,6 +198,8 @@ public: const std::deque >& getDiskWriterEntries() const; + + const std::string& getStoreDir() const; }; typedef SharedHandle MultiDiskAdaptorHandle; diff --git a/src/MultiFileAllocationIterator.cc b/src/MultiFileAllocationIterator.cc index 7fcb7b3e..7ab33832 100644 --- a/src/MultiFileAllocationIterator.cc +++ b/src/MultiFileAllocationIterator.cc @@ -59,7 +59,7 @@ void MultiFileAllocationIterator::allocateChunk() FileEntryHandle fileEntry = entry->getFileEntry(); // Open file before calling DiskWriterEntry::size() _diskAdaptor->openIfNot(entry, &DiskWriterEntry::openFile, - _diskAdaptor->getTopDirPath()); + _diskAdaptor->getStoreDir()); entry->enableDirectIO(); if(entry->needsFileAllocation() && entry->size() < fileEntry->getLength()) { // Calling private function of MultiDiskAdaptor. diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc index 9387881c..6b6ef14a 100644 --- a/src/OptionHandlerFactory.cc +++ b/src/OptionHandlerFactory.cc @@ -968,6 +968,14 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() op->addTag(TAG_BITTORRENT); handlers.push_back(op); } + { + SharedHandle op(new IndexOutOptionHandler + (PREF_INDEX_OUT, + TEXT_INDEX_OUT, + 'O')); + op->addTag(TAG_BITTORRENT); + handlers.push_back(op); + } { SharedHandle op(new IntegerRangeOptionHandler (PREF_LISTEN_PORT, diff --git a/src/OptionHandlerImpl.h b/src/OptionHandlerImpl.h index d20ddbba..2475d4a9 100644 --- a/src/OptionHandlerImpl.h +++ b/src/OptionHandlerImpl.h @@ -366,6 +366,32 @@ public: } }; +class IndexOutOptionHandler : public NameMatchOptionHandler { +private: +public: + IndexOutOptionHandler(const std::string& optName, + const std::string& description, + char shortName = 0): + NameMatchOptionHandler(optName, description, NO_DEFAULT_VALUE, + OptionHandler::REQ_ARG, shortName) {} + + virtual ~IndexOutOptionHandler() {} + + virtual void parseArg(Option& option, const std::string& optarg) + { + // See optarg is in the fomrat of "INDEX=PATH" + Util::parseIndexPath(optarg); + std::string value = option.get(_optName); + value += optarg+"\n"; + option.put(_optName, value); + } + + virtual std::string createPossibleValuesString() const + { + return "INDEX=PATH"; + } +}; + class ParameterOptionHandler : public NameMatchOptionHandler { private: std::deque _validParamValues; diff --git a/src/Util.cc b/src/Util.cc index c8227779..21ce6d37 100644 --- a/src/Util.cc +++ b/src/Util.cc @@ -941,4 +941,26 @@ std::string Util::htmlEscape(const std::string& src) return dest; } +std::map::value_type +Util::parseIndexPath(const std::string& line) +{ + std::pair p = Util::split(line, "="); + size_t index = parseUInt(p.first); + if(p.second.empty()) { + throw DlAbortEx(StringFormat("Path with index=%u is empty.", + static_cast(index)).str()); + } + return std::map::value_type(index, p.second); +} + +std::map Util::createIndexPathMap(std::istream& i) +{ + std::map indexPathMap; + std::string line; + while(getline(i, line)) { + indexPathMap.insert(indexPathMap.begin(), parseIndexPath(line)); + } + return indexPathMap; +} + } // namespace aria2 diff --git a/src/Util.h b/src/Util.h index f171ac13..b1b5005d 100644 --- a/src/Util.h +++ b/src/Util.h @@ -44,6 +44,7 @@ #include #include #include +#include #include "SharedHandle.h" #include "IntSequence.h" @@ -306,6 +307,13 @@ public: return std::accumulate(elements.begin()+1, elements.end(), elements[0], Concat("/")); } + + // Parses INDEX=PATH format string. INDEX must be an unsigned + // integer. + static std::map::value_type + parseIndexPath(const std::string& line); + + static std::map createIndexPathMap(std::istream& i); }; } // namespace aria2 diff --git a/src/download_helper.cc b/src/download_helper.cc index 67988b6e..490c2215 100644 --- a/src/download_helper.cc +++ b/src/download_helper.cc @@ -37,6 +37,7 @@ #include #include #include +#include #include "RequestGroup.h" #include "Option.h" @@ -124,6 +125,13 @@ createBtRequestGroup(const std::string& torrentFilePath, btContext->setDir(requestOption.get(PREF_DIR)); btContext->setFileFilter (Util::parseIntRange(requestOption.get(PREF_SELECT_FILE))); + std::istringstream indexOutIn(requestOption.get(PREF_INDEX_OUT)); + std::map indexPathMap = + Util::createIndexPathMap(indexOutIn); + for(std::map::const_iterator i = indexPathMap.begin(); + i != indexPathMap.end(); ++i) { + btContext->setFilePathWithIndex((*i).first, (*i).second); + } rg->setDownloadContext(btContext); btContext->setOwnerRequestGroup(rg.get()); return rg; @@ -295,11 +303,13 @@ static void createRequestGroupForUriList if(uris.empty()) { continue; } + // TODO use OptionParser to validate the value in the options. // These options can be specified in input list(-i list). static const std::string REQUEST_OPTIONS[] = { PREF_DIR, PREF_OUT, - PREF_SELECT_FILE + PREF_SELECT_FILE, + PREF_INDEX_OUT }; foreachCopyIfndef(&REQUEST_OPTIONS[0], &REQUEST_OPTIONS[arrayLength(REQUEST_OPTIONS)], diff --git a/src/prefs.cc b/src/prefs.cc index 765fd801..9306c127 100644 --- a/src/prefs.cc +++ b/src/prefs.cc @@ -283,6 +283,8 @@ const std::string PREF_BT_HASH_CHECK_SEED("bt-hash-check-seed"); const std::string PREF_BT_MAX_PEERS("bt-max-peers"); // values: a string (IP address) const std::string PREF_BT_EXTERNAL_IP("bt-external-ip"); +// values: 1*digit '=' a string that your file system recognizes as a file name. +const std::string PREF_INDEX_OUT("index-out"); /** * Metalink related preferences diff --git a/src/prefs.h b/src/prefs.h index dbaa1f2c..4a95b821 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -287,6 +287,8 @@ extern const std::string PREF_BT_HASH_CHECK_SEED; extern const std::string PREF_BT_MAX_PEERS; // values: a string (IP address) extern const std::string PREF_BT_EXTERNAL_IP; +// values: 1*digit '=' a string that your file system recognizes as a file name. +extern const std::string PREF_INDEX_OUT; /** * Metalink related preferences diff --git a/src/usage_text.h b/src/usage_text.h index 92ae0bc0..ffce426c 100644 --- a/src/usage_text.h +++ b/src/usage_text.h @@ -493,3 +493,9 @@ _(" --http-auth-challenge[=true|false] Send HTTP authorization header only when " are embedded in URI, authorization header is\n"\ " always sent to the server regardless of this\n"\ " option.") +#define TEXT_INDEX_OUT \ +_(" -O, --index-out=INDEX=PATH Set file path for file with index=INDEX. You can\n"\ + " find the file index using the --show-files option.\n"\ + " PATH is a relative path to the path specified in\n"\ + " --dir option. You can use this option multiple\n"\ + " times.") diff --git a/test/DefaultBtContextTest.cc b/test/DefaultBtContextTest.cc index 0824b485..dd0ad2b5 100644 --- a/test/DefaultBtContextTest.cc +++ b/test/DefaultBtContextTest.cc @@ -108,11 +108,11 @@ void DefaultBtContextTest::testGetFileEntries() { std::deque >::iterator itr = fileEntries.begin(); SharedHandle fileEntry1 = *itr; - CPPUNIT_ASSERT_EQUAL(std::string("aria2/src/aria2c"), + CPPUNIT_ASSERT_EQUAL(std::string("aria2-test/aria2/src/aria2c"), fileEntry1->getPath()); itr++; SharedHandle fileEntry2 = *itr; - CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.2.2.tar.bz2"), + CPPUNIT_ASSERT_EQUAL(std::string("aria2-test/aria2-0.2.2.tar.bz2"), fileEntry2->getPath()); } @@ -289,7 +289,7 @@ void DefaultBtContextTest::testGetFileEntries_multiFileUrlList() { std::deque >::iterator itr = fileEntries.begin(); SharedHandle fileEntry1 = *itr; - CPPUNIT_ASSERT_EQUAL(std::string("aria2/src/aria2c"), + CPPUNIT_ASSERT_EQUAL(std::string("aria2-test/aria2/src/aria2c"), fileEntry1->getPath()); std::deque uris1 = fileEntry1->getAssociatedUris(); CPPUNIT_ASSERT_EQUAL((size_t)2, uris1.size()); @@ -300,7 +300,7 @@ void DefaultBtContextTest::testGetFileEntries_multiFileUrlList() { itr++; SharedHandle fileEntry2 = *itr; - CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.2.2.tar.bz2"), + CPPUNIT_ASSERT_EQUAL(std::string("aria2-test/aria2-0.2.2.tar.bz2"), fileEntry2->getPath()); std::deque uris2 = fileEntry2->getAssociatedUris(); CPPUNIT_ASSERT_EQUAL((size_t)2, uris2.size()); diff --git a/test/MultiDiskAdaptorTest.cc b/test/MultiDiskAdaptorTest.cc index 7e6fc395..bc7498a2 100644 --- a/test/MultiDiskAdaptorTest.cc +++ b/test/MultiDiskAdaptorTest.cc @@ -434,9 +434,7 @@ void MultiDiskAdaptorTest::testSize() void MultiDiskAdaptorTest::testUtime() { - std::string storeDir = "/tmp"; - std::string topDir = "aria2_MultiDiskAdaptorTest_testUtime"; - std::string prefix = storeDir+"/"+topDir; + std::string storeDir = "/tmp/aria2_MultiDiskAdaptorTest_testUtime"; SharedHandle entries[] = { SharedHandle(new FileEntry("requested", 0, 0)), SharedHandle(new FileEntry("notFound", 0, 0)), @@ -444,10 +442,10 @@ void MultiDiskAdaptorTest::testUtime() SharedHandle(new FileEntry("anotherRequested", 0, 0)), }; - createFile(prefix+"/"+entries[0]->getPath(), entries[0]->getLength()); - File(prefix+"/"+entries[1]->getPath()).remove(); - createFile(prefix+"/"+entries[2]->getPath(), entries[2]->getLength()); - createFile(prefix+"/"+entries[3]->getPath(), entries[3]->getLength()); + createFile(storeDir+"/"+entries[0]->getPath(), entries[0]->getLength()); + File(storeDir+"/"+entries[1]->getPath()).remove(); + createFile(storeDir+"/"+entries[2]->getPath(), entries[2]->getLength()); + createFile(storeDir+"/"+entries[3]->getPath(), entries[3]->getLength()); entries[2]->setRequested(false); @@ -455,7 +453,6 @@ void MultiDiskAdaptorTest::testUtime() (&entries[0], &entries[arrayLength(entries)]); MultiDiskAdaptor adaptor; adaptor.setStoreDir(storeDir); - adaptor.setTopDir(topDir); adaptor.setFileEntries(fileEntries); time_t atime = (time_t) 100000; @@ -464,14 +461,14 @@ void MultiDiskAdaptorTest::testUtime() CPPUNIT_ASSERT_EQUAL((size_t)2, adaptor.utime(Time(atime), Time(mtime))); CPPUNIT_ASSERT_EQUAL((time_t)mtime, - File(prefix+"/"+entries[0]->getPath()) + File(storeDir+"/"+entries[0]->getPath()) .getModifiedTime().getTime()); CPPUNIT_ASSERT_EQUAL((time_t)mtime, - File(prefix+"/"+entries[3]->getPath()) + File(storeDir+"/"+entries[3]->getPath()) .getModifiedTime().getTime()); - CPPUNIT_ASSERT((time_t)mtime != File(prefix+"/"+entries[2]->getPath()) + CPPUNIT_ASSERT((time_t)mtime != File(storeDir+"/"+entries[2]->getPath()) .getModifiedTime().getTime()); } diff --git a/test/MultiFileAllocationIteratorTest.cc b/test/MultiFileAllocationIteratorTest.cc index 1ca3dfb0..90c7e74c 100644 --- a/test/MultiFileAllocationIteratorTest.cc +++ b/test/MultiFileAllocationIteratorTest.cc @@ -1,4 +1,10 @@ #include "MultiFileAllocationIterator.h" + +#include +#include + +#include + #include "File.h" #include "MultiDiskAdaptor.h" #include "FileEntry.h" @@ -6,9 +12,6 @@ #include "array_fun.h" #include "TestUtil.h" #include "DiskWriter.h" -#include -#include -#include namespace aria2 { @@ -53,20 +56,17 @@ void MultiFileAllocationIteratorTest::testMakeDiskWriterEntries() fs[8]->setRequested(false); // file9 fs[9]->setRequested(false); // fileA - std::string topDir = "top"; std::string storeDir = "/tmp/aria2_MultiFileAllocationIteratorTest" "_testMakeDiskWriterEntries"; - std::string prefix = storeDir+"/"+topDir; // create empty file4 - createFile(prefix+std::string("/file4"), 0); + createFile(storeDir+std::string("/file4"), 0); SharedHandle diskAdaptor(new MultiDiskAdaptor()); diskAdaptor->setFileEntries (std::deque >(&fs[0], &fs[arrayLength(fs)])); diskAdaptor->setPieceLength(1024); diskAdaptor->setStoreDir(storeDir); - diskAdaptor->setTopDir(topDir); diskAdaptor->openFile(); SharedHandle itr @@ -78,67 +78,67 @@ void MultiFileAllocationIteratorTest::testMakeDiskWriterEntries() CPPUNIT_ASSERT_EQUAL((size_t)11, entries.size()); // file1 - CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file1"), - entries[0]->getFilePath(prefix)); + CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/file1"), + entries[0]->getFilePath(storeDir)); CPPUNIT_ASSERT(entries[0]->needsFileAllocation()); CPPUNIT_ASSERT(!entries[0]->getDiskWriter().isNull()); // file2 - CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file2"), - entries[1]->getFilePath(prefix)); + CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/file2"), + entries[1]->getFilePath(storeDir)); CPPUNIT_ASSERT(entries[1]->needsFileAllocation()); CPPUNIT_ASSERT(!entries[1]->getDiskWriter().isNull()); // file3 - CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file3"), - entries[2]->getFilePath(prefix)); + CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/file3"), + entries[2]->getFilePath(storeDir)); CPPUNIT_ASSERT(entries[2]->needsFileAllocation()); CPPUNIT_ASSERT(!entries[2]->getDiskWriter().isNull()); // file4, diskWriter is not null, because file exists. - CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file4"), - entries[3]->getFilePath(prefix)); + CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/file4"), + entries[3]->getFilePath(storeDir)); CPPUNIT_ASSERT(!entries[3]->needsFileAllocation()); CPPUNIT_ASSERT(!entries[3]->getDiskWriter().isNull()); // file5 - CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file5"), - entries[4]->getFilePath(prefix)); + CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/file5"), + entries[4]->getFilePath(storeDir)); CPPUNIT_ASSERT(!entries[4]->needsFileAllocation()); CPPUNIT_ASSERT(entries[4]->getDiskWriter().isNull()); // file6 - CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file6"), - entries[5]->getFilePath(prefix)); + CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/file6"), + entries[5]->getFilePath(storeDir)); CPPUNIT_ASSERT(entries[5]->needsFileAllocation()); CPPUNIT_ASSERT(!entries[5]->getDiskWriter().isNull()); // file7 - CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file7"), - entries[6]->getFilePath(prefix)); + CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/file7"), + entries[6]->getFilePath(storeDir)); CPPUNIT_ASSERT(entries[6]->needsFileAllocation()); CPPUNIT_ASSERT(!entries[6]->getDiskWriter().isNull()); // file8 - CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file8"), - entries[7]->getFilePath(prefix)); + CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/file8"), + entries[7]->getFilePath(storeDir)); CPPUNIT_ASSERT(entries[7]->needsFileAllocation()); CPPUNIT_ASSERT(!entries[7]->getDiskWriter().isNull()); // file9 - CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file9"), - entries[8]->getFilePath(prefix)); + CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/file9"), + entries[8]->getFilePath(storeDir)); CPPUNIT_ASSERT(!entries[8]->needsFileAllocation()); CPPUNIT_ASSERT(!entries[8]->getDiskWriter().isNull()); // fileA - CPPUNIT_ASSERT_EQUAL(prefix+std::string("/fileA"), - entries[9]->getFilePath(prefix)); + CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/fileA"), + entries[9]->getFilePath(storeDir)); CPPUNIT_ASSERT(!entries[9]->needsFileAllocation()); CPPUNIT_ASSERT(entries[9]->getDiskWriter().isNull()); // fileB - CPPUNIT_ASSERT_EQUAL(prefix+std::string("/fileB"), - entries[10]->getFilePath(prefix)); + CPPUNIT_ASSERT_EQUAL(storeDir+std::string("/fileB"), + entries[10]->getFilePath(storeDir)); CPPUNIT_ASSERT(entries[10]->needsFileAllocation()); CPPUNIT_ASSERT(!entries[10]->getDiskWriter().isNull()); } void MultiFileAllocationIteratorTest::testAllocate() { - std::string dir = "/tmp"; - std::string topDir = "aria2_MultiFileAllocationIteratorTest_testAllocate"; - std::string prefix = dir+"/"+topDir; + std::string storeDir = + "/tmp/aria2_MultiFileAllocationIteratorTest_testAllocate"; + std::string fname1 = "file1"; std::string fname2 = "file2"; std::string fname3 = "file3"; @@ -154,8 +154,7 @@ void MultiFileAllocationIteratorTest::testAllocate() try { SharedHandle diskAdaptor(new MultiDiskAdaptor()); - diskAdaptor->setStoreDir(dir); - diskAdaptor->setTopDir(topDir); + diskAdaptor->setStoreDir(storeDir); diskAdaptor->setPieceLength(1); int64_t offset = 0; @@ -199,12 +198,12 @@ void MultiFileAllocationIteratorTest::testAllocate() diskAdaptor->setFileEntries(fs); - File(prefix+"/"+fname1).remove(); - File(prefix+"/"+fname2).remove(); - File(prefix+"/"+fname3).remove(); - File(prefix+"/"+fname4).remove(); - File(prefix+"/"+fname5).remove(); - File(prefix+"/"+fname6).remove(); + File(storeDir+"/"+fname1).remove(); + File(storeDir+"/"+fname2).remove(); + File(storeDir+"/"+fname3).remove(); + File(storeDir+"/"+fname4).remove(); + File(storeDir+"/"+fname5).remove(); + File(storeDir+"/"+fname6).remove(); // we have to open file first. diskAdaptor->initAndOpenFile(); @@ -214,13 +213,13 @@ void MultiFileAllocationIteratorTest::testAllocate() while(!itr->finished()) { itr->allocateChunk(); } - CPPUNIT_ASSERT_EQUAL((uint64_t)length1, File(prefix+"/"+fname1).size()); - CPPUNIT_ASSERT_EQUAL((uint64_t)length2, File(prefix+"/"+fname2).size()); - CPPUNIT_ASSERT_EQUAL((uint64_t)length3, File(prefix+"/"+fname3).size()); - CPPUNIT_ASSERT(!File(prefix+"/"+fname4).isFile()); + CPPUNIT_ASSERT_EQUAL((uint64_t)length1, File(storeDir+"/"+fname1).size()); + CPPUNIT_ASSERT_EQUAL((uint64_t)length2, File(storeDir+"/"+fname2).size()); + CPPUNIT_ASSERT_EQUAL((uint64_t)length3, File(storeDir+"/"+fname3).size()); + CPPUNIT_ASSERT(!File(storeDir+"/"+fname4).isFile()); - CPPUNIT_ASSERT_EQUAL((uint64_t)length5, File(prefix+"/"+fname5).size()); - CPPUNIT_ASSERT(!File(prefix+"/"+fname6).isFile()); + CPPUNIT_ASSERT_EQUAL((uint64_t)length5, File(storeDir+"/"+fname5).size()); + CPPUNIT_ASSERT(!File(storeDir+"/"+fname6).isFile()); } catch(Exception& e) { CPPUNIT_FAIL(e.stackTrace()); diff --git a/test/UtilTest.cc b/test/UtilTest.cc index cc3a38b7..15697eab 100644 --- a/test/UtilTest.cc +++ b/test/UtilTest.cc @@ -54,6 +54,8 @@ class UtilTest:public CppUnit::TestFixture { CPPUNIT_TEST(testUrlencode); CPPUNIT_TEST(testHtmlEscape); CPPUNIT_TEST(testJoinPath); + CPPUNIT_TEST(testParseIndexPath); + CPPUNIT_TEST(testCreateIndexPathMap); CPPUNIT_TEST_SUITE_END(); private: @@ -97,6 +99,8 @@ public: void testUrlencode(); void testHtmlEscape(); void testJoinPath(); + void testParseIndexPath(); + void testCreateIndexPathMap(); }; @@ -778,4 +782,36 @@ void UtilTest::testJoinPath() &parentdot[arrayLength(parentdot)])); } +void UtilTest::testParseIndexPath() +{ + std::map::value_type p = Util::parseIndexPath("1=foo"); + CPPUNIT_ASSERT_EQUAL((size_t)1, p.first); + CPPUNIT_ASSERT_EQUAL(std::string("foo"), p.second); + try { + Util::parseIndexPath("1X=foo"); + CPPUNIT_FAIL("exception must be thrown."); + } catch(Exception& e) { + // success + } + try { + Util::parseIndexPath("1="); + CPPUNIT_FAIL("exception must be thrown."); + } catch(Exception& e) { + // success + } +} + +void UtilTest::testCreateIndexPathMap() +{ + std::stringstream in + ("1=/tmp/myfile\n" + "100=/myhome/mypicture.png\n"); + std::map m = Util::createIndexPathMap(in); + CPPUNIT_ASSERT_EQUAL((size_t)2, m.size()); + CPPUNIT_ASSERT(m.find(1) != m.end()); + CPPUNIT_ASSERT_EQUAL(std::string("/tmp/myfile"), m[1]); + CPPUNIT_ASSERT(m.find(100) != m.end()); + CPPUNIT_ASSERT_EQUAL(std::string("/myhome/mypicture.png"), m[100]); +} + } // namespace aria2