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/json/writer/json_value_ut.cpp | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/json/writer/json_value_ut.cpp')
-rw-r--r-- | library/cpp/json/writer/json_value_ut.cpp | 650 |
1 files changed, 650 insertions, 0 deletions
diff --git a/library/cpp/json/writer/json_value_ut.cpp b/library/cpp/json/writer/json_value_ut.cpp new file mode 100644 index 0000000000..dc7f6affdf --- /dev/null +++ b/library/cpp/json/writer/json_value_ut.cpp @@ -0,0 +1,650 @@ +#include "json_value.h" + +#include <library/cpp/testing/unittest/registar.h> + +#include <util/stream/input.h> + +using namespace NJson; + +Y_UNIT_TEST_SUITE(TJsonValueTest) { + Y_UNIT_TEST(UndefTest) { + TJsonValue undef; + TJsonValue null(JSON_NULL); + TJsonValue _false(false); + TJsonValue zeroInt(0); + TJsonValue zeroDouble(0.0); + TJsonValue emptyStr(""); + TJsonValue emptyArray(JSON_ARRAY); + TJsonValue emptyMap(JSON_MAP); + + UNIT_ASSERT(!undef.IsDefined()); + UNIT_ASSERT(!null.IsDefined()); // json NULL is undefined too! + UNIT_ASSERT(_false.IsDefined()); + UNIT_ASSERT(zeroInt.IsDefined()); + UNIT_ASSERT(zeroDouble.IsDefined()); + UNIT_ASSERT(emptyStr.IsDefined()); + UNIT_ASSERT(emptyArray.IsDefined()); + UNIT_ASSERT(emptyMap.IsDefined()); + + UNIT_ASSERT(undef == TJsonValue()); + UNIT_ASSERT(undef != null); + UNIT_ASSERT(undef != _false); + UNIT_ASSERT(undef != zeroInt); + UNIT_ASSERT(undef != zeroDouble); + UNIT_ASSERT(undef != emptyStr); + UNIT_ASSERT(undef != emptyArray); + UNIT_ASSERT(undef != emptyMap); + } + + Y_UNIT_TEST(DefaultCompareTest) { + { + TJsonValue lhs; + TJsonValue rhs; + UNIT_ASSERT(lhs == rhs); + UNIT_ASSERT(rhs == lhs); + } + + { + TJsonValue lhs; + TJsonValue rhs(JSON_NULL); + UNIT_ASSERT(lhs != rhs); + UNIT_ASSERT(rhs != lhs); + } + } + + Y_UNIT_TEST(NullCompareTest) { + TJsonValue lhs(JSON_NULL); + TJsonValue rhs(JSON_NULL); + UNIT_ASSERT(lhs == rhs); + UNIT_ASSERT(rhs == lhs); + } + + Y_UNIT_TEST(StringCompareTest) { + { + TJsonValue lhs(JSON_STRING); + TJsonValue rhs(JSON_STRING); + UNIT_ASSERT(lhs == rhs); + UNIT_ASSERT(rhs == lhs); + } + + { + TJsonValue lhs(""); + TJsonValue rhs(""); + UNIT_ASSERT(lhs == rhs); + UNIT_ASSERT(rhs == lhs); + } + + { + TJsonValue lhs("abc"); + TJsonValue rhs("abc"); + UNIT_ASSERT(lhs == rhs); + UNIT_ASSERT(rhs == lhs); + } + + { + TJsonValue lhs("1"); + TJsonValue rhs(1); + UNIT_ASSERT(lhs != rhs); + UNIT_ASSERT(rhs != lhs); + } + } + + Y_UNIT_TEST(ArrayCompareTest) { + { + TJsonValue lhs(JSON_ARRAY); + TJsonValue rhs(JSON_ARRAY); + UNIT_ASSERT(lhs == rhs); + UNIT_ASSERT(rhs == lhs); + } + + { + TJsonValue lhs; + TJsonValue rhs; + + lhs.AppendValue(TJsonValue()); + + UNIT_ASSERT(lhs != rhs); + UNIT_ASSERT(rhs != lhs); + } + + { + TJsonValue lhs; + TJsonValue rhs; + + lhs.AppendValue(1); + lhs.AppendValue("2"); + lhs.AppendValue(3.0); + lhs.AppendValue(TJsonValue()); + lhs.AppendValue(TJsonValue(JSON_NULL)); + + rhs.AppendValue(1); + rhs.AppendValue("2"); + rhs.AppendValue(3.0); + rhs.AppendValue(TJsonValue()); + rhs.AppendValue(TJsonValue(JSON_NULL)); + + UNIT_ASSERT(lhs == rhs); + UNIT_ASSERT(rhs == lhs); + } + + { + TJsonValue lhs; + TJsonValue rhs; + + lhs.AppendValue(1); + rhs.AppendValue("1"); + + UNIT_ASSERT(lhs != rhs); + UNIT_ASSERT(rhs != lhs); + } + } + + Y_UNIT_TEST(CompareTest) { + { + TJsonValue lhs; + lhs.InsertValue("null value", TJsonValue(JSON_NULL)); + lhs.InsertValue("int key", TJsonValue(10)); + lhs.InsertValue("double key", TJsonValue(11.11)); + lhs.InsertValue("string key", TJsonValue("string")); + + TJsonValue array; + array.AppendValue(1); + array.AppendValue(2); + array.AppendValue(3); + array.AppendValue("string"); + lhs.InsertValue("array", array); + + lhs.InsertValue("bool key", TJsonValue(true)); + + TJsonValue rhs; + rhs = lhs; + + UNIT_ASSERT(lhs == rhs); + UNIT_ASSERT(rhs == lhs); + } + + { + // Insert keys in different orders + const int NUM_KEYS = 1000; + + TJsonValue lhs; + for (int i = 0; i < NUM_KEYS; ++i) + lhs.InsertValue(ToString(i), i); + + TJsonValue rhs; + for (int i = 0; i < NUM_KEYS; i += 2) + rhs.InsertValue(ToString(i), i); + for (int i = 1; i < NUM_KEYS; i += 2) + rhs.InsertValue(ToString(i), i); + + UNIT_ASSERT(lhs == rhs); + UNIT_ASSERT(rhs == lhs); + } + + { + TJsonValue lhs; + lhs.InsertValue("null value", TJsonValue(JSON_NULL)); + lhs.InsertValue("int key", TJsonValue(10)); + lhs.InsertValue("double key", TJsonValue(11.11)); + lhs.InsertValue("string key", TJsonValue("string")); + + TJsonValue array; + array.AppendValue(1); + array.AppendValue(2); + array.AppendValue(3); + array.AppendValue("string"); + lhs.InsertValue("array", array); + + lhs.InsertValue("bool key", TJsonValue(true)); + + TJsonValue rhs; + rhs.InsertValue("null value", TJsonValue(JSON_NULL)); + rhs.InsertValue("int key", TJsonValue(10)); + rhs.InsertValue("double key", TJsonValue(11.11)); + rhs.InsertValue("string key", TJsonValue("string")); + rhs.InsertValue("bool key", TJsonValue(true)); + + UNIT_ASSERT(lhs != rhs); + UNIT_ASSERT(rhs != lhs); + } + } + + Y_UNIT_TEST(SwapTest) { + { + TJsonValue lhs; + lhs.InsertValue("a", "b"); + TJsonValue lhsCopy = lhs; + + TJsonValue rhs(JSON_NULL); + TJsonValue rhsCopy = rhs; + + UNIT_ASSERT(lhs == lhsCopy); + UNIT_ASSERT(rhs == rhsCopy); + + lhs.Swap(rhs); + + UNIT_ASSERT(rhs == lhsCopy); + UNIT_ASSERT(lhs == rhsCopy); + + lhs.Swap(rhs); + + UNIT_ASSERT(lhs == lhsCopy); + UNIT_ASSERT(rhs == rhsCopy); + } + } + + Y_UNIT_TEST(GetValueByPathTest) { + { + TJsonValue lhs; + TJsonValue first; + TJsonValue second; + TJsonValue last; + first.InsertValue("e", "f"); + second.InsertValue("c", first); + last.InsertValue("a", second); + lhs.InsertValue("l", last); + + TJsonValue result; + UNIT_ASSERT(lhs.GetValueByPath("l/a/c/e", result, '/')); + UNIT_ASSERT(result.GetStringRobust() == "f"); + UNIT_ASSERT(!lhs.GetValueByPath("l/a/c/se", result, '/')); + UNIT_ASSERT(lhs.GetValueByPath("l/a/c", result, '/')); + UNIT_ASSERT(result.GetStringRobust() == "{\"e\":\"f\"}"); + + // faster TStringBuf version + UNIT_ASSERT_EQUAL(*lhs.GetValueByPath("l", '/'), last); + UNIT_ASSERT_EQUAL(*lhs.GetValueByPath("l/a", '/'), second); + UNIT_ASSERT_EQUAL(*lhs.GetValueByPath("l/a/c", '/'), first); + UNIT_ASSERT_EQUAL(*lhs.GetValueByPath("l.a.c.e", '.'), "f"); + UNIT_ASSERT_EQUAL(lhs.GetValueByPath("l/a/c/e/x", '/'), NULL); + UNIT_ASSERT_EQUAL(lhs.GetValueByPath("a/c/e/x", '/'), NULL); + UNIT_ASSERT_EQUAL(lhs.GetValueByPath("nokey", '/'), NULL); + UNIT_ASSERT_EQUAL(*lhs.GetValueByPath("", '/'), lhs); // itself + + TJsonValue array; + TJsonValue third; + array[0] = first; + array[1] = second; + third["t"] = array; + + UNIT_ASSERT(array.GetValueByPath("[0].e", result)); + UNIT_ASSERT(result.GetStringRobust() == "f"); + UNIT_ASSERT(third.GetValueByPath("t.[0].e", result)); + UNIT_ASSERT(result.GetStringRobust() == "f"); + UNIT_ASSERT(third.GetValueByPath("t.[1].c.e", result)); + UNIT_ASSERT(result.GetStringRobust() == "f"); + UNIT_ASSERT(!third.GetValueByPath("t.[2]", result)); + + UNIT_ASSERT(third.SetValueByPath("t.[2]", "g")); + UNIT_ASSERT(third.GetValueByPath("t.[2]", result)); + UNIT_ASSERT(result.GetStringRobust() == "g"); + + UNIT_ASSERT(lhs.SetValueByPath("l/a/c/se", "h", '/')); + UNIT_ASSERT(lhs.GetValueByPath("l/a/c/se", result, '/')); + UNIT_ASSERT(result.GetStringRobust() == "h"); + } + } + + Y_UNIT_TEST(GetValueByPathConstTest) { + TJsonValue lhs; + TJsonValue first; + TJsonValue second; + TJsonValue last; + first.InsertValue("e", "f"); + second.InsertValue("c", first); + last.InsertValue("a", second); + lhs.InsertValue("l", last); + + { + const TJsonValue* result = lhs.GetValueByPath("l", '/'); + UNIT_ASSERT_EQUAL(*result, last); + } + { + const TJsonValue* result = lhs.GetValueByPath("l/a", '/'); + UNIT_ASSERT_EQUAL(*result, second); + } + { + const TJsonValue* result = lhs.GetValueByPath("l/a/c", '/'); + UNIT_ASSERT_EQUAL(*result, first); + } + { + const TJsonValue* result = lhs.GetValueByPath("l.a.c.e", '.'); + UNIT_ASSERT_EQUAL(*result, "f"); + } + { + const TJsonValue* result = lhs.GetValueByPath("l/a/c/e/x", '/'); + UNIT_ASSERT_EQUAL(result, nullptr); + } + { + const TJsonValue* result = lhs.GetValueByPath("a/c/e/x", '/'); + UNIT_ASSERT_EQUAL(result, nullptr); + } + { + const TJsonValue* result = lhs.GetValueByPath("nokey", '/'); + UNIT_ASSERT_EQUAL(result, nullptr); + } + { + const TJsonValue* result = lhs.GetValueByPath("", '/'); + UNIT_ASSERT_EQUAL(*result, lhs); // itself + } + + TJsonValue array; + TJsonValue third; + array[0] = first; + array[1] = second; + third["t"] = array; + + UNIT_ASSERT(array.GetValueByPath("[0].e", '.')->GetStringRobust() == "f"); + UNIT_ASSERT(third.GetValueByPath("t.[0].e", '.')->GetStringRobust() == "f"); + UNIT_ASSERT(third.GetValueByPath("t.[1].c.e", '.')->GetStringRobust() == "f"); + } + + Y_UNIT_TEST(EraseValueFromArray) { + { + TJsonValue vec; + vec.AppendValue(TJsonValue(0)); + vec.AppendValue(TJsonValue(1)); + vec.AppendValue(TJsonValue("2")); + vec.AppendValue(TJsonValue("3.14")); + + TJsonValue vec1; + vec1.AppendValue(TJsonValue(0)); + vec1.AppendValue(TJsonValue("2")); + vec1.AppendValue(TJsonValue("3.14")); + + TJsonValue vec2; + vec2.AppendValue(TJsonValue(0)); + vec2.AppendValue(TJsonValue("2")); + + TJsonValue vec3; + vec3.AppendValue(TJsonValue("2")); + + TJsonValue vec4(JSON_ARRAY); + + UNIT_ASSERT(vec.IsArray()); + UNIT_ASSERT(vec.GetArray().size() == 4); + vec.EraseValue(1); + UNIT_ASSERT(vec.GetArray().size() == 3); + UNIT_ASSERT(vec == vec1); + vec.EraseValue(2); + UNIT_ASSERT(vec.GetArray().size() == 2); + UNIT_ASSERT(vec == vec2); + vec.EraseValue(0); + UNIT_ASSERT(vec.GetArray().size() == 1); + UNIT_ASSERT(vec == vec3); + vec.EraseValue(0); + UNIT_ASSERT(vec.GetArray().size() == 0); + UNIT_ASSERT(vec == vec4); + } + } + + Y_UNIT_TEST(NonConstMethodsTest) { + { + TJsonValue src; + TJsonValue value1; + value1.AppendValue(1); + value1.AppendValue(2); + src.InsertValue("key", value1); + src.InsertValue("key1", "HI!"); + + TJsonValue dst; + TJsonValue value2; + value2.AppendValue(1); + value2.AppendValue(2); + value2.AppendValue(3); + dst.InsertValue("key", value2); + + src.GetValueByPath("key", '.')->AppendValue(3); + src.EraseValue("key1"); + UNIT_ASSERT(src == dst); + + dst.GetValueByPath("key", '.')->EraseValue(0); + UNIT_ASSERT(src != dst); + src.GetValueByPath("key", '.')->EraseValue(0); + UNIT_ASSERT(src == dst); + } + + { + TJsonValue src; + TJsonValue value1; + TJsonValue arr1; + value1.InsertValue("key", "value"); + arr1.AppendValue(value1); + arr1.AppendValue(value1); + arr1.AppendValue(value1); + src.InsertValue("arr", arr1); + + TJsonValue dst; + TJsonValue value2; + TJsonValue arr2; + value2.InsertValue("key", "value"); + value2.InsertValue("yek", "eulav"); + arr2.AppendValue(value2); + arr2.AppendValue(value2); + arr2.AppendValue(value2); + arr2.AppendValue(value2); + dst.InsertValue("arr", arr2); + + src["arr"].AppendValue(value1); + for (auto& node : src["arr"].GetArraySafe()) { + node.InsertValue("yek", "eulav"); + } + UNIT_ASSERT(src == dst); + } + + { + TJsonValue src; + TJsonValue value1; + TJsonValue arr1; + value1.InsertValue("key", "value"); + arr1.AppendValue(value1); + arr1.AppendValue(value1); + arr1.AppendValue(value1); + src.InsertValue("arr", arr1); + + TJsonValue dst; + TJsonValue value2; + TJsonValue arr2; + value2.InsertValue("key", "value"); + value2.InsertValue("yek", "eulav"); + arr2.AppendValue(value2); + arr2.AppendValue(value2); + arr2.AppendValue(value2); + arr2.AppendValue(value2); + dst.InsertValue("arr", arr2); + + src["arr"].AppendValue(value1); + for (auto& node : src.GetValueByPath("arr", '.')->GetArraySafe()) { + node.InsertValue("yek", "eulav"); + } + UNIT_ASSERT(src == dst); + } + + { + TJsonValue json; + json.InsertValue("key", "value"); + try { + json.GetArraySafe(); + UNIT_ASSERT(false); + } catch (const TJsonException&) { + } + + const TJsonValue constJson(json); + try { + constJson.GetArray(); + } catch (...) { + UNIT_ASSERT(false); + } + } + + { + // Check non-const GetArraySafe() + TJsonValue json{JSON_ARRAY}; + json.GetArraySafe().push_back(TJsonValue{"foo"}); + + TJsonValue expectedJson; + expectedJson.AppendValue(TJsonValue{"foo"}); + UNIT_ASSERT(json == expectedJson); + + TJsonValue::TArray jsonArray = std::move(json.GetArraySafe()); + TJsonValue::TArray expectedArray = {TJsonValue{"foo"}}; + UNIT_ASSERT(jsonArray == expectedArray); + } + + { + // Check non-const GetMap() + TJsonValue json{JSON_MAP}; + json.GetMapSafe()["foo"] = "bar"; + + TJsonValue expectedJson; + expectedJson.InsertValue("foo", "bar"); + UNIT_ASSERT(json == expectedJson); + + TJsonValue::TMapType jsonMap = std::move(json.GetMapSafe()); + TJsonValue::TMapType expectedMap = {{"foo", TJsonValue{"bar"}}}; + UNIT_ASSERT(jsonMap == expectedMap); + } + } + + Y_UNIT_TEST(NonexistentFieldAccessTest) { + { + TJsonValue json; + json.InsertValue("some", "key"); + + UNIT_ASSERT(!json["some"]["weird"]["access"]["sequence"].Has("value")); + UNIT_ASSERT(!json["some"]["weird"]["access"]["sequence"].IsDefined()); + + UNIT_ASSERT(json["some"].GetType() == JSON_MAP); + } + } + + Y_UNIT_TEST(DefaultValuesTest) { + { + TJsonValue json; + json.InsertValue("some", "key"); + json.InsertValue("existing", 1.2); + + UNIT_ASSERT_VALUES_EQUAL(json["existing"].GetDoubleSafe(), 1.2); + UNIT_ASSERT_VALUES_EQUAL(json["existing"].GetDoubleSafe(15), 1.2); + + UNIT_ASSERT_EXCEPTION(json["some"].GetUIntegerSafe(), yexception); + UNIT_ASSERT_EXCEPTION(json["some"].GetUIntegerSafe(12), yexception); + + UNIT_ASSERT_EXCEPTION(json["nonexistent"].GetUIntegerSafe(), yexception); + UNIT_ASSERT_VALUES_EQUAL(json["nonexistent"].GetUIntegerSafe(12), 12); + UNIT_ASSERT_VALUES_EQUAL(json["nonexistent"]["more_nonexistent"].GetUIntegerSafe(12), 12); + + json.InsertValue("map", TJsonValue(JSON_MAP)); + + UNIT_ASSERT_VALUES_EQUAL(json["map"]["nonexistent"].GetUIntegerSafe(12), 12); + } + } + + Y_UNIT_TEST(GetArrayPointerInArrayTest) { + TJsonValue outer; + { + TJsonValue json; + json.AppendValue(1); + json.AppendValue(2); + json.AppendValue(3); + + outer.AppendValue(json); + } + const TJsonValue::TArray* array = nullptr; + GetArrayPointer(outer, 0, &array); + UNIT_ASSERT_VALUES_EQUAL((*array)[1], 2); + } + + Y_UNIT_TEST(GetArrayPointerInMapTest) { + TJsonValue outer; + { + TJsonValue json; + json.AppendValue(1); + json.AppendValue(2); + json.AppendValue(3); + + outer.InsertValue("x", json); + } + const TJsonValue::TArray* array = nullptr; + GetArrayPointer(outer, "x", &array); + UNIT_ASSERT_VALUES_EQUAL((*array)[1], 2); + } + + Y_UNIT_TEST(GetMapPointerInArrayTest) { + TJsonValue outer; + { + TJsonValue json; + json.InsertValue("a", 1); + json.InsertValue("b", 2); + json.InsertValue("c", 3); + + outer.AppendValue(json); + } + const TJsonValue::TMapType* map = nullptr; + GetMapPointer(outer, 0, &map); + UNIT_ASSERT_VALUES_EQUAL((*map).at("b"), 2); + } + + Y_UNIT_TEST(GetMapPointerInMapTest) { + TJsonValue outer; + { + TJsonValue json; + json.InsertValue("a", 1); + json.InsertValue("b", 2); + json.InsertValue("c", 3); + + outer.InsertValue("x", json); + } + const TJsonValue::TMapType* map = nullptr; + GetMapPointer(outer, "x", &map); + UNIT_ASSERT_VALUES_EQUAL((*map).at("b"), 2); + } + + Y_UNIT_TEST(GetIntegerRobustBignumStringTest) { + TString value = "1626862681464633683"; + TJsonValue json(value); + UNIT_ASSERT_VALUES_EQUAL(json.GetUIntegerRobust(), FromString<ui64>(value)); + UNIT_ASSERT_VALUES_EQUAL(json.GetIntegerRobust(), FromString<i64>(value)); + } + + Y_UNIT_TEST(MoveSubpartToSelf) { + TJsonValue json; + json[0] = "testing 0"; + json[1] = "testing 1"; + json[2] = "testing 2"; + json = std::move(json[1]); + UNIT_ASSERT_VALUES_EQUAL(json.GetString(), "testing 1"); + + const char* longTestString = + "Testing TJsonValue& operator=(TJsonValue&&) subpart self moving " + "after TJsonValue was constrcuted from TString&&."; + + json["hello"] = TString{longTestString}; + json = std::move(json["hello"]); + UNIT_ASSERT_VALUES_EQUAL(json.GetString(), longTestString); + } + + Y_UNIT_TEST(TJsonArrayMapConstructor) { + TJsonMap emptyMap; + UNIT_ASSERT_VALUES_EQUAL(emptyMap.GetType(), JSON_MAP); + UNIT_ASSERT_VALUES_EQUAL(emptyMap.GetMapSafe().size(), 0); + + TJsonArray emptyArray; + UNIT_ASSERT_VALUES_EQUAL(emptyArray.GetType(), JSON_ARRAY); + UNIT_ASSERT_VALUES_EQUAL(emptyArray.GetArraySafe().size(), 0); + + TJsonMap filled = { + {"1", 1}, + {"2", "2"}, + {"3", TJsonArray{3}}, + {"4", TJsonMap{{"5", 5}}}, + }; + UNIT_ASSERT_VALUES_EQUAL(filled.GetType(), JSON_MAP); + UNIT_ASSERT_VALUES_EQUAL(filled["1"], TJsonValue{1}); + UNIT_ASSERT_VALUES_EQUAL(filled["2"], TJsonValue{"2"}); + UNIT_ASSERT_VALUES_EQUAL(filled["3"].GetArraySafe().size(), 1); + UNIT_ASSERT_VALUES_EQUAL(filled["3"][0], TJsonValue{3}); + UNIT_ASSERT_VALUES_EQUAL(filled["4"].GetMapSafe().size(), 1); + UNIT_ASSERT_VALUES_EQUAL(filled["4"]["5"], TJsonValue{5}); + } +} // TJsonValueTest |