summaryrefslogtreecommitdiff
path: root/protocols/Telegram/tdlib/td/tdutils/test/json.cpp
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2024-09-29 19:03:55 +0300
committerGeorge Hazan <george.hazan@gmail.com>2024-09-29 19:04:03 +0300
commitcebfc5c8facbf6ae335499f7f4b3dc57a60af999 (patch)
tree4c39e613c87f6164df1fe80601e611987aaaec84 /protocols/Telegram/tdlib/td/tdutils/test/json.cpp
parent189164bebda4bca9bb3d672500d844bfe7f26517 (diff)
TDLIB update up to the current state
Diffstat (limited to 'protocols/Telegram/tdlib/td/tdutils/test/json.cpp')
-rw-r--r--protocols/Telegram/tdlib/td/tdutils/test/json.cpp211
1 files changed, 210 insertions, 1 deletions
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<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\"");
+}