ChunkedDecodingStreamFilterTest.cc 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #include "ChunkedDecodingStreamFilter.h"
  2. #include <cstdlib>
  3. #include <iostream>
  4. #include <cppunit/extensions/HelperMacros.h>
  5. #include "DlAbortEx.h"
  6. #include "Segment.h"
  7. #include "ByteArrayDiskWriter.h"
  8. #include "SinkStreamFilter.h"
  9. #include "MockSegment.h"
  10. namespace aria2 {
  11. class ChunkedDecodingStreamFilterTest:public CppUnit::TestFixture {
  12. CPPUNIT_TEST_SUITE(ChunkedDecodingStreamFilterTest);
  13. CPPUNIT_TEST(testTransform);
  14. CPPUNIT_TEST(testTransform_withoutTrailer);
  15. CPPUNIT_TEST(testTransform_with2Trailers);
  16. CPPUNIT_TEST(testTransform_largeChunkSize);
  17. CPPUNIT_TEST(testTransform_tooLargeChunkSize);
  18. CPPUNIT_TEST(testTransform_chunkSizeMismatch);
  19. CPPUNIT_TEST(testGetName);
  20. CPPUNIT_TEST_SUITE_END();
  21. SharedHandle<ChunkedDecodingStreamFilter> filter_;
  22. SharedHandle<SinkStreamFilter> sinkFilter_;
  23. SharedHandle<ByteArrayDiskWriter> writer_;
  24. SharedHandle<Segment> segment_;
  25. void clearWriter()
  26. {
  27. writer_->setString("");
  28. }
  29. public:
  30. void setUp()
  31. {
  32. writer_.reset(new ByteArrayDiskWriter());
  33. sinkFilter_.reset(new SinkStreamFilter());
  34. filter_.reset(new ChunkedDecodingStreamFilter(sinkFilter_));
  35. sinkFilter_->init();
  36. filter_->init();
  37. segment_.reset(new MockSegment());
  38. }
  39. void testTransform();
  40. void testTransform_withoutTrailer();
  41. void testTransform_with2Trailers();
  42. void testTransform_largeChunkSize();
  43. void testTransform_tooLargeChunkSize();
  44. void testTransform_chunkSizeMismatch();
  45. void testGetName();
  46. };
  47. CPPUNIT_TEST_SUITE_REGISTRATION( ChunkedDecodingStreamFilterTest );
  48. void ChunkedDecodingStreamFilterTest::testTransform()
  49. {
  50. try {
  51. {
  52. std::basic_string<unsigned char> msg =
  53. reinterpret_cast<const unsigned char*>("a\r\n1234567890\r\n");
  54. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  55. CPPUNIT_ASSERT_EQUAL((ssize_t)10, r);
  56. CPPUNIT_ASSERT_EQUAL(std::string("1234567890"), writer_->getString());
  57. }
  58. clearWriter();
  59. // Feed extension; see it is ignored.
  60. {
  61. std::basic_string<unsigned char> msg =
  62. reinterpret_cast<const unsigned char*>
  63. ("3;extensionIgnored\r\n123\r\n");
  64. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  65. CPPUNIT_ASSERT_EQUAL((ssize_t)3, r);
  66. CPPUNIT_ASSERT_EQUAL(std::string("123"), writer_->getString());
  67. }
  68. clearWriter();
  69. // Feed 2extensions; see it is ignored.
  70. {
  71. std::basic_string<unsigned char> msg =
  72. reinterpret_cast<const unsigned char*>
  73. ("3;extension1;extension2;\r\n123\r\n");
  74. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  75. CPPUNIT_ASSERT_EQUAL((ssize_t)3, r);
  76. CPPUNIT_ASSERT_EQUAL(std::string("123"), writer_->getString());
  77. }
  78. clearWriter();
  79. // Not all chunk size is available
  80. {
  81. std::basic_string<unsigned char> msg =
  82. reinterpret_cast<const unsigned char*>("1");
  83. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  84. CPPUNIT_ASSERT_EQUAL((ssize_t)0, r);
  85. }
  86. clearWriter();
  87. {
  88. std::basic_string<unsigned char> msg =
  89. reinterpret_cast<const unsigned char*>("0\r\n1234567890123456\r\n");
  90. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  91. CPPUNIT_ASSERT_EQUAL((ssize_t)16, r);
  92. CPPUNIT_ASSERT_EQUAL(std::string("1234567890123456"),
  93. writer_->getString());
  94. }
  95. clearWriter();
  96. // Not all chunk data is available
  97. {
  98. std::basic_string<unsigned char> msg =
  99. reinterpret_cast<const unsigned char*>("10\r\n1234567890");
  100. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  101. CPPUNIT_ASSERT_EQUAL((ssize_t)10, r);
  102. CPPUNIT_ASSERT_EQUAL(std::string("1234567890"), writer_->getString());
  103. }
  104. clearWriter();
  105. {
  106. std::basic_string<unsigned char> msg =
  107. reinterpret_cast<const unsigned char*>("123456\r\n");
  108. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  109. CPPUNIT_ASSERT_EQUAL((ssize_t)6, r);
  110. CPPUNIT_ASSERT_EQUAL(std::string("123456"), writer_->getString());
  111. }
  112. clearWriter();
  113. // no trailing CR LF.
  114. {
  115. std::basic_string<unsigned char> msg =
  116. reinterpret_cast<const unsigned char*>("10\r\n1234567890123456");
  117. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  118. CPPUNIT_ASSERT_EQUAL((ssize_t)16, r);
  119. CPPUNIT_ASSERT_EQUAL(std::string("1234567890123456"),
  120. writer_->getString());
  121. }
  122. clearWriter();
  123. // feed only CR
  124. {
  125. std::basic_string<unsigned char> msg =
  126. reinterpret_cast<const unsigned char*>("\r");
  127. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  128. CPPUNIT_ASSERT_EQUAL((ssize_t)0, r);
  129. }
  130. // feed next LF
  131. {
  132. std::basic_string<unsigned char> msg =
  133. reinterpret_cast<const unsigned char*>("\n");
  134. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  135. CPPUNIT_ASSERT_EQUAL((ssize_t)0, r);
  136. CPPUNIT_ASSERT_EQUAL(std::string(""), writer_->getString());
  137. }
  138. // feed 0 CR LF.
  139. {
  140. std::basic_string<unsigned char> msg =
  141. reinterpret_cast<const unsigned char*>("0\r\n");
  142. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  143. CPPUNIT_ASSERT_EQUAL((ssize_t)0, r);
  144. }
  145. // feed trailer
  146. {
  147. std::basic_string<unsigned char> msg =
  148. reinterpret_cast<const unsigned char*>("trailer\r\n");
  149. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  150. CPPUNIT_ASSERT_EQUAL((ssize_t)0, r);
  151. }
  152. // feed final CRLF
  153. {
  154. std::basic_string<unsigned char> msg =
  155. reinterpret_cast<const unsigned char*>("\r\n");
  156. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  157. CPPUNIT_ASSERT_EQUAL((ssize_t)0, r);
  158. }
  159. // input is over
  160. CPPUNIT_ASSERT(filter_->finished());
  161. } catch(DlAbortEx& e) {
  162. CPPUNIT_FAIL(e.stackTrace());
  163. }
  164. }
  165. void ChunkedDecodingStreamFilterTest::testTransform_withoutTrailer()
  166. {
  167. CPPUNIT_ASSERT_EQUAL
  168. ((ssize_t)0,
  169. filter_->transform
  170. (writer_, segment_,
  171. reinterpret_cast<const unsigned char*>("0\r\n\r\n"), 5));
  172. CPPUNIT_ASSERT(filter_->finished());
  173. }
  174. void ChunkedDecodingStreamFilterTest::testTransform_with2Trailers()
  175. {
  176. CPPUNIT_ASSERT_EQUAL
  177. ((ssize_t)0,
  178. filter_->transform
  179. (writer_, segment_,
  180. reinterpret_cast<const unsigned char*>("0\r\nt1\r\nt2\r\n\r\n"), 13));
  181. CPPUNIT_ASSERT(filter_->finished());
  182. }
  183. void ChunkedDecodingStreamFilterTest::testTransform_largeChunkSize()
  184. {
  185. // chunkSize should be under 2^64-1
  186. {
  187. std::basic_string<unsigned char> msg =
  188. reinterpret_cast<const unsigned char*>("ffffffffffffffff\r\n");
  189. filter_->transform(writer_, segment_, msg.data(), msg.size());
  190. }
  191. }
  192. void ChunkedDecodingStreamFilterTest::testTransform_tooLargeChunkSize()
  193. {
  194. // chunkSize 2^64 causes error
  195. {
  196. std::basic_string<unsigned char> msg =
  197. reinterpret_cast<const unsigned char*>("10000000000000000\r\n");
  198. try {
  199. filter_->transform(writer_, segment_, msg.data(), msg.size());
  200. CPPUNIT_FAIL("exception must be thrown.");
  201. } catch(DlAbortEx& e) {
  202. // success
  203. }
  204. }
  205. }
  206. void ChunkedDecodingStreamFilterTest::testTransform_chunkSizeMismatch()
  207. {
  208. std::basic_string<unsigned char> msg =
  209. reinterpret_cast<const unsigned char*>("3\r\n1234\r\n");
  210. try {
  211. filter_->transform(writer_, segment_, msg.data(), msg.size());
  212. CPPUNIT_FAIL("exception must be thrown.");
  213. } catch(DlAbortEx& e) {
  214. // success
  215. }
  216. }
  217. void ChunkedDecodingStreamFilterTest::testGetName()
  218. {
  219. CPPUNIT_ASSERT_EQUAL
  220. (std::string("ChunkedDecodingStreamFilter"), filter_->getName());
  221. }
  222. } // namespace aria2