| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 | #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"#include "a2functional.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();  std::unique_ptr<ChunkedDecodingStreamFilter> filter_;  std::shared_ptr<ByteArrayDiskWriter> writer_;  std::shared_ptr<Segment> segment_;  void clearWriter() { writer_->setString(""); }public:  void setUp()  {    writer_ = std::make_shared<ByteArrayDiskWriter>();    auto sinkFilter = make_unique<SinkStreamFilter>();    sinkFilter->init();    filter_ = make_unique<ChunkedDecodingStreamFilter>(std::move(sinkFilter));    filter_->init();    segment_ = std::make_shared<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());    CPPUNIT_ASSERT_EQUAL((size_t)15, filter_->getBytesProcessed());  }  catch (DlAbortEx& e) {    CPPUNIT_FAIL(e.stackTrace());  }  clearWriter();  try {    // 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());    CPPUNIT_ASSERT_EQUAL((size_t)25, filter_->getBytesProcessed());  }  catch (DlAbortEx& e) {    CPPUNIT_FAIL(e.stackTrace());  }  clearWriter();  // Feed 2extensions; see it is ignored.  try {    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());  }  catch (DlAbortEx& e) {    CPPUNIT_FAIL(e.stackTrace());  }  clearWriter();  // Not all chunk size is available  try {    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);  }  catch (DlAbortEx& e) {    CPPUNIT_FAIL(e.stackTrace());  }  clearWriter();  try {    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());  }  catch (DlAbortEx& e) {    CPPUNIT_FAIL(e.stackTrace());  }  clearWriter();  // Not all chunk data is available  try {    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());  }  catch (DlAbortEx& e) {    CPPUNIT_FAIL(e.stackTrace());  }  clearWriter();  try {    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());  }  catch (DlAbortEx& e) {    CPPUNIT_FAIL(e.stackTrace());  }  clearWriter();  // no trailing CR LF.  try {    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());  }  catch (DlAbortEx& e) {    CPPUNIT_FAIL(e.stackTrace());  }  clearWriter();  // feed only CR  try {    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);  }  catch (DlAbortEx& e) {    CPPUNIT_FAIL(e.stackTrace());  }  // feed next LF  try {    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());  }  catch (DlAbortEx& e) {    CPPUNIT_FAIL(e.stackTrace());  }  // feed 0 CR LF.  try {    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);  }  catch (DlAbortEx& e) {    CPPUNIT_FAIL(e.stackTrace());  }  // feed trailer  try {    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);  }  catch (DlAbortEx& e) {    CPPUNIT_FAIL(e.stackTrace());  }  // feed final CRLF  try {    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);  }  catch (DlAbortEx& e) {    CPPUNIT_FAIL(e.stackTrace());  }  // input is over  CPPUNIT_ASSERT(filter_->finished());}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^63-1  {    std::basic_string<unsigned char> msg =        reinterpret_cast<const unsigned char*>("7fffffffffffffff\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*>("ffffffffffffffff\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
 |