From cebfc5c8facbf6ae335499f7f4b3dc57a60af999 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 29 Sep 2024 19:03:55 +0300 Subject: TDLIB update up to the current state --- protocols/Telegram/tdlib/td/tdutils/test/json.cpp | 211 +++++++++++++++++++++- 1 file changed, 210 insertions(+), 1 deletion(-) (limited to 'protocols/Telegram/tdlib/td/tdutils/test/json.cpp') diff --git a/protocols/Telegram/tdlib/td/tdutils/test/json.cpp b/protocols/Telegram/tdlib/td/tdutils/test/json.cpp index 8b42751a3d..928dea80eb 100644 --- a/protocols/Telegram/tdlib/td/tdutils/test/json.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/test/json.cpp @@ -1,12 +1,14 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) // +#include "td/utils/benchmark.h" #include "td/utils/common.h" #include "td/utils/JsonBuilder.h" #include "td/utils/logging.h" +#include "td/utils/Parser.h" #include "td/utils/Slice.h" #include "td/utils/StringBuilder.h" #include "td/utils/tests.h" @@ -89,3 +91,210 @@ TEST(JSON, kphp) { "{\"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(object.extract_field("null")), "null"); + ASSERT_EQ(td::json_encode(object.extract_field("bool")), "true"); + ASSERT_EQ(td::json_encode(object.extract_field("bool")), "null"); + ASSERT_EQ(td::json_encode(object.extract_field("int")), "\"1\""); + ASSERT_EQ(td::json_encode(object.extract_field("int2")), "2"); + ASSERT_EQ(td::json_encode(object.extract_field("int3")), "null"); + ASSERT_EQ(td::json_encode(object.extract_field("long")), "\"123456789012\""); + ASSERT_EQ(td::json_encode(object.extract_field("long2")), "2123456789012"); + ASSERT_EQ(td::json_encode(object.extract_field("double")), "12345678901.1"); + ASSERT_EQ(td::json_encode(object.extract_field("string")), "\"string\""); + ASSERT_EQ(td::json_encode(object.extract_field("string2")), "12345e+1"); + ASSERT_EQ(td::json_encode(object.extract_field("array")), "[]"); + ASSERT_EQ(td::json_encode(object.extract_field("object")), "{}"); + ASSERT_EQ(td::json_encode(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(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\""); +} -- cgit v1.2.3