ValueBaseBencodeParserTest.cc 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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 = parser.parseFinal(src.c_str(), src.size(),
  19. 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 = parser.parseFinal(src.c_str(), src.size(),
  32. 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 = parser.parseFinal(src.c_str(), src.size(),
  39. 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 = parser.parseFinal(src.c_str(), src.size(),
  46. error);
  47. CPPUNIT_ASSERT(downcast<Dict>(d)->empty());
  48. }
  49. {
  50. // empty list
  51. std::string src = "le";
  52. std::shared_ptr<ValueBase> l = parser.parseFinal(src.c_str(), src.size(),
  53. error);
  54. CPPUNIT_ASSERT(downcast<List>(l)->empty());
  55. }
  56. {
  57. // string
  58. std::string src = "3:foo";
  59. std::shared_ptr<ValueBase> s = parser.parseFinal(src.c_str(), src.size(),
  60. 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 = parser.parseFinal(src.c_str(), src.size(),
  67. 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 = parser.parseFinal(src.c_str(), src.size(),
  75. 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 = parser.parseFinal(src.c_str(), src.size(),
  86. 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 = parser.parseFinal(src.c_str(), src.size(),
  101. 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 = parser.parseFinal(src.c_str(), src.size(),
  112. 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,
  119. downcast<Integer>(list->get(1))->i());
  120. }
  121. {
  122. // string, integer and list in dict
  123. std::string src = "d4:name5:aria24:sizei12345678900e5:filesl3:bin3:docee";
  124. std::shared_ptr<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  125. error);
  126. const Dict* dict = downcast<Dict>(r);
  127. CPPUNIT_ASSERT(dict);
  128. CPPUNIT_ASSERT_EQUAL(std::string("aria2"),
  129. downcast<String>(dict->get("name"))->s());
  130. CPPUNIT_ASSERT_EQUAL(static_cast<Integer::ValueType>(12345678900LL),
  131. downcast<Integer>(dict->get("size"))->i());
  132. const List* list = downcast<List>(dict->get("files"));
  133. CPPUNIT_ASSERT(list);
  134. CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), list->size());
  135. CPPUNIT_ASSERT_EQUAL(std::string("bin"),
  136. downcast<String>(list->get(0))->s());
  137. CPPUNIT_ASSERT_EQUAL(std::string("doc"),
  138. downcast<String>(list->get(1))->s());
  139. }
  140. {
  141. // dict in list
  142. std::string src = "ld1:ki123eee";
  143. std::shared_ptr<ValueBase> r = parser.parseFinal(src.c_str(), src.size(),
  144. error);
  145. const List* list = downcast<List>(r);
  146. CPPUNIT_ASSERT(list);
  147. CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), list->size());
  148. const Dict* dict = downcast<Dict>(list->get(0));
  149. CPPUNIT_ASSERT(dict);
  150. CPPUNIT_ASSERT_EQUAL(static_cast<Integer::ValueType>(123),
  151. downcast<Integer>(dict->get("k"))->i());
  152. }
  153. {
  154. // empty key is allowed
  155. std::string src = "d0:1:ve";
  156. std::shared_ptr<ValueBase> s = parser.parseFinal(src.c_str(), src.size(),
  157. error);
  158. }
  159. {
  160. // empty encoded data
  161. std::string src = "";
  162. std::shared_ptr<ValueBase> s = parser.parseFinal(src.c_str(), src.size(),
  163. error);
  164. CPPUNIT_ASSERT(!s);
  165. }
  166. // integer, without ending 'e'
  167. checkDecodeError("i3");
  168. // dict, without ending 'e'
  169. checkDecodeError("d");
  170. // list, without ending 'e'
  171. checkDecodeError("l");
  172. // string, less than the specified length.
  173. checkDecodeError("3:ab");
  174. // string, but length is invalid
  175. checkDecodeError("x:abc");
  176. // string with minus length
  177. checkDecodeError("-1:a");
  178. // too deep structure
  179. checkDecodeError(std::string(51, 'l')+std::string(51,'e'));
  180. checkDecodeError(std::string(50, 'l')+"d3:fooi100ee"+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 = parser.parseFinal(src.c_str(), src.size(),
  185. 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