reader_ut.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. #include <library/cpp/yson_pull/exceptions.h>
  2. #include <library/cpp/yson_pull/range.h>
  3. #include <library/cpp/yson_pull/reader.h>
  4. #include <library/cpp/yson_pull/detail/cescape.h>
  5. #include <library/cpp/yson_pull/detail/macros.h>
  6. #include <library/cpp/testing/unittest/registar.h>
  7. namespace {
  8. NYsonPull::TReader memory_reader(TStringBuf data, NYsonPull::EStreamType mode) {
  9. return NYsonPull::TReader(
  10. NYsonPull::NInput::FromMemory(data),
  11. mode);
  12. }
  13. template <typename T>
  14. void expect_scalar(const NYsonPull::TScalar& scalar, T value) {
  15. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::TScalar{value}, scalar);
  16. }
  17. template <>
  18. void expect_scalar(const NYsonPull::TScalar& scalar, double value) {
  19. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EScalarType::Float64, scalar.Type());
  20. auto scalarValue = scalar.AsFloat64();
  21. auto message = TStringBuilder() << "expected " << value << ", got " << scalarValue;
  22. if (std::isfinite(value)) {
  23. UNIT_ASSERT_C(std::isfinite(scalarValue), message);
  24. UNIT_ASSERT_DOUBLES_EQUAL(value, scalarValue, 1e-5);
  25. } else if (std::isnan(value)) {
  26. UNIT_ASSERT_C(std::isnan(scalarValue), message);
  27. } else if (value > 0) {
  28. UNIT_ASSERT_C(std::isinf(scalarValue) && (scalarValue > 0), message);
  29. } else {
  30. UNIT_ASSERT_C(std::isinf(scalarValue) && (scalarValue < 0), message);
  31. }
  32. }
  33. template <typename T>
  34. void test_scalar(TStringBuf data, T value) {
  35. // SCOPED_TRACE(NYsonPull::detail::cescape::quote(data));
  36. auto reader = memory_reader(data, NYsonPull::EStreamType::Node);
  37. try {
  38. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::BeginStream, reader.NextEvent().Type());
  39. {
  40. auto& event = reader.NextEvent();
  41. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, event.Type());
  42. expect_scalar(event.AsScalar(), value);
  43. }
  44. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::EndStream, reader.NextEvent().Type());
  45. } catch (const std::exception& err) {
  46. UNIT_FAIL(err.what());
  47. }
  48. }
  49. void consume(TStringBuf data, NYsonPull::EStreamType mode = NYsonPull::EStreamType::Node) {
  50. // SCOPED_TRACE(NYsonPull::detail::cescape::quote(data));
  51. auto input_range = NYsonPull::TStreamEventsRange(
  52. NYsonPull::NInput::FromMemory(data),
  53. mode);
  54. for (auto& event : input_range) {
  55. Y_UNUSED(event);
  56. }
  57. }
  58. #define ACCEPT(data) UNIT_ASSERT_NO_EXCEPTION(consume(data))
  59. #define REJECT(data) UNIT_ASSERT_EXCEPTION(consume(data), NYsonPull::NException::TBadInput)
  60. #define ACCEPT2(data, mode) UNIT_ASSERT_NO_EXCEPTION(consume(data, mode))
  61. #define REJECT2(data, mode) UNIT_ASSERT_EXCEPTION(consume(data, mode), NYsonPull::NException::TBadInput)
  62. } // anonymous namespace
  63. Y_UNIT_TEST_SUITE(Reader) {
  64. Y_UNIT_TEST(ScalarEntity) {
  65. test_scalar(TStringBuf("#"), NYsonPull::TScalar{});
  66. }
  67. Y_UNIT_TEST(ScalarBoolean) {
  68. test_scalar(TStringBuf("%true"), true);
  69. test_scalar(TStringBuf("%false"), false);
  70. test_scalar(TStringBuf("\x05"sv), true);
  71. test_scalar(TStringBuf("\x04"sv), false);
  72. REJECT("%");
  73. REJECT("%trueth");
  74. REJECT("%tru");
  75. REJECT("%falseth");
  76. REJECT("%fals");
  77. REJECT("%hithere");
  78. }
  79. Y_UNIT_TEST(ScalarInt64) {
  80. test_scalar(TStringBuf("1"), i64{1});
  81. test_scalar(TStringBuf("+1"), i64{1});
  82. test_scalar(TStringBuf("100000"), i64{100000});
  83. test_scalar(TStringBuf("+100000"), i64{100000});
  84. test_scalar(TStringBuf("-100000"), i64{-100000});
  85. test_scalar(TStringBuf("9223372036854775807"), i64{9223372036854775807});
  86. test_scalar(TStringBuf("+9223372036854775807"), i64{9223372036854775807});
  87. test_scalar(TStringBuf("\x02\x02"sv), i64{1});
  88. test_scalar(TStringBuf("\x02\xc0\x9a\x0c"sv), i64{100000});
  89. test_scalar(TStringBuf("\x02\xbf\x9a\x0c"sv), i64{-100000});
  90. test_scalar(TStringBuf("\x02\xfe\xff\xff\xff\xff\xff\xff\xff\xff\x01"sv), i64{9223372036854775807});
  91. REJECT("1a2");
  92. REJECT("1-1-1-1");
  93. REJECT("1+0");
  94. }
  95. Y_UNIT_TEST(SclarUInt64) {
  96. test_scalar(TStringBuf("1u"), ui64{1});
  97. test_scalar(TStringBuf("+1u"), ui64{1});
  98. test_scalar(TStringBuf("100000u"), ui64{100000});
  99. test_scalar(TStringBuf("+100000u"), ui64{100000});
  100. test_scalar(TStringBuf("9223372036854775807u"), ui64{9223372036854775807u});
  101. test_scalar(TStringBuf("+9223372036854775807u"), ui64{9223372036854775807u});
  102. test_scalar(TStringBuf("18446744073709551615u"), ui64{18446744073709551615u});
  103. test_scalar(TStringBuf("+18446744073709551615u"), ui64{18446744073709551615u});
  104. REJECT("1a2u");
  105. REJECT("1-1-1-1u");
  106. REJECT("1+0u");
  107. // TODO: binary
  108. }
  109. Y_UNIT_TEST(ScalarFloat64) {
  110. test_scalar(TStringBuf("0.0"), double{0.0});
  111. test_scalar(TStringBuf("+0.0"), double{0.0});
  112. test_scalar(TStringBuf("+.0"), double{0.0});
  113. test_scalar(TStringBuf("+.5"), double{0.5});
  114. test_scalar(TStringBuf("-.5"), double{-0.5});
  115. test_scalar(TStringBuf("1.0"), double{1.0});
  116. test_scalar(TStringBuf("+1.0"), double{1.0});
  117. test_scalar(TStringBuf("-1.0"), double{-1.0});
  118. test_scalar(TStringBuf("1000.0"), double{1000.0});
  119. test_scalar(TStringBuf("+1000.0"), double{1000.0});
  120. test_scalar(TStringBuf("-1000.0"), double{-1000.0});
  121. test_scalar(TStringBuf("1e12"), double{1e12});
  122. test_scalar(TStringBuf("1e+12"), double{1e12});
  123. test_scalar(TStringBuf("+1e+12"), double{1e12});
  124. test_scalar(TStringBuf("-1e+12"), double{-1e12});
  125. test_scalar(TStringBuf("1e-12"), double{1e-12});
  126. test_scalar(TStringBuf("+1e-12"), double{1e-12});
  127. test_scalar(TStringBuf("-1e-12"), double{-1e-12});
  128. test_scalar(TStringBuf("\x03\x00\x00\x00\x00\x00\x00\x00\x00"sv), double{0.0});
  129. test_scalar(
  130. TStringBuf("\x03\x00\x00\x00\x00\x00\x00\xf8\x7f"sv),
  131. double{std::numeric_limits<double>::quiet_NaN()});
  132. test_scalar(
  133. TStringBuf("\x03\x00\x00\x00\x00\x00\x00\xf0\x7f"sv),
  134. double{std::numeric_limits<double>::infinity()});
  135. test_scalar(
  136. TStringBuf("\x03\x00\x00\x00\x00\x00\x00\xf0\xff"sv),
  137. double{-std::numeric_limits<double>::infinity()});
  138. test_scalar(
  139. TStringBuf("%nan"),
  140. double{std::numeric_limits<double>::quiet_NaN()});
  141. test_scalar(
  142. TStringBuf("%inf"),
  143. double{std::numeric_limits<double>::infinity()});
  144. test_scalar(
  145. TStringBuf("%-inf"),
  146. double{-std::numeric_limits<double>::infinity()});
  147. REJECT("++0.0");
  148. REJECT("++1.0");
  149. REJECT("++.1");
  150. REJECT("1.0.0");
  151. //REJECT("1e+10000");
  152. REJECT(TStringBuf("\x03\x00\x00\x00\x00\x00\x00\x00"sv));
  153. // XXX: Questionable behaviour?
  154. ACCEPT("+.0");
  155. ACCEPT("-.0");
  156. // XXX: Rejected on Mac OS, accepted on Linux (?!)
  157. //REJECT(".0");
  158. //REJECT(".5");
  159. REJECT("%NaN");
  160. REJECT("%+inf");
  161. REJECT("%infinity");
  162. REJECT("%na");
  163. REJECT("%in");
  164. REJECT("%-in");
  165. }
  166. Y_UNIT_TEST(ScalarString) {
  167. test_scalar(TStringBuf(R"(foobar)"), TStringBuf("foobar"));
  168. test_scalar(TStringBuf(R"(foobar11)"), TStringBuf("foobar11"));
  169. test_scalar(TStringBuf(R"("foobar")"), TStringBuf("foobar"));
  170. // wat? "\x0cf" parsed as a single char? no way!
  171. test_scalar("\x01\x0c" "foobar"sv,
  172. TStringBuf("foobar"));
  173. REJECT(R"("foobar)");
  174. REJECT("\x01\x0c" "fooba"sv);
  175. REJECT("\x01\x0d" "foobar"sv); // negative length
  176. }
  177. Y_UNIT_TEST(EmptyList) {
  178. auto reader = memory_reader("[]", NYsonPull::EStreamType::Node);
  179. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::BeginStream, reader.NextEvent().Type());
  180. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::BeginList, reader.NextEvent().Type());
  181. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::EndList, reader.NextEvent().Type());
  182. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::EndStream, reader.NextEvent().Type());
  183. REJECT("[");
  184. REJECT("]");
  185. }
  186. Y_UNIT_TEST(EmptyMap) {
  187. auto reader = memory_reader("{}", NYsonPull::EStreamType::Node);
  188. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::BeginStream, reader.NextEvent().Type());
  189. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::BeginMap, reader.NextEvent().Type());
  190. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::EndMap, reader.NextEvent().Type());
  191. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::EndStream, reader.NextEvent().Type());
  192. REJECT("{");
  193. REJECT("}");
  194. }
  195. Y_UNIT_TEST(Sample) {
  196. auto reader = memory_reader(
  197. R"({"11"=11;"nothing"=#;"zero"=0.;"foo"="bar";"list"=[1;2;3]})",
  198. NYsonPull::EStreamType::Node);
  199. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::BeginStream, reader.NextEvent().Type());
  200. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::BeginMap, reader.NextEvent().Type());
  201. {
  202. auto& e = reader.NextEvent();
  203. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Key, e.Type());
  204. UNIT_ASSERT_VALUES_EQUAL(TStringBuf("11"), e.AsString());
  205. }
  206. {
  207. auto& e = reader.NextEvent();
  208. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, e.Type());
  209. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::TScalar{i64{11}}, e.AsScalar());
  210. }
  211. {
  212. auto& e = reader.NextEvent();
  213. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Key, e.Type());
  214. UNIT_ASSERT_VALUES_EQUAL(TStringBuf("nothing"), e.AsString());
  215. }
  216. {
  217. auto& e = reader.NextEvent();
  218. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, e.Type());
  219. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::TScalar{}, e.AsScalar());
  220. }
  221. {
  222. auto& e = reader.NextEvent();
  223. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Key, e.Type());
  224. UNIT_ASSERT_VALUES_EQUAL(TStringBuf("zero"), e.AsString());
  225. }
  226. {
  227. auto& e = reader.NextEvent();
  228. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, e.Type());
  229. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::TScalar{0.0}, e.AsScalar());
  230. }
  231. {
  232. auto& e = reader.NextEvent();
  233. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Key, e.Type());
  234. UNIT_ASSERT_VALUES_EQUAL(TStringBuf("foo"), e.AsString());
  235. }
  236. {
  237. auto& e = reader.NextEvent();
  238. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, e.Type());
  239. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::TScalar{TStringBuf("bar")}, e.AsScalar());
  240. }
  241. {
  242. auto& e = reader.NextEvent();
  243. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Key, e.Type());
  244. UNIT_ASSERT_VALUES_EQUAL(TStringBuf("list"), e.AsString());
  245. }
  246. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::BeginList, reader.NextEvent().Type());
  247. {
  248. auto& e = reader.NextEvent();
  249. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, e.Type());
  250. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::TScalar{i64{1}}, e.AsScalar());
  251. }
  252. {
  253. auto& e = reader.NextEvent();
  254. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, e.Type());
  255. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::TScalar{i64{2}}, e.AsScalar());
  256. }
  257. {
  258. auto& e = reader.NextEvent();
  259. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, e.Type());
  260. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::TScalar{i64{3}}, e.AsScalar());
  261. }
  262. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::EndList, reader.NextEvent().Type());
  263. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::EndMap, reader.NextEvent().Type());
  264. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::EndStream, reader.NextEvent().Type());
  265. }
  266. Y_UNIT_TEST(Accept) {
  267. ACCEPT("[]");
  268. ACCEPT("{}");
  269. ACCEPT("<>[]");
  270. ACCEPT("<>{}");
  271. ACCEPT("[{};{};{}]");
  272. ACCEPT("[{};{};{};]");
  273. ACCEPT("[<>{};<>{};<>{}]");
  274. ACCEPT("[<>{};<>{};<>{};]");
  275. ACCEPT("foo");
  276. ACCEPT("[foo]");
  277. ACCEPT("[foo;]");
  278. ACCEPT("{foo=foo}");
  279. ACCEPT("{foo=foo;}");
  280. ACCEPT("<>{foo=foo}");
  281. ACCEPT("{foo=<foo=foo>foo}");
  282. ACCEPT("{foo=<foo=foo;>foo}");
  283. ACCEPT("{foo=<foo=foo>[foo;foo]}");
  284. }
  285. Y_UNIT_TEST(Reject) {
  286. REJECT("[");
  287. REJECT("{");
  288. REJECT("<");
  289. REJECT("[[}]");
  290. REJECT("<>{]");
  291. REJECT("[>]");
  292. REJECT("<><>[]");
  293. REJECT("[<>;<>]");
  294. REJECT("{<>foo=foo}");
  295. REJECT("{foo=<>}");
  296. REJECT("{foo}");
  297. REJECT("<a=b>");
  298. REJECT("<>");
  299. REJECT("@");
  300. }
  301. Y_UNIT_TEST(ReadPastEnd) {
  302. auto reader = memory_reader("#", NYsonPull::EStreamType::Node);
  303. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::BeginStream, reader.NextEvent().Type());
  304. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, reader.NextEvent().Type());
  305. UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::EndStream, reader.NextEvent().Type());
  306. UNIT_ASSERT_EXCEPTION(reader.NextEvent(), NYsonPull::NException::TBadInput);
  307. }
  308. Y_UNIT_TEST(BadInput) {
  309. // max_size<ui32> < varint size < max_size<ui64>
  310. auto t = TString("\x01\xff\xff\xff\xff\xff\xff\xff\xff");
  311. auto reader = memory_reader(t, NYsonPull::EStreamType::Node);
  312. UNIT_ASSERT_EQUAL(reader.NextEvent().Type(), NYsonPull::EEventType::BeginStream);
  313. UNIT_ASSERT_EXCEPTION(reader.NextEvent(), NYsonPull::NException::TBadInput);
  314. }
  315. Y_UNIT_TEST(StreamType) {
  316. REJECT2("", NYsonPull::EStreamType::Node);
  317. ACCEPT2("", NYsonPull::EStreamType::ListFragment);
  318. ACCEPT2("", NYsonPull::EStreamType::MapFragment);
  319. ACCEPT2("[1]", NYsonPull::EStreamType::Node);
  320. ACCEPT2("[1]", NYsonPull::EStreamType::ListFragment);
  321. REJECT2("[1]", NYsonPull::EStreamType::MapFragment);
  322. ACCEPT2("<foo=bar>[1]", NYsonPull::EStreamType::Node);
  323. ACCEPT2("<foo=bar>[1]", NYsonPull::EStreamType::ListFragment);
  324. REJECT2("<foo=bar>[1]", NYsonPull::EStreamType::MapFragment);
  325. ACCEPT2(" [1] \t \t ", NYsonPull::EStreamType::Node);
  326. ACCEPT2(" [1] \t \t ", NYsonPull::EStreamType::ListFragment);
  327. REJECT2(" [1] \t \t ", NYsonPull::EStreamType::MapFragment);
  328. REJECT2("[1];", NYsonPull::EStreamType::Node);
  329. ACCEPT2("[1];", NYsonPull::EStreamType::ListFragment);
  330. REJECT2("[1];", NYsonPull::EStreamType::MapFragment);
  331. REJECT2("[1]; foobar", NYsonPull::EStreamType::Node);
  332. ACCEPT2("[1]; foobar", NYsonPull::EStreamType::ListFragment);
  333. REJECT2("[1]; foobar", NYsonPull::EStreamType::MapFragment);
  334. REJECT2("a=[1]", NYsonPull::EStreamType::Node);
  335. REJECT2("a=[1]", NYsonPull::EStreamType::ListFragment);
  336. ACCEPT2("a=[1]", NYsonPull::EStreamType::MapFragment);
  337. REJECT2("a=[1]; ", NYsonPull::EStreamType::Node);
  338. REJECT2("a=[1]; ", NYsonPull::EStreamType::ListFragment);
  339. ACCEPT2("a=[1]; ", NYsonPull::EStreamType::MapFragment);
  340. REJECT2("a=[1]; b=foobar", NYsonPull::EStreamType::Node);
  341. REJECT2("a=[1]; b=foobar", NYsonPull::EStreamType::ListFragment);
  342. ACCEPT2("a=[1]; b=foobar", NYsonPull::EStreamType::MapFragment);
  343. }
  344. } // Y_UNIT_TEST_SUITE(Reader)