mirror of
https://github.com/aria2/aria2.git
synced 2025-04-04 21:17:41 +03:00
2010-09-06 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Data from remote server in HTTP/FTP download are now written to the disk(or memory) through StreamFilter. Decoding chunked and gziped streams are done cascading StreamFilter. Removed inefficient 1byte read code. * src/ChunkedDecodingStreamFilter.cc * src/ChunkedDecodingStreamFilter.h * src/DownloadCommand.cc * src/DownloadCommand.h * src/GZipDecodingStreamFilter.cc * src/GZipDecodingStreamFilter.h * src/HttpConnection.cc * src/HttpDownloadCommand.cc * src/HttpResponse.cc * src/HttpResponse.h * src/HttpResponseCommand.cc * src/HttpResponseCommand.h * src/HttpSkipResponseCommand.cc * src/HttpSkipResponseCommand.h * src/Makefile.am * src/NullSinkStreamFilter.cc * src/NullSinkStreamFilter.h * src/RequestGroup.cc * src/SinkStreamFilter.cc * src/SinkStreamFilter.h * src/StreamFilter.cc * src/StreamFilter.h * test/ChunkedDecodingStreamFilterTest.cc * test/GZipDecodingStreamFilterTest.cc * test/HttpResponseTest.cc * test/Makefile.am * test/MockSegment.h
This commit is contained in:
parent
552c753dbb
commit
efbfe4c006
30 changed files with 1767 additions and 231 deletions
240
test/ChunkedDecodingStreamFilterTest.cc
Normal file
240
test/ChunkedDecodingStreamFilterTest.cc
Normal file
|
@ -0,0 +1,240 @@
|
|||
#include "ChunkedDecodingStreamFilter.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
#include "DlAbortEx.h"
|
||||
#include "Segment.h"
|
||||
#include "ByteArrayDiskWriter.h"
|
||||
#include "SinkStreamFilter.h"
|
||||
#include "MockSegment.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
class ChunkedDecodingStreamFilterTest:public CppUnit::TestFixture {
|
||||
|
||||
CPPUNIT_TEST_SUITE(ChunkedDecodingStreamFilterTest);
|
||||
CPPUNIT_TEST(testTransform);
|
||||
CPPUNIT_TEST(testTransform_withoutTrailer);
|
||||
CPPUNIT_TEST(testTransform_with2Trailers);
|
||||
CPPUNIT_TEST(testTransform_largeChunkSize);
|
||||
CPPUNIT_TEST(testTransform_tooLargeChunkSize);
|
||||
CPPUNIT_TEST(testTransform_chunkSizeMismatch);
|
||||
CPPUNIT_TEST(testGetName);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
SharedHandle<ChunkedDecodingStreamFilter> filter_;
|
||||
SharedHandle<SinkStreamFilter> sinkFilter_;
|
||||
SharedHandle<ByteArrayDiskWriter> writer_;
|
||||
SharedHandle<Segment> segment_;
|
||||
|
||||
void clearWriter()
|
||||
{
|
||||
writer_->setString("");
|
||||
}
|
||||
public:
|
||||
void setUp()
|
||||
{
|
||||
writer_.reset(new ByteArrayDiskWriter());
|
||||
sinkFilter_.reset(new SinkStreamFilter());
|
||||
filter_.reset(new ChunkedDecodingStreamFilter(sinkFilter_));
|
||||
sinkFilter_->init();
|
||||
filter_->init();
|
||||
segment_.reset(new MockSegment());
|
||||
}
|
||||
|
||||
void testTransform();
|
||||
void testTransform_withoutTrailer();
|
||||
void testTransform_with2Trailers();
|
||||
void testTransform_largeChunkSize();
|
||||
void testTransform_tooLargeChunkSize();
|
||||
void testTransform_chunkSizeMismatch();
|
||||
void testGetName();
|
||||
};
|
||||
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION( ChunkedDecodingStreamFilterTest );
|
||||
|
||||
void ChunkedDecodingStreamFilterTest::testTransform()
|
||||
{
|
||||
try {
|
||||
{
|
||||
std::basic_string<unsigned char> msg =
|
||||
reinterpret_cast<const unsigned char*>("a\r\n1234567890\r\n");
|
||||
ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
|
||||
CPPUNIT_ASSERT_EQUAL((ssize_t)10, r);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("1234567890"), writer_->getString());
|
||||
}
|
||||
clearWriter();
|
||||
// Feed extension; see it is ignored.
|
||||
{
|
||||
std::basic_string<unsigned char> msg =
|
||||
reinterpret_cast<const unsigned char*>
|
||||
("3;extensionIgnored\r\n123\r\n");
|
||||
ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
|
||||
CPPUNIT_ASSERT_EQUAL((ssize_t)3, r);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("123"), writer_->getString());
|
||||
}
|
||||
clearWriter();
|
||||
// Feed 2extensions; see it is ignored.
|
||||
{
|
||||
std::basic_string<unsigned char> msg =
|
||||
reinterpret_cast<const unsigned char*>
|
||||
("3;extension1;extension2;\r\n123\r\n");
|
||||
ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
|
||||
CPPUNIT_ASSERT_EQUAL((ssize_t)3, r);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("123"), writer_->getString());
|
||||
}
|
||||
clearWriter();
|
||||
// Not all chunk size is available
|
||||
{
|
||||
std::basic_string<unsigned char> msg =
|
||||
reinterpret_cast<const unsigned char*>("1");
|
||||
ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
|
||||
CPPUNIT_ASSERT_EQUAL((ssize_t)0, r);
|
||||
}
|
||||
clearWriter();
|
||||
{
|
||||
std::basic_string<unsigned char> msg =
|
||||
reinterpret_cast<const unsigned char*>("0\r\n1234567890123456\r\n");
|
||||
ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
|
||||
CPPUNIT_ASSERT_EQUAL((ssize_t)16, r);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("1234567890123456"),
|
||||
writer_->getString());
|
||||
}
|
||||
clearWriter();
|
||||
// Not all chunk data is available
|
||||
{
|
||||
std::basic_string<unsigned char> msg =
|
||||
reinterpret_cast<const unsigned char*>("10\r\n1234567890");
|
||||
ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
|
||||
CPPUNIT_ASSERT_EQUAL((ssize_t)10, r);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("1234567890"), writer_->getString());
|
||||
}
|
||||
clearWriter();
|
||||
{
|
||||
std::basic_string<unsigned char> msg =
|
||||
reinterpret_cast<const unsigned char*>("123456\r\n");
|
||||
ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
|
||||
CPPUNIT_ASSERT_EQUAL((ssize_t)6, r);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("123456"), writer_->getString());
|
||||
}
|
||||
clearWriter();
|
||||
// no trailing CR LF.
|
||||
{
|
||||
std::basic_string<unsigned char> msg =
|
||||
reinterpret_cast<const unsigned char*>("10\r\n1234567890123456");
|
||||
ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
|
||||
CPPUNIT_ASSERT_EQUAL((ssize_t)16, r);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("1234567890123456"),
|
||||
writer_->getString());
|
||||
}
|
||||
clearWriter();
|
||||
// feed only CR
|
||||
{
|
||||
std::basic_string<unsigned char> msg =
|
||||
reinterpret_cast<const unsigned char*>("\r");
|
||||
ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
|
||||
CPPUNIT_ASSERT_EQUAL((ssize_t)0, r);
|
||||
}
|
||||
// feed next LF
|
||||
{
|
||||
std::basic_string<unsigned char> msg =
|
||||
reinterpret_cast<const unsigned char*>("\n");
|
||||
ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
|
||||
CPPUNIT_ASSERT_EQUAL((ssize_t)0, r);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string(""), writer_->getString());
|
||||
}
|
||||
// feed 0 CR LF.
|
||||
{
|
||||
std::basic_string<unsigned char> msg =
|
||||
reinterpret_cast<const unsigned char*>("0\r\n");
|
||||
ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
|
||||
CPPUNIT_ASSERT_EQUAL((ssize_t)0, r);
|
||||
}
|
||||
// feed trailer
|
||||
{
|
||||
std::basic_string<unsigned char> msg =
|
||||
reinterpret_cast<const unsigned char*>("trailer\r\n");
|
||||
ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
|
||||
CPPUNIT_ASSERT_EQUAL((ssize_t)0, r);
|
||||
}
|
||||
// feed final CRLF
|
||||
{
|
||||
std::basic_string<unsigned char> msg =
|
||||
reinterpret_cast<const unsigned char*>("\r\n");
|
||||
ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
|
||||
CPPUNIT_ASSERT_EQUAL((ssize_t)0, r);
|
||||
}
|
||||
// input is over
|
||||
CPPUNIT_ASSERT(filter_->finished());
|
||||
} catch(DlAbortEx& e) {
|
||||
CPPUNIT_FAIL(e.stackTrace());
|
||||
}
|
||||
}
|
||||
|
||||
void ChunkedDecodingStreamFilterTest::testTransform_withoutTrailer()
|
||||
{
|
||||
CPPUNIT_ASSERT_EQUAL
|
||||
((ssize_t)0,
|
||||
filter_->transform
|
||||
(writer_, segment_,
|
||||
reinterpret_cast<const unsigned char*>("0\r\n\r\n"), 5));
|
||||
CPPUNIT_ASSERT(filter_->finished());
|
||||
}
|
||||
|
||||
void ChunkedDecodingStreamFilterTest::testTransform_with2Trailers()
|
||||
{
|
||||
CPPUNIT_ASSERT_EQUAL
|
||||
((ssize_t)0,
|
||||
filter_->transform
|
||||
(writer_, segment_,
|
||||
reinterpret_cast<const unsigned char*>("0\r\nt1\r\nt2\r\n\r\n"), 13));
|
||||
CPPUNIT_ASSERT(filter_->finished());
|
||||
}
|
||||
|
||||
void ChunkedDecodingStreamFilterTest::testTransform_largeChunkSize()
|
||||
{
|
||||
// chunkSize should be under 2^64-1
|
||||
{
|
||||
std::basic_string<unsigned char> msg =
|
||||
reinterpret_cast<const unsigned char*>("ffffffffffffffff\r\n");
|
||||
filter_->transform(writer_, segment_, msg.data(), msg.size());
|
||||
}
|
||||
}
|
||||
|
||||
void ChunkedDecodingStreamFilterTest::testTransform_tooLargeChunkSize()
|
||||
{
|
||||
// chunkSize 2^64 causes error
|
||||
{
|
||||
std::basic_string<unsigned char> msg =
|
||||
reinterpret_cast<const unsigned char*>("10000000000000000\r\n");
|
||||
try {
|
||||
filter_->transform(writer_, segment_, msg.data(), msg.size());
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(DlAbortEx& e) {
|
||||
// success
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChunkedDecodingStreamFilterTest::testTransform_chunkSizeMismatch()
|
||||
{
|
||||
std::basic_string<unsigned char> msg =
|
||||
reinterpret_cast<const unsigned char*>("3\r\n1234\r\n");
|
||||
try {
|
||||
filter_->transform(writer_, segment_, msg.data(), msg.size());
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(DlAbortEx& e) {
|
||||
// success
|
||||
}
|
||||
}
|
||||
|
||||
void ChunkedDecodingStreamFilterTest::testGetName()
|
||||
{
|
||||
CPPUNIT_ASSERT_EQUAL
|
||||
(std::string("ChunkedDecodingStreamFilter"), filter_->getName());
|
||||
}
|
||||
|
||||
} // namespace aria2
|
Loading…
Add table
Add a link
Reference in a new issue