ValueBaseBencodeParserTest.cc 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #include "ValueBaseBencodeParser.h"
  2. #include <cppunit/extensions/HelperMacros.h>
  3. #include "ValueBase.h"
  4. #include "BencodeParser.h"
  5. namespace aria2 {
  6. class ValueBaseBencodeParserTest : public CppUnit::TestFixture {
  7. CPPUNIT_TEST_SUITE(ValueBaseBencodeParserTest);
  8. CPPUNIT_TEST(testParseUpdate);
  9. CPPUNIT_TEST_SUITE_END();
  10. public:
  11. void testParseUpdate();
  12. };
  13. CPPUNIT_TEST_SUITE_REGISTRATION(ValueBaseBencodeParserTest);
  14. namespace {
  15. void checkDecodeError(const std::string& src)
  16. {
  17. bittorrent::ValueBaseBencodeParser parser;
  18. ssize_t error;
  19. std::shared_ptr<ValueBase> r =
  20. parser.parseFinal(src.c_str(), src.size(), error);
  21. CPPUNIT_ASSERT(!r);
  22. CPPUNIT_ASSERT(error < 0);
  23. }
  24. } // namespace
  25. void ValueBaseBencodeParserTest::testParseUpdate()
  26. {
  27. bittorrent::ValueBaseBencodeParser parser;
  28. ssize_t error;
  29. {
  30. // empty string
  31. std::string src = "0:";
  32. std::shared_ptr<ValueBase> s =
  33. parser.parseFinal(src.c_str(), src.size(), error);
  34. CPPUNIT_ASSERT_EQUAL(std::string(""), downcast<String>(s)->s());
  35. }
  36. {
  37. // integer 0
  38. std::string src = "i0e";
  39. std::shared_ptr<ValueBase> s =
  40. parser.parseFinal(src.c_str(), src.size(), error);
  41. CPPUNIT_ASSERT_EQUAL((int64_t)0, downcast<Integer>(s)->i());
  42. }
  43. {
  44. // empty dict
  45. std::string src = "de";
  46. std::shared_ptr<ValueBase> d =
  47. parser.parseFinal(src.c_str(), src.size(), error);
  48. CPPUNIT_ASSERT(downcast<Dict>(d)->empty());
  49. }
  50. {
  51. // empty list
  52. std::string src = "le";
  53. std::shared_ptr<ValueBase> l =
  54. parser.parseFinal(src.c_str(), src.size(), error);
  55. CPPUNIT_ASSERT(downcast<List>(l)->empty());
  56. }
  57. {
  58. // string
  59. std::string src = "3:foo";
  60. std::shared_ptr<ValueBase> s =
  61. parser.parseFinal(src.c_str(), src.size(), error);
  62. CPPUNIT_ASSERT_EQUAL(std::string("foo"), downcast<String>(s)->s());
  63. }
  64. {
  65. // integer
  66. std::string src = "i9223372036854775807e";
  67. std::shared_ptr<ValueBase> s =
  68. parser.parseFinal(src.c_str(), src.size(), error);
  69. CPPUNIT_ASSERT_EQUAL((int64_t)9223372036854775807LL,
  70. downcast<Integer>(s)->i());
  71. }
  72. {
  73. // float number, ignored and always 0.
  74. std::string src = "i+343243.342E-1333e";
  75. auto s = parser.parseFinal(src.c_str(), src.size(), error);
  76. CPPUNIT_ASSERT_EQUAL((int64_t)0, downcast<Integer>(s)->i());
  77. }
  78. {
  79. // dict, size 1
  80. std::string src = "d3:fooi123ee";
  81. std::shared_ptr<ValueBase> d =
  82. parser.parseFinal(src.c_str(), src.size(), error);
  83. Dict* dict = downcast<Dict>(d);
  84. CPPUNIT_ASSERT(dict);
  85. CPPUNIT_ASSERT(dict->get("foo"));
  86. CPPUNIT_ASSERT_EQUAL((int64_t)123,
  87. downcast<Integer>(dict->get("foo"))->i());
  88. }
  89. {
  90. // dict, size 2
  91. std::string src = "d3:fooi123e3:bar1:ee";
  92. std::shared_ptr<ValueBase> d =
  93. parser.parseFinal(src.c_str(), src.size(), error);
  94. Dict* dict = downcast<Dict>(d);
  95. CPPUNIT_ASSERT(dict);
  96. CPPUNIT_ASSERT_EQUAL((size_t)2, dict->size());
  97. CPPUNIT_ASSERT(dict->get("foo"));
  98. CPPUNIT_ASSERT_EQUAL((int64_t)123,
  99. downcast<Integer>(dict->get("foo"))->i());
  100. CPPUNIT_ASSERT(dict->get("bar"));
  101. CPPUNIT_ASSERT_EQUAL(std::string("e"),
  102. downcast<String>(dict->get("bar"))->s());
  103. }
  104. {
  105. // list, size 1
  106. std::string src = "l3:fooe";
  107. std::shared_ptr<ValueBase> l =
  108. parser.parseFinal(src.c_str(), src.size(), error);
  109. List* list = downcast<List>(l);
  110. CPPUNIT_ASSERT(list);
  111. CPPUNIT_ASSERT_EQUAL((size_t)1, list->size());
  112. CPPUNIT_ASSERT_EQUAL(std::string("foo"),
  113. downcast<String>(list->get(0))->s());
  114. }
  115. {
  116. // list, size 2
  117. std::string src = "l3:fooi123ee";
  118. std::shared_ptr<ValueBase> l =
  119. parser.parseFinal(src.c_str(), src.size(), error);
  120. List* list = downcast<List>(l);
  121. CPPUNIT_ASSERT(list);
  122. CPPUNIT_ASSERT_EQUAL((size_t)2, list->size());
  123. CPPUNIT_ASSERT_EQUAL(std::string("foo"),
  124. downcast<String>(list->get(0))->s());
  125. CPPUNIT_ASSERT_EQUAL((int64_t)123, downcast<Integer>(list->get(1))->i());
  126. }
  127. {
  128. // string, integer and list in dict
  129. std::string src = "d4:name5:aria24:sizei12345678900e5:filesl3:bin3:docee";
  130. std::shared_ptr<ValueBase> r =
  131. parser.parseFinal(src.c_str(), src.size(), error);
  132. const Dict* dict = downcast<Dict>(r);
  133. CPPUNIT_ASSERT(dict);
  134. CPPUNIT_ASSERT_EQUAL(std::string("aria2"),
  135. downcast<String>(dict->get("name"))->s());
  136. CPPUNIT_ASSERT_EQUAL(static_cast<Integer::ValueType>(12345678900LL),
  137. downcast<Integer>(dict->get("size"))->i());
  138. const List* list = downcast<List>(dict->get("files"));
  139. CPPUNIT_ASSERT(list);
  140. CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), list->size());
  141. CPPUNIT_ASSERT_EQUAL(std::string("bin"),
  142. downcast<String>(list->get(0))->s());
  143. CPPUNIT_ASSERT_EQUAL(std::string("doc"),
  144. downcast<String>(list->get(1))->s());
  145. }
  146. {
  147. // dict in list
  148. std::string src = "ld1:ki123eee";
  149. std::shared_ptr<ValueBase> r =
  150. parser.parseFinal(src.c_str(), src.size(), error);
  151. const List* list = downcast<List>(r);
  152. CPPUNIT_ASSERT(list);
  153. CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), list->size());
  154. const Dict* dict = downcast<Dict>(list->get(0));
  155. CPPUNIT_ASSERT(dict);
  156. CPPUNIT_ASSERT_EQUAL(static_cast<Integer::ValueType>(123),
  157. downcast<Integer>(dict->get("k"))->i());
  158. }
  159. {
  160. // empty key is allowed
  161. std::string src = "d0:1:ve";
  162. std::shared_ptr<ValueBase> s =
  163. parser.parseFinal(src.c_str(), src.size(), error);
  164. }
  165. {
  166. // empty encoded data
  167. std::string src = "";
  168. std::shared_ptr<ValueBase> s =
  169. parser.parseFinal(src.c_str(), src.size(), error);
  170. CPPUNIT_ASSERT(!s);
  171. }
  172. // integer, without ending 'e'
  173. checkDecodeError("i3");
  174. // dict, without ending 'e'
  175. checkDecodeError("d");
  176. // list, without ending 'e'
  177. checkDecodeError("l");
  178. // string, less than the specified length.
  179. checkDecodeError("3:ab");
  180. // string, but length is invalid
  181. checkDecodeError("x:abc");
  182. // string with minus length
  183. checkDecodeError("-1:a");
  184. // too deep structure
  185. checkDecodeError(std::string(51, 'l') + std::string(51, 'e'));
  186. checkDecodeError(std::string(50, 'l') + "d3:fooi100ee" +
  187. std::string(50, 'e'));
  188. // float number, but including bad characters
  189. checkDecodeError("i-1.134a+33e");
  190. checkDecodeError("ixe");
  191. // empty number
  192. checkDecodeError("ie");
  193. {
  194. // ignore trailing garbage at the end of the input.
  195. std::string src = "5:aria2trail";
  196. std::shared_ptr<ValueBase> s =
  197. parser.parseFinal(src.c_str(), src.size(), error);
  198. CPPUNIT_ASSERT_EQUAL(std::string("aria2"), downcast<String>(s)->s());
  199. // Get trailing garbage position
  200. CPPUNIT_ASSERT_EQUAL((ssize_t)7, error);
  201. }
  202. {
  203. // dict, empty member name
  204. std::string src = "d0:i123ee";
  205. std::shared_ptr<ValueBase> d =
  206. parser.parseFinal(src.c_str(), src.size(), error);
  207. Dict* dict = downcast<Dict>(d);
  208. CPPUNIT_ASSERT(dict);
  209. CPPUNIT_ASSERT(dict->get(""));
  210. CPPUNIT_ASSERT_EQUAL((int64_t)123, downcast<Integer>(dict->get(""))->i());
  211. }
  212. }
  213. } // namespace aria2