ChunkedDecodingStreamFilterTest.cc 8.4 KB

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