ValueBaseBencodeParserTest.cc 6.4 KB

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