فهرست منبع

Fixed assertion failure if Chunked encoding along with Content-Length is used.

Tatsuhiro Tsujikawa 13 سال پیش
والد
کامیت
5bff877eae
3فایلهای تغییر یافته به همراه112 افزوده شده و 5 حذف شده
  1. 16 4
      src/SinkStreamFilter.cc
  2. 2 1
      test/Makefile.am
  3. 94 0
      test/SinkStreamFilterTest.cc

+ 16 - 4
src/SinkStreamFilter.cc

@@ -49,16 +49,28 @@ ssize_t SinkStreamFilter::transform
  const SharedHandle<Segment>& segment,
  const unsigned char* inbuf, size_t inlen)
 {
+  size_t wlen;
   if(inlen > 0) {
-    out->writeData(inbuf, inlen, segment->getPositionToWrite());
+    if(segment->getLength() > 0) {
+      // We must not write data larger than available space in
+      // segment.
+      assert(segment->getLength() >= segment->getWrittenLength());
+      size_t lenAvail = segment->getLength()-segment->getWrittenLength();
+      wlen = std::min(inlen, lenAvail);
+    } else {
+      wlen = inlen;
+    }
+    out->writeData(inbuf, wlen, segment->getPositionToWrite());
 #ifdef ENABLE_MESSAGE_DIGEST
     if(hashUpdate_) {
-      segment->updateHash(segment->getWrittenLength(), inbuf, inlen);
+      segment->updateHash(segment->getWrittenLength(), inbuf, wlen);
     }
 #endif // ENABLE_MESSAGE_DIGEST
-    segment->updateWrittenLength(inlen);
+    segment->updateWrittenLength(wlen);
+  } else {
+    wlen = 0;
   }
-  bytesProcessed_ = inlen;
+  bytesProcessed_ = wlen;
   return bytesProcessed_;
 }
 

+ 2 - 1
test/Makefile.am

@@ -81,7 +81,8 @@ aria2c_SOURCES = AllTest.cc\
 	SegListTest.cc\
 	ParamedStringTest.cc\
 	RpcHelperTest.cc\
-	AbstractCommandTest.cc
+	AbstractCommandTest.cc\
+	SinkStreamFilterTest.cc
 
 if ENABLE_XML_RPC
 aria2c_SOURCES += XmlRpcRequestParserControllerTest.cc

+ 94 - 0
test/SinkStreamFilterTest.cc

@@ -0,0 +1,94 @@
+#include "SinkStreamFilter.h"
+
+#include <cstdlib>
+#include <iostream>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "Segment.h"
+#include "ByteArrayDiskWriter.h"
+#include "SinkStreamFilter.h"
+#include "MockSegment.h"
+
+namespace aria2 {
+
+class SinkStreamFilterTest:public CppUnit::TestFixture {
+
+  CPPUNIT_TEST_SUITE(SinkStreamFilterTest);
+  CPPUNIT_TEST(testTransform_with_length);
+  CPPUNIT_TEST(testTransform_without_length);
+  CPPUNIT_TEST_SUITE_END();
+
+  class MockSegment2:public MockSegment {
+  public:
+    MockSegment2(int32_t length):length(length), writtenLength(0) {}
+
+    virtual int32_t getLength() const
+    {
+      return length;
+    }
+
+    virtual int32_t getWrittenLength() const
+    {
+      return writtenLength;
+    }
+
+    virtual void updateWrittenLength(int32_t bytes)
+    {
+      writtenLength += bytes;
+    }
+
+    int32_t length;
+    int32_t writtenLength;
+  };
+
+  SharedHandle<SinkStreamFilter> filter_;
+  SharedHandle<SinkStreamFilter> sinkFilter_;
+  SharedHandle<ByteArrayDiskWriter> writer_;
+  SharedHandle<MockSegment2> segment_;
+
+  void clearWriter()
+  {
+    writer_->setString("");
+  }
+public:
+  void setUp()
+  {
+    writer_.reset(new ByteArrayDiskWriter());
+    sinkFilter_.reset(new SinkStreamFilter());
+    filter_.reset(new SinkStreamFilter(sinkFilter_));
+    sinkFilter_->init();
+    filter_->init();
+    segment_.reset(new MockSegment2(16));
+  }
+
+  void testTransform_with_length();
+  void testTransform_without_length();
+};
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION( SinkStreamFilterTest );
+
+void SinkStreamFilterTest::testTransform_with_length()
+{
+  // If segment_->getLength() > 0, make sure that at most
+  // segment_->getLength()-segment_->getWrittenLength() bytes are
+  // written.
+  std::string msg("01234567890123456");
+  ssize_t r = filter_->transform
+    (writer_, segment_,
+     reinterpret_cast<const unsigned char*>(msg.c_str()), msg.size());
+  CPPUNIT_ASSERT_EQUAL((ssize_t)16, r);
+}
+
+void SinkStreamFilterTest::testTransform_without_length()
+{
+  // If segment_->getLength() == 0, all incoming bytes are written.
+  segment_->length = 0;
+  std::string msg("01234567890123456");
+  ssize_t r = filter_->transform
+    (writer_, segment_,
+     reinterpret_cast<const unsigned char*>(msg.c_str()), msg.size());
+  CPPUNIT_ASSERT_EQUAL((ssize_t)17, r);
+}
+
+} // namespace aria2