Buckets:
localhost1978/localhost / LOCALHOST1978 /Modules /SSK_Providers /Vendor /td /tdutils /test /json.cpp
| // | |
| // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2026 | |
| // | |
| // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
| // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
| // | |
| static void decode_encode(const td::string &str, td::string result = td::string()) { | |
| auto str_copy = str; | |
| auto r_value = td::json_decode(str_copy); | |
| ASSERT_TRUE(r_value.is_ok()); | |
| if (r_value.is_error()) { | |
| LOG(INFO) << r_value.error(); | |
| return; | |
| } | |
| auto new_str = td::json_encode<td::string>(r_value.ok()); | |
| if (result.empty()) { | |
| result = str; | |
| } | |
| ASSERT_EQ(result, new_str); | |
| } | |
| TEST(JSON, array) { | |
| char tmp[1000]; | |
| td::StringBuilder sb(td::MutableSlice{tmp, sizeof(tmp)}); | |
| td::JsonBuilder jb(std::move(sb)); | |
| jb.enter_value().enter_array() << "Hello" << -123; | |
| ASSERT_EQ(jb.string_builder().is_error(), false); | |
| auto encoded = jb.string_builder().as_cslice().str(); | |
| ASSERT_EQ("[\"Hello\",-123]", encoded); | |
| decode_encode(encoded); | |
| } | |
| TEST(JSON, object) { | |
| char tmp[1000]; | |
| td::StringBuilder sb(td::MutableSlice{tmp, sizeof(tmp)}); | |
| td::JsonBuilder jb(std::move(sb)); | |
| auto c = jb.enter_object(); | |
| c("key", "value"); | |
| c("1", 2); | |
| c.leave(); | |
| ASSERT_EQ(jb.string_builder().is_error(), false); | |
| auto encoded = jb.string_builder().as_cslice().str(); | |
| ASSERT_EQ("{\"key\":\"value\",\"1\":2}", encoded); | |
| decode_encode(encoded); | |
| } | |
| TEST(JSON, nested) { | |
| char tmp[1000]; | |
| td::StringBuilder sb(td::MutableSlice{tmp, sizeof(tmp)}); | |
| td::JsonBuilder jb(std::move(sb)); | |
| { | |
| auto a = jb.enter_array(); | |
| a << 1; | |
| { a.enter_value().enter_array() << 2; } | |
| a << 3; | |
| } | |
| ASSERT_EQ(jb.string_builder().is_error(), false); | |
| auto encoded = jb.string_builder().as_cslice().str(); | |
| ASSERT_EQ("[1,[2],3]", encoded); | |
| decode_encode(encoded); | |
| } | |
| TEST(JSON, kphp) { | |
| decode_encode("[]"); | |
| decode_encode("[[]]"); | |
| decode_encode("{}"); | |
| decode_encode("{}"); | |
| decode_encode("\"\\n\""); | |
| decode_encode( | |
| "\"" | |
| "some long string \\t \\r \\\\ \\n \\f \\\" " | |
| "\\u1234" | |
| "\""); | |
| decode_encode( | |
| "{\"keyboard\":[[\"\\u2022 abcdefg\"],[\"\\u2022 hijklmnop\"],[\"\\u2022 " | |
| "qrstuvwxyz\"]],\"one_time_keyboard\":true}"); | |
| decode_encode( | |
| " \n { \"keyboard\" : \n [[ \"\\u2022 abcdefg\" ] , \n [ \"\\u2022 hijklmnop\" \n ],[ \n \"\\u2022 " | |
| "qrstuvwxyz\"]], \n \"one_time_keyboard\"\n:\ntrue\n}\n \n", | |
| "{\"keyboard\":[[\"\\u2022 abcdefg\"],[\"\\u2022 hijklmnop\"],[\"\\u2022 " | |
| "qrstuvwxyz\"]],\"one_time_keyboard\":true}"); | |
| } | |
| TEST(JSON, json_object_get_field) { | |
| const td::string encoded_object = | |
| "{\"null\":null,\"bool\":true,\"int\":\"1\",\"int2\":2,\"long\":\"123456789012\",\"long2\":2123456789012," | |
| "\"double\":12345678901.1,\"string\":\"string\",\"string2\":12345e+1,\"array\":[],\"object\":{}}"; | |
| { | |
| td::string encoded_object_copy = encoded_object; | |
| auto value = td::json_decode(encoded_object_copy).move_as_ok(); | |
| auto &object = value.get_object(); | |
| ASSERT_EQ(td::json_encode<td::string>(object.extract_field("null")), "null"); | |
| ASSERT_EQ(td::json_encode<td::string>(object.extract_field("bool")), "true"); | |
| ASSERT_EQ(td::json_encode<td::string>(object.extract_field("bool")), "null"); | |
| ASSERT_EQ(td::json_encode<td::string>(object.extract_field("int")), "\"1\""); | |
| ASSERT_EQ(td::json_encode<td::string>(object.extract_field("int2")), "2"); | |
| ASSERT_EQ(td::json_encode<td::string>(object.extract_field("int3")), "null"); | |
| ASSERT_EQ(td::json_encode<td::string>(object.extract_field("long")), "\"123456789012\""); | |
| ASSERT_EQ(td::json_encode<td::string>(object.extract_field("long2")), "2123456789012"); | |
| ASSERT_EQ(td::json_encode<td::string>(object.extract_field("double")), "12345678901.1"); | |
| ASSERT_EQ(td::json_encode<td::string>(object.extract_field("string")), "\"string\""); | |
| ASSERT_EQ(td::json_encode<td::string>(object.extract_field("string2")), "12345e+1"); | |
| ASSERT_EQ(td::json_encode<td::string>(object.extract_field("array")), "[]"); | |
| ASSERT_EQ(td::json_encode<td::string>(object.extract_field("object")), "{}"); | |
| ASSERT_EQ(td::json_encode<td::string>(object.extract_field("")), "null"); | |
| } | |
| { | |
| td::string encoded_object_copy = encoded_object; | |
| auto value = td::json_decode(encoded_object_copy).move_as_ok(); | |
| auto &object = value.get_object(); | |
| ASSERT_TRUE(object.extract_optional_field("int", td::JsonValue::Type::Number).is_error()); | |
| ASSERT_TRUE(object.extract_optional_field("int", td::JsonValue::Type::Number).is_error()); | |
| ASSERT_TRUE(object.extract_optional_field("int2", td::JsonValue::Type::Number).is_ok()); | |
| ASSERT_TRUE(object.extract_optional_field("int2", td::JsonValue::Type::Number).is_error()); | |
| ASSERT_TRUE(object.extract_optional_field("int3", td::JsonValue::Type::Number).is_ok()); | |
| ASSERT_TRUE(object.extract_optional_field("int3", td::JsonValue::Type::Null).is_ok()); | |
| ASSERT_EQ(object.extract_optional_field("int", td::JsonValue::Type::String).ok().get_string(), "1"); | |
| ASSERT_TRUE(object.extract_optional_field("int", td::JsonValue::Type::Number).is_error()); | |
| ASSERT_EQ(object.extract_optional_field("int", td::JsonValue::Type::Null).ok().type(), td::JsonValue::Type::Null); | |
| ASSERT_TRUE(object.extract_required_field("long", td::JsonValue::Type::Number).is_error()); | |
| ASSERT_TRUE(object.extract_required_field("long", td::JsonValue::Type::Number).is_error()); | |
| ASSERT_TRUE(object.extract_required_field("long2", td::JsonValue::Type::Number).is_ok()); | |
| ASSERT_TRUE(object.extract_required_field("long2", td::JsonValue::Type::Number).is_error()); | |
| ASSERT_TRUE(object.extract_required_field("long3", td::JsonValue::Type::Number).is_error()); | |
| ASSERT_TRUE(object.extract_required_field("long3", td::JsonValue::Type::Null).is_error()); | |
| ASSERT_EQ(object.extract_required_field("long", td::JsonValue::Type::String).ok().get_string(), "123456789012"); | |
| ASSERT_TRUE(object.extract_required_field("long", td::JsonValue::Type::Number).is_error()); | |
| ASSERT_EQ(object.extract_required_field("long", td::JsonValue::Type::Null).ok().type(), td::JsonValue::Type::Null); | |
| } | |
| td::string encoded_object_copy = encoded_object; | |
| auto value = td::json_decode(encoded_object_copy).move_as_ok(); | |
| const auto &object = value.get_object(); | |
| ASSERT_TRUE(object.has_field("null")); | |
| ASSERT_TRUE(object.has_field("object")); | |
| ASSERT_TRUE(!object.has_field("")); | |
| ASSERT_TRUE(!object.has_field("objec")); | |
| ASSERT_TRUE(!object.has_field("object2")); | |
| ASSERT_TRUE(object.get_optional_bool_field("int").is_error()); | |
| ASSERT_EQ(object.get_optional_bool_field("bool").ok(), true); | |
| ASSERT_EQ(object.get_optional_bool_field("bool", false).ok(), true); | |
| ASSERT_EQ(object.get_required_bool_field("bool").ok(), true); | |
| ASSERT_EQ(object.get_optional_bool_field("bool3").ok(), false); | |
| ASSERT_EQ(object.get_optional_bool_field("bool4", true).ok(), true); | |
| ASSERT_TRUE(object.get_required_bool_field("bool5").is_error()); | |
| ASSERT_TRUE(object.get_optional_int_field("null").is_error()); | |
| ASSERT_EQ(object.get_optional_int_field("int").ok(), 1); | |
| ASSERT_EQ(object.get_optional_int_field("int").ok(), 1); | |
| ASSERT_EQ(object.get_required_int_field("int").ok(), 1); | |
| ASSERT_EQ(object.get_optional_int_field("int2").ok(), 2); | |
| ASSERT_EQ(object.get_optional_int_field("int2").ok(), 2); | |
| ASSERT_EQ(object.get_required_int_field("int2").ok(), 2); | |
| ASSERT_EQ(object.get_optional_int_field("int3").ok(), 0); | |
| ASSERT_EQ(object.get_optional_int_field("int4", 5).ok(), 5); | |
| ASSERT_TRUE(object.get_required_int_field("int5").is_error()); | |
| ASSERT_EQ(object.get_optional_int_field("long").is_error(), true); | |
| ASSERT_EQ(object.get_optional_int_field("long2").is_error(), true); | |
| ASSERT_TRUE(object.get_optional_long_field("null").is_error()); | |
| ASSERT_EQ(object.get_optional_long_field("long").ok(), 123456789012); | |
| ASSERT_EQ(object.get_optional_long_field("long").ok(), 123456789012); | |
| ASSERT_EQ(object.get_required_long_field("long").ok(), 123456789012); | |
| ASSERT_EQ(object.get_optional_long_field("long2").ok(), 2123456789012); | |
| ASSERT_EQ(object.get_optional_long_field("long2").ok(), 2123456789012); | |
| ASSERT_EQ(object.get_required_long_field("long2").ok(), 2123456789012); | |
| ASSERT_EQ(object.get_optional_long_field("long3").ok(), 0); | |
| ASSERT_EQ(object.get_optional_long_field("long4", 5).ok(), 5); | |
| ASSERT_TRUE(object.get_required_long_field("long5").is_error()); | |
| ASSERT_EQ(object.get_optional_long_field("int").ok(), 1); | |
| ASSERT_EQ(object.get_optional_long_field("int2").ok(), 2); | |
| auto are_equal_double = [](double lhs, double rhs) { | |
| return rhs - 1e-3 < lhs && lhs < rhs + 1e-3; | |
| }; | |
| ASSERT_TRUE(object.get_optional_double_field("null").is_error()); | |
| ASSERT_TRUE(are_equal_double(object.get_optional_double_field("double").ok(), 12345678901.1)); | |
| ASSERT_TRUE(are_equal_double(object.get_optional_double_field("double").ok(), 12345678901.1)); | |
| ASSERT_TRUE(are_equal_double(object.get_required_double_field("double").ok(), 12345678901.1)); | |
| ASSERT_TRUE(are_equal_double(object.get_optional_double_field("long2").ok(), 2123456789012.0)); | |
| ASSERT_TRUE(are_equal_double(object.get_optional_double_field("long2").ok(), 2123456789012.0)); | |
| ASSERT_TRUE(are_equal_double(object.get_required_double_field("long2").ok(), 2123456789012.0)); | |
| ASSERT_TRUE(are_equal_double(object.get_optional_double_field("double3").ok(), 0.0)); | |
| ASSERT_TRUE(are_equal_double(object.get_optional_double_field("double4", -5.23).ok(), -5.23)); | |
| ASSERT_TRUE(object.get_required_double_field("double5").is_error()); | |
| ASSERT_TRUE(object.get_optional_double_field("int").is_error()); | |
| ASSERT_TRUE(are_equal_double(object.get_optional_double_field("int2").ok(), 2)); | |
| ASSERT_TRUE(object.get_optional_string_field("null").is_error()); | |
| ASSERT_EQ(object.get_optional_string_field("string").ok(), "string"); | |
| ASSERT_EQ(object.get_optional_string_field("string").ok(), "string"); | |
| ASSERT_EQ(object.get_required_string_field("string").ok(), "string"); | |
| ASSERT_EQ(object.get_optional_string_field("string2").ok(), "12345e+1"); | |
| ASSERT_EQ(object.get_optional_string_field("string2").ok(), "12345e+1"); | |
| ASSERT_EQ(object.get_required_string_field("string2").ok(), "12345e+1"); | |
| ASSERT_EQ(object.get_optional_string_field("string3").ok(), td::string()); | |
| ASSERT_EQ(object.get_optional_string_field("string4", "abacaba").ok(), "abacaba"); | |
| ASSERT_TRUE(object.get_required_string_field("string5").is_error()); | |
| ASSERT_EQ(object.get_optional_string_field("int").ok(), "1"); | |
| ASSERT_EQ(object.get_optional_string_field("int2").ok(), "2"); | |
| } | |
| class JsonStringDecodeBenchmark final : public td::Benchmark { | |
| td::string str_; | |
| public: | |
| explicit JsonStringDecodeBenchmark(td::string str) : str_('"' + str + '"') { | |
| } | |
| td::string get_description() const final { | |
| return td::string("JsonStringDecodeBenchmark") + str_.substr(1, 6); | |
| } | |
| void run(int n) final { | |
| for (int i = 0; i < n; i++) { | |
| auto str = str_; | |
| td::Parser parser(str); | |
| td::json_string_decode(parser).ensure(); | |
| } | |
| } | |
| }; | |
| TEST(JSON, bench_json_string_decode) { | |
| td::bench(JsonStringDecodeBenchmark(td::string(1000, 'a'))); | |
| td::bench(JsonStringDecodeBenchmark(td::string(1000, '\\'))); | |
| td::string str; | |
| for (int i = 32; i < 128; i++) { | |
| if (i == 'u') { | |
| continue; | |
| } | |
| str += "a\\"; | |
| str += static_cast<char>(i); | |
| } | |
| td::bench(JsonStringDecodeBenchmark(str)); | |
| } | |
| static void test_string_decode(td::string str, const td::string &result) { | |
| auto str_copy = str; | |
| td::Parser skip_parser(str_copy); | |
| auto status = td::json_string_skip(skip_parser); | |
| ASSERT_TRUE(status.is_ok()); | |
| ASSERT_TRUE(skip_parser.empty()); | |
| td::Parser parser(str); | |
| auto r_value = td::json_string_decode(parser); | |
| ASSERT_TRUE(r_value.is_ok()); | |
| ASSERT_TRUE(parser.empty()); | |
| ASSERT_EQ(result, r_value.ok()); | |
| } | |
| static void test_string_decode_error(td::string str) { | |
| auto str_copy = str; | |
| td::Parser skip_parser(str_copy); | |
| auto status = td::json_string_skip(skip_parser); | |
| ASSERT_TRUE(status.is_error()); | |
| td::Parser parser(str); | |
| auto r_value = td::json_string_decode(parser); | |
| ASSERT_TRUE(r_value.is_error()); | |
| } | |
| TEST(JSON, string_decode) { | |
| test_string_decode("\"\"", ""); | |
| test_string_decode("\"abacaba\"", "abacaba"); | |
| test_string_decode( | |
| "\"\\1\\a\\b\\c\\d\\e\\f\\g\\h\\i\\j\\k\\l\\m\\n\\o\\p\\q\\r\\s\\t\\u00201\\v\\w\\x\\y\\z\\U\\\"\\\\\\/\\+\\-\"", | |
| "1a\bcde\fghijklm\nopq\rs\t 1vwxyzU\"\\/+-"); | |
| test_string_decode("\"\\u0373\\ud7FB\\uD840\\uDC04\\uD840a\\uD840\\u0373\"", | |
| "\xCD\xB3\xED\x9F\xBB\xF0\xA0\x80\x84\xed\xa1\x80\x61\xed\xa1\x80\xCD\xB3"); | |
| test_string_decode_error(" \"\""); | |
| test_string_decode_error("\""); | |
| test_string_decode_error("\"\\"); | |
| test_string_decode_error("\"\\b'"); | |
| test_string_decode_error("\"\\u\""); | |
| test_string_decode_error("\"\\u123\""); | |
| test_string_decode_error("\"\\u123g\""); | |
| test_string_decode_error("\"\\u123G\""); | |
| test_string_decode_error("\"\\u123 \""); | |
| test_string_decode_error("\"\\ug123\""); | |
| test_string_decode_error("\"\\uG123\""); | |
| test_string_decode_error("\"\\u 123\""); | |
| test_string_decode_error("\"\\uD800\\ug123\""); | |
| test_string_decode_error("\"\\uD800\\u123\""); | |
| } | |
Xet Storage Details
- Size:
- 13.6 kB
- Xet hash:
- 5b6423f66af3214d7c150a86ffdcf7c76923c5341e46588f49dcde52c0933b78
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.