#include "library/cpp/json/converter/converter.h" #include #include #include "library/cpp/json/writer/json_value.h" #include #include #include #include #include #include #include namespace NJson { void AssertJsonsEqual(const TJsonValue& actualJson, const TJsonValue& expectedJson) { const auto actualString = WriteJson(actualJson, /*formatOutput*/ true, /*sortkeys*/ true, /*validateUtf8*/ true); const auto expectedString = WriteJson(expectedJson, /*formatOutput*/ true, /*sortkeys*/ true, /*validateUtf8*/ true); UNIT_ASSERT_NO_DIFF(actualString, expectedString); } void AssertJsonsEqual(const TJsonValue& actualJson, TStringBuf expectedString) { const auto expectedJson = ReadJsonFastTree(expectedString); AssertJsonsEqual(actualJson, expectedJson); } template struct TConverterTester { using TValues = THashMap; static void TestEncoding(const TValues& values) { for (const auto& [serializedValue, value] : values) { const auto encodedValue = TConverter::Encode(value); AssertJsonsEqual(encodedValue, serializedValue); } } static void TestDecoding(const TValues& values) { for (const auto& [serializedValue, value] : values) { const auto decodedValue = TConverter::Decode(ReadJsonFastTree(serializedValue)); UNIT_ASSERT_EQUAL(decodedValue, value); } } static void TestDecodingException(TStringBuf serializedValue) { try { TConverter::Decode(ReadJsonFastTree(serializedValue)); UNIT_ASSERT(false); } catch (...) { } } static void Test(const TValues& values) { TestEncoding(values); TestDecoding(values); for (const auto& [serializedValue, value] : values) { const auto encodedValue = TConverter::Encode(value); const auto decodedValue = TConverter::Decode(encodedValue); UNIT_ASSERT_EQUAL(value, decodedValue); } } }; template requires std::is_floating_point_v struct TConverterTester { using TValues = THashMap; static void TestDecoding(const TValues& values) { for (const auto& [serializedValue, value] : values) { { const auto decodedValue = TConverter::Decode(ReadJsonFastTree(serializedValue)); UNIT_ASSERT_DOUBLES_EQUAL(decodedValue, value, 0.000001); } } } static void Test(const TValues& values) { TestDecoding(values); for (const auto& [serializedValue, value] : values) { { const auto encodedValue = TConverter::Encode(value); const auto decodedValue = TConverter::Decode(encodedValue); UNIT_ASSERT_DOUBLES_EQUAL(decodedValue, value, 0.000001); } } } }; Y_UNIT_TEST_SUITE(ConversionTests) { Y_UNIT_TEST(PrimitivesTest) { TConverterTester::Test({{"true", true}, {"false", false}}); TConverterTester::Test({{"0", 0}, {"255", 255}}); TConverterTester::Test({{"-128", -128}, {"127", 127}}); TConverterTester::Test({{"0", 0}, {"65535", 65535}}); TConverterTester::Test({{"-32768", -32768}, {"32767", 32767}}); TConverterTester::Test({{"0", 0}, {"4294967295", 4294967295}}); TConverterTester::Test({{"-2147483648", -2147483648}, {"2147483647", 2147483647}}); TConverterTester::Test({{"0", 0}, {"18446744073709551615", 18446744073709551615u}}); TConverterTester::Test({ {"-9223372036854775808", -9223372036854775808u}, {"9223372036854775807", 9223372036854775807}, }); TConverterTester::TestDecodingException("128"); TConverterTester::TestDecodingException("-129"); TConverterTester::TestDecodingException("256"); TConverterTester::TestDecodingException("32768"); TConverterTester::TestDecodingException("-32769"); TConverterTester::TestDecodingException("65536"); TConverterTester::TestDecodingException("-2147483649"); TConverterTester::TestDecodingException("2147483649"); TConverterTester::TestDecodingException("4294967296"); TConverterTester::Test({{"0", 0}, {"255", 255}}); TConverterTester::Test({{"-128", -128}, {"127", 127}}); TConverterTester::Test({{"0", 0}, {"65535", 65535}}); TConverterTester::Test({{"-32768", -32768}, {"32767", 32767}}); TConverterTester::Test({{"0", 0}, {"65535", 65535}}); TConverterTester::Test({{"-32768", -32768}, {"32767", 32767}}); TConverterTester::Test({{"0", 0}, {"4294967295", 4294967295}}); TConverterTester::Test({{"-2147483648", -2147483648}, {"2147483647", 2147483647}}); TConverterTester::Test({{"0", 0}, {"18446744073709551615", 18446744073709551615u}}); TConverterTester::Test({ {"-9223372036854775808", -9223372036854775808u}, {"9223372036854775807", 9223372036854775807}, }); TConverterTester::Test({{"0", 0}, {"65535", 65535}}); TConverterTester::Test({{"-1.12312", -1.12312}, {"3434.25674", 3434.25674}}); TConverterTester::Test({{"-1.12312E+42", -1.12312E+42}, {"3.25E+120", 3.25E+120}}); } Y_UNIT_TEST(StringsTest) { TConverterTester::TestEncoding({ {R"("Let's permit using of Rust in Arcadia")", "Let's permit using of Rust in Arcadia"}, }); TConverterTester::Test({ { R"("Всякое непрерывное отображение замкнутого n-мерного шара в себя обладает неподвижной точкой")", "Всякое непрерывное отображение замкнутого n-мерного шара в себя обладает неподвижной точкой", }, }); } Y_UNIT_TEST(MaybeTest) { TConverterTester>::Test({ {"true", TMaybe(true)}, {"null", Nothing()}, {"false", TMaybe(false)}, }); } Y_UNIT_TEST(ArraysTest) { TConverterTester>::Test({{"[true, true, false]", {true, true, false}}}); TConverterTester>::Test({{R"(["a", "b"])", {"a", "b"}}}); TConverterTester>::Test({{"[false, true, false]", {false, true, false}}}); } Y_UNIT_TEST(MapsTest) { TConverterTester>::TestEncoding({ {R"({"a": true, "b": false})", {{"a", true}, {"b", false}}}, }); TConverterTester>::Test({ {R"({"a": true, "b": false})", {{"a", true}, {"b", false}}}, }); TConverterTester>::TestEncoding({ {R"({"a": "A", "b": "B"})", {{"a", "A"}, {"b", "B"}}}, }); TConverterTester>::Test({ {R"({"a": "A", "b": "B"})", {{"a", "A"}, {"b", "B"}}}, }); } Y_UNIT_TEST(NestedTest) { TConverterTester>>>::Test({ { R"([ { "Three": [0, 1, 2], "Five": [0, 1, 2, 3, 4] }, { "Four": [0, 1, 2, 3], "Six": [0, 1, 2, 3, 4, 5] }, ])", { { {"Three", {0, 1, 2}}, {"Five", {0, 1, 2, 3, 4}}, }, { {"Four", {0, 1, 2, 3}}, {"Six", {0, 1, 2, 3, 4, 5}}, }, }, }, }); } } }