Преглед на файлове

2007-07-01 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

	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.
Tatsuhiro Tsujikawa преди 18 години
родител
ревизия
055c9e0b21
променени са 10 файла, в които са добавени 285 реда и са изтрити 9 реда
  1. 9 0
      ChangeLog
  2. 6 0
      TODO
  3. 17 0
      src/RequestGroup.cc
  4. 2 0
      src/RequestGroup.h
  5. 16 0
      test/FileTest.cc
  6. 198 0
      test/HttpHeaderProcessorTest.cc
  7. 1 0
      test/Makefile.am
  8. 4 1
      test/Makefile.in
  9. 28 4
      test/UtilTest.cc
  10. 4 4
      test/Xml2MetalinkProcessorTest.cc

+ 9 - 0
ChangeLog

@@ -1,3 +1,11 @@
+2007-07-01  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	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  <tujikawa at rednoah dot com>
 
 	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.

+ 6 - 0
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"

+ 17 - 0
src/RequestGroup.cc

@@ -48,6 +48,7 @@
 #include "FatalException.h"
 #include "CheckIntegrityEntry.h"
 #include "DownloadCommand.h"
+#include <cerrno>
 
 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();

+ 2 - 0
src/RequestGroup.h

@@ -187,6 +187,8 @@ public:
 
   string getFilePath() const;
 
+  string getDir() const;
+
   int64_t getExistingFileLength() const;
 
   int64_t getTotalLength() const

+ 16 - 0
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());
+}

+ 198 - 0
test/HttpHeaderProcessorTest.cc

@@ -0,0 +1,198 @@
+#include "HttpHeaderProcessor.h"
+#include "DlRetryEx.h"
+#include "DlAbortEx.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+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<string, HttpHeaderHandle> 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<string, HttpHeaderHandle> 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<string, HttpHeaderHandle> 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<string, HttpHeaderHandle> 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());
+}

+ 1 - 0
test/Makefile.am

@@ -1,6 +1,7 @@
 TESTS = aria2c
 check_PROGRAMS = $(TESTS)
 aria2c_SOURCES = AllTest.cc\
+	HttpHeaderProcessorTest.cc\
 	UtilTest.cc\
 	CookieBoxTest.cc\
 	RequestTest.cc\

+ 4 - 1
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@

+ 28 - 4
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());
+}

+ 4 - 4
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);