diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2010-09-06 14:29:36 +0000 |
|---|---|---|
| committer | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2010-09-06 14:29:36 +0000 |
| commit | efbfe4c006cfb6e0bf3ee4ed57d0657c0cd85c19 (patch) | |
| tree | a72723a125c34220772259f051673ff88598bded /test/ChunkedDecodingStreamFilterTest.cc | |
| parent | 552c753dbba55005964ad60698d803a44dac6391 (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.cc | 240 |
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 |
