diff --git a/ChangeLog b/ChangeLog index 5afa7067..c1133581 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2007-07-01 Tatsuhiro Tsujikawa + + Create directory structure specified in metalink file. + * src/RequestGroup.h, src/RequestGroup.cc + (initAndOpenFile): Create a directory to store files if it does not + exist. + (getDir): New function. + 2007-06-30 Tatsuhiro Tsujikawa Made -S option work with metalink file and provided selective download @@ -49,6 +57,7 @@ HttpRequestEntryHandle. (findEndOfHeader): Removed. (receiveResponse): Rewritten. + * src/HttpHeaderProcessor.h, src/HttpHeaderProcessor.cc: New class. Updated doc for -j option to notice that it should be used with -i option. diff --git a/TODO b/TODO index 5a306116..2ca840b4 100644 --- a/TODO +++ b/TODO @@ -26,3 +26,9 @@ * exit status: all downloads have been successful-> EXIT_SUCCESS, some of downloads have been failed -> EXIT_FAILURE + +* Create directory structure before initAndOpen: + HttpResponseCommand.cc + RequestGroup.cc + TorrentRequestInfo.cc: <- not the case +* Add ETA like: ETA:01.23'45" \ No newline at end of file diff --git a/src/RequestGroup.cc b/src/RequestGroup.cc index be1af6d7..b1f6eaf7 100644 --- a/src/RequestGroup.cc +++ b/src/RequestGroup.cc @@ -48,6 +48,7 @@ #include "FatalException.h" #include "CheckIntegrityEntry.h" #include "DownloadCommand.h" +#include SegmentManHandle RequestGroup::initSegmentMan() { @@ -123,6 +124,13 @@ void RequestGroup::shouldCancelDownloadForSafety() void RequestGroup::initAndOpenFile() { + File d(getDir()); + if(d.isDir()) { + } else if(d.exists()) { + throw new FatalException(EX_MAKE_DIR, getDir().c_str(), "not a directory"); + } else if(!d.mkdirs()) { + throw new FatalException(EX_MAKE_DIR, getDir().c_str(), strerror(errno)); + } _segmentMan->diskWriter->initAndOpenFile(_segmentMan->getFilePath()); } @@ -151,6 +159,15 @@ string RequestGroup::getFilePath() const } } +string RequestGroup::getDir() const +{ + if(_segmentMan.isNull()) { + return ""; + } else { + return _segmentMan->dir; + } +} + void RequestGroup::loadAndOpenFile() { bool segFileExists = segmentFileExists(); diff --git a/src/RequestGroup.h b/src/RequestGroup.h index edde7cf7..006fb318 100644 --- a/src/RequestGroup.h +++ b/src/RequestGroup.h @@ -187,6 +187,8 @@ public: string getFilePath() const; + string getDir() const; + int64_t getExistingFileLength() const; int64_t getTotalLength() const diff --git a/test/FileTest.cc b/test/FileTest.cc index 3dfd65bf..66e2e64f 100644 --- a/test/FileTest.cc +++ b/test/FileTest.cc @@ -16,6 +16,8 @@ class FileTest:public CppUnit::TestFixture { CPPUNIT_TEST(testRemove); CPPUNIT_TEST(testSize); CPPUNIT_TEST(testMkdir); + CPPUNIT_TEST(testGetDirname); + CPPUNIT_TEST(testGetBasename); CPPUNIT_TEST_SUITE_END(); private: @@ -29,6 +31,8 @@ public: void testRemove(); void testSize(); void testMkdir(); + void testGetDirname(); + void testGetBasename(); }; @@ -112,3 +116,15 @@ void FileTest::testMkdir() { // already exists. CPPUNIT_ASSERT(!d.mkdirs()); } + +void FileTest::testGetDirname() +{ + File f("/tmp/dist/aria2.tar.bz2"); + CPPUNIT_ASSERT_EQUAL(string("/tmp/dist"), f.getDirname()); +} + +void FileTest::testGetBasename() +{ + File f("/tmp/dist/aria2.tar.bz2"); + CPPUNIT_ASSERT_EQUAL(string("aria2.tar.bz2"), f.getBasename()); +} diff --git a/test/HttpHeaderProcessorTest.cc b/test/HttpHeaderProcessorTest.cc new file mode 100644 index 00000000..732a3fbe --- /dev/null +++ b/test/HttpHeaderProcessorTest.cc @@ -0,0 +1,198 @@ +#include "HttpHeaderProcessor.h" +#include "DlRetryEx.h" +#include "DlAbortEx.h" +#include + +class HttpHeaderProcessorTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(HttpHeaderProcessorTest); + CPPUNIT_TEST(testUpdate1); + CPPUNIT_TEST(testUpdate2); + CPPUNIT_TEST(testGetPutBackDataLength); + CPPUNIT_TEST(testGetPutBackDataLength_nullChar); + CPPUNIT_TEST(testGetHttpStatusHeader); + CPPUNIT_TEST(testGetHttpStatusHeader_empty); + CPPUNIT_TEST(testGetHttpStatusHeader_statusOnly); + CPPUNIT_TEST(testGetHttpStatusHeader_insufficientStatusLength); + CPPUNIT_TEST(testBeyondLimit); + CPPUNIT_TEST(testGetHeaderString); + CPPUNIT_TEST_SUITE_END(); + +public: + void testUpdate1(); + void testUpdate2(); + void testGetPutBackDataLength(); + void testGetPutBackDataLength_nullChar(); + void testGetHttpStatusHeader(); + void testGetHttpStatusHeader_empty(); + void testGetHttpStatusHeader_statusOnly(); + void testGetHttpStatusHeader_insufficientStatusLength(); + void testBeyondLimit(); + void testGetHeaderString(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION( HttpHeaderProcessorTest ); + +void HttpHeaderProcessorTest::testUpdate1() +{ + HttpHeaderProcessor proc; + string hd1 = "HTTP/1.1 200 OK\r\n"; + proc.update(hd1); + CPPUNIT_ASSERT(!proc.eoh()); + proc.update("\r\n"); + CPPUNIT_ASSERT(proc.eoh()); +} + +void HttpHeaderProcessorTest::testUpdate2() +{ + HttpHeaderProcessor proc; + string hd1 = "HTTP/1.1 200 OK\n"; + proc.update(hd1); + CPPUNIT_ASSERT(!proc.eoh()); + proc.update("\n"); + CPPUNIT_ASSERT(proc.eoh()); +} + +void HttpHeaderProcessorTest::testGetPutBackDataLength() +{ + HttpHeaderProcessor proc; + string hd1 = "HTTP/1.1 200 OK\r\n" + "\r\nputbackme"; + proc.update(hd1); + CPPUNIT_ASSERT(proc.eoh()); + CPPUNIT_ASSERT_EQUAL(9, proc.getPutBackDataLength()); + + proc.clear(); + + string hd2 = "HTTP/1.1 200 OK\n" + "\nputbackme"; + proc.update(hd2); + CPPUNIT_ASSERT(proc.eoh()); + CPPUNIT_ASSERT_EQUAL(9, proc.getPutBackDataLength()); +} + +void HttpHeaderProcessorTest::testGetPutBackDataLength_nullChar() +{ + HttpHeaderProcessor proc; + proc.update("HTTP/1.1 200 OK\r\n" + "foo: foo\0bar\r\n" + "\r\nputbackme", 35+7); + CPPUNIT_ASSERT(proc.eoh()); + CPPUNIT_ASSERT_EQUAL(9, proc.getPutBackDataLength()); + +} + +void HttpHeaderProcessorTest::testGetHttpStatusHeader() +{ + HttpHeaderProcessor proc; + string hd = "HTTP/1.1 200 OK\r\n" + "Date: Mon, 25 Jun 2007 16:04:59 GMT\r\n" + "Server: Apache/2.2.3 (Debian)\r\n" + "Last-Modified: Tue, 12 Jun 2007 14:28:43 GMT\r\n" + "ETag: \"594065-23e3-50825cc0\"\r\n" + "Accept-Ranges: bytes\r\n" + "Content-Length: 9187\r\n" + "Connection: close\r\n" + "Content-Type: text/html; charset=UTF-8\r\n" + "\r\n"; + + proc.update(hd); + + pair statusHeader = proc.getHttpStatusHeader(); + string status = statusHeader.first; + HttpHeaderHandle header = statusHeader.second; + CPPUNIT_ASSERT_EQUAL(string("200"), status); + CPPUNIT_ASSERT_EQUAL(string("Mon, 25 Jun 2007 16:04:59 GMT"), header->getFirst("Date")); + CPPUNIT_ASSERT_EQUAL(string("Apache/2.2.3 (Debian)"), header->getFirst("Server")); + CPPUNIT_ASSERT_EQUAL(9187LL, header->getFirstAsLLInt("Content-Length")); + CPPUNIT_ASSERT_EQUAL(string("text/html; charset=UTF-8"), header->getFirst("Content-Type")); +} + +void HttpHeaderProcessorTest::testGetHttpStatusHeader_empty() +{ + HttpHeaderProcessor proc; + + try { + pair statusHeader = proc.getHttpStatusHeader(); + CPPUNIT_FAIL("Exception must be threw."); + } catch(DlRetryEx* ex) { + cout << ex->getMsg() << endl; + delete ex; + } + +} + +void HttpHeaderProcessorTest::testGetHttpStatusHeader_statusOnly() +{ + HttpHeaderProcessor proc; + + string hd = "HTTP/1.1 200\r\n\r\n"; + proc.update(hd); + pair statusHeader = proc.getHttpStatusHeader(); + CPPUNIT_ASSERT_EQUAL(string("200"), statusHeader.first); + CPPUNIT_ASSERT(!statusHeader.second.isNull()); +} + +void HttpHeaderProcessorTest::testGetHttpStatusHeader_insufficientStatusLength() +{ + HttpHeaderProcessor proc; + + string hd = "HTTP/1.1 20\r\n\r\n"; + proc.update(hd); + try { + pair statusHeader = proc.getHttpStatusHeader(); + CPPUNIT_FAIL("Exception must be threw."); + } catch(DlRetryEx* ex) { + cout << ex->getMsg() << endl; + delete ex; + } + +} + +void HttpHeaderProcessorTest::testBeyondLimit() +{ + HttpHeaderProcessor proc; + proc.setHeaderLimit(20); + + string hd1 = "HTTP/1.1 200 OK\r\n"; + string hd2 = "Date: Mon, 25 Jun 2007 16:04:59 GMT\r\n"; + + proc.update(hd1); + + try { + proc.update(hd2); + CPPUNIT_FAIL("Exception must be threw."); + } catch(DlAbortEx* ex) { + cout << ex->getMsg() << endl; + delete ex; + } +} + +void HttpHeaderProcessorTest::testGetHeaderString() +{ + HttpHeaderProcessor proc; + string hd = "HTTP/1.1 200 OK\r\n" + "Date: Mon, 25 Jun 2007 16:04:59 GMT\r\n" + "Server: Apache/2.2.3 (Debian)\r\n" + "Last-Modified: Tue, 12 Jun 2007 14:28:43 GMT\r\n" + "ETag: \"594065-23e3-50825cc0\"\r\n" + "Accept-Ranges: bytes\r\n" + "Content-Length: 9187\r\n" + "Connection: close\r\n" + "Content-Type: text/html; charset=UTF-8\r\n" + "\r\nputbackme"; + + proc.update(hd); + + CPPUNIT_ASSERT_EQUAL(string("HTTP/1.1 200 OK\r\n" + "Date: Mon, 25 Jun 2007 16:04:59 GMT\r\n" + "Server: Apache/2.2.3 (Debian)\r\n" + "Last-Modified: Tue, 12 Jun 2007 14:28:43 GMT\r\n" + "ETag: \"594065-23e3-50825cc0\"\r\n" + "Accept-Ranges: bytes\r\n" + "Content-Length: 9187\r\n" + "Connection: close\r\n" + "Content-Type: text/html; charset=UTF-8"), + proc.getHeaderString()); +} diff --git a/test/Makefile.am b/test/Makefile.am index 3ce03908..acd2a8e7 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,6 +1,7 @@ TESTS = aria2c check_PROGRAMS = $(TESTS) aria2c_SOURCES = AllTest.cc\ + HttpHeaderProcessorTest.cc\ UtilTest.cc\ CookieBoxTest.cc\ RequestTest.cc\ diff --git a/test/Makefile.in b/test/Makefile.in index 8475bbd1..aca47d17 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -57,7 +57,8 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = am__EXEEXT_1 = aria2c$(EXEEXT) -am_aria2c_OBJECTS = AllTest.$(OBJEXT) UtilTest.$(OBJEXT) \ +am_aria2c_OBJECTS = AllTest.$(OBJEXT) \ + HttpHeaderProcessorTest.$(OBJEXT) UtilTest.$(OBJEXT) \ CookieBoxTest.$(OBJEXT) RequestTest.$(OBJEXT) \ CookieParserTest.$(OBJEXT) HttpRequestTest.$(OBJEXT) \ CookieBoxFactoryTest.$(OBJEXT) \ @@ -268,6 +269,7 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ TESTS = aria2c aria2c_SOURCES = AllTest.cc\ + HttpHeaderProcessorTest.cc\ UtilTest.cc\ CookieBoxTest.cc\ RequestTest.cc\ @@ -450,6 +452,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FeatureConfigTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GlowFileAllocatorTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpHeaderProcessorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpHeaderTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpRequestTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpResponseTest.Po@am__quote@ diff --git a/test/UtilTest.cc b/test/UtilTest.cc index 48fd0031..5312def9 100644 --- a/test/UtilTest.cc +++ b/test/UtilTest.cc @@ -24,6 +24,7 @@ class UtilTest:public CppUnit::TestFixture { CPPUNIT_TEST(testCountBit); CPPUNIT_TEST(testGetRealSize); CPPUNIT_TEST(testAbbrevSize); + CPPUNIT_TEST(testToStream); CPPUNIT_TEST_SUITE_END(); private: @@ -48,6 +49,7 @@ public: void testCountBit(); void testGetRealSize(); void testAbbrevSize(); + void testToStream(); }; @@ -304,11 +306,33 @@ void UtilTest::testGetRealSize() void UtilTest::testAbbrevSize() { - CPPUNIT_ASSERT_EQUAL(string("4,096.0M"), Util::abbrevSize(4294967296LL)); - CPPUNIT_ASSERT_EQUAL(string("1.0K"), Util::abbrevSize(1024)); + CPPUNIT_ASSERT_EQUAL(string("4,096.0Mi"), Util::abbrevSize(4294967296LL)); + CPPUNIT_ASSERT_EQUAL(string("1.0Ki"), Util::abbrevSize(1024)); CPPUNIT_ASSERT_EQUAL(string("1,023"), Util::abbrevSize(1023)); CPPUNIT_ASSERT_EQUAL(string("0"), Util::abbrevSize(0)); - CPPUNIT_ASSERT_EQUAL(string("1.1K"), Util::abbrevSize(1127)); - CPPUNIT_ASSERT_EQUAL(string("1.5M"), Util::abbrevSize(1572864)); + CPPUNIT_ASSERT_EQUAL(string("1.1Ki"), Util::abbrevSize(1127)); + CPPUNIT_ASSERT_EQUAL(string("1.5Mi"), Util::abbrevSize(1572864)); } + +void UtilTest::testToStream() +{ + ostringstream os; + FileEntryHandle f1 = new FileEntry("aria2.tar.bz2", 12300, 0); + FileEntryHandle f2 = new FileEntry("aria2.txt", 556, 0); + FileEntries entries; + entries.push_back(f1); + entries.push_back(f2); + Util::toStream(os, entries); + CPPUNIT_ASSERT_EQUAL( + string("Files:\n" + "idx|path/length\n" + "===+===========================================================================\n" + " 1|aria2.tar.bz2\n" + " |12,300 bytes\n" + "---+---------------------------------------------------------------------------\n" + " 2|aria2.txt\n" + " |556 bytes\n" + "---+---------------------------------------------------------------------------\n"), + os.str()); +} diff --git a/test/Xml2MetalinkProcessorTest.cc b/test/Xml2MetalinkProcessorTest.cc index f76bcc83..ed72176e 100644 --- a/test/Xml2MetalinkProcessorTest.cc +++ b/test/Xml2MetalinkProcessorTest.cc @@ -32,8 +32,8 @@ void Xml2MetalinkProcessorTest::testParseFile() { MetalinkEntries::iterator entryItr = metalinker->entries.begin(); MetalinkEntryHandle entry1 = *entryItr; - CPPUNIT_ASSERT_EQUAL(string("aria2-0.5.2.tar.bz2"), entry1->filename); - CPPUNIT_ASSERT_EQUAL((int64_t)0, entry1->size); + CPPUNIT_ASSERT_EQUAL(string("aria2-0.5.2.tar.bz2"), entry1->getPath()); + CPPUNIT_ASSERT_EQUAL((int64_t)0, entry1->getLength()); CPPUNIT_ASSERT_EQUAL(string("0.5.2"), entry1->version); CPPUNIT_ASSERT_EQUAL(string("en-US"), entry1->language); CPPUNIT_ASSERT_EQUAL(string("Linux-x86"), entry1->os); @@ -59,8 +59,8 @@ void Xml2MetalinkProcessorTest::testParseFile() { entryItr++; MetalinkEntryHandle entry2 = *entryItr; - CPPUNIT_ASSERT_EQUAL(string("aria2-0.5.1.tar.bz2"), entry2->filename); - CPPUNIT_ASSERT_EQUAL((int64_t)345689, entry2->size); + CPPUNIT_ASSERT_EQUAL(string("aria2-0.5.1.tar.bz2"), entry2->getPath()); + CPPUNIT_ASSERT_EQUAL((int64_t)345689, entry2->getLength()); CPPUNIT_ASSERT_EQUAL(string("0.5.1"), entry2->version); CPPUNIT_ASSERT_EQUAL(string("ja-JP"), entry2->language); CPPUNIT_ASSERT_EQUAL(string("Linux-m68k"), entry2->os);