ChunkedDecodingStreamFilterTest.cc 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  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. std::basic_string<unsigned char> msg =
  52. reinterpret_cast<const unsigned char*>("a\r\n1234567890\r\n");
  53. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  54. CPPUNIT_ASSERT_EQUAL((ssize_t)10, r);
  55. CPPUNIT_ASSERT_EQUAL(std::string("1234567890"), writer_->getString());
  56. CPPUNIT_ASSERT_EQUAL((size_t)15, filter_->getBytesProcessed());
  57. } catch(DlAbortEx& e) {
  58. CPPUNIT_FAIL(e.stackTrace());
  59. }
  60. clearWriter();
  61. try {
  62. // Feed extension; see it is ignored.
  63. std::basic_string<unsigned char> msg =
  64. reinterpret_cast<const unsigned char*>
  65. ("3;extensionIgnored\r\n123\r\n");
  66. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  67. CPPUNIT_ASSERT_EQUAL((ssize_t)3, r);
  68. CPPUNIT_ASSERT_EQUAL(std::string("123"), writer_->getString());
  69. CPPUNIT_ASSERT_EQUAL((size_t)25, filter_->getBytesProcessed());
  70. } catch(DlAbortEx& e) {
  71. CPPUNIT_FAIL(e.stackTrace());
  72. }
  73. clearWriter();
  74. // Feed 2extensions; see it is ignored.
  75. try {
  76. std::basic_string<unsigned char> msg =
  77. reinterpret_cast<const unsigned char*>
  78. ("3;extension1;extension2;\r\n123\r\n");
  79. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  80. CPPUNIT_ASSERT_EQUAL((ssize_t)3, r);
  81. CPPUNIT_ASSERT_EQUAL(std::string("123"), writer_->getString());
  82. } catch(DlAbortEx& e) {
  83. CPPUNIT_FAIL(e.stackTrace());
  84. }
  85. clearWriter();
  86. // Not all chunk size is available
  87. try {
  88. std::basic_string<unsigned char> msg =
  89. reinterpret_cast<const unsigned char*>("1");
  90. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  91. CPPUNIT_ASSERT_EQUAL((ssize_t)0, r);
  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"),
  102. writer_->getString());
  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. } catch(DlAbortEx& e) {
  115. CPPUNIT_FAIL(e.stackTrace());
  116. }
  117. clearWriter();
  118. try {
  119. std::basic_string<unsigned char> msg =
  120. reinterpret_cast<const unsigned char*>("123456\r\n");
  121. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  122. CPPUNIT_ASSERT_EQUAL((ssize_t)6, r);
  123. CPPUNIT_ASSERT_EQUAL(std::string("123456"), writer_->getString());
  124. } catch(DlAbortEx& e) {
  125. CPPUNIT_FAIL(e.stackTrace());
  126. }
  127. clearWriter();
  128. // no trailing CR LF.
  129. try {
  130. std::basic_string<unsigned char> msg =
  131. reinterpret_cast<const unsigned char*>("10\r\n1234567890123456");
  132. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  133. CPPUNIT_ASSERT_EQUAL((ssize_t)16, r);
  134. CPPUNIT_ASSERT_EQUAL(std::string("1234567890123456"),
  135. writer_->getString());
  136. } catch(DlAbortEx& e) {
  137. CPPUNIT_FAIL(e.stackTrace());
  138. }
  139. clearWriter();
  140. // feed only CR
  141. try {
  142. std::basic_string<unsigned char> msg =
  143. reinterpret_cast<const unsigned char*>("\r");
  144. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  145. CPPUNIT_ASSERT_EQUAL((ssize_t)0, r);
  146. } catch(DlAbortEx& e) {
  147. CPPUNIT_FAIL(e.stackTrace());
  148. }
  149. // feed next LF
  150. try {
  151. std::basic_string<unsigned char> msg =
  152. reinterpret_cast<const unsigned char*>("\n");
  153. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  154. CPPUNIT_ASSERT_EQUAL((ssize_t)0, r);
  155. CPPUNIT_ASSERT_EQUAL(std::string(""), writer_->getString());
  156. } catch(DlAbortEx& e) {
  157. CPPUNIT_FAIL(e.stackTrace());
  158. }
  159. // feed 0 CR LF.
  160. try {
  161. std::basic_string<unsigned char> msg =
  162. reinterpret_cast<const unsigned char*>("0\r\n");
  163. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  164. CPPUNIT_ASSERT_EQUAL((ssize_t)0, r);
  165. } catch(DlAbortEx& e) {
  166. CPPUNIT_FAIL(e.stackTrace());
  167. }
  168. // feed trailer
  169. try {
  170. std::basic_string<unsigned char> msg =
  171. reinterpret_cast<const unsigned char*>("trailer\r\n");
  172. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  173. CPPUNIT_ASSERT_EQUAL((ssize_t)0, r);
  174. } catch(DlAbortEx& e) {
  175. CPPUNIT_FAIL(e.stackTrace());
  176. }
  177. // feed final CRLF
  178. try {
  179. std::basic_string<unsigned char> msg =
  180. reinterpret_cast<const unsigned char*>("\r\n");
  181. ssize_t r = filter_->transform(writer_, segment_, msg.data(), msg.size());
  182. CPPUNIT_ASSERT_EQUAL((ssize_t)0, r);
  183. } catch(DlAbortEx& e) {
  184. CPPUNIT_FAIL(e.stackTrace());
  185. }
  186. // input is over
  187. CPPUNIT_ASSERT(filter_->finished());
  188. }
  189. void ChunkedDecodingStreamFilterTest::testTransform_withoutTrailer()
  190. {
  191. CPPUNIT_ASSERT_EQUAL
  192. ((ssize_t)0,
  193. filter_->transform
  194. (writer_, segment_,
  195. reinterpret_cast<const unsigned char*>("0\r\n\r\n"), 5));
  196. CPPUNIT_ASSERT(filter_->finished());
  197. }
  198. void ChunkedDecodingStreamFilterTest::testTransform_with2Trailers()
  199. {
  200. CPPUNIT_ASSERT_EQUAL
  201. ((ssize_t)0,
  202. filter_->transform
  203. (writer_, segment_,
  204. reinterpret_cast<const unsigned char*>("0\r\nt1\r\nt2\r\n\r\n"), 13));
  205. CPPUNIT_ASSERT(filter_->finished());
  206. }
  207. void ChunkedDecodingStreamFilterTest::testTransform_largeChunkSize()
  208. {
  209. // chunkSize should be under 2^63-1
  210. {
  211. std::basic_string<unsigned char> msg =
  212. reinterpret_cast<const unsigned char*>("7fffffffffffffff\r\n");
  213. filter_->transform(writer_, segment_, msg.data(), msg.size());
  214. }
  215. }
  216. void ChunkedDecodingStreamFilterTest::testTransform_tooLargeChunkSize()
  217. {
  218. // chunkSize 2^64 causes error
  219. {
  220. std::basic_string<unsigned char> msg =
  221. reinterpret_cast<const unsigned char*>("ffffffffffffffff\r\n");
  222. try {
  223. filter_->transform(writer_, segment_, msg.data(), msg.size());
  224. CPPUNIT_FAIL("exception must be thrown.");
  225. } catch(DlAbortEx& e) {
  226. // success
  227. }
  228. }
  229. }
  230. void ChunkedDecodingStreamFilterTest::testTransform_chunkSizeMismatch()
  231. {
  232. std::basic_string<unsigned char> msg =
  233. reinterpret_cast<const unsigned char*>("3\r\n1234\r\n");
  234. try {
  235. filter_->transform(writer_, segment_, msg.data(), msg.size());
  236. CPPUNIT_FAIL("exception must be thrown.");
  237. } catch(DlAbortEx& e) {
  238. // success
  239. }
  240. }
  241. void ChunkedDecodingStreamFilterTest::testGetName()
  242. {
  243. CPPUNIT_ASSERT_EQUAL
  244. (std::string("ChunkedDecodingStreamFilter"), filter_->getName());
  245. }
  246. } // namespace aria2