123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- #include <library/cpp/yson_pull/exceptions.h>
- #include <library/cpp/yson_pull/range.h>
- #include <library/cpp/yson_pull/reader.h>
- #include <library/cpp/yson_pull/detail/cescape.h>
- #include <library/cpp/yson_pull/detail/macros.h>
- #include <library/cpp/testing/unittest/registar.h>
- namespace {
- NYsonPull::TReader memory_reader(TStringBuf data, NYsonPull::EStreamType mode) {
- return NYsonPull::TReader(
- NYsonPull::NInput::FromMemory(data),
- mode);
- }
- template <typename T>
- void expect_scalar(const NYsonPull::TScalar& scalar, T value) {
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::TScalar{value}, scalar);
- }
- template <>
- void expect_scalar(const NYsonPull::TScalar& scalar, double value) {
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EScalarType::Float64, scalar.Type());
- auto scalarValue = scalar.AsFloat64();
- auto message = TStringBuilder() << "expected " << value << ", got " << scalarValue;
- if (std::isfinite(value)) {
- UNIT_ASSERT_C(std::isfinite(scalarValue), message);
- UNIT_ASSERT_DOUBLES_EQUAL(value, scalarValue, 1e-5);
- } else if (std::isnan(value)) {
- UNIT_ASSERT_C(std::isnan(scalarValue), message);
- } else if (value > 0) {
- UNIT_ASSERT_C(std::isinf(scalarValue) && (scalarValue > 0), message);
- } else {
- UNIT_ASSERT_C(std::isinf(scalarValue) && (scalarValue < 0), message);
- }
- }
- template <typename T>
- void test_scalar(TStringBuf data, T value) {
- // SCOPED_TRACE(NYsonPull::detail::cescape::quote(data));
- auto reader = memory_reader(data, NYsonPull::EStreamType::Node);
- try {
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::BeginStream, reader.NextEvent().Type());
- {
- auto& event = reader.NextEvent();
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, event.Type());
- expect_scalar(event.AsScalar(), value);
- }
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::EndStream, reader.NextEvent().Type());
- } catch (const std::exception& err) {
- UNIT_FAIL(err.what());
- }
- }
- void consume(TStringBuf data, NYsonPull::EStreamType mode = NYsonPull::EStreamType::Node) {
- // SCOPED_TRACE(NYsonPull::detail::cescape::quote(data));
- auto input_range = NYsonPull::TStreamEventsRange(
- NYsonPull::NInput::FromMemory(data),
- mode);
- for (auto& event : input_range) {
- Y_UNUSED(event);
- }
- }
- #define ACCEPT(data) UNIT_ASSERT_NO_EXCEPTION(consume(data))
- #define REJECT(data) UNIT_ASSERT_EXCEPTION(consume(data), NYsonPull::NException::TBadInput)
- #define ACCEPT2(data, mode) UNIT_ASSERT_NO_EXCEPTION(consume(data, mode))
- #define REJECT2(data, mode) UNIT_ASSERT_EXCEPTION(consume(data, mode), NYsonPull::NException::TBadInput)
- } // anonymous namespace
- Y_UNIT_TEST_SUITE(Reader) {
- Y_UNIT_TEST(ScalarEntity) {
- test_scalar(TStringBuf("#"), NYsonPull::TScalar{});
- }
- Y_UNIT_TEST(ScalarBoolean) {
- test_scalar(TStringBuf("%true"), true);
- test_scalar(TStringBuf("%false"), false);
- test_scalar(TStringBuf("\x05"sv), true);
- test_scalar(TStringBuf("\x04"sv), false);
- REJECT("%");
- REJECT("%trueth");
- REJECT("%tru");
- REJECT("%falseth");
- REJECT("%fals");
- REJECT("%hithere");
- }
- Y_UNIT_TEST(ScalarInt64) {
- test_scalar(TStringBuf("1"), i64{1});
- test_scalar(TStringBuf("+1"), i64{1});
- test_scalar(TStringBuf("100000"), i64{100000});
- test_scalar(TStringBuf("+100000"), i64{100000});
- test_scalar(TStringBuf("-100000"), i64{-100000});
- test_scalar(TStringBuf("9223372036854775807"), i64{9223372036854775807});
- test_scalar(TStringBuf("+9223372036854775807"), i64{9223372036854775807});
- test_scalar(TStringBuf("\x02\x02"sv), i64{1});
- test_scalar(TStringBuf("\x02\xc0\x9a\x0c"sv), i64{100000});
- test_scalar(TStringBuf("\x02\xbf\x9a\x0c"sv), i64{-100000});
- test_scalar(TStringBuf("\x02\xfe\xff\xff\xff\xff\xff\xff\xff\xff\x01"sv), i64{9223372036854775807});
- REJECT("1a2");
- REJECT("1-1-1-1");
- REJECT("1+0");
- }
- Y_UNIT_TEST(SclarUInt64) {
- test_scalar(TStringBuf("1u"), ui64{1});
- test_scalar(TStringBuf("+1u"), ui64{1});
- test_scalar(TStringBuf("100000u"), ui64{100000});
- test_scalar(TStringBuf("+100000u"), ui64{100000});
- test_scalar(TStringBuf("9223372036854775807u"), ui64{9223372036854775807u});
- test_scalar(TStringBuf("+9223372036854775807u"), ui64{9223372036854775807u});
- test_scalar(TStringBuf("18446744073709551615u"), ui64{18446744073709551615u});
- test_scalar(TStringBuf("+18446744073709551615u"), ui64{18446744073709551615u});
- REJECT("1a2u");
- REJECT("1-1-1-1u");
- REJECT("1+0u");
- // TODO: binary
- }
- Y_UNIT_TEST(ScalarFloat64) {
- test_scalar(TStringBuf("0.0"), double{0.0});
- test_scalar(TStringBuf("+0.0"), double{0.0});
- test_scalar(TStringBuf("+.0"), double{0.0});
- test_scalar(TStringBuf("+.5"), double{0.5});
- test_scalar(TStringBuf("-.5"), double{-0.5});
- test_scalar(TStringBuf("1.0"), double{1.0});
- test_scalar(TStringBuf("+1.0"), double{1.0});
- test_scalar(TStringBuf("-1.0"), double{-1.0});
- test_scalar(TStringBuf("1000.0"), double{1000.0});
- test_scalar(TStringBuf("+1000.0"), double{1000.0});
- test_scalar(TStringBuf("-1000.0"), double{-1000.0});
- test_scalar(TStringBuf("1e12"), double{1e12});
- test_scalar(TStringBuf("1e+12"), double{1e12});
- test_scalar(TStringBuf("+1e+12"), double{1e12});
- test_scalar(TStringBuf("-1e+12"), double{-1e12});
- test_scalar(TStringBuf("1e-12"), double{1e-12});
- test_scalar(TStringBuf("+1e-12"), double{1e-12});
- test_scalar(TStringBuf("-1e-12"), double{-1e-12});
- test_scalar(TStringBuf("\x03\x00\x00\x00\x00\x00\x00\x00\x00"sv), double{0.0});
- test_scalar(
- TStringBuf("\x03\x00\x00\x00\x00\x00\x00\xf8\x7f"sv),
- double{std::numeric_limits<double>::quiet_NaN()});
- test_scalar(
- TStringBuf("\x03\x00\x00\x00\x00\x00\x00\xf0\x7f"sv),
- double{std::numeric_limits<double>::infinity()});
- test_scalar(
- TStringBuf("\x03\x00\x00\x00\x00\x00\x00\xf0\xff"sv),
- double{-std::numeric_limits<double>::infinity()});
- test_scalar(
- TStringBuf("%nan"),
- double{std::numeric_limits<double>::quiet_NaN()});
- test_scalar(
- TStringBuf("%inf"),
- double{std::numeric_limits<double>::infinity()});
- test_scalar(
- TStringBuf("%-inf"),
- double{-std::numeric_limits<double>::infinity()});
- REJECT("++0.0");
- REJECT("++1.0");
- REJECT("++.1");
- REJECT("1.0.0");
- //REJECT("1e+10000");
- REJECT(TStringBuf("\x03\x00\x00\x00\x00\x00\x00\x00"sv));
- // XXX: Questionable behaviour?
- ACCEPT("+.0");
- ACCEPT("-.0");
- // XXX: Rejected on Mac OS, accepted on Linux (?!)
- //REJECT(".0");
- //REJECT(".5");
- REJECT("%NaN");
- REJECT("%+inf");
- REJECT("%infinity");
- REJECT("%na");
- REJECT("%in");
- REJECT("%-in");
- }
- Y_UNIT_TEST(ScalarString) {
- test_scalar(TStringBuf(R"(foobar)"), TStringBuf("foobar"));
- test_scalar(TStringBuf(R"(foobar11)"), TStringBuf("foobar11"));
- test_scalar(TStringBuf(R"("foobar")"), TStringBuf("foobar"));
- // wat? "\x0cf" parsed as a single char? no way!
- test_scalar("\x01\x0c" "foobar"sv,
- TStringBuf("foobar"));
- REJECT(R"("foobar)");
- REJECT("\x01\x0c" "fooba"sv);
- REJECT("\x01\x0d" "foobar"sv); // negative length
- }
- Y_UNIT_TEST(EmptyList) {
- auto reader = memory_reader("[]", NYsonPull::EStreamType::Node);
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::BeginStream, reader.NextEvent().Type());
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::BeginList, reader.NextEvent().Type());
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::EndList, reader.NextEvent().Type());
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::EndStream, reader.NextEvent().Type());
- REJECT("[");
- REJECT("]");
- }
- Y_UNIT_TEST(EmptyMap) {
- auto reader = memory_reader("{}", NYsonPull::EStreamType::Node);
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::BeginStream, reader.NextEvent().Type());
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::BeginMap, reader.NextEvent().Type());
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::EndMap, reader.NextEvent().Type());
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::EndStream, reader.NextEvent().Type());
- REJECT("{");
- REJECT("}");
- }
- Y_UNIT_TEST(Sample) {
- auto reader = memory_reader(
- R"({"11"=11;"nothing"=#;"zero"=0.;"foo"="bar";"list"=[1;2;3]})",
- NYsonPull::EStreamType::Node);
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::BeginStream, reader.NextEvent().Type());
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::BeginMap, reader.NextEvent().Type());
- {
- auto& e = reader.NextEvent();
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Key, e.Type());
- UNIT_ASSERT_VALUES_EQUAL(TStringBuf("11"), e.AsString());
- }
- {
- auto& e = reader.NextEvent();
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, e.Type());
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::TScalar{i64{11}}, e.AsScalar());
- }
- {
- auto& e = reader.NextEvent();
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Key, e.Type());
- UNIT_ASSERT_VALUES_EQUAL(TStringBuf("nothing"), e.AsString());
- }
- {
- auto& e = reader.NextEvent();
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, e.Type());
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::TScalar{}, e.AsScalar());
- }
- {
- auto& e = reader.NextEvent();
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Key, e.Type());
- UNIT_ASSERT_VALUES_EQUAL(TStringBuf("zero"), e.AsString());
- }
- {
- auto& e = reader.NextEvent();
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, e.Type());
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::TScalar{0.0}, e.AsScalar());
- }
- {
- auto& e = reader.NextEvent();
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Key, e.Type());
- UNIT_ASSERT_VALUES_EQUAL(TStringBuf("foo"), e.AsString());
- }
- {
- auto& e = reader.NextEvent();
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, e.Type());
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::TScalar{TStringBuf("bar")}, e.AsScalar());
- }
- {
- auto& e = reader.NextEvent();
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Key, e.Type());
- UNIT_ASSERT_VALUES_EQUAL(TStringBuf("list"), e.AsString());
- }
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::BeginList, reader.NextEvent().Type());
- {
- auto& e = reader.NextEvent();
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, e.Type());
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::TScalar{i64{1}}, e.AsScalar());
- }
- {
- auto& e = reader.NextEvent();
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, e.Type());
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::TScalar{i64{2}}, e.AsScalar());
- }
- {
- auto& e = reader.NextEvent();
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, e.Type());
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::TScalar{i64{3}}, e.AsScalar());
- }
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::EndList, reader.NextEvent().Type());
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::EndMap, reader.NextEvent().Type());
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::EndStream, reader.NextEvent().Type());
- }
- Y_UNIT_TEST(Accept) {
- ACCEPT("[]");
- ACCEPT("{}");
- ACCEPT("<>[]");
- ACCEPT("<>{}");
- ACCEPT("[{};{};{}]");
- ACCEPT("[{};{};{};]");
- ACCEPT("[<>{};<>{};<>{}]");
- ACCEPT("[<>{};<>{};<>{};]");
- ACCEPT("foo");
- ACCEPT("[foo]");
- ACCEPT("[foo;]");
- ACCEPT("{foo=foo}");
- ACCEPT("{foo=foo;}");
- ACCEPT("<>{foo=foo}");
- ACCEPT("{foo=<foo=foo>foo}");
- ACCEPT("{foo=<foo=foo;>foo}");
- ACCEPT("{foo=<foo=foo>[foo;foo]}");
- }
- Y_UNIT_TEST(Reject) {
- REJECT("[");
- REJECT("{");
- REJECT("<");
- REJECT("[[}]");
- REJECT("<>{]");
- REJECT("[>]");
- REJECT("<><>[]");
- REJECT("[<>;<>]");
- REJECT("{<>foo=foo}");
- REJECT("{foo=<>}");
- REJECT("{foo}");
- REJECT("<a=b>");
- REJECT("<>");
- REJECT("@");
- }
- Y_UNIT_TEST(ReadPastEnd) {
- auto reader = memory_reader("#", NYsonPull::EStreamType::Node);
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::BeginStream, reader.NextEvent().Type());
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, reader.NextEvent().Type());
- UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::EndStream, reader.NextEvent().Type());
- UNIT_ASSERT_EXCEPTION(reader.NextEvent(), NYsonPull::NException::TBadInput);
- }
- Y_UNIT_TEST(BadInput) {
- // max_size<ui32> < varint size < max_size<ui64>
- auto t = TString("\x01\xff\xff\xff\xff\xff\xff\xff\xff");
- auto reader = memory_reader(t, NYsonPull::EStreamType::Node);
- UNIT_ASSERT_EQUAL(reader.NextEvent().Type(), NYsonPull::EEventType::BeginStream);
- UNIT_ASSERT_EXCEPTION(reader.NextEvent(), NYsonPull::NException::TBadInput);
- }
- Y_UNIT_TEST(StreamType) {
- REJECT2("", NYsonPull::EStreamType::Node);
- ACCEPT2("", NYsonPull::EStreamType::ListFragment);
- ACCEPT2("", NYsonPull::EStreamType::MapFragment);
- ACCEPT2("[1]", NYsonPull::EStreamType::Node);
- ACCEPT2("[1]", NYsonPull::EStreamType::ListFragment);
- REJECT2("[1]", NYsonPull::EStreamType::MapFragment);
- ACCEPT2("<foo=bar>[1]", NYsonPull::EStreamType::Node);
- ACCEPT2("<foo=bar>[1]", NYsonPull::EStreamType::ListFragment);
- REJECT2("<foo=bar>[1]", NYsonPull::EStreamType::MapFragment);
- ACCEPT2(" [1] \t \t ", NYsonPull::EStreamType::Node);
- ACCEPT2(" [1] \t \t ", NYsonPull::EStreamType::ListFragment);
- REJECT2(" [1] \t \t ", NYsonPull::EStreamType::MapFragment);
- REJECT2("[1];", NYsonPull::EStreamType::Node);
- ACCEPT2("[1];", NYsonPull::EStreamType::ListFragment);
- REJECT2("[1];", NYsonPull::EStreamType::MapFragment);
- REJECT2("[1]; foobar", NYsonPull::EStreamType::Node);
- ACCEPT2("[1]; foobar", NYsonPull::EStreamType::ListFragment);
- REJECT2("[1]; foobar", NYsonPull::EStreamType::MapFragment);
- REJECT2("a=[1]", NYsonPull::EStreamType::Node);
- REJECT2("a=[1]", NYsonPull::EStreamType::ListFragment);
- ACCEPT2("a=[1]", NYsonPull::EStreamType::MapFragment);
- REJECT2("a=[1]; ", NYsonPull::EStreamType::Node);
- REJECT2("a=[1]; ", NYsonPull::EStreamType::ListFragment);
- ACCEPT2("a=[1]; ", NYsonPull::EStreamType::MapFragment);
- REJECT2("a=[1]; b=foobar", NYsonPull::EStreamType::Node);
- REJECT2("a=[1]; b=foobar", NYsonPull::EStreamType::ListFragment);
- ACCEPT2("a=[1]; b=foobar", NYsonPull::EStreamType::MapFragment);
- }
- } // Y_UNIT_TEST_SUITE(Reader)
|