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

This commit is contained in:
Tatsuhiro Tsujikawa 2012-03-05 12:45:05 +09:00
parent e73c3c53ff
commit 5bff877eae
3 changed files with 112 additions and 5 deletions

View File

@ -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_;
}

View File

@ -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

View File

@ -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