From efc336e60cf1331bf5f3213d296981b87b8b2a6c Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 4 Jun 2023 19:24:05 +0300 Subject: =?UTF-8?q?fixes=20#3537=20(Telegram:=2032-=D1=80=D0=B0=D0=B7?= =?UTF-8?q?=D1=80=D1=8F=D0=B4=D0=BD=D0=B0=D1=8F=20=D0=B2=D0=B5=D1=80=D1=81?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=BF=D0=B0=D0=B4=D0=B0=D0=B5=D1=82=20=D0=B2=20?= =?UTF-8?q?64-=D1=80=D0=B0=D0=B7=D1=80=D1=8F=D0=B4=D0=BD=D0=BE=D0=B9=20Win?= =?UTF-8?q?dows)=20+=20update=20to=20the=20fresh=20TDLIB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- protocols/Telegram/tdlib/td/test/CMakeLists.txt | 1 + protocols/Telegram/tdlib/td/test/country_info.cpp | 59 +- protocols/Telegram/tdlib/td/test/crypto.cpp | 2 +- protocols/Telegram/tdlib/td/test/data.cpp | 2 +- protocols/Telegram/tdlib/td/test/data.h | 2 +- protocols/Telegram/tdlib/td/test/db.cpp | 112 +++- protocols/Telegram/tdlib/td/test/fuzz_url.cpp | 2 +- protocols/Telegram/tdlib/td/test/http.cpp | 3 +- protocols/Telegram/tdlib/td/test/link.cpp | 681 +++++++++++++-------- protocols/Telegram/tdlib/td/test/main.cpp | 4 +- .../Telegram/tdlib/td/test/message_entities.cpp | 141 ++--- protocols/Telegram/tdlib/td/test/mtproto.cpp | 6 +- protocols/Telegram/tdlib/td/test/online.cpp | 28 +- protocols/Telegram/tdlib/td/test/poll.cpp | 2 +- protocols/Telegram/tdlib/td/test/query_merger.cpp | 102 +++ protocols/Telegram/tdlib/td/test/secret.cpp | 40 +- .../Telegram/tdlib/td/test/secure_storage.cpp | 6 +- .../Telegram/tdlib/td/test/set_with_position.cpp | 2 +- .../Telegram/tdlib/td/test/string_cleaning.cpp | 3 +- protocols/Telegram/tdlib/td/test/tdclient.cpp | 29 +- protocols/Telegram/tdlib/td/test/tqueue.cpp | 16 +- 21 files changed, 802 insertions(+), 441 deletions(-) create mode 100644 protocols/Telegram/tdlib/td/test/query_merger.cpp (limited to 'protocols/Telegram/tdlib/td/test') diff --git a/protocols/Telegram/tdlib/td/test/CMakeLists.txt b/protocols/Telegram/tdlib/td/test/CMakeLists.txt index 2ac9ad32d6..2a140a3af7 100644 --- a/protocols/Telegram/tdlib/td/test/CMakeLists.txt +++ b/protocols/Telegram/tdlib/td/test/CMakeLists.txt @@ -11,6 +11,7 @@ set(TD_TEST_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/message_entities.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mtproto.cpp ${CMAKE_CURRENT_SOURCE_DIR}/poll.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/query_merger.cpp ${CMAKE_CURRENT_SOURCE_DIR}/secret.cpp ${CMAKE_CURRENT_SOURCE_DIR}/secure_storage.cpp ${CMAKE_CURRENT_SOURCE_DIR}/set_with_position.cpp diff --git a/protocols/Telegram/tdlib/td/test/country_info.cpp b/protocols/Telegram/tdlib/td/test/country_info.cpp index bf88173915..0a9e3c26b6 100644 --- a/protocols/Telegram/tdlib/td/test/country_info.cpp +++ b/protocols/Telegram/tdlib/td/test/country_info.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 // // 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) @@ -7,11 +7,13 @@ #include "td/telegram/CountryInfoManager.h" #include "td/utils/common.h" +#include "td/utils/logging.h" #include "td/utils/tests.h" static void check_phone_number_info(td::string phone_number_prefix, const td::string &country_code, - const td::string &calling_code, const td::string &formatted_phone_number) { - auto result = td::CountryInfoManager::get_phone_number_info_sync(td::string(), std::move(phone_number_prefix)); + const td::string &calling_code, const td::string &formatted_phone_number, + bool is_anonymous = false) { + auto result = td::CountryInfoManager::get_phone_number_info_sync(td::string(), phone_number_prefix); CHECK(result != nullptr); if (result->country_ == nullptr) { CHECK(country_code.empty()); @@ -19,7 +21,11 @@ static void check_phone_number_info(td::string phone_number_prefix, const td::st CHECK(result->country_->country_code_ == country_code); } CHECK(result->country_calling_code_ == calling_code); - CHECK(result->formatted_phone_number_ == formatted_phone_number); + if (result->formatted_phone_number_ != formatted_phone_number) { + LOG(ERROR) << phone_number_prefix << ' ' << result->formatted_phone_number_ << ' ' << formatted_phone_number; + CHECK(result->formatted_phone_number_ == formatted_phone_number); + } + CHECK(result->is_anonymous_ == is_anonymous); } TEST(CountryInfo, phone_number_info) { @@ -52,7 +58,7 @@ TEST(CountryInfo, phone_number_info) { check_phone_number_info("77654321", "KZ", "7", "765 432 1- --"); check_phone_number_info("3", "", "3", ""); check_phone_number_info("37", "", "37", ""); - check_phone_number_info("372", "EE", "372", "---- ----"); + check_phone_number_info("372", "EE", "372", "---- ---"); check_phone_number_info("42", "", "42", ""); check_phone_number_info("420", "CZ", "420", "--- --- ---"); check_phone_number_info("421", "SK", "421", "--- --- ---"); @@ -61,27 +67,36 @@ TEST(CountryInfo, phone_number_info) { check_phone_number_info("424", "YL", "42", "4"); check_phone_number_info("4241234567890", "YL", "42", "41234567890"); check_phone_number_info("4", "", "4", ""); - check_phone_number_info("49", "DE", "49", "---- -------"); - check_phone_number_info("491", "DE", "49", "1--- -------"); - check_phone_number_info("492", "DE", "49", "2--- -------"); - check_phone_number_info("4915", "DE", "49", "15-- -------"); - check_phone_number_info("4916", "DE", "49", "16- -------"); - check_phone_number_info("4917", "DE", "49", "17- -------"); - check_phone_number_info("4918", "DE", "49", "18-- -------"); - check_phone_number_info("493", "DE", "49", "3--- -------"); - check_phone_number_info("4936", "DE", "49", "36-- -------"); - check_phone_number_info("49360", "DE", "49", "360- -------"); - check_phone_number_info("493601", "DE", "49", "3601 -------"); - check_phone_number_info("4936014", "DE", "49", "3601 4------"); - check_phone_number_info("4936015", "DE", "49", "3601 5------"); - check_phone_number_info("493601419", "DE", "49", "3601 419----"); - check_phone_number_info("4936014198", "DE", "49", "3601 4198--"); - check_phone_number_info("49360141980", "DE", "49", "3601 41980-"); + check_phone_number_info("49", "DE", "49", ""); + check_phone_number_info("491", "DE", "49", "1"); + check_phone_number_info("492", "DE", "49", "2"); + check_phone_number_info("4915", "DE", "49", "15"); + check_phone_number_info("4916", "DE", "49", "16"); + check_phone_number_info("4917", "DE", "49", "17"); + check_phone_number_info("4918", "DE", "49", "18"); + check_phone_number_info("493", "DE", "49", "3"); + check_phone_number_info("4936", "DE", "49", "36"); + check_phone_number_info("49360", "DE", "49", "360"); + check_phone_number_info("493601", "DE", "49", "3601"); + check_phone_number_info("4936014", "DE", "49", "36014"); + check_phone_number_info("4936015", "DE", "49", "36015"); + check_phone_number_info("493601419", "DE", "49", "3601419"); + check_phone_number_info("4936014198", "DE", "49", "36014198"); + check_phone_number_info("49360141980", "DE", "49", "360141980"); check_phone_number_info("841234567890", "VN", "84", "1234567890"); check_phone_number_info("31", "NL", "31", "- -- -- -- --"); check_phone_number_info("318", "NL", "31", "8 -- -- -- --"); check_phone_number_info("319", "NL", "31", "9 -- -- -- --"); check_phone_number_info("3196", "NL", "31", "9 6- -- -- --"); - check_phone_number_info("3197", "NL", "31", "97 ---- -----"); + check_phone_number_info("3197", "NL", "31", "9 7- -- -- --"); check_phone_number_info("3198", "NL", "31", "9 8- -- -- --"); + check_phone_number_info("88", "", "88", ""); + check_phone_number_info("888", "FT", "888", "---- ----", true); + check_phone_number_info("8888", "FT", "888", "8 ---", true); + check_phone_number_info("88888", "FT", "888", "8 8--", true); + check_phone_number_info("888888", "FT", "888", "8 88-", true); + check_phone_number_info("8888888", "FT", "888", "8 888", true); + check_phone_number_info("88888888", "FT", "888", "8 8888", true); + check_phone_number_info("888888888", "FT", "888", "8 88888", true); + check_phone_number_info("8888888888", "FT", "888", "8 888888", true); } diff --git a/protocols/Telegram/tdlib/td/test/crypto.cpp b/protocols/Telegram/tdlib/td/test/crypto.cpp index 1837cef631..f6657747f1 100644 --- a/protocols/Telegram/tdlib/td/test/crypto.cpp +++ b/protocols/Telegram/tdlib/td/test/crypto.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 // // 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) diff --git a/protocols/Telegram/tdlib/td/test/data.cpp b/protocols/Telegram/tdlib/td/test/data.cpp index 34aff9b333..c53658d243 100644 --- a/protocols/Telegram/tdlib/td/test/data.cpp +++ b/protocols/Telegram/tdlib/td/test/data.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 // // 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) diff --git a/protocols/Telegram/tdlib/td/test/data.h b/protocols/Telegram/tdlib/td/test/data.h index 07d863a894..79093e1996 100644 --- a/protocols/Telegram/tdlib/td/test/data.h +++ b/protocols/Telegram/tdlib/td/test/data.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 // // 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) diff --git a/protocols/Telegram/tdlib/td/test/db.cpp b/protocols/Telegram/tdlib/td/test/db.cpp index 61757e9893..9e56e331f4 100644 --- a/protocols/Telegram/tdlib/td/test/db.cpp +++ b/protocols/Telegram/tdlib/td/test/db.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 // // 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) @@ -30,6 +30,7 @@ #include "td/utils/Random.h" #include "td/utils/Slice.h" #include "td/utils/Status.h" +#include "td/utils/StringBuilder.h" #include "td/utils/tests.h" #include @@ -62,6 +63,7 @@ TEST(DB, binlog_encryption_bug) { binlog_name.str(), [&](const td::BinlogEvent &x) {}, cucumber) .ensure(); } + td::Binlog::destroy(binlog_name).ignore(); } TEST(DB, binlog_encryption) { @@ -75,21 +77,22 @@ TEST(DB, binlog_encryption) { { td::Binlog binlog; binlog.init(binlog_name.str(), [](const td::BinlogEvent &x) {}).ensure(); - binlog.add_raw_event(td::BinlogEvent::create_raw(binlog.next_id(), 1, 0, td::create_storer("AAAA")), + binlog.add_raw_event(td::BinlogEvent::create_raw(binlog.next_event_id(), 1, 0, td::create_storer("AAAA")), td::BinlogDebugInfo{__FILE__, __LINE__}); - binlog.add_raw_event(td::BinlogEvent::create_raw(binlog.next_id(), 1, 0, td::create_storer("BBBB")), + binlog.add_raw_event(td::BinlogEvent::create_raw(binlog.next_event_id(), 1, 0, td::create_storer("BBBB")), td::BinlogDebugInfo{__FILE__, __LINE__}); - binlog.add_raw_event(td::BinlogEvent::create_raw(binlog.next_id(), 1, 0, td::create_storer(long_data)), + binlog.add_raw_event(td::BinlogEvent::create_raw(binlog.next_event_id(), 1, 0, td::create_storer(long_data)), td::BinlogDebugInfo{__FILE__, __LINE__}); LOG(INFO) << "SET PASSWORD"; binlog.change_key(cucumber); binlog.change_key(hello); LOG(INFO) << "OK"; - binlog.add_raw_event(td::BinlogEvent::create_raw(binlog.next_id(), 1, 0, td::create_storer("CCCC")), + binlog.add_raw_event(td::BinlogEvent::create_raw(binlog.next_event_id(), 1, 0, td::create_storer("CCCC")), td::BinlogDebugInfo{__FILE__, __LINE__}); binlog.close().ensure(); } + td::Binlog::destroy(binlog_name).ignore(); return; auto add_suffix = [&] { @@ -105,7 +108,7 @@ TEST(DB, binlog_encryption) { td::Binlog binlog; binlog .init( - binlog_name.str(), [&](const td::BinlogEvent &x) { v.push_back(x.data_.str()); }, hello) + binlog_name.str(), [&](const td::BinlogEvent &x) { v.push_back(x.get_data().str()); }, hello) .ensure(); CHECK(v == td::vector({"AAAA", "BBBB", long_data, "CCCC"})); } @@ -117,7 +120,7 @@ TEST(DB, binlog_encryption) { LOG(INFO) << "RESTART"; td::Binlog binlog; auto status = binlog.init( - binlog_name.str(), [&](const td::BinlogEvent &x) { v.push_back(x.data_.str()); }, cucumber); + binlog_name.str(), [&](const td::BinlogEvent &x) { v.push_back(x.get_data().str()); }, cucumber); CHECK(status.is_error()); } @@ -128,9 +131,11 @@ TEST(DB, binlog_encryption) { LOG(INFO) << "RESTART"; td::Binlog binlog; auto status = binlog.init( - binlog_name.str(), [&](const td::BinlogEvent &x) { v.push_back(x.data_.str()); }, cucumber, hello); + binlog_name.str(), [&](const td::BinlogEvent &x) { v.push_back(x.get_data().str()); }, cucumber, hello); CHECK(v == td::vector({"AAAA", "BBBB", long_data, "CCCC"})); } + + td::Binlog::destroy(binlog_name).ignore(); } TEST(DB, sqlite_lfs) { @@ -264,13 +269,32 @@ TEST(DB, sqlite_encryption_migrate_v4) { using SeqNo = td::uint64; struct DbQuery { - enum class Type { Get, Set, Erase } type = Type::Get; + enum class Type { Get, Set, Erase, EraseBatch } type = Type::Get; SeqNo tid = 0; - td::int32 id = 0; td::string key; td::string value; + + // for EraseBatch + td::vector erased_keys; }; +static td::StringBuilder &operator<<(td::StringBuilder &string_builder, const DbQuery &query) { + string_builder << "seq_no = " << query.tid << ": "; + switch (query.type) { + case DbQuery::Type::Get: + return string_builder << "Get " << query.key << " = " << query.value; + case DbQuery::Type::Set: + return string_builder << "Set " << query.key << " = " << query.value; + case DbQuery::Type::Erase: + return string_builder << "Del " << query.key; + case DbQuery::Type::EraseBatch: + return string_builder << "Del " << query.erased_keys; + default: + UNREACHABLE(); + return string_builder; + } +} + template class QueryHandler { public: @@ -290,6 +314,10 @@ class QueryHandler { impl_.erase(query.key); query.tid = 1; return; + case DbQuery::Type::EraseBatch: + impl_.erase_batch(query.erased_keys); + query.tid = 1; + return; } } @@ -314,6 +342,9 @@ class SeqQueryHandler { case DbQuery::Type::Erase: query.tid = impl_.erase(query.key); return; + case DbQuery::Type::EraseBatch: + query.tid = impl_.erase_batch(query.erased_keys); + return; } } @@ -334,6 +365,12 @@ class SqliteKV { kv_->get().erase(key); return 0; } + SeqNo erase_batch(td::vector keys) { + for (auto &key : keys) { + kv_->get().erase(key); + } + return 0; + } td::Status init(const td::string &name) { auto sql_connection = std::make_shared(name, td::DbKey::empty()); kv_ = std::make_shared("kv", sql_connection); @@ -360,6 +397,14 @@ class BaselineKV { map_.erase(key); return ++current_tid_; } + SeqNo erase_batch(td::vector keys) { + for (auto &key : keys) { + map_.erase(key); + } + SeqNo result = current_tid_ + 1; + current_tid_ += map_.size(); + return result; + } private: std::map map_; @@ -380,9 +425,8 @@ TEST(DB, key_value) { int queries_n = 1000; td::vector queries(queries_n); for (auto &q : queries) { - int op = td::Random::fast(0, 2); + int op = td::Random::fast(0, 3); const auto &key = rand_elem(keys); - const auto &value = rand_elem(values); if (op == 0) { q.type = DbQuery::Type::Get; q.key = key; @@ -392,7 +436,13 @@ TEST(DB, key_value) { } else if (op == 2) { q.type = DbQuery::Type::Set; q.key = key; - q.value = value; + q.value = rand_elem(values); + } else if (op == 3) { + q.type = DbQuery::Type::EraseBatch; + q.erased_keys.resize(td::Random::fast(0, 3)); + for (auto &erased_key : q.erased_keys) { + erased_key = rand_elem(keys); + } } } @@ -494,17 +544,22 @@ TEST(DB, thread_key_value) { for (auto &q : qs) { int op = td::Random::fast(0, 10); const auto &key = rand_elem(keys); - const auto &value = rand_elem(values); - if (op > 1) { - q.type = DbQuery::Type::Get; - q.key = key; - } else if (op == 0) { + if (op == 0) { q.type = DbQuery::Type::Erase; q.key = key; } else if (op == 1) { + q.type = DbQuery::Type::EraseBatch; + q.erased_keys.resize(td::Random::fast(0, 3)); + for (auto &erased_key : q.erased_keys) { + erased_key = rand_elem(keys); + } + } else if (op <= 6) { q.type = DbQuery::Type::Set; q.key = key; - q.value = value; + q.value = rand_elem(values); + } else { + q.type = DbQuery::Type::Get; + q.key = key; } } } @@ -606,17 +661,22 @@ TEST(DB, persistent_key_value) { for (auto &q : qs) { int op = td::Random::fast(0, 10); const auto &key = rand_elem(keys); - const auto &value = rand_elem(values); - if (op > 1) { - q.type = DbQuery::Type::Get; - q.key = key; - } else if (op == 0) { + if (op == 0) { q.type = DbQuery::Type::Erase; q.key = key; } else if (op == 1) { + q.type = DbQuery::Type::EraseBatch; + q.erased_keys.resize(td::Random::fast(0, 3)); + for (auto &erased_key : q.erased_keys) { + erased_key = rand_elem(keys); + } + } else if (op <= 6) { q.type = DbQuery::Type::Set; q.key = key; - q.value = value; + q.value = rand_elem(values); + } else { + q.type = DbQuery::Type::Get; + q.key = key; } } } @@ -718,6 +778,7 @@ TEST(DB, persistent_key_value) { if (was) { continue; } + LOG(DEBUG) << pos; int best = -1; SeqNo best_tid = 0; @@ -728,6 +789,7 @@ TEST(DB, persistent_key_value) { } was = true; auto &q = res[i][p]; + LOG(DEBUG) << i << ' ' << p << ' ' << q; if (q.tid != 0) { if (best == -1 || q.tid < best_tid) { best = i; diff --git a/protocols/Telegram/tdlib/td/test/fuzz_url.cpp b/protocols/Telegram/tdlib/td/test/fuzz_url.cpp index 0a1e880cbb..cd7af58a77 100644 --- a/protocols/Telegram/tdlib/td/test/fuzz_url.cpp +++ b/protocols/Telegram/tdlib/td/test/fuzz_url.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 // // 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) diff --git a/protocols/Telegram/tdlib/td/test/http.cpp b/protocols/Telegram/tdlib/td/test/http.cpp index 2498c53e5c..e3d2301f6e 100644 --- a/protocols/Telegram/tdlib/td/test/http.cpp +++ b/protocols/Telegram/tdlib/td/test/http.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 // // 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) @@ -347,6 +347,7 @@ TEST(Http, aes_file_encryption) { auto result = sink.result()->move_as_buffer_slice().as_slice().str(); ASSERT_EQ(str, result); } + td::unlink(name).ignore(); } TEST(Http, chunked_flow) { diff --git a/protocols/Telegram/tdlib/td/test/link.cpp b/protocols/Telegram/tdlib/td/test/link.cpp index 13c4613174..67b81c1354 100644 --- a/protocols/Telegram/tdlib/td/test/link.cpp +++ b/protocols/Telegram/tdlib/td/test/link.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 // // 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) @@ -81,14 +81,74 @@ TEST(Link, check_link) { check_link("https://.", ""); } +static td::td_api::object_ptr get_internal_link_type_object( + const td::unique_ptr &link) { + auto object = link->get_internal_link_type_object(); + if (object->get_id() == td::td_api::internalLinkTypeMessageDraft::ID) { + static_cast(object.get())->text_->entities_.clear(); + } + return object; +} + static void parse_internal_link(const td::string &url, td::td_api::object_ptr expected) { auto result = td::LinkManager::parse_internal_link(url); if (result != nullptr) { - auto object = result->get_internal_link_type_object(); - if (object->get_id() == td::td_api::internalLinkTypeMessageDraft::ID) { - static_cast(object.get())->text_->entities_.clear(); - } + auto object = get_internal_link_type_object(result); ASSERT_STREQ(url + ' ' + to_string(expected), url + ' ' + to_string(object)); + + for (auto is_internal : {true, false}) { + if (!is_internal && expected->get_id() == td::td_api::internalLinkTypeMessage::ID) { + // external message links must be generated with getMessageLink + continue; + } + if (expected->get_id() == td::td_api::internalLinkTypeQrCodeAuthentication::ID) { + // QR code authentication links must never be generated manually + continue; + } + auto r_link = td::LinkManager::get_internal_link(expected, is_internal); + if (r_link.is_error()) { + if (r_link.error().message() == "HTTP link is unavailable for the link type") { + // some links are tg-only + continue; + } + if (r_link.error().message() == "Deep link is unavailable for the link type") { + // some links are HTTP-only + continue; + } + if (r_link.error().message() == "WALLPAPER_INVALID") { + continue; + } + LOG(ERROR) << url << ' ' << r_link.error() << ' ' << to_string(expected); + ASSERT_TRUE(r_link.is_ok()); + } + auto new_result = td::LinkManager::parse_internal_link(r_link.ok()); + ASSERT_TRUE(new_result != nullptr); + auto new_object = get_internal_link_type_object(new_result); + + auto new_object_str = to_string(new_object); + auto expected_str = to_string(expected); + if (expected->get_id() == td::td_api::internalLinkTypeBackground::ID) { + for (auto &c : expected_str) { + if (c == '~') { + // getInternalLink always use '-' + c = '-'; + } + } + if (new_object_str != expected_str && td::ends_with(expected_str, "\"\n}\n")) { + // getInternalLink always adds rotation parameter, because default value differs between apps + expected_str = expected_str.substr(0, expected_str.size() - 4) + "?rotation=0\"\n}\n"; + } + } + ASSERT_EQ(new_object_str, expected_str); + + r_link = td::LinkManager::get_internal_link(new_object, is_internal); + ASSERT_TRUE(r_link.is_ok()); + new_result = td::LinkManager::parse_internal_link(r_link.ok()); + ASSERT_TRUE(new_result != nullptr); + + // the object must be the same after 2 round of conversion + ASSERT_STREQ(to_string(new_object), to_string(get_internal_link_type_object(new_result))); + } } else { LOG_IF(ERROR, expected != nullptr) << url; ASSERT_TRUE(expected == nullptr); @@ -97,159 +157,215 @@ static void parse_internal_link(const td::string &url, td::td_api::object_ptr( - can_manage_chat, can_change_info, can_post_messages, can_edit_messages, can_delete_messages, can_invite_users, - can_restrict_members, can_pin_messages, can_manage_topics, can_promote_members, can_manage_video_chats, - is_anonymous); - }; - auto target_chat_chosen = [](bool allow_users, bool allow_bots, bool allow_groups, bool allow_channels) { - return td::td_api::make_object(allow_users, allow_bots, allow_groups, allow_channels); - }; - - auto active_sessions = [] { - return td::td_api::make_object(); - }; - auto attachment_menu_bot = [](td::td_api::object_ptr chat_types, + return td::td_api::make_object( + can_manage_chat, can_change_info, can_post_messages, can_edit_messages, can_delete_messages, can_invite_users, + can_restrict_members, can_pin_messages, can_manage_topics, can_promote_members, can_manage_video_chats, + is_anonymous); +} + +static auto target_chat_chosen(bool allow_users, bool allow_bots, bool allow_groups, bool allow_channels) { + return td::td_api::make_object(allow_users, allow_bots, allow_groups, allow_channels); +} + +static auto active_sessions() { + return td::td_api::make_object(); +} + +static auto attachment_menu_bot(td::td_api::object_ptr chat_types, td::td_api::object_ptr chat_link, const td::string &bot_username, const td::string &start_parameter) { - td::td_api::object_ptr target_chat; - if (chat_link != nullptr) { - target_chat = td::td_api::make_object(std::move(chat_link)); - } else if (chat_types != nullptr) { - target_chat = std::move(chat_types); - } else { - target_chat = td::td_api::make_object(); - } - return td::td_api::make_object( - std::move(target_chat), bot_username, start_parameter.empty() ? td::string() : "start://" + start_parameter); - }; - auto authentication_code = [](const td::string &code) { - return td::td_api::make_object(code); - }; - auto background = [](const td::string &background_name) { - return td::td_api::make_object(background_name); - }; - auto bot_add_to_channel = [](const td::string &bot_username, + td::td_api::object_ptr target_chat; + if (chat_link != nullptr) { + target_chat = td::td_api::make_object(std::move(chat_link)); + } else if (chat_types != nullptr) { + target_chat = std::move(chat_types); + } else { + target_chat = td::td_api::make_object(); + } + return td::td_api::make_object( + std::move(target_chat), bot_username, start_parameter.empty() ? td::string() : "start://" + start_parameter); +} + +static auto authentication_code(const td::string &code) { + return td::td_api::make_object(code); +} + +static auto background(const td::string &background_name) { + return td::td_api::make_object(background_name); +} + +static auto bot_add_to_channel(const td::string &bot_username, td::td_api::object_ptr &&administrator_rights) { - return td::td_api::make_object(bot_username, - std::move(administrator_rights)); - }; - auto bot_start = [](const td::string &bot_username, const td::string &start_parameter) { - return td::td_api::make_object(bot_username, start_parameter, false); - }; - auto bot_start_in_group = [](const td::string &bot_username, const td::string &start_parameter, + return td::td_api::make_object(bot_username, + std::move(administrator_rights)); +} + +static auto bot_start(const td::string &bot_username, const td::string &start_parameter) { + return td::td_api::make_object(bot_username, start_parameter, false); +} + +static auto bot_start_in_group(const td::string &bot_username, const td::string &start_parameter, td::td_api::object_ptr &&administrator_rights) { - return td::td_api::make_object(bot_username, start_parameter, - std::move(administrator_rights)); - }; - auto change_phone_number = [] { - return td::td_api::make_object(); - }; - auto chat_invite = [](const td::string &hash) { - return td::td_api::make_object("tg:join?invite=" + hash); - }; - auto filter_settings = [] { - return td::td_api::make_object(); - }; - auto game = [](const td::string &bot_username, const td::string &game_short_name) { - return td::td_api::make_object(bot_username, game_short_name); - }; - auto instant_view = [](const td::string &url, const td::string &fallback_url) { - return td::td_api::make_object(url, fallback_url); - }; - auto invoice = [](const td::string &invoice_name) { - return td::td_api::make_object(invoice_name); - }; - auto language_pack = [](const td::string &language_pack_name) { - return td::td_api::make_object(language_pack_name); - }; - auto language_settings = [] { - return td::td_api::make_object(); - }; - auto message = [](const td::string &url) { - return td::td_api::make_object(url); - }; - auto message_draft = [](td::string text, bool contains_url) { - auto formatted_text = td::td_api::make_object(); - formatted_text->text_ = std::move(text); - return td::td_api::make_object(std::move(formatted_text), contains_url); - }; - auto passport_data_request = [](td::int32 bot_user_id, const td::string &scope, const td::string &public_key, + return td::td_api::make_object(bot_username, start_parameter, + std::move(administrator_rights)); +} + +static auto change_phone_number() { + return td::td_api::make_object(); +} + +static auto chat_folder_invite(const td::string &slug) { + return td::td_api::make_object("tg:addlist?slug=" + slug); +} + +static auto chat_folder_settings() { + return td::td_api::make_object(); +} + +static auto chat_invite(const td::string &hash) { + return td::td_api::make_object("tg:join?invite=" + hash); +} + +static auto default_message_auto_delete_timer_settings() { + return td::td_api::make_object(); +} + +static auto edit_profile_settings() { + return td::td_api::make_object(); +} + +static auto game(const td::string &bot_username, const td::string &game_short_name) { + return td::td_api::make_object(bot_username, game_short_name); +} + +static auto instant_view(const td::string &url, const td::string &fallback_url) { + return td::td_api::make_object(url, fallback_url); +} + +static auto invoice(const td::string &invoice_name) { + return td::td_api::make_object(invoice_name); +} + +static auto language_pack(const td::string &language_pack_name) { + return td::td_api::make_object(language_pack_name); +} + +static auto language_settings() { + return td::td_api::make_object(); +} + +static auto message(const td::string &url) { + return td::td_api::make_object(url); +} + +static auto message_draft(td::string text, bool contains_url) { + auto formatted_text = td::td_api::make_object(); + formatted_text->text_ = std::move(text); + return td::td_api::make_object(std::move(formatted_text), contains_url); +} + +static auto passport_data_request(td::int32 bot_user_id, const td::string &scope, const td::string &public_key, const td::string &nonce, const td::string &callback_url) { - return td::td_api::make_object(bot_user_id, scope, public_key, - nonce, callback_url); - }; - auto phone_number_confirmation = [](const td::string &hash, const td::string &phone_number) { - return td::td_api::make_object(hash, phone_number); - }; - auto premium_features = [](const td::string &referrer) { - return td::td_api::make_object(referrer); - }; - auto privacy_and_security_settings = [] { - return td::td_api::make_object(); - }; - auto proxy_mtproto = [](const td::string &server, td::int32 port, const td::string &secret) { - return td::td_api::make_object( - server, port, td::td_api::make_object(secret)); - }; - auto proxy_socks = [](const td::string &server, td::int32 port, const td::string &username, + return td::td_api::make_object(bot_user_id, scope, public_key, nonce, + callback_url); +} + +static auto phone_number_confirmation(const td::string &hash, const td::string &phone_number) { + return td::td_api::make_object(hash, phone_number); +} + +static auto premium_features(const td::string &referrer) { + return td::td_api::make_object(referrer); +} + +static auto privacy_and_security_settings() { + return td::td_api::make_object(); +} + +static auto proxy_mtproto(const td::string &server, td::int32 port, const td::string &secret) { + return td::td_api::make_object( + server, port, td::td_api::make_object(secret)); +} + +static auto proxy_socks(const td::string &server, td::int32 port, const td::string &username, const td::string &password) { - return td::td_api::make_object( - server, port, td::td_api::make_object(username, password)); - }; - auto public_chat = [](const td::string &chat_username) { - return td::td_api::make_object(chat_username); - }; - auto qr_code_authentication = [] { - return td::td_api::make_object(); - }; - auto restore_purchases = [] { - return td::td_api::make_object(); - }; - auto settings = [] { - return td::td_api::make_object(); - }; - auto sticker_set = [](const td::string &sticker_set_name) { - return td::td_api::make_object(sticker_set_name); - }; - auto theme = [](const td::string &theme_name) { - return td::td_api::make_object(theme_name); - }; - auto theme_settings = [] { - return td::td_api::make_object(); - }; - auto unknown_deep_link = [](const td::string &link) { - return td::td_api::make_object(link); - }; - auto unsupported_proxy = [] { - return td::td_api::make_object(); - }; - auto user_phone_number = [](const td::string &phone_number) { - return td::td_api::make_object(phone_number); - }; - auto video_chat = [](const td::string &chat_username, const td::string &invite_hash, bool is_live_stream) { - return td::td_api::make_object(chat_username, invite_hash, is_live_stream); - }; - - parse_internal_link("t.me/levlam/1", message("tg:resolve?domain=levlam&post=1")); - parse_internal_link("telegram.me/levlam/1", message("tg:resolve?domain=levlam&post=1")); - parse_internal_link("telegram.dog/levlam/1", message("tg:resolve?domain=levlam&post=1")); - parse_internal_link("www.t.me/levlam/1", message("tg:resolve?domain=levlam&post=1")); - parse_internal_link("www%2etelegram.me/levlam/1", message("tg:resolve?domain=levlam&post=1")); - parse_internal_link("www%2Etelegram.dog/levlam/1", message("tg:resolve?domain=levlam&post=1")); + return td::td_api::make_object( + server, port, td::td_api::make_object(username, password)); +} + +static auto public_chat(const td::string &chat_username) { + return td::td_api::make_object(chat_username); +} + +static auto qr_code_authentication() { + return td::td_api::make_object(); +} + +static auto restore_purchases() { + return td::td_api::make_object(); +} + +static auto settings() { + return td::td_api::make_object(); +} + +static auto sticker_set(const td::string &sticker_set_name, bool expect_custom_emoji) { + return td::td_api::make_object(sticker_set_name, expect_custom_emoji); +} + +static auto theme(const td::string &theme_name) { + return td::td_api::make_object(theme_name); +} + +static auto theme_settings() { + return td::td_api::make_object(); +} + +static auto unknown_deep_link(const td::string &link) { + return td::td_api::make_object(link); +} + +static auto unsupported_proxy() { + return td::td_api::make_object(); +} + +static auto user_phone_number(const td::string &phone_number) { + return td::td_api::make_object(phone_number); +} + +static auto user_token(const td::string &token) { + return td::td_api::make_object(token); +} + +static auto video_chat(const td::string &chat_username, const td::string &invite_hash, bool is_live_stream) { + return td::td_api::make_object(chat_username, invite_hash, is_live_stream); +} + +static auto web_app(const td::string &bot_username, const td::string &web_app_short_name, + const td::string &start_parameter) { + return td::td_api::make_object(bot_username, web_app_short_name, start_parameter); +} + +TEST(Link, parse_internal_link_part1) { + parse_internal_link("t.me/levlam/1", message("tg://resolve?domain=levlam&post=1")); + parse_internal_link("telegram.me/levlam/1", message("tg://resolve?domain=levlam&post=1")); + parse_internal_link("telegram.dog/levlam/1", message("tg://resolve?domain=levlam&post=1")); + parse_internal_link("www.t.me/levlam/1", message("tg://resolve?domain=levlam&post=1")); + parse_internal_link("www%2etelegram.me/levlam/1", message("tg://resolve?domain=levlam&post=1")); + parse_internal_link("www%2Etelegram.dog/levlam/1", message("tg://resolve?domain=levlam&post=1")); parse_internal_link("www%252Etelegram.dog/levlam/1", nullptr); - parse_internal_link("www.t.me/s/s/s/s/s/joinchat/1", chat_invite("1")); - parse_internal_link("www.t.me/s/%73/%73/s/%73/joinchat/1", chat_invite("1")); - parse_internal_link("http://t.me/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/joinchat/1", chat_invite("1")); - parse_internal_link("http://t.me/levlam/1", message("tg:resolve?domain=levlam&post=1")); - parse_internal_link("https://t.me/levlam/1", message("tg:resolve?domain=levlam&post=1")); - parse_internal_link("hTtp://www.t.me:443/levlam/1", message("tg:resolve?domain=levlam&post=1")); - parse_internal_link("httPs://t.me:80/levlam/1", message("tg:resolve?domain=levlam&post=1")); + parse_internal_link("www.t.me/s/s/s/s/s/joinchat/1", nullptr); + parse_internal_link("www.t.me/s/s/s/s/s/joinchat/a", chat_invite("a")); + parse_internal_link("www.t.me/s/%73/%73/s/%73/joinchat/a", chat_invite("a")); + parse_internal_link("http://t.me/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/joinchat/a", chat_invite("a")); + parse_internal_link("http://t.me/levlam/1", message("tg://resolve?domain=levlam&post=1")); + parse_internal_link("https://t.me/levlam/1", message("tg://resolve?domain=levlam&post=1")); + parse_internal_link("hTtp://www.t.me:443/levlam/1", message("tg://resolve?domain=levlam&post=1")); + parse_internal_link("httPs://t.me:80/levlam/1", message("tg://resolve?domain=levlam&post=1")); parse_internal_link("https://t.me:200/levlam/1", nullptr); parse_internal_link("http:t.me/levlam/1", nullptr); parse_internal_link("t.dog/levlam/1", nullptr); @@ -257,13 +373,13 @@ TEST(Link, parse_internal_link) { parse_internal_link("t.men/levlam/1", nullptr); parse_internal_link("tg:resolve?domain=username&post=12345&single", - message("tg:resolve?domain=username&post=12345&single")); + message("tg://resolve?domain=username&post=12345&single")); parse_internal_link("tg:resolve?domain=username&post=12345&single&startattach=1&attach=test", - message("tg:resolve?domain=username&post=12345&single")); + message("tg://resolve?domain=username&post=12345&single")); parse_internal_link("tg:resolve?domain=user%31name&post=%312345&single&comment=456&t=789&single&thread=123%20%31", - message("tg:resolve?domain=user1name&post=12345&single&thread=123%201&comment=456&t=789")); + message("tg://resolve?domain=user1name&post=12345&single&thread=123%201&comment=456&t=789")); parse_internal_link("TG://resolve?domain=username&post=12345&single&voicechat=aasd", - message("tg:resolve?domain=username&post=12345&single")); + message("tg://resolve?domain=username&post=12345&single")); parse_internal_link("TG://test@resolve?domain=username&post=12345&single", nullptr); parse_internal_link("tg:resolve:80?domain=username&post=12345&single", nullptr); parse_internal_link("tg:http://resolve?domain=username&post=12345&single", nullptr); @@ -318,20 +434,33 @@ TEST(Link, parse_internal_link) { parse_internal_link("tg:resolve?phone=+123", unknown_deep_link("tg://resolve?phone=+123")); parse_internal_link("tg:resolve?phone=123456 ", unknown_deep_link("tg://resolve?phone=123456 ")); - parse_internal_link("t.me/username/12345?single", message("tg:resolve?domain=username&post=12345&single")); - parse_internal_link("t.me/username/12345?asdasd", message("tg:resolve?domain=username&post=12345")); - parse_internal_link("t.me/username/12345", message("tg:resolve?domain=username&post=12345")); - parse_internal_link("t.me/username/12345/", message("tg:resolve?domain=username&post=12345")); - parse_internal_link("t.me/username/12345#asdasd", message("tg:resolve?domain=username&post=12345")); + parse_internal_link("tg:contact?token=1", user_token("1")); + parse_internal_link("tg:contact?token=123456", user_token("123456")); + parse_internal_link("tg:contact?token=123456&startattach", user_token("123456")); + parse_internal_link("tg:contact?token=123456&startattach=123", user_token("123456")); + parse_internal_link("tg:contact?token=123456&attach=", user_token("123456")); + parse_internal_link("tg:contact?token=123456&attach=&startattach", user_token("123456")); + parse_internal_link("tg:contact?token=123456&attach=&startattach=123", user_token("123456")); + parse_internal_link("tg:contact?token=01234567890123456789012345678912", + user_token("01234567890123456789012345678912")); + parse_internal_link("tg:contact?token=012345678901234567890123456789123", + user_token("012345678901234567890123456789123")); + parse_internal_link("tg:contact?token=", unknown_deep_link("tg://contact?token=")); + parse_internal_link("tg:contact?token=+123", user_token(" 123")); + + parse_internal_link("t.me/username/12345?single", message("tg://resolve?domain=username&post=12345&single")); + parse_internal_link("t.me/username/12345?asdasd", message("tg://resolve?domain=username&post=12345")); + parse_internal_link("t.me/username/12345", message("tg://resolve?domain=username&post=12345")); + parse_internal_link("t.me/username/12345/", message("tg://resolve?domain=username&post=12345")); + parse_internal_link("t.me/username/12345#asdasd", message("tg://resolve?domain=username&post=12345")); parse_internal_link("t.me/username/12345//?voicechat=&single", - message("tg:resolve?domain=username&post=12345&single")); + message("tg://resolve?domain=username&post=12345&single")); parse_internal_link("t.me/username/12345/asdasd//asd/asd/asd/?single", - message("tg:resolve?domain=username&post=12345&single")); + message("tg://resolve?domain=username&post=12345&single")); parse_internal_link("t.me/username/12345/67890/asdasd//asd/asd/asd/?single", - message("tg:resolve?domain=username&post=67890&single&thread=12345")); + message("tg://resolve?domain=username&post=67890&single&thread=12345")); parse_internal_link("t.me/username/1asdasdas/asdasd//asd/asd/asd/?single", - message("tg:resolve?domain=username&post=1&single")); - parse_internal_link("t.me/username/asd", public_chat("username")); + message("tg://resolve?domain=username&post=1&single")); parse_internal_link("t.me/username/0", public_chat("username")); parse_internal_link("t.me/username/-12345", public_chat("username")); parse_internal_link("t.me//12345?single", nullptr); @@ -364,19 +493,19 @@ TEST(Link, parse_internal_link) { parse_internal_link("tg:privatepost?channel=username/12345&single", unknown_deep_link("tg://privatepost?channel=username/12345&single")); parse_internal_link("tg:privatepost?channel=username&post=12345", - message("tg:privatepost?channel=username&post=12345")); + message("tg://privatepost?channel=username&post=12345")); parse_internal_link("t.me/c/12345?single", nullptr); parse_internal_link("t.me/c/1/c?single", nullptr); parse_internal_link("t.me/c/c/1?single", nullptr); parse_internal_link("t.me/c//1?single", nullptr); - parse_internal_link("t.me/c/12345/123", message("tg:privatepost?channel=12345&post=123")); - parse_internal_link("t.me/c/12345/123?single", message("tg:privatepost?channel=12345&post=123&single")); - parse_internal_link("t.me/c/12345/123/asd/asd////?single", message("tg:privatepost?channel=12345&post=123&single")); + parse_internal_link("t.me/c/12345/123", message("tg://privatepost?channel=12345&post=123")); + parse_internal_link("t.me/c/12345/123?single", message("tg://privatepost?channel=12345&post=123&single")); + parse_internal_link("t.me/c/12345/123/asd/asd////?single", message("tg://privatepost?channel=12345&post=123&single")); parse_internal_link("t.me/c/12345/123/456/asd/asd////?single", - message("tg:privatepost?channel=12345&post=456&single&thread=123")); + message("tg://privatepost?channel=12345&post=456&single&thread=123")); parse_internal_link("t.me/c/%312345/%3123?comment=456&t=789&single&thread=123%20%31", - message("tg:privatepost?channel=12345&post=123&single&thread=123%201&comment=456&t=789")); + message("tg://privatepost?channel=12345&post=123&single&thread=123%201&comment=456&t=789")); parse_internal_link("tg:bg?color=111111#asdasd", background("111111")); parse_internal_link("tg:bg?color=11111%31", background("111111")); @@ -386,16 +515,16 @@ TEST(Link, parse_internal_link) { background("111111-222222%20?rotation=180%20")); parse_internal_link("tg:bg?gradient=111111~222222", background("111111~222222")); parse_internal_link("tg:bg?gradient=abacaba", background("abacaba")); - parse_internal_link("tg:bg?slug=111111~222222#asdasd", background("111111~222222")); - parse_internal_link("tg:bg?slug=111111~222222&mode=12", background("111111~222222?mode=12")); - parse_internal_link("tg:bg?slug=111111~222222&mode=12&text=1", background("111111~222222?mode=12")); - parse_internal_link("tg:bg?slug=111111~222222&mode=12&mode=1", background("111111~222222?mode=12")); - parse_internal_link("tg:bg?slug=test&mode=12&rotation=4&intensity=2&bg_color=3", - background("test?mode=12&intensity=2&bg_color=3&rotation=4")); - parse_internal_link("tg:bg?mode=12&&slug=test&intensity=2&bg_color=3", - background("test?mode=12&intensity=2&bg_color=3")); - parse_internal_link("tg:bg?mode=12&intensity=2&bg_color=3", - unknown_deep_link("tg://bg?mode=12&intensity=2&bg_color=3")); + parse_internal_link("tg:bg?slug=test#asdasd", background("test")); + parse_internal_link("tg:bg?slug=test&mode=blur", background("test?mode=blur")); + parse_internal_link("tg:bg?slug=test&mode=blur&text=1", background("test?mode=blur")); + parse_internal_link("tg:bg?slug=test&mode=blur&mode=1", background("test?mode=blur")); + parse_internal_link("tg:bg?slug=test&mode=blur&rotation=4&intensity=2&bg_color=3", + background("test?mode=blur&intensity=2&bg_color=3&rotation=4")); + parse_internal_link("tg:bg?mode=blur&&slug=test&intensity=2&bg_color=3", + background("test?mode=blur&intensity=2&bg_color=3")); + parse_internal_link("tg:bg?mode=blur&intensity=2&bg_color=3", + unknown_deep_link("tg://bg?mode=blur&intensity=2&bg_color=3")); parse_internal_link("tg:bg?color=111111#asdasd", background("111111")); parse_internal_link("tg:bg?color=11111%31", background("111111")); @@ -403,18 +532,18 @@ TEST(Link, parse_internal_link) { parse_internal_link("tg:bg?gradient=111111-222222", background("111111-222222")); parse_internal_link("tg:bg?rotation=180%20&gradient=111111-222222%20", background("111111-222222%20?rotation=180%20")); - parse_internal_link("tg:bg?gradient=111111~222222", background("111111~222222")); + parse_internal_link("tg:bg?gradient=111111~222222&mode=blur", background("111111~222222")); parse_internal_link("tg:bg?gradient=abacaba", background("abacaba")); - parse_internal_link("tg:bg?slug=111111~222222#asdasd", background("111111~222222")); - parse_internal_link("tg:bg?slug=111111~222222&mode=12", background("111111~222222?mode=12")); - parse_internal_link("tg:bg?slug=111111~222222&mode=12&text=1", background("111111~222222?mode=12")); - parse_internal_link("tg:bg?slug=111111~222222&mode=12&mode=1", background("111111~222222?mode=12")); - parse_internal_link("tg:bg?slug=test&mode=12&rotation=4&intensity=2&bg_color=3", - background("test?mode=12&intensity=2&bg_color=3&rotation=4")); - parse_internal_link("tg:bg?mode=12&&slug=test&intensity=2&bg_color=3", - background("test?mode=12&intensity=2&bg_color=3")); - parse_internal_link("tg:bg?mode=12&intensity=2&bg_color=3", - unknown_deep_link("tg://bg?mode=12&intensity=2&bg_color=3")); + parse_internal_link("tg:bg?slug=test#asdasd", background("test")); + parse_internal_link("tg:bg?slug=test&mode=blur", background("test?mode=blur")); + parse_internal_link("tg:bg?slug=test&mode=blur&text=1", background("test?mode=blur")); + parse_internal_link("tg:bg?slug=test&mode=blur&mode=1", background("test?mode=blur")); + parse_internal_link("tg:bg?slug=test&mode=blur&rotation=4&intensity=2&bg_color=3", + background("test?mode=blur&intensity=2&bg_color=3&rotation=4")); + parse_internal_link("tg:bg?mode=blur&&slug=test&intensity=2&bg_color=3", + background("test?mode=blur&intensity=2&bg_color=3")); + parse_internal_link("tg:bg?mode=blur&intensity=2&bg_color=3", + unknown_deep_link("tg://bg?mode=blur&intensity=2&bg_color=3")); parse_internal_link("%54.me/bg/111111#asdasd", background("111111")); parse_internal_link("t.me/bg/11111%31", background("111111")); @@ -423,19 +552,21 @@ TEST(Link, parse_internal_link) { parse_internal_link("t.me/bg/111111-222222%20?rotation=180%20", background("111111-222222%20?rotation=180%20")); parse_internal_link("t.me/bg/111111~222222", background("111111~222222")); parse_internal_link("t.me/bg/abacaba", background("abacaba")); - parse_internal_link("t.me/Bg/abacaba", public_chat("Bg")); + parse_internal_link("t.me/Bg/abacaba", web_app("Bg", "abacaba", "")); parse_internal_link("t.me/bg/111111~222222#asdasd", background("111111~222222")); - parse_internal_link("t.me/bg/111111~222222?mode=12", background("111111~222222?mode=12")); - parse_internal_link("t.me/bg/111111~222222?mode=12&text=1", background("111111~222222?mode=12")); - parse_internal_link("t.me/bg/111111~222222?mode=12&mode=1", background("111111~222222?mode=12")); - parse_internal_link("t.me/bg/test?mode=12&rotation=4&intensity=2&bg_color=3", - background("test?mode=12&intensity=2&bg_color=3&rotation=4")); - parse_internal_link("t.me/%62g/test/?mode=12&&&intensity=2&bg_color=3", - background("test?mode=12&intensity=2&bg_color=3")); + parse_internal_link("t.me/bg/111111~222222?mode=blur", background("111111~222222")); + parse_internal_link("t.me/bg/111111~222222?mode=blur&text=1", background("111111~222222")); + parse_internal_link("t.me/bg/111111~222222?mode=blur&mode=1", background("111111~222222")); + parse_internal_link("t.me/bg/testteststststststststststststs?mode=blur&rotation=4&intensity=2&bg_color=3&mode=1", + background("testteststststststststststststs?mode=blur&intensity=2&bg_color=3&rotation=4")); + parse_internal_link("t.me/%62g/testteststststststststststststs/?mode=blur+motion&&&intensity=2&bg_color=3", + background("testteststststststststststststs?mode=blur%20motion&intensity=2&bg_color=3")); parse_internal_link("t.me/bg//", nullptr); parse_internal_link("t.me/bg/%20/", background("%20")); parse_internal_link("t.me/bg/", nullptr); +} +TEST(Link, parse_internal_link_part2) { parse_internal_link("t.me/invoice?slug=abcdef", nullptr); parse_internal_link("t.me/invoice", nullptr); parse_internal_link("t.me/invoice/", nullptr); @@ -540,12 +671,15 @@ TEST(Link, parse_internal_link) { parse_internal_link("t.me/joinchat/?abcdef", nullptr); parse_internal_link("t.me/joinchat/#abcdef", nullptr); parse_internal_link("t.me/joinchat/abacaba", chat_invite("abacaba")); - parse_internal_link("t.me/joinchat/aba%20aba", chat_invite("aba%20aba")); + parse_internal_link("t.me/joinchat/aba%20aba", nullptr); parse_internal_link("t.me/joinchat/aba%30aba", chat_invite("aba0aba")); parse_internal_link("t.me/joinchat/123456a", chat_invite("123456a")); - parse_internal_link("t.me/joinchat/12345678901", chat_invite("12345678901")); - parse_internal_link("t.me/joinchat/123456", chat_invite("123456")); - parse_internal_link("t.me/joinchat/123456/123123/12/31/a/s//21w/?asdas#test", chat_invite("123456")); + parse_internal_link("t.me/joinchat/12345678901", nullptr); + parse_internal_link("t.me/joinchat/123456", nullptr); + parse_internal_link("t.me/joinchat/123456/123123/12/31/a/s//21w/?asdas#test", nullptr); + parse_internal_link("t.me/joinchat/12345678901a", chat_invite("12345678901a")); + parse_internal_link("t.me/joinchat/123456a", chat_invite("123456a")); + parse_internal_link("t.me/joinchat/123456a/123123/12/31/a/s//21w/?asdas#test", chat_invite("123456a")); parse_internal_link("t.me/+?invite=abcdef", nullptr); parse_internal_link("t.me/+a", chat_invite("a")); @@ -555,7 +689,7 @@ TEST(Link, parse_internal_link) { parse_internal_link("t.me/+?abcdef", nullptr); parse_internal_link("t.me/+#abcdef", nullptr); parse_internal_link("t.me/ abacaba", chat_invite("abacaba")); - parse_internal_link("t.me/+aba%20aba", chat_invite("aba%20aba")); + parse_internal_link("t.me/+aba%20aba", nullptr); parse_internal_link("t.me/+aba%30aba", chat_invite("aba0aba")); parse_internal_link("t.me/+123456a", chat_invite("123456a")); parse_internal_link("t.me/%2012345678901", user_phone_number("12345678901")); @@ -573,11 +707,40 @@ TEST(Link, parse_internal_link) { parse_internal_link("t.me/+123456?attach=bot&startattach=1", attachment_menu_bot(nullptr, user_phone_number("123456"), "bot", "1")); + parse_internal_link("t.me/addlist?invite=abcdef", nullptr); + parse_internal_link("t.me/addlist", nullptr); + parse_internal_link("t.me/addlist/", nullptr); + parse_internal_link("t.me/addlist//abcdef", nullptr); + parse_internal_link("t.me/addlist?/abcdef", nullptr); + parse_internal_link("t.me/addlist/?abcdef", nullptr); + parse_internal_link("t.me/addlist/#abcdef", nullptr); + parse_internal_link("t.me/addlist/abacaba", chat_folder_invite("abacaba")); + parse_internal_link("t.me/addlist/aba%20aba", nullptr); + parse_internal_link("t.me/addlist/aba%30aba", chat_folder_invite("aba0aba")); + parse_internal_link("t.me/addlist/123456a", chat_folder_invite("123456a")); + parse_internal_link("t.me/addlist/12345678901", chat_folder_invite("12345678901")); + parse_internal_link("t.me/addlist/123456", chat_folder_invite("123456")); + parse_internal_link("t.me/addlist/123456/123123/12/31/a/s//21w/?asdas#test", chat_folder_invite("123456")); + parse_internal_link("t.me/addlist/12345678901a", chat_folder_invite("12345678901a")); + parse_internal_link("t.me/addlist/123456a", chat_folder_invite("123456a")); + parse_internal_link("t.me/addlist/123456a/123123/12/31/a/s//21w/?asdas#test", chat_folder_invite("123456a")); + + parse_internal_link("t.me/contact/startattach/adasd", user_token("startattach")); + parse_internal_link("t.me/contact/startattach", user_token("startattach")); + parse_internal_link("t.me/contact/startattach=1", user_token("startattach=1")); + parse_internal_link("t.me/contact/", nullptr); + parse_internal_link("t.me/contact/?attach=&startattach", nullptr); + parse_internal_link("tg:join?invite=abcdef", chat_invite("abcdef")); - parse_internal_link("tg:join?invite=abc%20def", chat_invite("abc%20def")); + parse_internal_link("tg:join?invite=abc%20def", unknown_deep_link("tg://join?invite=abc%20def")); parse_internal_link("tg://join?invite=abc%30def", chat_invite("abc0def")); parse_internal_link("tg:join?invite=", unknown_deep_link("tg://join?invite=")); + parse_internal_link("tg:addlist?slug=abcdef", chat_folder_invite("abcdef")); + parse_internal_link("tg:addlist?slug=abc%20def", unknown_deep_link("tg://addlist?slug=abc%20def")); + parse_internal_link("tg://addlist?slug=abc%30def", chat_folder_invite("abc0def")); + parse_internal_link("tg:addlist?slug=", unknown_deep_link("tg://addlist?slug=")); + parse_internal_link("t.me/addstickers?set=abcdef", nullptr); parse_internal_link("t.me/addstickers", nullptr); parse_internal_link("t.me/addstickers/", nullptr); @@ -585,15 +748,15 @@ TEST(Link, parse_internal_link) { parse_internal_link("t.me/addstickers?/abcdef", nullptr); parse_internal_link("t.me/addstickers/?abcdef", nullptr); parse_internal_link("t.me/addstickers/#abcdef", nullptr); - parse_internal_link("t.me/addstickers/abacaba", sticker_set("abacaba")); - parse_internal_link("t.me/addstickers/aba%20aba", sticker_set("aba aba")); - parse_internal_link("t.me/addstickers/123456a", sticker_set("123456a")); - parse_internal_link("t.me/addstickers/12345678901", sticker_set("12345678901")); - parse_internal_link("t.me/addstickers/123456", sticker_set("123456")); - parse_internal_link("t.me/addstickers/123456/123123/12/31/a/s//21w/?asdas#test", sticker_set("123456")); - - parse_internal_link("tg:addstickers?set=abcdef", sticker_set("abcdef")); - parse_internal_link("tg:addstickers?set=abc%30ef", sticker_set("abc0ef")); + parse_internal_link("t.me/addstickers/abacaba", sticker_set("abacaba", false)); + parse_internal_link("t.me/addstickers/aba%20aba", sticker_set("aba aba", false)); + parse_internal_link("t.me/addstickers/123456a", sticker_set("123456a", false)); + parse_internal_link("t.me/addstickers/12345678901", sticker_set("12345678901", false)); + parse_internal_link("t.me/addstickers/123456", sticker_set("123456", false)); + parse_internal_link("t.me/addstickers/123456/123123/12/31/a/s//21w/?asdas#test", sticker_set("123456", false)); + + parse_internal_link("tg:addstickers?set=abcdef", sticker_set("abcdef", false)); + parse_internal_link("tg:addstickers?set=abc%30ef", sticker_set("abc0ef", false)); parse_internal_link("tg://addstickers?set=", unknown_deep_link("tg://addstickers?set=")); parse_internal_link("t.me/addemoji?set=abcdef", nullptr); @@ -603,17 +766,19 @@ TEST(Link, parse_internal_link) { parse_internal_link("t.me/addemoji?/abcdef", nullptr); parse_internal_link("t.me/addemoji/?abcdef", nullptr); parse_internal_link("t.me/addemoji/#abcdef", nullptr); - parse_internal_link("t.me/addemoji/abacaba", sticker_set("abacaba")); - parse_internal_link("t.me/addemoji/aba%20aba", sticker_set("aba aba")); - parse_internal_link("t.me/addemoji/123456a", sticker_set("123456a")); - parse_internal_link("t.me/addemoji/12345678901", sticker_set("12345678901")); - parse_internal_link("t.me/addemoji/123456", sticker_set("123456")); - parse_internal_link("t.me/addemoji/123456/123123/12/31/a/s//21w/?asdas#test", sticker_set("123456")); - - parse_internal_link("tg:addemoji?set=abcdef", sticker_set("abcdef")); - parse_internal_link("tg:addemoji?set=abc%30ef", sticker_set("abc0ef")); + parse_internal_link("t.me/addemoji/abacaba", sticker_set("abacaba", true)); + parse_internal_link("t.me/addemoji/aba%20aba", sticker_set("aba aba", true)); + parse_internal_link("t.me/addemoji/123456a", sticker_set("123456a", true)); + parse_internal_link("t.me/addemoji/12345678901", sticker_set("12345678901", true)); + parse_internal_link("t.me/addemoji/123456", sticker_set("123456", true)); + parse_internal_link("t.me/addemoji/123456/123123/12/31/a/s//21w/?asdas#test", sticker_set("123456", true)); + + parse_internal_link("tg:addemoji?set=abcdef", sticker_set("abcdef", true)); + parse_internal_link("tg:addemoji?set=abc%30ef", sticker_set("abc0ef", true)); parse_internal_link("tg://addemoji?set=", unknown_deep_link("tg://addemoji?set=")); +} +TEST(Link, parse_internal_link_part3) { parse_internal_link("t.me/confirmphone?hash=abc%30ef&phone=", nullptr); parse_internal_link("t.me/confirmphone/123456/123123/12/31/a/s//21w/?hash=abc%30ef&phone=123456789", phone_number_confirmation("abc0ef", "123456789")); @@ -683,9 +848,9 @@ TEST(Link, parse_internal_link) { parse_internal_link("tg://addtheme?slug=", unknown_deep_link("tg://addtheme?slug=")); parse_internal_link("t.me/proxy?server=1.2.3.4&port=80&secret=1234567890abcdef1234567890ABCDEF", - proxy_mtproto("1.2.3.4", 80, "1234567890abcdef1234567890ABCDEF")); + proxy_mtproto("1.2.3.4", 80, "1234567890abcdef1234567890abcdef")); parse_internal_link("t.me/proxy?server=1.2.3.4&port=80adasdas&secret=1234567890abcdef1234567890ABCDEF", - proxy_mtproto("1.2.3.4", 80, "1234567890abcdef1234567890ABCDEF")); + proxy_mtproto("1.2.3.4", 80, "1234567890abcdef1234567890abcdef")); parse_internal_link("t.me/proxy?server=1.2.3.4&port=adasdas&secret=1234567890abcdef1234567890ABCDEF", unsupported_proxy()); parse_internal_link("t.me/proxy?server=1.2.3.4&port=65536&secret=1234567890abcdef1234567890ABCDEF", @@ -693,9 +858,9 @@ TEST(Link, parse_internal_link) { parse_internal_link("t.me/proxy?server=google.com&port=8%30&secret=", unsupported_proxy()); parse_internal_link("t.me/proxy?server=google.com&port=8%30&secret=12", unsupported_proxy()); parse_internal_link("t.me/proxy?server=google.com&port=8%30&secret=1234567890abcdef1234567890ABCDEF", - proxy_mtproto("google.com", 80, "1234567890abcdef1234567890ABCDEF")); + proxy_mtproto("google.com", 80, "1234567890abcdef1234567890abcdef")); parse_internal_link("t.me/proxy?server=google.com&port=8%30&secret=dd1234567890abcdef1234567890ABCDEF", - proxy_mtproto("google.com", 80, "dd1234567890abcdef1234567890ABCDEF")); + proxy_mtproto("google.com", 80, "dd1234567890abcdef1234567890abcdef")); parse_internal_link("t.me/proxy?server=google.com&port=8%30&secret=de1234567890abcdef1234567890ABCDEF", unsupported_proxy()); parse_internal_link("t.me/proxy?server=google.com&port=8%30&secret=ee1234567890abcdef1234567890ABCDEF", @@ -703,25 +868,25 @@ TEST(Link, parse_internal_link) { parse_internal_link("t.me/proxy?server=google.com&port=8%30&secret=ee1234567890abcdef1234567890ABCDEF0", unsupported_proxy()); parse_internal_link("t.me/proxy?server=google.com&port=8%30&secret=ee1234567890abcdef1234567890ABCDEF%30%30", - proxy_mtproto("google.com", 80, "ee1234567890abcdef1234567890ABCDEF00")); + proxy_mtproto("google.com", 80, "7hI0VniQq83vEjRWeJCrze8A")); parse_internal_link( "t.me/proxy?server=google.com&port=8%30&secret=ee1234567890abcdef1234567890ABCDEF010101010101010101", - proxy_mtproto("google.com", 80, "ee1234567890abcdef1234567890ABCDEF010101010101010101")); + proxy_mtproto("google.com", 80, "7hI0VniQq83vEjRWeJCrze8BAQEBAQEBAQE")); parse_internal_link("t.me/proxy?server=google.com&port=8%30&secret=7tAAAAAAAAAAAAAAAAAAAAAAAAcuZ29vZ2xlLmNvbQ", proxy_mtproto("google.com", 80, "7tAAAAAAAAAAAAAAAAAAAAAAAAcuZ29vZ2xlLmNvbQ")); parse_internal_link("tg:proxy?server=1.2.3.4&port=80&secret=1234567890abcdef1234567890ABCDEF", - proxy_mtproto("1.2.3.4", 80, "1234567890abcdef1234567890ABCDEF")); + proxy_mtproto("1.2.3.4", 80, "1234567890abcdef1234567890abcdef")); parse_internal_link("tg:proxy?server=1.2.3.4&port=80adasdas&secret=1234567890abcdef1234567890ABCDEF", - proxy_mtproto("1.2.3.4", 80, "1234567890abcdef1234567890ABCDEF")); + proxy_mtproto("1.2.3.4", 80, "1234567890abcdef1234567890abcdef")); parse_internal_link("tg:proxy?server=1.2.3.4&port=adasdas&secret=1234567890abcdef1234567890ABCDEF", unsupported_proxy()); parse_internal_link("tg:proxy?server=1.2.3.4&port=65536&secret=1234567890abcdef1234567890ABCDEF", unsupported_proxy()); parse_internal_link("tg:proxy?server=google.com&port=8%30&secret=1234567890abcdef1234567890ABCDEF", - proxy_mtproto("google.com", 80, "1234567890abcdef1234567890ABCDEF")); + proxy_mtproto("google.com", 80, "1234567890abcdef1234567890abcdef")); parse_internal_link("tg:proxy?server=google.com&port=8%30&secret=dd1234567890abcdef1234567890ABCDEF", - proxy_mtproto("google.com", 80, "dd1234567890abcdef1234567890ABCDEF")); + proxy_mtproto("google.com", 80, "dd1234567890abcdef1234567890abcdef")); parse_internal_link("tg:proxy?server=google.com&port=8%30&secret=de1234567890abcdef1234567890ABCDEF", unsupported_proxy()); @@ -757,7 +922,7 @@ TEST(Link, parse_internal_link) { parse_internal_link("t.me/username/0/a//s/as?voicechat=", video_chat("username", "", false)); parse_internal_link("t.me/username/0/a//s/as?videochat=2", video_chat("username", "2", false)); parse_internal_link("t.me/username/0/a//s/as?livestream=3", video_chat("username", "3", true)); - parse_internal_link("t.me/username/aasdas?test=1&voicechat=#12312", video_chat("username", "", false)); + parse_internal_link("t.me/username/aasdas/2?test=1&voicechat=#12312", video_chat("username", "", false)); parse_internal_link("t.me/username/0?voicechat=", video_chat("username", "", false)); parse_internal_link("t.me/username/-1?voicechat=asdasd", video_chat("username", "asdasd", false)); parse_internal_link("t.me/username?voicechat=", video_chat("username", "", false)); @@ -775,7 +940,7 @@ TEST(Link, parse_internal_link) { parse_internal_link("tg:resolve?domain=telegram&&&&&&&start=%30", bot_start("telegram", "0")); parse_internal_link("t.me/username/0/a//s/as?start=", bot_start("username", "")); - parse_internal_link("t.me/username/aasdas?test=1&start=#12312", bot_start("username", "")); + parse_internal_link("t.me/username/aasdas/2?test=1&start=#12312", bot_start("username", "")); parse_internal_link("t.me/username/0?start=", bot_start("username", "")); parse_internal_link("t.me/username/-1?start=asdasd", bot_start("username", "asdasd")); parse_internal_link("t.me/username?start=", bot_start("username", "")); @@ -821,7 +986,7 @@ TEST(Link, parse_internal_link) { true, true, false))); parse_internal_link("t.me/username/0/a//s/as?startgroup=", bot_start_in_group("username", "", nullptr)); - parse_internal_link("t.me/username/aasdas?test=1&startgroup=#12312", bot_start_in_group("username", "", nullptr)); + parse_internal_link("t.me/username/aasdas/2?test=1&startgroup=#12312", bot_start_in_group("username", "", nullptr)); parse_internal_link("t.me/username/0?startgroup=", bot_start_in_group("username", "", nullptr)); parse_internal_link("t.me/username/-1?startgroup=asdasd", bot_start_in_group("username", "asdasd", nullptr)); parse_internal_link("t.me/username?startgroup=", bot_start_in_group("username", "", nullptr)); @@ -857,7 +1022,9 @@ TEST(Link, parse_internal_link) { "restrict_members+pin_messages+manage_topics+promote_members+manage_video_chats+anonymous", bot_add_to_channel("username", chat_administrator_rights(true, true, true, true, true, true, true, false, false, true, true, false))); +} +TEST(Link, parse_internal_link_part4) { parse_internal_link("tg:resolve?domain=username&game=aasdasd", game("username", "aasdasd")); parse_internal_link("TG://resolve?domain=username&game=", public_chat("username")); parse_internal_link("TG://test@resolve?domain=username&game=asd", nullptr); @@ -865,10 +1032,12 @@ TEST(Link, parse_internal_link) { parse_internal_link("tg:http://resolve?domain=username&game=asd", nullptr); parse_internal_link("tg:https://resolve?domain=username&game=asd", nullptr); parse_internal_link("tg:resolve?domain=&game=asd", unknown_deep_link("tg://resolve?domain=&game=asd")); - parse_internal_link("tg:resolve?domain=telegram&&&&&&&game=%30", game("telegram", "0")); + parse_internal_link("tg:resolve?domain=telegram&&&&&&&game=%30", public_chat("telegram")); + parse_internal_link("tg:resolve?domain=telegram&&&&&&&game=%30ab", public_chat("telegram")); + parse_internal_link("tg:resolve?domain=telegram&&&&&&&game=ab%30", game("telegram", "ab0")); parse_internal_link("t.me/username/0/a//s/as?game=asd", game("username", "asd")); - parse_internal_link("t.me/username/aasdas?test=1&game=asd#12312", game("username", "asd")); + parse_internal_link("t.me/username/aasdas/2?test=1&game=asd#12312", game("username", "asd")); parse_internal_link("t.me/username/0?game=asd", game("username", "asd")); parse_internal_link("t.me/username/-1?game=asdasd", game("username", "asdasd")); parse_internal_link("t.me/username?game=asd", game("username", "asd")); @@ -877,6 +1046,35 @@ TEST(Link, parse_internal_link) { parse_internal_link("t.me//username?game=asd", nullptr); parse_internal_link("https://telegram.dog/tele%63ram?game=t%63st", game("telecram", "tcst")); + parse_internal_link("tg:resolve?domain=username&appname=aasdasd&startapp=123asd", + web_app("username", "aasdasd", "123asd")); + parse_internal_link("TG://resolve?domain=username&appname=&startapp=123asd", public_chat("username")); + parse_internal_link("TG://test@resolve?domain=username&appname=asd", nullptr); + parse_internal_link("tg:resolve:80?domain=username&appname=asd", nullptr); + parse_internal_link("tg:http://resolve?domain=username&appname=asd", nullptr); + parse_internal_link("tg:https://resolve?domain=username&appname=asd", nullptr); + parse_internal_link("tg:resolve?domain=&appname=asd", unknown_deep_link("tg://resolve?domain=&appname=asd")); + parse_internal_link("tg:resolve?domain=telegram&&&&&&&appname=%41&startapp=", public_chat("telegram")); + parse_internal_link("tg:resolve?domain=telegram&&&&&&&appname=%41b&startapp=", public_chat("telegram")); + parse_internal_link("tg:resolve?domain=telegram&&&&&&&appname=%41bc&startapp=", web_app("telegram", "Abc", "")); + + parse_internal_link("t.me/username/0/a//s/as?appname=asd", public_chat("username")); + parse_internal_link("t.me/username/aasdas/2?test=1&appname=asd#12312", public_chat("username")); + parse_internal_link("t.me/username/0?appname=asd", public_chat("username")); + parse_internal_link("t.me/username/-1?appname=asdasd", public_chat("username")); + parse_internal_link("t.me/username?appname=asd", public_chat("username")); + parse_internal_link("t.me/username?appname=", public_chat("username")); + parse_internal_link("t.me/username#appname=asdas", public_chat("username")); + parse_internal_link("t.me//username?appname=asd", nullptr); + parse_internal_link("https://telegram.dog/tele%63ram?appname=t%63st", public_chat("telecram")); + parse_internal_link("t.me/username/def/asd", public_chat("username")); + parse_internal_link("t.me/username/asd#12312&startapp=qwe", web_app("username", "asd", "")); + parse_internal_link("t.me/username/asd?12312&startapp=qwe", web_app("username", "asd", "qwe")); + parse_internal_link("t.me/username/asdasd?startapp=0", web_app("username", "asdasd", "0")); + parse_internal_link("t.me/username/asd", web_app("username", "asd", "")); + parse_internal_link("t.me/username/", public_chat("username")); + parse_internal_link("https://telegram.dog/tele%63ram/t%63st", web_app("telecram", "tcst", "")); + parse_internal_link("tg:resolve?domain=username&Game=asd", public_chat("username")); parse_internal_link("TG://test@resolve?domain=username", nullptr); parse_internal_link("tg:resolve:80?domain=username", nullptr); @@ -898,7 +1096,7 @@ TEST(Link, parse_internal_link) { parse_internal_link("t.me/asdf0", public_chat("asdf0")); parse_internal_link("t.me/asd__fg", nullptr); parse_internal_link("t.me/username/0/a//s/as?gam=asd", public_chat("username")); - parse_internal_link("t.me/username/aasdas?test=1", public_chat("username")); + parse_internal_link("t.me/username/aasdas/2?test=1", public_chat("username")); parse_internal_link("t.me/username/0", public_chat("username")); parse_internal_link("t.me//username", nullptr); parse_internal_link("https://telegram.dog/tele%63ram", public_chat("telecram")); @@ -943,9 +1141,11 @@ TEST(Link, parse_internal_link) { parse_internal_link("tg://settings/themes/?as#rad", theme_settings()); parse_internal_link("tg://settings/themes/a", settings()); parse_internal_link("tg://settings/asdsathemesasdas/devices", settings()); + parse_internal_link("tg://settings/auto_delete", default_message_auto_delete_timer_settings()); parse_internal_link("tg://settings/devices", active_sessions()); parse_internal_link("tg://settings/change_number", change_phone_number()); - parse_internal_link("tg://settings/folders", filter_settings()); + parse_internal_link("tg://settings/edit_profile", edit_profile_settings()); + parse_internal_link("tg://settings/folders", chat_folder_settings()); parse_internal_link("tg://settings/filters", settings()); parse_internal_link("tg://settings/language", language_settings()); parse_internal_link("tg://settings/privacy", privacy_and_security_settings()); @@ -953,8 +1153,8 @@ TEST(Link, parse_internal_link) { parse_internal_link("username.t.me////0/a//s/as?start=", bot_start("username", "")); parse_internal_link("username.t.me?start=as", bot_start("username", "as")); parse_internal_link("username.t.me", public_chat("username")); - parse_internal_link("aAAb.t.me/12345?single", message("tg:resolve?domain=aaab&post=12345&single")); - parse_internal_link("telegram.t.me/195", message("tg:resolve?domain=telegram&post=195")); + parse_internal_link("aAAb.t.me/12345?single", message("tg://resolve?domain=aaab&post=12345&single")); + parse_internal_link("telegram.t.me/195", message("tg://resolve?domain=telegram&post=195")); parse_internal_link("shares.t.me", public_chat("shares")); parse_internal_link("c.t.me/12345?single", nullptr); @@ -963,6 +1163,7 @@ TEST(Link, parse_internal_link) { parse_internal_link("0aaa.t.me/12345?single", nullptr); parse_internal_link("_aaa.t.me/12345?single", nullptr); parse_internal_link("addemoji.t.me", nullptr); + parse_internal_link("addlist.t.me", nullptr); parse_internal_link("addstickers.t.me", nullptr); parse_internal_link("addtheme.t.me", nullptr); parse_internal_link("auth.t.me", nullptr); diff --git a/protocols/Telegram/tdlib/td/test/main.cpp b/protocols/Telegram/tdlib/td/test/main.cpp index 064871ae31..9a774b37db 100644 --- a/protocols/Telegram/tdlib/td/test/main.cpp +++ b/protocols/Telegram/tdlib/td/test/main.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 // // 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) @@ -32,6 +32,8 @@ int main(int argc, char **argv) { td::OptionParser options; options.add_option('f', "filter", "run only specified tests", [&](td::Slice filter) { runner.add_substr_filter(filter.str()); }); + options.add_option('o', "offset", "run tests from the specified test", + [&](td::Slice offset) { runner.set_offset(offset.str()); }); options.add_option('s', "stress", "run tests infinitely", [&] { runner.set_stress_flag(true); }); options.add_checked_option('v', "verbosity", "log verbosity level", td::OptionParser::parse_integer(default_verbosity_level)); diff --git a/protocols/Telegram/tdlib/td/test/message_entities.cpp b/protocols/Telegram/tdlib/td/test/message_entities.cpp index 9c62415579..378e76b23a 100644 --- a/protocols/Telegram/tdlib/td/test/message_entities.cpp +++ b/protocols/Telegram/tdlib/td/test/message_entities.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 // // 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) @@ -725,16 +725,16 @@ static void check_fix_formatted_text(td::string str, td::vector &expected_entities, bool allow_empty = true, bool skip_new_entities = false, bool skip_bot_commands = false, - bool for_draft = true) { - ASSERT_TRUE(td::fix_formatted_text(str, entities, allow_empty, skip_new_entities, skip_bot_commands, true, for_draft) + bool skip_trim = true) { + ASSERT_TRUE(td::fix_formatted_text(str, entities, allow_empty, skip_new_entities, skip_bot_commands, true, skip_trim) .is_ok()); ASSERT_STREQ(expected_str, str); ASSERT_EQ(expected_entities, entities); } static void check_fix_formatted_text(td::string str, td::vector entities, bool allow_empty, - bool skip_new_entities, bool skip_bot_commands, bool for_draft) { - ASSERT_TRUE(td::fix_formatted_text(str, entities, allow_empty, skip_new_entities, skip_bot_commands, true, for_draft) + bool skip_new_entities, bool skip_bot_commands, bool skip_trim) { + ASSERT_TRUE(td::fix_formatted_text(str, entities, allow_empty, skip_new_entities, skip_bot_commands, true, skip_trim) .is_error()); } @@ -815,9 +815,9 @@ TEST(MessageEntities, fix_formatted_text) { } str = " /test @abaca #ORD $ABC telegram.org "; - for (auto for_draft : {false, true}) { - td::int32 shift = for_draft ? 2 : 0; - td::string expected_str = for_draft ? str : str.substr(2, str.size() - 3); + for (auto skip_trim : {false, true}) { + td::int32 shift = skip_trim ? 2 : 0; + td::string expected_str = skip_trim ? str : str.substr(2, str.size() - 3); for (auto skip_new_entities : {false, true}) { for (auto skip_bot_commands : {false, true}) { @@ -833,9 +833,9 @@ TEST(MessageEntities, fix_formatted_text) { } check_fix_formatted_text(str, {}, expected_str, entities, true, skip_new_entities, skip_bot_commands, - for_draft); + skip_trim); check_fix_formatted_text(str, {}, expected_str, entities, false, skip_new_entities, skip_bot_commands, - for_draft); + skip_trim); } } } @@ -846,8 +846,8 @@ TEST(MessageEntities, fix_formatted_text) { for (td::int32 offset = 0; static_cast(offset + length) <= str.size(); offset++) { for (auto type : {td::MessageEntity::Type::Bold, td::MessageEntity::Type::Url, td::MessageEntity::Type::TextUrl, td::MessageEntity::Type::MentionName}) { - for (auto for_draft : {false, true}) { - fixed_str = for_draft ? "aba \n caba " : "aba \n caba"; + for (auto skip_trim : {false, true}) { + fixed_str = skip_trim ? "aba \n caba " : "aba \n caba"; auto fixed_length = offset <= 4 && offset + length >= 5 ? length - 1 : length; auto fixed_offset = offset >= 5 ? offset - 1 : offset; if (static_cast(fixed_offset) >= fixed_str.size()) { @@ -885,7 +885,7 @@ TEST(MessageEntities, fix_formatted_text) { } } } - check_fix_formatted_text(str, entities, fixed_str, fixed_entities, true, false, false, for_draft); + check_fix_formatted_text(str, entities, fixed_str, fixed_entities, true, false, false, skip_trim); } } } @@ -1250,66 +1250,50 @@ TEST(MessageEntities, parse_html) { check_parse_html("🏟 🏟<aa", - "Unmatched end tag at byte offset 17, expected \"\", found \"\""); + check_parse_html("🏟 🏟<a", "Unmatched end tag at byte offset 17, expected \"\", found \"\""); check_parse_html("", "", {}); check_parse_html("➡️ ➡️", "➡️ ➡️", {}); - check_parse_html("<>&"«»�", "<>&\"«»�", {}); - check_parse_html("➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️", - {{td::MessageEntity::Type::Italic, 5, 5}}); - check_parse_html("➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️", - {{td::MessageEntity::Type::Italic, 5, 5}}); - check_parse_html("➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️", - {{td::MessageEntity::Type::Bold, 5, 5}}); - check_parse_html("➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️", - {{td::MessageEntity::Type::Bold, 5, 5}}); - check_parse_html("➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️", - {{td::MessageEntity::Type::Underline, 5, 5}}); - check_parse_html("➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️", - {{td::MessageEntity::Type::Underline, 5, 5}}); - check_parse_html("➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️", - {{td::MessageEntity::Type::Strikethrough, 5, 5}}); - check_parse_html("➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️", - {{td::MessageEntity::Type::Strikethrough, 5, 5}}); - check_parse_html("➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️", - {{td::MessageEntity::Type::Strikethrough, 5, 5}}); + check_parse_html("≥<>&"«»�", "≥<>&\"«»�", {}); + check_parse_html("⩔", "⩔", {}); + check_parse_html("➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️", {{td::MessageEntity::Type::Italic, 5, 5}}); + check_parse_html("➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️", {{td::MessageEntity::Type::Italic, 5, 5}}); + check_parse_html("➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️", {{td::MessageEntity::Type::Bold, 5, 5}}); + check_parse_html("➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️", {{td::MessageEntity::Type::Bold, 5, 5}}); + check_parse_html("➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️", {{td::MessageEntity::Type::Underline, 5, 5}}); + check_parse_html("➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️", {{td::MessageEntity::Type::Underline, 5, 5}}); + check_parse_html("➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️", {{td::MessageEntity::Type::Strikethrough, 5, 5}}); + check_parse_html("➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️", {{td::MessageEntity::Type::Strikethrough, 5, 5}}); + check_parse_html("➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️", {{td::MessageEntity::Type::Strikethrough, 5, 5}}); check_parse_html("➡️ ➡️➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️➡️ ➡️", {{td::MessageEntity::Type::Italic, 5, 5}, {td::MessageEntity::Type::Bold, 10, 5}}); check_parse_html("🏟 🏟🏟 <🏟", "🏟 🏟🏟 <🏟", {{td::MessageEntity::Type::Italic, 5, 6}}); check_parse_html("🏟 🏟🏟 ><🏟", "🏟 🏟🏟 ><🏟", {{td::MessageEntity::Type::Italic, 5, 7}, {td::MessageEntity::Type::Bold, 9, 3}}); - check_parse_html("🏟 🏟<a", "🏟 🏟a", "🏟 🏟a", "🏟 🏟a", "🏟 🏟a", "🏟 🏟a", "🏟 🏟a", "🏟 🏟🏟 🏟<", "🏟 🏟<🏟 🏟<", - {{td::MessageEntity::Type::Italic, 6, 6}}); + check_parse_html("🏟 🏟<🏟 🏟<", "🏟 🏟<🏟 🏟<", {{td::MessageEntity::Type::Italic, 6, 6}}); check_parse_html("🏟 🏟<a", "🏟 🏟a", "🏟 🏟", "🏟 🏟<", {}); check_parse_html("\t", "\t", {{td::MessageEntity::Type::Italic, 0, 1}}); check_parse_html("\r", "\r", {{td::MessageEntity::Type::Italic, 0, 1}}); check_parse_html("\n", "\n", {{td::MessageEntity::Type::Italic, 0, 1}}); - check_parse_html("➡️ ➡️➡️ ➡️➡️ ➡️", - "➡️ ➡️➡️ ➡️➡️ ➡️", + check_parse_html("➡️ ➡️➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️➡️ ➡️", {{td::MessageEntity::Type::Spoiler, 5, 5}, {td::MessageEntity::Type::Bold, 10, 5}}); check_parse_html("🏟 🏟🏟 <🏟", "🏟 🏟🏟 <🏟", {{td::MessageEntity::Type::Spoiler, 5, 6}}); - check_parse_html("🏟 🏟🏟 ><🏟", - "🏟 🏟🏟 ><🏟", + check_parse_html("🏟 🏟🏟 ><🏟", "🏟 🏟🏟 ><🏟", {{td::MessageEntity::Type::Spoiler, 5, 7}, {td::MessageEntity::Type::Bold, 9, 3}}); - check_parse_html("➡️ ➡️➡️ ➡️➡️ ➡️", - "➡️ ➡️➡️ ➡️➡️ ➡️", + check_parse_html("➡️ ➡️➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️➡️ ➡️", {{td::MessageEntity::Type::Spoiler, 5, 5}, {td::MessageEntity::Type::Bold, 10, 5}}); - check_parse_html("🏟 🏟🏟 <🏟", "🏟 🏟🏟 <🏟", - {{td::MessageEntity::Type::Spoiler, 5, 6}}); + check_parse_html("🏟 🏟🏟 <🏟", "🏟 🏟🏟 <🏟", {{td::MessageEntity::Type::Spoiler, 5, 6}}); check_parse_html("🏟 🏟🏟 ><🏟", "🏟 🏟🏟 ><🏟", {{td::MessageEntity::Type::Spoiler, 5, 7}, {td::MessageEntity::Type::Bold, 9, 3}}); check_parse_html("\t", "\t", @@ -1343,10 +1327,8 @@ TEST(MessageEntities, parse_html) { {{td::MessageEntity::Type::TextUrl, 0, 12, "http://telegram.org/"}}); check_parse_html("https://telegram.org/asdsa?asdasdwe#12e3we", "https://telegram.org/asdsa?asdasdwe#12e3we", {{td::MessageEntity::Type::TextUrl, 0, 42, "https://telegram.org/asdsa?asdasdwe#12e3we"}}); - check_parse_html("🏟 🏟<
🏟 🏟<", "🏟 🏟<🏟 🏟<",
-                   {{td::MessageEntity::Type::Pre, 6, 6}});
-  check_parse_html("🏟 🏟<🏟 🏟<", "🏟 🏟<🏟 🏟<",
-                   {{td::MessageEntity::Type::Code, 6, 6}});
+  check_parse_html("🏟 🏟<
🏟 🏟<", "🏟 🏟<🏟 🏟<", {{td::MessageEntity::Type::Pre, 6, 6}});
+  check_parse_html("🏟 🏟<🏟 🏟<", "🏟 🏟<🏟 🏟<", {{td::MessageEntity::Type::Code, 6, 6}});
   check_parse_html("🏟 🏟<
🏟 🏟<", "🏟 🏟<🏟 🏟<",
                    {{td::MessageEntity::Type::Pre, 6, 6}, {td::MessageEntity::Type::Code, 6, 6}});
   check_parse_html("🏟 🏟<
🏟 🏟<", "🏟 🏟<🏟 🏟<",
@@ -1359,8 +1341,7 @@ TEST(MessageEntities, parse_html) {
                    {{td::MessageEntity::Type::Pre, 6, 7}, {td::MessageEntity::Type::Code, 6, 6}});
   check_parse_html("🏟 🏟<
 🏟 🏟<", "🏟 🏟< 🏟 🏟<",
                    {{td::MessageEntity::Type::Pre, 6, 7}, {td::MessageEntity::Type::Code, 7, 6}});
-  check_parse_html("➡️ ➡️➡️ ➡️➡️ ➡️",
-                   "➡️ ➡️➡️ ➡️➡️ ➡️",
+  check_parse_html("➡️ ➡️➡️ ➡️➡️ ➡️", "➡️ ➡️➡️ ➡️➡️ ➡️",
                    {{td::MessageEntity::Type::CustomEmoji, 5, 5, td::CustomEmojiId(static_cast(12345))},
                     {td::MessageEntity::Type::Bold, 10, 5}});
   check_parse_html("🏟 🏟🏟 <🏟", "🏟 🏟🏟 <🏟",
@@ -1443,8 +1424,7 @@ TEST(MessageEntities, parse_markdown) {
   check_parse_markdown("🏟 🏟_abac \\* asd _", "🏟 🏟abac * asd ", {{td::MessageEntity::Type::Italic, 5, 11}});
   check_parse_markdown("🏟 \\.🏟_🏟\\. 🏟_", "🏟 .🏟🏟. 🏟", {{td::MessageEntity::Type::Italic, 6, 6}});
   check_parse_markdown("\\\\\\a\\b\\c\\d\\e\\f\\1\\2\\3\\4\\➡️\\", "\\abcdef1234\\➡️\\", {});
-  check_parse_markdown("➡️ ➡️_➡️ ➡️_", "➡️ ➡️➡️ ➡️",
-                       {{td::MessageEntity::Type::Italic, 5, 5}});
+  check_parse_markdown("➡️ ➡️_➡️ ➡️_", "➡️ ➡️➡️ ➡️", {{td::MessageEntity::Type::Italic, 5, 5}});
   check_parse_markdown("➡️ ➡️_➡️ ➡️_*➡️ ➡️*", "➡️ ➡️➡️ ➡️➡️ ➡️",
                        {{td::MessageEntity::Type::Italic, 5, 5}, {td::MessageEntity::Type::Bold, 10, 5}});
   check_parse_markdown("🏟 🏟_🏟 \\.🏟_", "🏟 🏟🏟 .🏟", {{td::MessageEntity::Type::Italic, 5, 6}});
@@ -1457,22 +1437,14 @@ TEST(MessageEntities, parse_markdown) {
   check_parse_markdown("🏟 🏟__🏟 _🏟_\\___", "🏟 🏟🏟 🏟_",
                        {{td::MessageEntity::Type::Underline, 5, 6}, {td::MessageEntity::Type::Italic, 8, 2}});
   check_parse_markdown("🏟 🏟`🏟 🏟```", "🏟 🏟🏟 🏟", {{td::MessageEntity::Type::Code, 5, 5}});
-  check_parse_markdown("🏟 🏟```🏟 🏟```", "🏟 🏟 🏟",
-                       {{td::MessageEntity::Type::PreCode, 5, 3, "🏟"}});
-  check_parse_markdown("🏟 🏟```🏟\n🏟```", "🏟 🏟🏟",
-                       {{td::MessageEntity::Type::PreCode, 5, 2, "🏟"}});
-  check_parse_markdown("🏟 🏟```🏟\r🏟```", "🏟 🏟🏟",
-                       {{td::MessageEntity::Type::PreCode, 5, 2, "🏟"}});
-  check_parse_markdown("🏟 🏟```🏟\n\r🏟```", "🏟 🏟🏟",
-                       {{td::MessageEntity::Type::PreCode, 5, 2, "🏟"}});
-  check_parse_markdown("🏟 🏟```🏟\r\n🏟```", "🏟 🏟🏟",
-                       {{td::MessageEntity::Type::PreCode, 5, 2, "🏟"}});
-  check_parse_markdown("🏟 🏟```🏟\n\n🏟```", "🏟 🏟\n🏟",
-                       {{td::MessageEntity::Type::PreCode, 5, 3, "🏟"}});
-  check_parse_markdown("🏟 🏟```🏟\r\r🏟```", "🏟 🏟\r🏟",
-                       {{td::MessageEntity::Type::PreCode, 5, 3, "🏟"}});
-  check_parse_markdown("🏟 🏟```🏟 \\\\\\`🏟```", "🏟 🏟 \\`🏟",
-                       {{td::MessageEntity::Type::PreCode, 5, 5, "🏟"}});
+  check_parse_markdown("🏟 🏟```🏟 🏟```", "🏟 🏟 🏟", {{td::MessageEntity::Type::PreCode, 5, 3, "🏟"}});
+  check_parse_markdown("🏟 🏟```🏟\n🏟```", "🏟 🏟🏟", {{td::MessageEntity::Type::PreCode, 5, 2, "🏟"}});
+  check_parse_markdown("🏟 🏟```🏟\r🏟```", "🏟 🏟🏟", {{td::MessageEntity::Type::PreCode, 5, 2, "🏟"}});
+  check_parse_markdown("🏟 🏟```🏟\n\r🏟```", "🏟 🏟🏟", {{td::MessageEntity::Type::PreCode, 5, 2, "🏟"}});
+  check_parse_markdown("🏟 🏟```🏟\r\n🏟```", "🏟 🏟🏟", {{td::MessageEntity::Type::PreCode, 5, 2, "🏟"}});
+  check_parse_markdown("🏟 🏟```🏟\n\n🏟```", "🏟 🏟\n🏟", {{td::MessageEntity::Type::PreCode, 5, 3, "🏟"}});
+  check_parse_markdown("🏟 🏟```🏟\r\r🏟```", "🏟 🏟\r🏟", {{td::MessageEntity::Type::PreCode, 5, 3, "🏟"}});
+  check_parse_markdown("🏟 🏟```🏟 \\\\\\`🏟```", "🏟 🏟 \\`🏟", {{td::MessageEntity::Type::PreCode, 5, 5, "🏟"}});
   check_parse_markdown("🏟 🏟**", "🏟 🏟", {});
   check_parse_markdown("||test||", "test", {{td::MessageEntity::Type::Spoiler, 0, 4}});
   check_parse_markdown("🏟 🏟``", "🏟 🏟", {});
@@ -1532,19 +1504,18 @@ TEST(MessageEntities, parse_markdown_v3) {
   check_parse_markdown_v3("🏟````🏟``🏟`aba🏟```c🏟`aba🏟 daba🏟```c🏟`aba🏟```🏟 `🏟``🏟```",
                           "🏟````🏟``🏟aba🏟```c🏟aba🏟 daba🏟c🏟`aba🏟🏟 `🏟``🏟```",
                           {{td::MessageEntity::Type::Code, 12, 11}, {td::MessageEntity::Type::Pre, 35, 9}});
-  check_parse_markdown_v3(
-      "🏟````🏟``🏟`aba🏟```c🏟`aba🏟 daba🏟```c🏟`aba🏟🏟```🏟 `🏟``🏟```",
-      {{td::MessageEntity::Type::Italic, 12, 1},
-       {td::MessageEntity::Type::Italic, 44, 1},
-       {td::MessageEntity::Type::Bold, 45, 1},
-       {td::MessageEntity::Type::Bold, 49, 2}},
-      "🏟````🏟``🏟`aba🏟c🏟`aba🏟 daba🏟c🏟`aba🏟🏟🏟 `🏟``🏟",
-      {{td::MessageEntity::Type::Italic, 12, 1},
-       {td::MessageEntity::Type::Pre, 18, 16},
-       {td::MessageEntity::Type::Italic, 38, 1},
-       {td::MessageEntity::Type::Bold, 39, 1},
-       {td::MessageEntity::Type::Bold, 43, 2},
-       {td::MessageEntity::Type::Pre, 45, 10}});
+  check_parse_markdown_v3("🏟````🏟``🏟`aba🏟```c🏟`aba🏟 daba🏟```c🏟`aba🏟🏟```🏟 `🏟``🏟```",
+                          {{td::MessageEntity::Type::Italic, 12, 1},
+                           {td::MessageEntity::Type::Italic, 44, 1},
+                           {td::MessageEntity::Type::Bold, 45, 1},
+                           {td::MessageEntity::Type::Bold, 49, 2}},
+                          "🏟````🏟``🏟`aba🏟c🏟`aba🏟 daba🏟c🏟`aba🏟🏟🏟 `🏟``🏟",
+                          {{td::MessageEntity::Type::Italic, 12, 1},
+                           {td::MessageEntity::Type::Pre, 18, 16},
+                           {td::MessageEntity::Type::Italic, 38, 1},
+                           {td::MessageEntity::Type::Bold, 39, 1},
+                           {td::MessageEntity::Type::Bold, 43, 2},
+                           {td::MessageEntity::Type::Pre, 45, 10}});
   check_parse_markdown_v3("` `", " ", {{td::MessageEntity::Type::Code, 0, 1}});
   check_parse_markdown_v3("`\n`", "\n", {{td::MessageEntity::Type::Code, 0, 1}});
   check_parse_markdown_v3("` `a", " a", {{td::MessageEntity::Type::Code, 0, 1}}, true);
diff --git a/protocols/Telegram/tdlib/td/test/mtproto.cpp b/protocols/Telegram/tdlib/td/test/mtproto.cpp
index 89f5441ab5..614e153e6f 100644
--- a/protocols/Telegram/tdlib/td/test/mtproto.cpp
+++ b/protocols/Telegram/tdlib/td/test/mtproto.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
 //
 // 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)
@@ -241,7 +241,7 @@ class TestPingActor final : public td::Actor {
       return stop();
     }
     if (ping_connection_->was_pong()) {
-      LOG(INFO) << "GOT PONG";
+      LOG(INFO) << "Receive pong";
       return stop();
     }
   }
@@ -604,7 +604,7 @@ class FastPingTestActor final : public td::Actor {
       if (iteration_ % 2 == 0) {
         auth_data = td::make_unique();
         auth_data->set_tmp_auth_key(handshake_->get_auth_key());
-        auth_data->set_server_time_difference(handshake_->get_server_time_diff());
+        auth_data->reset_server_time_difference(handshake_->get_server_time_diff());
         auth_data->set_server_salt(handshake_->get_server_salt(), td::Time::now());
         auth_data->set_future_salts({td::mtproto::ServerSalt{0u, 1e20, 1e30}}, td::Time::now());
         auth_data->set_use_pfs(true);
diff --git a/protocols/Telegram/tdlib/td/test/online.cpp b/protocols/Telegram/tdlib/td/test/online.cpp
index 6bcdcec833..de7afa8a66 100644
--- a/protocols/Telegram/tdlib/td/test/online.cpp
+++ b/protocols/Telegram/tdlib/td/test/online.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
 //
 // 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)
@@ -23,6 +23,7 @@
 #include "td/utils/port/signals.h"
 #include "td/utils/Promise.h"
 #include "td/utils/Random.h"
+#include "td/utils/tests.h"
 
 #include 
 #include 
@@ -220,14 +221,12 @@ class InitTask : public Task {
  private:
   Options options_;
   td::Promise<> promise_;
-  bool start_flag_{false};
 
   void start_up() override {
-    send_query(td::make_tl_object(),
-               [this](auto res) { this->process_authorization_state(res.move_as_ok()); });
+    send_query(td::make_tl_object("version"),
+               [](auto res) { LOG(INFO) << td::td_api::to_string(res.ok()); });
   }
   void process_authorization_state(td::tl_object_ptr authorization_state) {
-    start_flag_ = true;
     td::tl_object_ptr function;
     switch (authorization_state->get_id()) {
       case td::td_api::authorizationStateReady::ID:
@@ -266,9 +265,6 @@ class InitTask : public Task {
     });
   }
   void process_update(std::shared_ptr update) override {
-    if (!start_flag_) {
-      return;
-    }
     if (!update->object) {
       return;
     }
@@ -325,7 +321,7 @@ class UploadFile : public Task {
     auto r_id = read_file(id_path_);
     if (r_id.is_ok() && r_id.ok().size() > 10) {
       auto id = r_id.move_as_ok();
-      LOG(ERROR) << "Got file from cache";
+      LOG(ERROR) << "Receive file from cache";
       Result res;
       res.content = std::move(content_);
       res.remote_id = id.as_slice().str();
@@ -437,16 +433,16 @@ class TestDownloadFile : public Task {
       begin = end;
     }
 
-    random_shuffle(as_mutable_span(ranges_), rnd);
+    rand_shuffle(as_mutable_span(ranges_), rnd);
     start_chunk();
   }
 
-  void got_chunk(const td_api::file &file) {
-    LOG(ERROR) << "Got chunk";
+  void on_get_chunk(const td_api::file &file) {
+    LOG(ERROR) << "Receive chunk";
     auto range = ranges_.back();
-    std::string got_chunk(range.end - range.begin, '\0');
-    FileFd::open(file.local_->path_, FileFd::Flags::Read).move_as_ok().pread(got_chunk, range.begin).ensure();
-    CHECK(got_chunk == as_slice(content_).substr(range.begin, range.end - range.begin));
+    std::string received_chunk(range.end - range.begin, '\0');
+    FileFd::open(file.local_->path_, FileFd::Flags::Read).move_as_ok().pread(received_chunk, range.begin).ensure();
+    CHECK(received_chunk == as_slice(content_).substr(range.begin, range.end - range.begin));
     ranges_.pop_back();
     if (ranges_.empty()) {
       promise_.set_value(Unit{});
@@ -459,7 +455,7 @@ class TestDownloadFile : public Task {
     send_query(td::make_tl_object(
                    file_id_, 1, static_cast(ranges_.back().begin),
                    static_cast(ranges_.back().end - ranges_.back().begin), true),
-               [this](auto res) { got_chunk(*res.ok()); });
+               [this](auto res) { on_get_chunk(*res.ok()); });
   }
 };
 
diff --git a/protocols/Telegram/tdlib/td/test/poll.cpp b/protocols/Telegram/tdlib/td/test/poll.cpp
index 4c8012e441..3629c3c136 100644
--- a/protocols/Telegram/tdlib/td/test/poll.cpp
+++ b/protocols/Telegram/tdlib/td/test/poll.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
 //
 // 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)
diff --git a/protocols/Telegram/tdlib/td/test/query_merger.cpp b/protocols/Telegram/tdlib/td/test/query_merger.cpp
new file mode 100644
index 0000000000..becac44e65
--- /dev/null
+++ b/protocols/Telegram/tdlib/td/test/query_merger.cpp
@@ -0,0 +1,102 @@
+//
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
+//
+// 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/telegram/QueryMerger.h"
+
+#include "td/actor/actor.h"
+#include "td/actor/ConcurrentScheduler.h"
+#include "td/actor/SleepActor.h"
+
+#include "td/utils/common.h"
+#include "td/utils/FlatHashSet.h"
+#include "td/utils/logging.h"
+#include "td/utils/Promise.h"
+#include "td/utils/Random.h"
+#include "td/utils/Status.h"
+#include "td/utils/tests.h"
+
+#include 
+
+class TestQueryMerger final : public td::Actor {
+  void start_up() final {
+    query_merger_.set_merge_function([this](td::vector query_ids, td::Promise &&promise) {
+      ASSERT_TRUE(!query_ids.empty());
+      ASSERT_EQ(query_ids.size(), td::min(next_query_ids_.size(), MAX_MERGED_QUERY_COUNT));
+      for (auto query_id : query_ids) {
+        auto next_query_id = next_query_ids_.front();
+        next_query_ids_.pop();
+        ASSERT_EQ(query_id, next_query_id);
+      }
+      current_query_count_++;
+      ASSERT_TRUE(current_query_count_ <= MAX_CONCURRENT_QUERY_COUNT);
+      if (!next_query_ids_.empty()) {
+        ASSERT_EQ(current_query_count_, MAX_CONCURRENT_QUERY_COUNT);
+      }
+      td::create_actor("CompleteMergeQuery", 0.02,
+                                       td::PromiseCreator::lambda([this, query_ids, promise = std::move(promise)](
+                                                                      td::Result result) mutable {
+                                         for (auto query_id : query_ids) {
+                                           LOG(INFO) << "Complete " << query_id;
+                                           bool is_erased = pending_query_ids_.erase(query_id) > 0;
+                                           ASSERT_TRUE(is_erased);
+                                         }
+                                         current_query_count_--;
+                                         promise.set_result(std::move(result));
+                                       }))
+          .release();
+      yield();
+    });
+    loop();
+  }
+
+  void loop() final {
+    std::size_t query_count = 0;
+    std::size_t added_queries = td::Random::fast(1, 3);
+    while (query_count++ < added_queries && total_query_count_++ < MAX_QUERY_COUNT) {
+      td::int64 query_id = td::Random::fast(1, 20);
+      if (pending_query_ids_.insert(query_id).second) {
+        next_query_ids_.push(query_id);
+      }
+      query_merger_.add_query(query_id, td::PromiseCreator::lambda([this](td::Result result) mutable {
+                                completed_query_count_++;
+                                if (completed_query_count_ == MAX_QUERY_COUNT) {
+                                  ASSERT_EQ(current_query_count_, 0u);
+                                  ASSERT_TRUE(next_query_ids_.empty());
+                                  ASSERT_TRUE(pending_query_ids_.empty());
+                                  td::Scheduler::instance()->finish();
+                                } else {
+                                  yield();
+                                }
+                              }));
+    }
+  }
+
+  static constexpr std::size_t MAX_CONCURRENT_QUERY_COUNT = 5;
+  static constexpr std::size_t MAX_MERGED_QUERY_COUNT = 3;
+  static constexpr std::size_t MAX_QUERY_COUNT = 1000;
+
+  td::QueryMerger query_merger_{"QueryMerger", MAX_CONCURRENT_QUERY_COUNT, MAX_MERGED_QUERY_COUNT};
+  std::size_t current_query_count_ = 0;
+  std::size_t total_query_count_ = 0;
+  std::size_t completed_query_count_ = 0;
+
+  std::queue next_query_ids_;
+  td::FlatHashSet pending_query_ids_;
+};
+
+constexpr std::size_t TestQueryMerger::MAX_CONCURRENT_QUERY_COUNT;
+constexpr std::size_t TestQueryMerger::MAX_MERGED_QUERY_COUNT;
+constexpr std::size_t TestQueryMerger::MAX_QUERY_COUNT;
+
+TEST(QueryMerger, stress) {
+  td::ConcurrentScheduler sched(0, 0);
+  sched.create_actor_unsafe(0, "TestQueryMerger").release();
+  sched.start();
+  while (sched.run_main(10)) {
+    // empty
+  }
+  sched.finish();
+}
diff --git a/protocols/Telegram/tdlib/td/test/secret.cpp b/protocols/Telegram/tdlib/td/test/secret.cpp
index 2c79b7e2d8..bd54705695 100644
--- a/protocols/Telegram/tdlib/td/test/secret.cpp
+++ b/protocols/Telegram/tdlib/td/test/secret.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
 //
 // 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)
@@ -382,14 +382,14 @@ class FakeBinlog final
   void force_flush() final {
   }
 
-  uint64 next_id() final {
-    auto res = last_id_;
-    last_id_++;
+  uint64 next_event_id() final {
+    auto res = last_event_id_;
+    last_event_id_++;
     return res;
   }
-  uint64 next_id(int32 shift) final {
-    auto res = last_id_;
-    last_id_ += shift;
+  uint64 next_event_id(int32 shift) final {
+    auto res = last_event_id_;
+    last_event_id_ += shift;
     return res;
   }
   template 
@@ -405,7 +405,7 @@ class FakeBinlog final
     cancel_timeout();
     for (auto &pending : pending_events_) {
       auto &event = pending.event;
-      if (!event.empty()) {
+      if (!event.is_empty()) {
         // LOG(ERROR) << "FORGET EVENT: " << event.id_ << " " << event;
       }
     }
@@ -420,7 +420,7 @@ class FakeBinlog final
   }
   void close_and_destroy_impl(Promise<> promise) final {
   }
-  void add_raw_event_impl(uint64 id, BufferSlice &&raw_event, Promise<> promise, BinlogDebugInfo info) final {
+  void add_raw_event_impl(uint64 event_id, BufferSlice &&raw_event, Promise<> promise, BinlogDebugInfo info) final {
     auto event = BinlogEvent(std::move(raw_event), info);
     LOG(INFO) << "ADD EVENT: " << event.id_ << " " << event;
     pending_events_.emplace_back();
@@ -439,7 +439,7 @@ class FakeBinlog final
     for (size_t i = 0; i <= pos; i++) {
       auto &pending = pending_events_[i];
       auto event = std::move(pending.event);
-      if (!event.empty()) {
+      if (!event.is_empty()) {
         LOG(INFO) << "SAVE EVENT: " << event.id_ << " " << event;
         events_processor_.add_event(std::move(event)).ensure();
       }
@@ -464,7 +464,7 @@ class FakeBinlog final
     }
   }
   bool has_request_sync = false;
-  uint64 last_id_ = 1;
+  uint64 last_event_id_ = 1;
   detail::BinlogEventsProcessor events_processor_;
 
   struct PendingEvent {
@@ -764,11 +764,11 @@ class Master final : public Actor {
     bob_ = create_actor("SecretChatProxy bob", "bob", actor_shared(this, 2));
     send_closure(alice_.get_actor_unsafe()->actor_, &SecretChatActor::create_chat, UserId(static_cast(2)), 0,
                  123, PromiseCreator::lambda([actor_id = actor_id(this)](Result res) {
-                   send_closure(actor_id, &Master::got_secret_chat_id, std::move(res), false);
+                   send_closure(actor_id, &Master::on_get_secret_chat_id, std::move(res), false);
                  }));
   }
 
-  void got_secret_chat_id(Result res, bool dummy) {
+  void on_get_secret_chat_id(Result res, bool dummy) {
     CHECK(res.is_ok());
     auto id = res.move_as_ok();
     LOG(INFO) << "SecretChatId = " << id;
@@ -825,14 +825,14 @@ class Master final : public Actor {
   }
   void process_net_query(my_api::messages_getDhConfig &&get_dh_config, NetQueryPtr net_query,
                          ActorShared callback) {
-    //LOG(INFO) << "Got query " << to_string(get_dh_config);
+    //LOG(INFO) << "Receive query " << to_string(get_dh_config);
     my_api::messages_dhConfig config;
     config.p_ = BufferSlice(base64url_decode(prime_base64).move_as_ok());
     config.g_ = g;
     config.version_ = 12;
     auto storer = TLObjectStorer(config);
     BufferSlice answer(storer.size());
-    auto real_size = storer.store(answer.as_slice().ubegin());
+    auto real_size = storer.store(answer.as_mutable_slice().ubegin());
     CHECK(real_size == answer.size());
     net_query->set_ok(std::move(answer));
     send_closure(std::move(callback), &NetQueryCallback::on_result, std::move(net_query));
@@ -857,7 +857,7 @@ class Master final : public Actor {
     my_api::encryptedChat encrypted_chat(123, 321, 0, 1, 2, BufferSlice(), request_encryption.key_fingerprint_);
     auto storer = TLObjectStorer(encrypted_chat);
     BufferSlice answer(storer.size());
-    auto real_size = storer.store(answer.as_slice().ubegin());
+    auto real_size = storer.store(answer.as_mutable_slice().ubegin());
     CHECK(real_size == answer.size());
     net_query->set_ok(std::move(answer));
     send_closure(std::move(callback), &NetQueryCallback::on_result, std::move(net_query));
@@ -899,8 +899,8 @@ class Master final : public Actor {
   void process_net_query_send_encrypted(BufferSlice data, NetQueryPtr net_query,
                                         ActorShared callback) {
     BufferSlice answer(8);
-    answer.as_slice().fill(0);
-    as(answer.as_slice().begin()) = static_cast(my_api::messages_sentEncryptedMessage::ID);
+    answer.as_mutable_slice().fill(0);
+    as(answer.as_mutable_slice().begin()) = static_cast(my_api::messages_sentEncryptedMessage::ID);
     net_query->set_ok(std::move(answer));
     send_closure(std::move(callback), &NetQueryCallback::on_result, std::move(net_query));
 
@@ -914,7 +914,7 @@ class Master final : public Actor {
   int32 last_ping_ = std::numeric_limits::max();
   void on_inbound_message(string message, Promise<> promise) {
     promise.set_value(Unit());
-    LOG(INFO) << "GOT INBOUND MESSAGE: " << message << " " << get_link_token();
+    LOG(INFO) << "Receive inbound message: " << message << " " << get_link_token();
     int32 cnt;
     int x = std::sscanf(message.c_str(), "PING: %d", &cnt);
     if (x != 1) {
@@ -967,7 +967,7 @@ class Master final : public Actor {
   std::map sent_messages_;
 
   void hangup_shared() final {
-    LOG(INFO) << "GOT HANGUP: " << get_link_token();
+    LOG(INFO) << "Receive hang up: " << get_link_token();
     send_closure(from(), &SecretChatProxy::on_closed);
   }
 };
diff --git a/protocols/Telegram/tdlib/td/test/secure_storage.cpp b/protocols/Telegram/tdlib/td/test/secure_storage.cpp
index 774dead5ac..714e92f77a 100644
--- a/protocols/Telegram/tdlib/td/test/secure_storage.cpp
+++ b/protocols/Telegram/tdlib/td/test/secure_storage.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
 //
 // 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)
@@ -7,6 +7,7 @@
 #include "td/telegram/SecureStorage.h"
 
 #include "td/utils/buffer.h"
+#include "td/utils/common.h"
 #include "td/utils/filesystem.h"
 #include "td/utils/port/path.h"
 #include "td/utils/SliceBuilder.h"
@@ -66,5 +67,8 @@ TEST(SecureStorage, simple) {
     auto hash = td::secure_storage::encrypt_file(value_secret, value_path, encrypted_path).move_as_ok();
     td::secure_storage::decrypt_file(value_secret, hash, encrypted_path, decrypted_path).ensure();
     ASSERT_TRUE(td::read_file(decrypted_path).move_as_ok().as_slice() == file_value);
+    td::unlink(value_path).ignore();
+    td::unlink(encrypted_path).ignore();
+    td::unlink(decrypted_path).ignore();
   }
 }
diff --git a/protocols/Telegram/tdlib/td/test/set_with_position.cpp b/protocols/Telegram/tdlib/td/test/set_with_position.cpp
index c65b8bc362..f8494b392b 100644
--- a/protocols/Telegram/tdlib/td/test/set_with_position.cpp
+++ b/protocols/Telegram/tdlib/td/test/set_with_position.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
 //
 // 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)
diff --git a/protocols/Telegram/tdlib/td/test/string_cleaning.cpp b/protocols/Telegram/tdlib/td/test/string_cleaning.cpp
index 442f82d913..c597d7616c 100644
--- a/protocols/Telegram/tdlib/td/test/string_cleaning.cpp
+++ b/protocols/Telegram/tdlib/td/test/string_cleaning.cpp
@@ -1,11 +1,12 @@
 //
-// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
 //
 // 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/telegram/misc.h"
 
+#include "td/utils/common.h"
 #include "td/utils/Slice.h"
 #include "td/utils/tests.h"
 
diff --git a/protocols/Telegram/tdlib/td/test/tdclient.cpp b/protocols/Telegram/tdlib/td/test/tdclient.cpp
index 6ced39da30..a608c75593 100644
--- a/protocols/Telegram/tdlib/td/test/tdclient.cpp
+++ b/protocols/Telegram/tdlib/td/test/tdclient.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
 //
 // 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)
@@ -146,7 +146,7 @@ class TestClient final : public td::Actor {
     td::rmrf(name_).ignore();
     auto old_context = set_context(std::make_shared());
     set_tag(name_);
-    LOG(INFO) << "START UP!";
+    LOG(INFO) << "Start up!";
 
     td_client_ = td::create_actor("Td-proxy", make_td_callback());
   }
@@ -204,11 +204,10 @@ class DoAuthentication final : public TestClinetTask {
       : name_(std::move(name)), phone_(std::move(phone)), code_(std::move(code)), promise_(std::move(promise)) {
   }
   void start_up() final {
-    send_query(td::make_tl_object(),
-               [this](auto res) { this->process_authorization_state(std::move(res)); });
+    send_query(td::make_tl_object("version"),
+               [](auto res) { LOG(INFO) << td::td_api::to_string(res); });
   }
   void process_authorization_state(td::tl_object_ptr authorization_state) {
-    start_flag_ = true;
     td::tl_object_ptr function;
     switch (authorization_state->get_id()) {
       case td::td_api::authorizationStateWaitPhoneNumber::ID:
@@ -252,7 +251,7 @@ class DoAuthentication final : public TestClinetTask {
     send_query(std::move(function), [](auto res) { LOG_CHECK(res->get_id() == td::td_api::ok::ID) << to_string(res); });
   }
   void on_authorization_ready() {
-    LOG(INFO) << "GOT AUTHORIZED";
+    LOG(INFO) << "Authorization is completed";
     stop();
   }
 
@@ -261,12 +260,8 @@ class DoAuthentication final : public TestClinetTask {
   td::string phone_;
   td::string code_;
   td::Promise<> promise_;
-  bool start_flag_{false};
 
   void process_update(std::shared_ptr update) final {
-    if (!start_flag_) {
-      return;
-    }
     if (!update->object) {
       return;
     }
@@ -299,7 +294,7 @@ class SetUsername final : public TestClinetTask {
     self_id_ = user->id_;
     auto current_username = user->usernames_ != nullptr ? user->usernames_->editable_username_ : td::string();
     if (current_username != username_) {
-      LOG(INFO) << "SET USERNAME: " << username_;
+      LOG(INFO) << "Set username: " << username_;
       send_query(td::make_tl_object(username_), [this](auto res) {
         CHECK(res->get_id() == td::td_api::ok::ID);
         this->send_self_message();
@@ -335,7 +330,7 @@ class SetUsername final : public TestClinetTask {
         auto messageText = td::move_tl_object_as(message->content_);
         auto text = messageText->text_->text_;
         if (text.substr(0, tag_.size()) == tag_) {
-          LOG(INFO) << "GOT SELF MESSAGE";
+          LOG(INFO) << "Receive self-message";
           return stop();
         }
       }
@@ -365,7 +360,7 @@ class CheckTestA final : public TestClinetTask {
           LOG_CHECK(text > previous_text_) << td::tag("now", text) << td::tag("previous", previous_text_);
           previous_text_ = text;
           cnt_--;
-          LOG(INFO) << "GOT " << td::tag("text", text) << td::tag("left", cnt_);
+          LOG(INFO) << "Receive " << td::tag("text", text) << td::tag("left", cnt_);
           if (cnt_ == 0) {
             return stop();
           }
@@ -432,7 +427,7 @@ class TestSecretChat final : public TestClinetTask {
           update_secret_chat->secret_chat_->state_->get_id() != td::td_api::secretChatStateReady::ID) {
         return;
       }
-      LOG(INFO) << "SEND ENCRYPTED MESSAGES";
+      LOG(INFO) << "Send encrypted messages";
       for (int i = 0; i < 20; i++) {
         send_query(
             td::make_tl_object(
@@ -487,7 +482,7 @@ class TestFileGenerated final : public TestClinetTask {
   }
 
   void one_file() {
-    LOG(ERROR) << "Start ONE_FILE test";
+    LOG(ERROR) << "Start one_file test";
     auto file_path = PSTRING() << "test_documents" << TD_DIR_SLASH << "a.txt";
     td::mkpath(file_path).ensure();
     auto raw_file =
@@ -559,7 +554,7 @@ class TestFileGenerated final : public TestClinetTask {
         }
       }
       auto ready = std::ftell(to);
-      LOG(ERROR) << "READY: " << ready;
+      LOG(ERROR) << "Ready: " << ready;
       parent_->send_query(td::make_tl_object(
                               id_, 1039823 /*yeah, exact size of this file*/, td::narrow_cast(ready)),
                           [](auto result) { check_td_error(result); });
@@ -636,7 +631,7 @@ class CheckTestC final : public TestClinetTask {
         auto text = messageDocument->caption_->text_;
         if (text.substr(0, tag_.size()) == tag_) {
           file_id_to_check_ = messageDocument->document_->document_->id_;
-          LOG(ERROR) << "GOT FILE " << to_string(messageDocument->document_->document_);
+          LOG(ERROR) << "Receive file " << to_string(messageDocument->document_->document_);
           send_query(td::make_tl_object(file_id_to_check_, 1, 0, 0, false),
                      [](auto res) { check_td_error(res); });
         }
diff --git a/protocols/Telegram/tdlib/td/test/tqueue.cpp b/protocols/Telegram/tdlib/td/test/tqueue.cpp
index b1bf94a09e..9c3da0034c 100644
--- a/protocols/Telegram/tdlib/td/test/tqueue.cpp
+++ b/protocols/Telegram/tdlib/td/test/tqueue.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
 //
 // 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)
@@ -68,6 +68,15 @@ class TestTQueue {
     binlog_->set_callback(std::move(tqueue_binlog));
   }
 
+  TestTQueue(const TestTQueue &) = delete;
+  TestTQueue &operator=(const TestTQueue &) = delete;
+  TestTQueue(TestTQueue &&) = delete;
+  TestTQueue &operator=(TestTQueue &&) = delete;
+
+  ~TestTQueue() {
+    td::Binlog::destroy(binlog_path()).ensure();
+  }
+
   void restart(td::Random::Xorshift128plus &rnd, td::int32 now) {
     if (rnd.fast(0, 10) == 0) {
       baseline_->run_gc(now);
@@ -234,17 +243,18 @@ TEST(TQueue, clear) {
   td::int32 now = 0;
   td::vector ids;
   td::Random::Xorshift128plus rnd(123);
-  for (size_t i = 0; i < 1000000; i++) {
+  for (size_t i = 0; i < 100000; i++) {
     tqueue->push(1, td::string(td::Random::fast(100, 500), 'a'), now + 600000, 0, {}).ensure();
   }
   auto tail_id = tqueue->get_tail(1);
   auto clear_start_time = td::Time::now();
   size_t keep_count = td::Random::fast(0, 2);
-  tqueue->clear(1, keep_count);
+  auto deleted_events = tqueue->clear(1, keep_count);
   auto finish_time = td::Time::now();
   LOG(INFO) << "Added TQueue events in " << clear_start_time - start_time << " seconds and cleared them in "
             << finish_time - clear_start_time << " seconds";
   CHECK(tqueue->get_size(1) == keep_count);
   CHECK(tqueue->get_head(1).advance(keep_count).ok() == tail_id);
   CHECK(tqueue->get_tail(1) == tail_id);
+  CHECK(deleted_events.size() == 100000 - keep_count);
 }
-- 
cgit v1.2.3