diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/yson_pull/ut | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/yson_pull/ut')
-rw-r--r-- | library/cpp/yson_pull/ut/cescape_ut.cpp | 71 | ||||
-rw-r--r-- | library/cpp/yson_pull/ut/loop_ut.cpp | 382 | ||||
-rw-r--r-- | library/cpp/yson_pull/ut/reader_ut.cpp | 410 | ||||
-rw-r--r-- | library/cpp/yson_pull/ut/writer_ut.cpp | 256 | ||||
-rw-r--r-- | library/cpp/yson_pull/ut/ya.make | 12 |
5 files changed, 1131 insertions, 0 deletions
diff --git a/library/cpp/yson_pull/ut/cescape_ut.cpp b/library/cpp/yson_pull/ut/cescape_ut.cpp new file mode 100644 index 0000000000..6628ba1d15 --- /dev/null +++ b/library/cpp/yson_pull/ut/cescape_ut.cpp @@ -0,0 +1,71 @@ +#include <library/cpp/yson_pull/detail/cescape.h> + +#include <library/cpp/testing/unittest/registar.h> + +using namespace NYsonPull::NDetail; + +namespace { + void test_roundtrip(const TVector<ui8>& str) { + TStringBuf str_buf( + reinterpret_cast<const char*>(str.data()), + str.size()); + auto tmp = NCEscape::encode(str_buf); + auto dest = NCEscape::decode(tmp); + UNIT_ASSERT_VALUES_EQUAL_C( + str_buf, TStringBuf(dest), + "A[" << str.size() << "]: " << str_buf << '\n' + << "B[" << tmp.size() << "]: " << tmp << '\n' + << "C[" << dest.size() << "]: " << dest); + } + + template <size_t N> + void test_exhaustive(TVector<ui8>& str) { + for (int i = 0; i < 256; ++i) { + str[str.size() - N] = static_cast<char>(i); + test_exhaustive<N - 1>(str); + } + } + + template <> + void test_exhaustive<0>(TVector<ui8>& str) { + test_roundtrip(str); + } + + template <size_t N> + void test_exhaustive() { + TVector<ui8> str(N, ' '); + test_exhaustive<N>(str); + } + +} // anonymous namespace + +Y_UNIT_TEST_SUITE(CEscape) { + Y_UNIT_TEST(ExhaustiveOneChar) { + test_exhaustive<1>(); + } + + Y_UNIT_TEST(ExhaustiveTwoChars) { + test_exhaustive<2>(); + } + + Y_UNIT_TEST(ExhaustiveThreeChars) { + test_exhaustive<3>(); + } + + Y_UNIT_TEST(SpecialEscapeEncode) { + //UNIT_ASSERT_VALUES_EQUAL(R"(\b)", NCEscape::encode("\b")); + //UNIT_ASSERT_VALUES_EQUAL(R"(\f)", NCEscape::encode("\f")); + UNIT_ASSERT_VALUES_EQUAL(R"(\n)", NCEscape::encode("\n")); + UNIT_ASSERT_VALUES_EQUAL(R"(\r)", NCEscape::encode("\r")); + UNIT_ASSERT_VALUES_EQUAL(R"(\t)", NCEscape::encode("\t")); + } + + Y_UNIT_TEST(SpecialEscapeDecode) { + UNIT_ASSERT_VALUES_EQUAL("\b", NCEscape::decode(R"(\b)")); + UNIT_ASSERT_VALUES_EQUAL("\f", NCEscape::decode(R"(\f)")); + UNIT_ASSERT_VALUES_EQUAL("\n", NCEscape::decode(R"(\n)")); + UNIT_ASSERT_VALUES_EQUAL("\r", NCEscape::decode(R"(\r)")); + UNIT_ASSERT_VALUES_EQUAL("\t", NCEscape::decode(R"(\t)")); + } + +} // Y_UNIT_TEST_SUITE(CEscape) diff --git a/library/cpp/yson_pull/ut/loop_ut.cpp b/library/cpp/yson_pull/ut/loop_ut.cpp new file mode 100644 index 0000000000..8c7b11dd1c --- /dev/null +++ b/library/cpp/yson_pull/ut/loop_ut.cpp @@ -0,0 +1,382 @@ +#include <library/cpp/yson_pull/input.h> +#include <library/cpp/yson_pull/output.h> +#include <library/cpp/yson_pull/reader.h> +#include <library/cpp/yson_pull/writer.h> + +#include <library/cpp/testing/unittest/registar.h> + +#include <cerrno> +#include <cmath> + +#ifdef _unix_ +#include <unistd.h> +#include <sys/wait.h> +#endif + +namespace { + constexpr const char* alphabet = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + void generate(NYsonPull::TWriter& writer, size_t count) { + writer.BeginStream(); + for (size_t i = 0; i < count; ++i) { + writer.BeginMap() + .Key("ints") + .BeginList() + .Int64(0) + .Int64(-1) + .Int64(1000) + .Int64(-1000) + .EndList() + .Key("uints") + .BeginList() + .UInt64(0) + .UInt64(1000) + .UInt64(10000000) + .EndList() + .Key("entities") + .BeginList() + .Entity() + .BeginAttributes() + .Key("color") + .String("blue") + .Key("size") + .Int64(100) + .EndAttributes() + .Entity() + .Entity() + .EndList() + .Key("booleans") + .BeginList() + .Boolean(true) + .Boolean(false) + .Boolean(true) + .EndList() + .Key("floats") + .BeginList() + .Float64(0.0) + .Float64(13.0e30) + .Float64(M_PI) + .EndList() + .Key("strings") + .BeginList() + .String("hello") + .String("") + .String("foo \"-bar-\" baz") + .String("oh\nwow") + .String(alphabet) + .EndList() + .EndMap(); + } + writer.EndStream(); + } + +#ifdef __clang__ + // XXX: With all the macros below (esp. UNIT_ASSERT_VALUES_EQUAL) unfolded, + // the time it takes clang to optimize generated code becomes abysmal. + // Locally disabling optimization brings it back to normal. + __attribute__((optnone)) +#endif // __clang__ + void + verify(NYsonPull::TReader& reader, size_t count) { +#define NEXT(name__) \ + { \ + auto& name__ = reader.NextEvent(); // SCOPED_TRACE(e); +#define END_NEXT } +#define NEXT_TYPE(type__) \ + NEXT(e) { \ + UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::type__, e.Type()); \ + } \ + END_NEXT +#define NEXT_KEY(key__) \ + NEXT(e) { \ + UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Key, e.Type()); \ + UNIT_ASSERT_VALUES_EQUAL(key__, e.AsString()); \ + } \ + END_NEXT +#define NEXT_SCALAR(type__, value__) \ + NEXT(e) { \ + UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, e.Type()); \ + UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EScalarType::type__, e.AsScalar().Type()); \ + UNIT_ASSERT_VALUES_EQUAL(value__, e.AsScalar().As##type__()); \ + } \ + END_NEXT +#define NEXT_ENTITY() \ + NEXT(e) { \ + UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, e.Type()); \ + UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EScalarType::Entity, e.AsScalar().Type()); \ + } \ + END_NEXT +#define NEXT_FLOAT64(value__) \ + NEXT(e) { \ + UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EEventType::Scalar, e.Type()); \ + UNIT_ASSERT_VALUES_EQUAL(NYsonPull::EScalarType::Float64, e.AsScalar().Type()); \ + UNIT_ASSERT_DOUBLES_EQUAL(value__, e.AsScalar().AsFloat64(), 1e-5); \ + } \ + END_NEXT + + constexpr auto true_ = true; + constexpr auto false_ = false; + + NEXT_TYPE(BeginStream); + for (size_t i = 0; i < count; ++i) { + NEXT_TYPE(BeginMap); + NEXT_KEY("ints") { + NEXT_TYPE(BeginList); + NEXT_SCALAR(Int64, 0); + NEXT_SCALAR(Int64, -1); + NEXT_SCALAR(Int64, 1000); + NEXT_SCALAR(Int64, -1000); + NEXT_TYPE(EndList); + } + NEXT_KEY("uints") { + NEXT_TYPE(BeginList); + NEXT_SCALAR(UInt64, 0U); + NEXT_SCALAR(UInt64, 1000U); + NEXT_SCALAR(UInt64, 10000000U); + NEXT_TYPE(EndList); + } + NEXT_KEY("entities") { + NEXT_TYPE(BeginList); + NEXT_ENTITY(); + NEXT_TYPE(BeginAttributes) { + NEXT_KEY("color") { + NEXT_SCALAR(String, "blue"); + } + NEXT_KEY("size") { + NEXT_SCALAR(Int64, 100); + } + } + NEXT_TYPE(EndAttributes); + NEXT_ENTITY(); + NEXT_ENTITY(); + NEXT_TYPE(EndList); + } + NEXT_KEY("booleans") { + NEXT_TYPE(BeginList); + NEXT_SCALAR(Boolean, true_); + NEXT_SCALAR(Boolean, false_); + NEXT_SCALAR(Boolean, true_); + NEXT_TYPE(EndList); + } + NEXT_KEY("floats") { + NEXT_TYPE(BeginList); + NEXT_FLOAT64(0.0); + NEXT_FLOAT64(13.0e30); + NEXT_FLOAT64(M_PI); + NEXT_TYPE(EndList); + } + NEXT_KEY("strings") { + NEXT_TYPE(BeginList); + NEXT_SCALAR(String, "hello"); + NEXT_SCALAR(String, ""); + NEXT_SCALAR(String, "foo \"-bar-\" baz"); + NEXT_SCALAR(String, "oh\nwow"); + NEXT_SCALAR(String, alphabet); + NEXT_TYPE(EndList); + } + NEXT_TYPE(EndMap); + } + NEXT_TYPE(EndStream); + +#undef NEXT +#undef END_NEXT +#undef NEXT_TYPE +#undef NEXT_KEY +#undef NEXT_SCALAR + } + + class sys_error {}; + + IOutputStream& operator<<(IOutputStream& stream, const sys_error&) { + stream << strerror(errno); + return stream; + } + + NYsonPull::TReader make_reader(THolder<NYsonPull::NInput::IStream> stream) { + return NYsonPull::TReader( + std::move(stream), + NYsonPull::EStreamType::ListFragment); + } + + template <typename Function> + void test_memory(Function make_writer, size_t nrepeat) { + TString text; + { + auto writer = make_writer(NYsonPull::NOutput::FromString(&text)); + generate(writer, nrepeat); + } + { + auto reader = make_reader(NYsonPull::NInput::FromMemory(text)); + verify(reader, nrepeat); + } + { + TStringInput input(text); + auto reader = make_reader(NYsonPull::NInput::FromInputStream(&input, /* buffer_size = */ 1)); + verify(reader, nrepeat); + } + } + +#ifdef _unix_ + template <typename Here, typename There> + void pipe(Here&& reader, There&& writer) { + int fildes[2]; + UNIT_ASSERT_VALUES_EQUAL_C(0, ::pipe(fildes), sys_error()); + auto read_fd = fildes[0]; + auto write_fd = fildes[1]; + + auto pid = ::fork(); + UNIT_ASSERT_C(pid >= 0, sys_error()); + if (pid > 0) { + // parent + UNIT_ASSERT_VALUES_EQUAL_C(0, ::close(write_fd), sys_error()); + reader(read_fd); + UNIT_ASSERT_VALUES_EQUAL_C(0, ::close(read_fd), sys_error()); + } else { + // child + UNIT_ASSERT_VALUES_EQUAL_C(0, ::close(read_fd), sys_error()); + UNIT_ASSERT_NO_EXCEPTION(writer(write_fd)); + UNIT_ASSERT_VALUES_EQUAL_C(0, ::close(write_fd), sys_error()); + ::exit(0); + } + int stat_loc; + UNIT_ASSERT_VALUES_EQUAL_C(pid, ::waitpid(pid, &stat_loc, 0), sys_error()); + } + + template <typename Function> + void test_posix_fd( + Function make_writer, + size_t nrepeat, + size_t read_buffer_size, + size_t write_buffer_size) { + pipe( + [&](int fd) { + auto reader = make_reader(NYsonPull::NInput::FromPosixFd(fd, read_buffer_size)); + verify(reader, nrepeat); + }, + [&](int fd) { + auto writer = make_writer(NYsonPull::NOutput::FromPosixFd(fd, write_buffer_size)); + generate(writer, nrepeat); + }); + } + + template <typename Function> + void test_stdio_file( + Function make_writer, + size_t nrepeat, + size_t read_buffer_size, + size_t write_buffer_size) { + pipe( + [&](int fd) { + auto file = ::fdopen(fd, "rb"); + UNIT_ASSERT_C(file != nullptr, sys_error()); + auto reader = make_reader(NYsonPull::NInput::FromStdioFile(file, read_buffer_size)); + verify(reader, nrepeat); + }, + [&](int fd) { + auto file = ::fdopen(fd, "wb"); + Y_UNUSED(write_buffer_size); + auto writer = make_writer(NYsonPull::NOutput::FromStdioFile(file, write_buffer_size)); + generate(writer, nrepeat); + fflush(file); + }); + } +#endif + + NYsonPull::TWriter text(THolder<NYsonPull::NOutput::IStream> stream) { + return NYsonPull::MakeTextWriter( + std::move(stream), + NYsonPull::EStreamType::ListFragment); + } + + NYsonPull::TWriter pretty_text(THolder<NYsonPull::NOutput::IStream> stream) { + return NYsonPull::MakePrettyTextWriter( + std::move(stream), + NYsonPull::EStreamType::ListFragment); + } + + NYsonPull::TWriter binary(THolder<NYsonPull::NOutput::IStream> stream) { + return NYsonPull::MakeBinaryWriter( + std::move(stream), + NYsonPull::EStreamType::ListFragment); + } + +} // anonymous namespace + +Y_UNIT_TEST_SUITE(Loop) { + Y_UNIT_TEST(memory_pretty_text) { + test_memory(pretty_text, 100); + } + + Y_UNIT_TEST(memory_text) { + test_memory(text, 100); + } + + Y_UNIT_TEST(memory_binary) { + test_memory(binary, 100); + } + +#ifdef _unix_ + Y_UNIT_TEST(posix_fd_pretty_text_buffered) { + test_posix_fd(pretty_text, 100, 1024, 1024); + } + + Y_UNIT_TEST(posix_fd_pretty_text_unbuffered) { + test_posix_fd(pretty_text, 100, 1, 0); + } + + Y_UNIT_TEST(posix_fd_text_buffered) { + test_posix_fd(text, 100, 1024, 1024); + } + + Y_UNIT_TEST(posix_fd_text_unbuffered) { + test_posix_fd(text, 100, 1, 0); + } + + Y_UNIT_TEST(posix_fd_binary_buffered) { + test_posix_fd(binary, 100, 1024, 1024); + } + + Y_UNIT_TEST(posix_fd_binary_unbuffered) { + test_posix_fd(binary, 100, 1, 0); + } + + Y_UNIT_TEST(stdio_file_pretty_text_buffered) { + test_stdio_file(pretty_text, 100, 1024, 1024); + } + + Y_UNIT_TEST(stdio_file_pretty_text_unbuffered) { + test_stdio_file(pretty_text, 100, 1, 0); + } + + Y_UNIT_TEST(stdio_file_text_buffered) { + test_stdio_file(text, 100, 1024, 1024); + } + + Y_UNIT_TEST(stdio_file_text_unbuffered) { + test_stdio_file(text, 100, 1, 0); + } + + Y_UNIT_TEST(stdio_file_binary_buffered) { + test_stdio_file(binary, 100, 1024, 1024); + } + + Y_UNIT_TEST(stdio_file_binary_unbuffered) { + test_stdio_file(binary, 100, 1, 0); + } +#endif +} // Y_UNIT_TEST_SUITE(Loop) diff --git a/library/cpp/yson_pull/ut/reader_ut.cpp b/library/cpp/yson_pull/ut/reader_ut.cpp new file mode 100644 index 0000000000..1184265ddb --- /dev/null +++ b/library/cpp/yson_pull/ut/reader_ut.cpp @@ -0,0 +1,410 @@ +#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) diff --git a/library/cpp/yson_pull/ut/writer_ut.cpp b/library/cpp/yson_pull/ut/writer_ut.cpp new file mode 100644 index 0000000000..5c304bad0f --- /dev/null +++ b/library/cpp/yson_pull/ut/writer_ut.cpp @@ -0,0 +1,256 @@ +#include <library/cpp/yson_pull/scalar.h> +#include <library/cpp/yson_pull/detail/writer.h> + +#include <library/cpp/testing/unittest/registar.h> + +#include <util/generic/string.h> + +#include <climits> +#include <limits> + +using namespace std::string_view_literals; + +namespace { + template <typename Writer, typename Function> + TString with_writer(Function&& function) { + TString result; + auto writer = NYsonPull::NDetail::make_writer<Writer>( + NYsonPull::NOutput::FromString(&result), + NYsonPull::EStreamType::Node); + + function(writer); + + return result; + } + + template <typename Writer> + TString to_yson_string(const NYsonPull::TScalar& value) { + return with_writer<Writer>([&](NYsonPull::TWriter& writer) { + writer.BeginStream().Scalar(value).EndStream(); + }); + } + + template <typename T> + TString to_yson_binary_string(T&& value) { + return to_yson_string<NYsonPull::NDetail::TBinaryWriterImpl>(std::forward<T>(value)); + } + + template <typename T> + TString to_yson_text_string(T&& value) { + return to_yson_string<NYsonPull::NDetail::TTextWriterImpl>(std::forward<T>(value)); + } + +} // anonymous namespace + +// =================== Text format ===================== + +Y_UNIT_TEST_SUITE(Writer) { + Y_UNIT_TEST(TextEntity) { + UNIT_ASSERT_VALUES_EQUAL( + "#", + to_yson_text_string(NYsonPull::TScalar{})); + } + + Y_UNIT_TEST(TextBoolean) { + UNIT_ASSERT_VALUES_EQUAL( + "%false", + to_yson_text_string(NYsonPull::TScalar{false})); + UNIT_ASSERT_VALUES_EQUAL( + "%true", + to_yson_text_string(NYsonPull::TScalar{true})); + } + + Y_UNIT_TEST(TextInt64) { + UNIT_ASSERT_VALUES_EQUAL( + "0", + to_yson_text_string(NYsonPull::TScalar{i64{0}})); + UNIT_ASSERT_VALUES_EQUAL( + "200", + to_yson_text_string(NYsonPull::TScalar{i64{200}})); + UNIT_ASSERT_VALUES_EQUAL( + "20000", + to_yson_text_string(NYsonPull::TScalar{i64{20000}})); + UNIT_ASSERT_VALUES_EQUAL( + "200000000", + to_yson_text_string(NYsonPull::TScalar{i64{200000000}})); + UNIT_ASSERT_VALUES_EQUAL( + "20000000000000000", + to_yson_text_string(NYsonPull::TScalar{i64{20000000000000000}})); + UNIT_ASSERT_VALUES_EQUAL( + "9223372036854775807", + to_yson_text_string(NYsonPull::TScalar{i64{INT64_MAX}})); + + UNIT_ASSERT_VALUES_EQUAL( + "-200", + to_yson_text_string(NYsonPull::TScalar{i64{-200}})); + UNIT_ASSERT_VALUES_EQUAL( + "-20000", + to_yson_text_string(NYsonPull::TScalar{i64{-20000}})); + UNIT_ASSERT_VALUES_EQUAL( + "-200000000", + to_yson_text_string(NYsonPull::TScalar{i64{-200000000}})); + UNIT_ASSERT_VALUES_EQUAL( + "-20000000000000000", + to_yson_text_string(NYsonPull::TScalar{i64{-20000000000000000}})); + UNIT_ASSERT_VALUES_EQUAL( + "-9223372036854775808", + to_yson_text_string(NYsonPull::TScalar{i64{INT64_MIN}})); + } + + Y_UNIT_TEST(TextUInt64) { + UNIT_ASSERT_VALUES_EQUAL( + "0u", + to_yson_text_string(NYsonPull::TScalar{ui64{0}})); + UNIT_ASSERT_VALUES_EQUAL( + "200u", + to_yson_text_string(NYsonPull::TScalar{ui64{200}})); + UNIT_ASSERT_VALUES_EQUAL( + "20000u", + to_yson_text_string(NYsonPull::TScalar{ui64{20000}})); + UNIT_ASSERT_VALUES_EQUAL( + "200000000u", + to_yson_text_string(NYsonPull::TScalar{ui64{200000000}})); + UNIT_ASSERT_VALUES_EQUAL( + "20000000000000000u", + to_yson_text_string(NYsonPull::TScalar{ui64{20000000000000000}})); + UNIT_ASSERT_VALUES_EQUAL( + "9223372036854775807u", + to_yson_text_string(NYsonPull::TScalar{ui64{INT64_MAX}})); + UNIT_ASSERT_VALUES_EQUAL( + "18446744073709551615u", + to_yson_text_string(NYsonPull::TScalar{ui64{UINT64_MAX}})); + } + + Y_UNIT_TEST(TextFloat64) { + UNIT_ASSERT_VALUES_EQUAL( + "%inf", + to_yson_text_string(NYsonPull::TScalar{std::numeric_limits<double>::infinity()})); + UNIT_ASSERT_VALUES_EQUAL( + "%-inf", + to_yson_text_string(NYsonPull::TScalar{-std::numeric_limits<double>::infinity()})); + UNIT_ASSERT_VALUES_EQUAL( + "%nan", + to_yson_text_string(NYsonPull::TScalar{std::numeric_limits<double>::quiet_NaN()})); + } + + Y_UNIT_TEST(TextString) { + UNIT_ASSERT_VALUES_EQUAL( + R"("")", + to_yson_text_string(NYsonPull::TScalar{""})); + UNIT_ASSERT_VALUES_EQUAL( + R"("hello")", + to_yson_text_string(NYsonPull::TScalar{"hello"})); + UNIT_ASSERT_VALUES_EQUAL( + R"("hello\nworld")", + to_yson_text_string(NYsonPull::TScalar{"hello\nworld"})); + } + + // =================== Binary format ===================== + + Y_UNIT_TEST(BinaryEntity) { + UNIT_ASSERT_VALUES_EQUAL( + "#", + to_yson_binary_string(NYsonPull::TScalar{})); + } + + Y_UNIT_TEST(BinaryBoolean) { + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x4"), + to_yson_binary_string(NYsonPull::TScalar{false})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x5"), + to_yson_binary_string(NYsonPull::TScalar{true})); + } + + Y_UNIT_TEST(BinaryInt64) { + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x2\0"sv), + to_yson_binary_string(NYsonPull::TScalar{i64{0}})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x2\x90\x3"), + to_yson_binary_string(NYsonPull::TScalar{i64{200}})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x2\xC0\xB8\x2"), + to_yson_binary_string(NYsonPull::TScalar{i64{20000}})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x2\x80\x88\xDE\xBE\x1"), + to_yson_binary_string(NYsonPull::TScalar{i64{200000000}})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x2\x80\x80\x90\xF8\x9B\xF9\x86G"), + to_yson_binary_string(NYsonPull::TScalar{i64{20000000000000000}})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x2\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x1"), + to_yson_binary_string(NYsonPull::TScalar{i64{INT64_MAX}})); + + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x2\x8F\x3"), + to_yson_binary_string(NYsonPull::TScalar{i64{-200}})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x2\xBF\xB8\x2"), + to_yson_binary_string(NYsonPull::TScalar{i64{-20000}})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x2\xFF\x87\xDE\xBE\x1"), + to_yson_binary_string(NYsonPull::TScalar{i64{-200000000}})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x2\xFF\xFF\x8F\xF8\x9B\xF9\x86G"), + to_yson_binary_string(NYsonPull::TScalar{i64{-20000000000000000}})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x2\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x1"), + to_yson_binary_string(NYsonPull::TScalar{i64{INT64_MIN}})); + } + + Y_UNIT_TEST(BinaryUInt64) { + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x6\0"sv), + to_yson_binary_string(NYsonPull::TScalar{ui64{0}})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x6\xC8\x1"), + to_yson_binary_string(NYsonPull::TScalar{ui64{200}})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x6\xA0\x9C\x1"), + to_yson_binary_string(NYsonPull::TScalar{ui64{20000}})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x6\x80\x84\xAF_"), + to_yson_binary_string(NYsonPull::TScalar{ui64{200000000}})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x6\x80\x80\x88\xFC\xCD\xBC\xC3#"), + to_yson_binary_string(NYsonPull::TScalar{ui64{20000000000000000}})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x6\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F"), + to_yson_binary_string(NYsonPull::TScalar{ui64{INT64_MAX}})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x6\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x1"), + to_yson_binary_string(NYsonPull::TScalar{ui64{UINT64_MAX}})); + } + + Y_UNIT_TEST(BinaryFloat64) { + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x03\x00\x00\x00\x00\x00\x00\xf0\x7f"sv), + to_yson_binary_string(NYsonPull::TScalar{std::numeric_limits<double>::infinity()})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x03\x00\x00\x00\x00\x00\x00\xf0\xff"sv), + to_yson_binary_string(NYsonPull::TScalar{-std::numeric_limits<double>::infinity()})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x03\x00\x00\x00\x00\x00\x00\xf8\x7f"sv), + to_yson_binary_string(NYsonPull::TScalar{std::numeric_limits<double>::quiet_NaN()})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x03\x9a\x99\x99\x99\x99\x99\xf1\x3f"), + to_yson_binary_string(NYsonPull::TScalar{double{1.1}})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x03\x9a\x99\x99\x99\x99\x99\xf1\xbf"), + to_yson_binary_string(NYsonPull::TScalar{double{-1.1}})); + } + + Y_UNIT_TEST(BinaryString) { + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x1\0"sv), + to_yson_binary_string(NYsonPull::TScalar{""})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x1\nhello"), + to_yson_binary_string(NYsonPull::TScalar{"hello"})); + UNIT_ASSERT_VALUES_EQUAL( + TStringBuf("\x1\x16hello\nworld"), + to_yson_binary_string(NYsonPull::TScalar{"hello\nworld"})); + } + +} // Y_UNIT_TEST_SUITE(Writer) diff --git a/library/cpp/yson_pull/ut/ya.make b/library/cpp/yson_pull/ut/ya.make new file mode 100644 index 0000000000..a269dfd2ad --- /dev/null +++ b/library/cpp/yson_pull/ut/ya.make @@ -0,0 +1,12 @@ +UNITTEST_FOR(library/cpp/yson_pull) + +OWNER(borman) + +SRCS( + cescape_ut.cpp + reader_ut.cpp + writer_ut.cpp + loop_ut.cpp +) + +END() |