summaryrefslogtreecommitdiff
path: root/test/ChunkedDecodingStreamFilterTest.cc
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2010-09-06 14:29:36 +0000
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2010-09-06 14:29:36 +0000
commitefbfe4c006cfb6e0bf3ee4ed57d0657c0cd85c19 (patch)
treea72723a125c34220772259f051673ff88598bded /test/ChunkedDecodingStreamFilterTest.cc
parent552c753dbba55005964ad60698d803a44dac6391 (diff)
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
Diffstat (limited to 'test/ChunkedDecodingStreamFilterTest.cc')
-rw-r--r--test/ChunkedDecodingStreamFilterTest.cc240
1 files changed, 240 insertions, 0 deletions
diff --git a/test/ChunkedDecodingStreamFilterTest.cc b/test/ChunkedDecodingStreamFilterTest.cc
new file mode 100644
index 00000000..8dea7bd1
--- /dev/null
+++ b/test/ChunkedDecodingStreamFilterTest.cc
@@ -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