diff options
Diffstat (limited to 'libs/tdlib/td/test')
-rw-r--r-- | libs/tdlib/td/test/CMakeLists.txt | 50 | ||||
-rw-r--r-- | libs/tdlib/td/test/TestsRunner.cpp | 63 | ||||
-rw-r--r-- | libs/tdlib/td/test/TestsRunner.h | 19 | ||||
-rw-r--r-- | libs/tdlib/td/test/data.cpp | 69 | ||||
-rw-r--r-- | libs/tdlib/td/test/data.h | 15 | ||||
-rw-r--r-- | libs/tdlib/td/test/db.cpp | 575 | ||||
-rw-r--r-- | libs/tdlib/td/test/fuzz_url.cpp | 33 | ||||
-rw-r--r-- | libs/tdlib/td/test/http.cpp | 373 | ||||
-rw-r--r-- | libs/tdlib/td/test/main.cpp | 40 | ||||
-rw-r--r-- | libs/tdlib/td/test/message_entities.cpp | 529 | ||||
-rw-r--r-- | libs/tdlib/td/test/mtproto.cpp | 347 | ||||
-rw-r--r-- | libs/tdlib/td/test/secret.cpp | 1056 | ||||
-rw-r--r-- | libs/tdlib/td/test/string_cleaning.cpp | 107 | ||||
-rw-r--r-- | libs/tdlib/td/test/tdclient.cpp | 837 | ||||
-rw-r--r-- | libs/tdlib/td/test/tests_runner.cpp | 18 | ||||
-rw-r--r-- | libs/tdlib/td/test/tests_runner.h | 18 |
16 files changed, 0 insertions, 4149 deletions
diff --git a/libs/tdlib/td/test/CMakeLists.txt b/libs/tdlib/td/test/CMakeLists.txt deleted file mode 100644 index d120d8d3fb..0000000000 --- a/libs/tdlib/td/test/CMakeLists.txt +++ /dev/null @@ -1,50 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) - -#SOURCE SETS -set(TD_TEST_SOURCE - ${CMAKE_CURRENT_SOURCE_DIR}/db.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/http.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/mtproto.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/message_entities.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/secret.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/string_cleaning.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/TestsRunner.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/tests_runner.cpp - - ${CMAKE_CURRENT_SOURCE_DIR}/TestsRunner.h - ${CMAKE_CURRENT_SOURCE_DIR}/tests_runner.h - - ${CMAKE_CURRENT_SOURCE_DIR}/data.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/data.h - - ${TDUTILS_TEST_SOURCE} - ${TDACTOR_TEST_SOURCE} -) -set(TD_TEST_SOURCE ${TD_TEST_SOURCE} PARENT_SCOPE) - -set(TESTS_MAIN - main.cpp -) - -add_library(all_tests STATIC ${TD_TEST_SOURCE}) -target_include_directories(all_tests PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>) -target_link_libraries(all_tests PRIVATE tdactor tddb tdcore tdnet tdutils) - -if (NOT CMAKE_CROSSCOMPILING OR EMSCRIPTEN) - #Tests - add_executable(run_all_tests ${TESTS_MAIN} ${TD_TEST_SOURCE}) - if (CLANG AND NOT CYGWIN AND NOT EMSCRIPTEN) - target_compile_options(run_all_tests PUBLIC -fsanitize=undefined -fno-sanitize=vptr) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined -fno-sanitize=vptr") - endif() - target_include_directories(run_all_tests PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>) - target_link_libraries(run_all_tests PRIVATE tdactor tddb tdcore tdnet tdutils) - - if (CLANG) -# add_executable(fuzz_url fuzz_url.cpp) -# target_link_libraries(fuzz_url PRIVATE tdclient) -# target_compile_options(fuzz_url PRIVATE "-fsanitize-coverage=trace-pc-guard") - endif() - - add_test(run_all_tests run_all_tests) -endif() diff --git a/libs/tdlib/td/test/TestsRunner.cpp b/libs/tdlib/td/test/TestsRunner.cpp deleted file mode 100644 index fbe155738e..0000000000 --- a/libs/tdlib/td/test/TestsRunner.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 -// -// 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 "test/TestsRunner.h" - -#include "td/utils/common.h" -#include "td/utils/FileLog.h" -#include "td/utils/format.h" -#include "td/utils/logging.h" -#include "td/utils/port/path.h" -#include "td/utils/tests.h" - -#include <limits> - -DESC_TESTS(string_cleaning); -DESC_TESTS(message_entities); -DESC_TESTS(variant); -DESC_TESTS(secret); -DESC_TESTS(actors_main); -DESC_TESTS(actors_simple); -DESC_TESTS(actors_workers); -DESC_TESTS(db); -DESC_TESTS(json); -DESC_TESTS(http); -DESC_TESTS(heap); -DESC_TESTS(pq); -DESC_TESTS(mtproto); - -namespace td { - -void TestsRunner::run_all_tests() { - LOAD_TESTS(string_cleaning); - LOAD_TESTS(message_entities); - LOAD_TESTS(variant); - LOAD_TESTS(secret); - LOAD_TESTS(actors_main); - LOAD_TESTS(actors_simple); - LOAD_TESTS(actors_workers); - LOAD_TESTS(db); - LOAD_TESTS(json); - LOAD_TESTS(http); - LOAD_TESTS(heap); - LOAD_TESTS(pq); - LOAD_TESTS(mtproto); - Test::run_all(); -} - -static FileLog file_log; -static TsLog ts_log(&file_log); - -void TestsRunner::init(string dir) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(WARNING)); - chdir(dir).ensure(); - LOG(WARNING) << "Redirect log into " << tag("file", dir + TD_DIR_SLASH + "log.txt"); - if (file_log.init("log.txt", std::numeric_limits<int64>::max())) { - log_interface = &ts_log; - } -} - -} // namespace td diff --git a/libs/tdlib/td/test/TestsRunner.h b/libs/tdlib/td/test/TestsRunner.h deleted file mode 100644 index a5bc66d855..0000000000 --- a/libs/tdlib/td/test/TestsRunner.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 -// -// 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) -// -#pragma once - -#include "td/utils/common.h" - -namespace td { - -class TestsRunner { - public: - static void init(string dir); - static void run_all_tests(); -}; - -} // namespace td diff --git a/libs/tdlib/td/test/data.cpp b/libs/tdlib/td/test/data.cpp deleted file mode 100644 index a57a9147c5..0000000000 --- a/libs/tdlib/td/test/data.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 -// -// 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 "test/data.h" -namespace td { -static const char thumbnail_arr[] = - "_9j_4AAQSkZJRgABAQEASABIAAD_2wBDAAICAgICAQICAgIDAgIDAwYEAwMDAwcFBQQGCAcJCAgHCAgJCg0LCQoMCggICw8LDA0ODg8OCQsQERAOEQ" - "0ODg7_2wBDAQIDAwMDAwcEBAcOCQgJDg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg7_wAARCAAyADIDASIA" - "AhEBAxEB_8QAHAAAAQUBAQEAAAAAAAAAAAAAAAUGBwgJAgQD_8QAMRAAAgEDAwMDAgUDBQAAAAAAAQIDBAURAAYSByExCBNBFCIVMlFhcZGhsQkjUm" - "KB_8QAGgEAAgMBAQAAAAAAAAAAAAAABgcAAggEBf_EACgRAAECBgIBBAMBAQAAAAAAAAECEQADBAUhMRJBBhMyUWEUIlJCkf_aAAwDAQACEQMRAD8A" - "381CvUXrbtzYtTLa6ZPx3cKj76SGQLHTn491-_E_9QC38a464dSH2H08gpLZMI9x3dmhom7EwKB98uP2yAP3Ofg6z2M8jVXvM5qqkyFpeTsCCR3Lk9" - "y2eWe_yD3znTG8esEqtR-TVAlJ9qRgqbZJ6T1956ELjyG_T6RRpqQhJHvWrIS-gkf6UfjrGHMTVePUH1HuVYxp7rTWOFj9sVDRocfoOUgYk_00nUXX" - "XqdQTrIdzmsQgHhWUcLowOcdwoPwfB1W3fG8KjaNlpnoqNK-veCWVYXk9qL26eMSOXkPZclUUdxkk-QMaiPZPqFp9wdT7btC92iltlRcZvpqea33Na" - "mNZSuVjcY7BsYDA-SMjByD5c2w01V-DMp5aS4HtffypjnXffULxNPeqmjNwlVU1YZRcFtfCSRjfXRIfUa1bG9SFuuddDbt6UUdkqHIVbhTkmmJPjmp" - "-6P-ckfrjVno5ElgSWJ1kjdQyspyGB8EH51kUWDShpFIbAAkQEjsDktk5wAMAD9hq2Pp16lTrdl2BeJzJSyKzWWWRs8Co5NCD8qR3A-CCv6aE7_45T" - "y5SqijSUKTlSNhvlJ-tkPrI0YMLD5DUmYiTVrE2WssmYMEK_lYxvQLbYHYi4-jRo0p4bUZ6-oC7y3P1IXajJ5QW-lio4jyIKgqsreDg_cwPceQMY86" - "hQAKoUeAMdzk6lzrhb5aT1R7kUqSKpoaiLt-YNEo_wAqw_8ANMuqsVbTWy3x1tEbeXV2E0isWkOcn7QPABAyTnPxp9zfJPH_ABO1US6xYSJwSMZIHE" - "krIyriFYJA2obyIzbMst_8oulZLpwVeiVkA4BPIAIBwORTkAnQOsExZNddoWn1T9Kju6G1yU9bLW01ILraKetiqKgLDJHSH3gVi94hoxIBkOYwCM6r" - "x6yLDYdt9fOi9T03l3DfN2_h8VRPBdYF-uWp-pWSCmZY40CyZYqYuPJOSqQp-0TtuK1dPt0b6oLNvfZg3R9HDM8UU8X3orcQxTDqAGwnEk4J8kAEa8" - "th2NtTZnVjprfZ62fd9vgsMU9jmu1OZJ7YaZ-ApqFsKEVXYq0vEBnZeJIw5UdRfrd5Fd6mptyipCVMFMwUyQXDsWwWcAk6Goc1ts9dZLNT01enishy" - "PcQ6jgs40csSAHc4MPynrYKyxwXHgaenngWfhMvExBl5cWB8Fc4IPgg6WbJdqi07ntd5pJ-Ro6mGpgfOSntsGwD-hGRj9zpSHTjfm-t6XWt2zXWqhg" - "J-rqqGpo-VNLKMMY4nVwW5sCzKue5YjAPHTbobXf6eWjs9-t0duv1RHFIaSGpWYAT_AJMEAEEkkFWAYEeMYJd9vvtHeJyKWanPByT_AEBkD6ZzCUuX" - "j1fYKeZVypmCviAM_ofaTjB5MPrbuRGucUizU0c0bZR1DL2-CMjRriliFNbKanzn2olTP8DGjWczvGo0onQfcV666bXhFwsXUGKnhq6m0LItRSTSGN" - "KpUR5olZgDxAdCCcHCuT8Y1nd0O3dW9X-gta1nv0fTvct_u9xZZ4LuK-sjZgrSSokhb2hyBVEAwBGDjuQdft02GPcuxLjZ3dYnniIhlePmI5B-Vivy" - "AfIyMjI-dUZpukO99qbiEtv6YxVFQjk-9QVkP08mD5BGJMHzhhkds_roG8lNVUKlOhSwkJCSHPEJUVMwBcEqJDgx7NqlU9P6hQySslSgeyQA-W6SIb" - "O6tqQbUk2jcEu0k93WrRPrGjVZPd4_mRhjv7gRyvEqCMnHjTT6f1VmrfUttCyb2RL7FT0sFos9NV0iJTQUsCPUksVHeV5QWLcTyZBnHwp9RoKy47tp" - "pr5a7haK6mOGiniaBBjHZc_GRnlnP9iI1u1huF9r7dV2GrnpNx0NSs9BUUqM5Dg5AKr3Iz_Tv8Egnvg_h12Rbq2pXI9JC-BlBRZSikK5nJ_UEEAOzk" - "dCF_5N5hbJVzpKZM4rKeYmcQ6U8m4aDqKSC_F2B7OIsX1grfTIfVHsSh6gRXPZW5LeJLlYLxaqeWgt0pMyoyTVKf7QkZ4lAVuLEHAbDYMc7F3jsHdX" - "-tXPtXb9FX38PRrW1N5p0MlKwp6f3qcyOo4BFaQxA5yWVVxjSjvDp31r6rdNVgvHS2WgqaWZaumd6yn9mr44WSLizLKnuAI6lk7PChPbOrhem3phH0" - "k9Ie1NpyWZbHdVgM9ypRULMY5nYkoZFGG4jio8-PJ8nsE2bSLJQeK8j_oIPz0SNwRLpqKsokKUrk5H6l2YEKSrQ7AwexE76NGjXmx0QaMDRo1IkfKS" - "KKZCk0ayp_xdQR_fXEVLS0yn6emip8-fbjC_40aNWc66ijDbZj0YGjRo1WLwaNGjUiR__9k"; - -const char *thumbnail = thumbnail_arr; -const size_t thumbnail_size = sizeof(thumbnail_arr) - 1; - -static const char gzip_bomb_arr[] = - "eJzt3VlQU2cYxvGTSFSkqHWJuIHTUqotAetIBmWzVUeUqlRrFcIqZlxCUKRshZBULVS0oqLiwqJWUVwAQQNBgSgt1EHFlS1AQCsZ1qAsASKTRonnnJ" - "ledHrViz5cfvMOOd_v_d-eJCK5vf6MaUmDLK7Jk_tZ9sSDEyYmdo7fOMeqdKSs-jXRxA_m8_fZPGTMW-Rhlf-AP7XxrGTW-qCOyWPtB90qdo-" - "NHtXfEi3Wlul0bWrxYNa1QaVY12ure9OdRgz_SVzyX-" - "nS59eYP1uYV68zHBLi7xcf2qyd7ddSbhX2geFsfPs3aeO04xhKLWffzBGGQyOHIeckkUmXZ1qZoH2a4XBWddSKRKGJ-" - "9UQxe8HGIbDXaZLU4U8SfDf_-UhiXroGG0wJSatvIgVcbXihV2YKTnpdP6ulHWxUtaxsez9U96O_ahCypHn9_AnOow0nI3uu1gRN-" - "Qq18SU0wZXFVfwlcxblapX025Sk6mPNymY37bVhV0LeK_hp7-3gu3nNZizl7pj1FNVSYxlY1QxnzZ4QanK2c7waeuO-" - "MWbmly9NUfIuBQadLP6C8PZouwzf-QKTebaiGp-o-7o1Nrt7zKhq1CZQxt8og6pySOyeiNvlWaSk4UX5tdICf12vNvNSF_" - "3P2ukLLOkokDaHc17B7ItjPsbtnvQBls0snaepGrQ0SegipxsWHsykCfZlqKwoTYROPt1oIK5382XS7tjwmB0dYJRtDrPmrayHq1XH0cuEJlnXROQk" - "-o5K6WcRTceCKdQm-BOipQKGaXnbU_R7rhM5Ny-" - "jFmk4bGpwbBBkY2W3XjDOaGq2o6c1ByxUrBPe6qktNqmxzsqpMSLx0kraXf81dmi72NkOTyILJElskSWBLJElgSyRJbDg8gSWSJLZEkgS2RJIEtkOT" - "yILJElskSWBLJElgSyRJbDi0CWyBJZIktkiSyH74gskSWyRJYEskSWBLJElu_uiCyRJbJElgSyRJbDvsgSWSJLZIkskeXwJLJElsgSWSJLZPluEFn-" - "11nq_NUHhOP3MGfHl7pe3eBeYz_S1Jhbye4pZRxnTCxxbZeP9Jw3gnXUOLb4jm1MyAOjcEmSo-ESnr5HI-2Nj9_kupErWfL5sYyx-" - "phmrlrZSlZXqylU6gsrH5TVryVZHqWWLdY_hU9x2cDJhe8f7efK9XzzVczmzPtrqMF4_qUS_" - "ebj1iYWkHN9InW4gt2YExOkeUru6brq1UH951Spg4vSyY2e7V13Ii5RIhPk0gY3nmjNZplVNT09R-7zrEiprZey8q-kKZxCSdSOSMdN-s_" - "pjUrOyiD5t4jWNTdZ-nXWWlODVzekLwxklIba22WQ-FuUmpg8IcOmTRW2mhKKMh-" - "nbyRiyFwlaCV7ACUoQQlKUIISlKAEJShBCUpQghKUoAQlKEEJSlCCEpSgBCUoQQlKUIISlKAEJShBCUpQghKUoAQlKEEJSlCCEpSgBCUoQQlKUIISl" - "KAEJShBCcp_ouzPDS_" - "jjv6KMWnp4tNs6yuBM3bHLpkuGBP1nLgnMfa3DN8xwjrl9p14o26PpinFCzbvcpC7meuhEyLZUuJCaJGU9nmanev3cOQBLQeSaHfIyLjcYdno0LOUW" - "khtk2bB9revxtcp15Cvxj9qCEj9iSPfmpIlpE0W1k32N-naUPDiE-oOwm2t2xyM-8eKDlELCesXPVC8_XoFTd5T8usVrmuOb_" - "Y32eGpEpyiTdqGL61mOh7rjFhO5XDqZEHtKmbRYt9z1EJmxqR1S99-F8IQJ5T8LoQOp2aPamZy5UAtbXX15d4fSomE8w4-" - "tBzS0zOliRL1wyk0oDil6pa-" - "pbYQsZs31SwoQQlKUIISlKAEJShBCUpQghKUoAQlKEEJSlCCEpSgBCUoQQlKUIISlKAEJShBCUpQghKUoAQlKEEJSlCCEpSgBCUoQQlKUIISlKAEJS" - "hBCUpQ_jtKiTgqPPDO3MOL_Pv3TxL68UbFJ5tlxpXs_XLFDAd3Gy-JIPvL_" - "KOXG414uxZmy1zt7B9axXrM53w9d0a0L0vMGGduuE7ODydO5bOO39kQKiPf5d-Udqb6Ck8SEOGbKSMXsSmvXuqVR1T4ireEkA9010f1xDnVKNpCMy_" - "8PeXBKz7NVkGM9LnfeXeS7_LXbJ7NbWM3mjUkCTrJRdQI8zhVHHl3lUVtHbnbnKqB6wmfMpRlhfdISsvLSbK9PMmc_euSyN-sd-2bGn-_" - "gGUfq3l5kvyhddcwhbA81KTrTW8cl3qg9lDnjhfL5ZpgW9qTt_KDnrP9xgQ8e0m-y39YFLsxN4hxoEkkayYXcbg-" - "TLGznukoHjpzn3qgqJTV2ogJXaK6ctqTgxKUoPyfUeqmx4szeRJuj3josnbUu0O57kcXXX-bi25IozxSONDzF5jalI4"; -const char *gzip_bomb = gzip_bomb_arr; -const size_t gzip_bomb_size = sizeof(gzip_bomb_arr) - 1; -} // namespace td diff --git a/libs/tdlib/td/test/data.h b/libs/tdlib/td/test/data.h deleted file mode 100644 index c447d5cba6..0000000000 --- a/libs/tdlib/td/test/data.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 -// -// 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) -// -#pragma once -#include "td/utils/common.h" -namespace td { -extern const char *thumbnail; -extern const size_t thumbnail_size; - -extern const char *gzip_bomb; -extern const size_t gzip_bomb_size; -} // namespace td diff --git a/libs/tdlib/td/test/db.cpp b/libs/tdlib/td/test/db.cpp deleted file mode 100644 index 8917dd65b8..0000000000 --- a/libs/tdlib/td/test/db.cpp +++ /dev/null @@ -1,575 +0,0 @@ -// -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 -// -// 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/db/binlog/BinlogHelper.h" -#include "td/db/BinlogKeyValue.h" -#include "td/db/SeqKeyValue.h" -#include "td/db/SqliteKeyValue.h" -#include "td/db/SqliteKeyValueSafe.h" -#include "td/db/TsSeqKeyValue.h" - -#include "td/utils/common.h" -#include "td/utils/logging.h" -#include "td/utils/port/FileFd.h" -#include "td/utils/port/thread.h" -#include "td/utils/Random.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" -#include "td/utils/tests.h" - -#include <limits> -#include <map> -#include <memory> - -REGISTER_TESTS(db); - -using namespace td; - -template <class ContainerT> -static typename ContainerT::value_type &rand_elem(ContainerT &cont) { - CHECK(0 < cont.size() && cont.size() <= static_cast<size_t>(std::numeric_limits<int>::max())); - return cont[Random::fast(0, static_cast<int>(cont.size()) - 1)]; -} - -TEST(DB, binlog_encryption) { - CSlice binlog_name = "test_binlog"; - Binlog::destroy(binlog_name).ignore(); - - auto hello = DbKey::raw_key(std::string(32, 'A')); - auto cucumber = DbKey::password("cucumber"); - auto empty = DbKey::empty(); - auto long_data = string(10000, 'Z'); - { - Binlog binlog; - binlog.init(binlog_name.str(), [](const BinlogEvent &x) {}).ensure(); - binlog.add_raw_event(BinlogEvent::create_raw(binlog.next_id(), 1, 0, create_storer("AAAA"))); - binlog.add_raw_event(BinlogEvent::create_raw(binlog.next_id(), 1, 0, create_storer("BBBB"))); - binlog.add_raw_event(BinlogEvent::create_raw(binlog.next_id(), 1, 0, create_storer(long_data))); - LOG(INFO) << "SET PASSWORD"; - binlog.change_key(cucumber); - binlog.change_key(hello); - LOG(INFO) << "OK"; - binlog.add_raw_event(BinlogEvent::create_raw(binlog.next_id(), 1, 0, create_storer("CCCC"))); - binlog.close().ensure(); - } - - auto add_suffix = [&] { - auto fd = FileFd::open(binlog_name, FileFd::Flags::Write | FileFd::Flags::Append).move_as_ok(); - fd.write("abacabadaba").ensure(); - }; - - add_suffix(); - - { - std::vector<string> v; - LOG(INFO) << "RESTART"; - Binlog binlog; - binlog.init(binlog_name.str(), [&](const BinlogEvent &x) { v.push_back(x.data_.str()); }, hello).ensure(); - CHECK(v == std::vector<string>({"AAAA", "BBBB", long_data, "CCCC"})); - } - - add_suffix(); - - { - std::vector<string> v; - LOG(INFO) << "RESTART"; - Binlog binlog; - auto status = binlog.init(binlog_name.str(), [&](const BinlogEvent &x) { v.push_back(x.data_.str()); }, cucumber); - CHECK(status.is_error()); - } - - add_suffix(); - - { - std::vector<string> v; - LOG(INFO) << "RESTART"; - Binlog binlog; - auto status = - binlog.init(binlog_name.str(), [&](const BinlogEvent &x) { v.push_back(x.data_.str()); }, cucumber, hello); - CHECK(v == std::vector<string>({"AAAA", "BBBB", long_data, "CCCC"})); - } -}; - -TEST(DB, sqlite_lfs) { - string path = "test_sqlite_db"; - SqliteDb::destroy(path).ignore(); - SqliteDb db; - db.init(path).ensure(); - db.exec("PRAGMA journal_mode=WAL").ensure(); - db.exec("PRAGMA user_version").ensure(); -} - -TEST(DB, sqlite_encryption) { - string path = "test_sqlite_db"; - SqliteDb::destroy(path).ignore(); - - auto empty = DbKey::empty(); - auto cucumber = DbKey::password("cucumber"); - auto tomato = DbKey::raw_key(string(32, 'a')); - - { - auto db = SqliteDb::open_with_key(path, empty).move_as_ok(); - db.set_user_version(123); - auto kv = SqliteKeyValue(); - kv.init_with_connection(db.clone(), "kv"); - kv.set("a", "b"); - } - SqliteDb::open_with_key(path, cucumber).ensure_error(); // key was set... - - SqliteDb::change_key(path, cucumber, empty).ensure(); - - SqliteDb::open_with_key(path, tomato).ensure_error(); - { - auto db = SqliteDb::open_with_key(path, cucumber).move_as_ok(); - auto kv = SqliteKeyValue(); - kv.init_with_connection(db.clone(), "kv"); - CHECK(kv.get("a") == "b"); - CHECK(db.user_version().ok() == 123); - } - - SqliteDb::change_key(path, tomato, cucumber).ensure(); - SqliteDb::change_key(path, tomato, cucumber).ensure(); - - SqliteDb::open_with_key(path, cucumber).ensure_error(); - { - auto db = SqliteDb::open_with_key(path, tomato).move_as_ok(); - auto kv = SqliteKeyValue(); - kv.init_with_connection(db.clone(), "kv"); - CHECK(kv.get("a") == "b"); - CHECK(db.user_version().ok() == 123); - } - - SqliteDb::change_key(path, empty, tomato).ensure(); - SqliteDb::change_key(path, empty, tomato).ensure(); - - { - auto db = SqliteDb::open_with_key(path, empty).move_as_ok(); - auto kv = SqliteKeyValue(); - kv.init_with_connection(db.clone(), "kv"); - CHECK(kv.get("a") == "b"); - CHECK(db.user_version().ok() == 123); - } - SqliteDb::open_with_key(path, cucumber).ensure_error(); -} - -using SeqNo = uint64; -struct DbQuery { - enum Type { Get, Set, Erase } type; - SeqNo tid = 0; - int32 id = 0; - string key; - string value; -}; - -template <class ImplT> -class QueryHandler { - public: - ImplT &impl() { - return impl_; - } - void do_query(DbQuery &query) { - switch (query.type) { - case DbQuery::Get: - query.value = impl_.get(query.key); - return; - case DbQuery::Set: - query.tid = impl_.set(query.key, query.value); - return; - case DbQuery::Erase: - query.tid = impl_.erase(query.key); - return; - } - } - - private: - ImplT impl_; -}; - -class SqliteKV { - public: - string get(string key) { - return kv_->get().get(key); - } - SeqNo set(string key, string value) { - kv_->get().set(key, value); - return 0; - } - SeqNo erase(string key) { - kv_->get().erase(key); - return 0; - } - Status init(string name) { - auto sql_connection = std::make_shared<SqliteConnectionSafe>(name); - kv_ = std::make_shared<SqliteKeyValueSafe>("kv", sql_connection); - return Status::OK(); - } - void close() { - kv_.reset(); - } - - private: - std::shared_ptr<SqliteKeyValueSafe> kv_; -}; - -class BaselineKV { - public: - string get(string key) { - return map_[key]; - } - SeqNo set(string key, string value) { - map_[key] = value; - return ++current_tid_; - } - SeqNo erase(string key) { - map_.erase(key); - return ++current_tid_; - } - - private: - std::map<string, string> map_; - SeqNo current_tid_ = 0; -}; - -TEST(DB, key_value) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(INFO)); - std::vector<std::string> keys; - std::vector<std::string> values; - - for (int i = 0; i < 100; i++) { - keys.push_back(rand_string('a', 'b', Random::fast(1, 10))); - } - for (int i = 0; i < 1000; i++) { - values.push_back(rand_string('a', 'b', Random::fast(1, 10))); - } - - int queries_n = 300000; - std::vector<DbQuery> queries(queries_n); - for (auto &q : queries) { - int op = Random::fast(0, 2); - const auto &key = rand_elem(keys); - const auto &value = rand_elem(values); - if (op == 0) { - q.type = DbQuery::Get; - q.key = key; - } else if (op == 1) { - q.type = DbQuery::Erase; - q.key = key; - } else if (op == 2) { - q.type = DbQuery::Set; - q.key = key; - q.value = value; - } - } - - QueryHandler<BaselineKV> baseline; - QueryHandler<SeqKeyValue> kv; - QueryHandler<TsSeqKeyValue> ts_kv; - QueryHandler<BinlogKeyValue<Binlog>> new_kv; - - CSlice new_kv_name = "test_new_kv"; - Binlog::destroy(new_kv_name).ignore(); - new_kv.impl().init(new_kv_name.str()).ensure(); - - QueryHandler<SqliteKeyValue> sqlite_kv; - CSlice name = "test_sqlite_kv"; - SqliteDb::destroy(name).ignore(); - sqlite_kv.impl().init(name.str()).ensure(); - - int cnt = 0; - for (auto &q : queries) { - DbQuery a = q; - DbQuery b = q; - DbQuery c = q; - DbQuery d = q; - DbQuery e = q; - baseline.do_query(a); - kv.do_query(b); - ts_kv.do_query(c); - sqlite_kv.do_query(d); - new_kv.do_query(e); - ASSERT_EQ(a.value, b.value); - ASSERT_EQ(a.value, c.value); - ASSERT_EQ(a.value, d.value); - ASSERT_EQ(a.value, e.value); - if (cnt++ % 10000 == 0) { - new_kv.impl().init(new_kv_name.str()).ensure(); - } - } -} - -TEST(DB, thread_key_value) { -#if !TD_THREAD_UNSUPPORTED - std::vector<std::string> keys; - std::vector<std::string> values; - - for (int i = 0; i < 100; i++) { - keys.push_back(rand_string('a', 'b', Random::fast(1, 10))); - } - for (int i = 0; i < 1000; i++) { - values.push_back(rand_string('a', 'b', Random::fast(1, 10))); - } - - int threads_n = 4; - int queries_n = 100000; - - std::vector<std::vector<DbQuery>> queries(threads_n, std::vector<DbQuery>(queries_n)); - for (auto &qs : queries) { - for (auto &q : qs) { - int op = Random::fast(0, 10); - const auto &key = rand_elem(keys); - const auto &value = rand_elem(values); - if (op > 1) { - q.type = DbQuery::Get; - q.key = key; - } else if (op == 0) { - q.type = DbQuery::Erase; - q.key = key; - } else if (op == 1) { - q.type = DbQuery::Set; - q.key = key; - q.value = value; - } - } - } - - QueryHandler<BaselineKV> baseline; - QueryHandler<TsSeqKeyValue> ts_kv; - - std::vector<thread> threads(threads_n); - std::vector<std::vector<DbQuery>> res(threads_n); - for (int i = 0; i < threads_n; i++) { - threads[i] = thread([&ts_kv, &queries, &res, i]() { - for (auto q : queries[i]) { - ts_kv.do_query(q); - res[i].push_back(q); - } - }); - } - for (auto &thread : threads) { - thread.join(); - } - - std::vector<std::size_t> pos(threads_n); - while (true) { - bool was = false; - for (int i = 0; i < threads_n; i++) { - auto p = pos[i]; - if (p == res[i].size()) { - continue; - } - auto &q = res[i][p]; - if (q.tid == 0) { - if (q.type == DbQuery::Get) { - auto nq = q; - baseline.do_query(nq); - if (nq.value == q.value) { - was = true; - pos[i]++; - } - } else { - was = true; - pos[i]++; - } - } - } - if (was) { - continue; - } - - int best = -1; - SeqNo best_tid = 0; - for (int i = 0; i < threads_n; i++) { - auto p = pos[i]; - if (p == res[i].size()) { - continue; - } - was = true; - auto &q = res[i][p]; - if (q.tid != 0) { - if (best == -1 || q.tid < best_tid) { - best = i; - best_tid = q.tid; - } - } - } - if (!was) { - break; - } - ASSERT_TRUE(best != -1); - baseline.do_query(res[best][pos[best]]); - pos[best]++; - } -#endif -} - -TEST(DB, persistent_key_value) { - using KeyValue = BinlogKeyValue<ConcurrentBinlog>; - // using KeyValue = PersistentKeyValue; - // using KeyValue = SqliteKV; - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(WARNING)); - std::vector<std::string> keys; - std::vector<std::string> values; - CSlice name = "test_pmc"; - Binlog::destroy(name).ignore(); - SqliteDb::destroy(name).ignore(); - - for (int i = 0; i < 100; i++) { - keys.push_back(rand_string('a', 'b', Random::fast(1, 10))); - } - for (int i = 0; i < 1000; i++) { - values.push_back(rand_string('a', 'b', Random::fast(1, 10))); - } - - QueryHandler<BaselineKV> baseline; - - for (int iter = 0; iter < 25; iter++) { - int threads_n = 4; - int queries_n = 3000 / threads_n; - - std::vector<std::vector<DbQuery>> queries(threads_n, std::vector<DbQuery>(queries_n)); - for (auto &qs : queries) { - for (auto &q : qs) { - int op = Random::fast(0, 10); - const auto &key = rand_elem(keys); - const auto &value = rand_elem(values); - if (op > 1) { - q.type = DbQuery::Get; - q.key = key; - } else if (op == 0) { - q.type = DbQuery::Erase; - q.key = key; - } else if (op == 1) { - q.type = DbQuery::Set; - q.key = key; - q.value = value; - } - } - } - - std::vector<std::vector<DbQuery>> res(threads_n); - class Worker : public Actor { - public: - Worker(ActorShared<> parent, std::shared_ptr<QueryHandler<KeyValue>> kv, const std::vector<DbQuery> *queries, - std::vector<DbQuery> *res) - : parent_(std::move(parent)), kv_(std::move(kv)), queries_(queries), res_(res) { - } - void loop() override { - for (auto q : *queries_) { - kv_->do_query(q); - res_->push_back(q); - } - stop(); - } - - private: - ActorShared<> parent_; - std::shared_ptr<QueryHandler<KeyValue>> kv_; - const std::vector<DbQuery> *queries_; - std::vector<DbQuery> *res_; - }; - class Main : public Actor { - public: - Main(int threads_n, const std::vector<std::vector<DbQuery>> *queries, std::vector<std::vector<DbQuery>> *res) - : threads_n_(threads_n), queries_(queries), res_(res) { - } - - void start_up() override { - LOG(INFO) << "start_up"; - kv_->impl().init("test_pmc").ensure(); - ref_cnt_ = threads_n_; - for (int i = 0; i < threads_n_; i++) { - create_actor_on_scheduler<Worker>("Worker", i + 1, actor_shared(this, 2), kv_, &queries_->at(i), &res_->at(i)) - .release(); - } - } - - void tear_down() override { - LOG(INFO) << "tear_down"; - // kv_->impl().close(); - } - void hangup_shared() override { - LOG(INFO) << "hangup"; - ref_cnt_--; - if (ref_cnt_ == 0) { - kv_->impl().close(); - Scheduler::instance()->finish(); - stop(); - } - } - void hangup() override { - LOG(ERROR) << "BAD HANGUP"; - } - - private: - int threads_n_; - const std::vector<std::vector<DbQuery>> *queries_; - std::vector<std::vector<DbQuery>> *res_; - - std::shared_ptr<QueryHandler<KeyValue>> kv_{new QueryHandler<KeyValue>()}; - int ref_cnt_; - }; - - ConcurrentScheduler sched; - sched.init(threads_n); - sched.create_actor_unsafe<Main>(0, "Main", threads_n, &queries, &res).release(); - sched.start(); - while (sched.run_main(10)) { - // empty - } - sched.finish(); - - std::vector<std::size_t> pos(threads_n); - while (true) { - bool was = false; - for (int i = 0; i < threads_n; i++) { - auto p = pos[i]; - if (p == res[i].size()) { - continue; - } - auto &q = res[i][p]; - if (q.tid == 0) { - if (q.type == DbQuery::Get) { - auto nq = q; - baseline.do_query(nq); - if (nq.value == q.value) { - was = true; - pos[i]++; - } - } else { - was = true; - pos[i]++; - } - } - } - if (was) { - continue; - } - - int best = -1; - SeqNo best_tid = 0; - for (int i = 0; i < threads_n; i++) { - auto p = pos[i]; - if (p == res[i].size()) { - continue; - } - was = true; - auto &q = res[i][p]; - if (q.tid != 0) { - if (best == -1 || q.tid < best_tid) { - best = i; - best_tid = q.tid; - } - } - } - if (!was) { - break; - } - ASSERT_TRUE(best != -1); - baseline.do_query(res[best][pos[best]]); - pos[best]++; - } - } -} diff --git a/libs/tdlib/td/test/fuzz_url.cpp b/libs/tdlib/td/test/fuzz_url.cpp deleted file mode 100644 index 74047135c0..0000000000 --- a/libs/tdlib/td/test/fuzz_url.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 -// -// 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/MessageEntity.h" - -#include "td/utils/common.h" -#include "td/utils/logging.h" -#include "td/utils/Slice.h" - -#include <cstddef> -#include <cstdint> - -static td::string get_utf_string(td::Slice from) { - td::string res; - td::string alph = " ab@./01#"; - for (auto c : from) { - res += alph[td::uint8(c) % alph.size()]; - } - LOG(ERROR) << res; - return res; -} - -extern "C" int LLVMFuzzerTestOneInput(std::uint8_t *data, std::size_t data_size) { - td::find_urls(get_utf_string(td::Slice(data, data_size))); - //td::find_hashtags(get_utf_string(td::Slice(data, data_size))); - //td::find_bot_commands(get_utf_string(td::Slice(data, data_size))); - //td::is_email_address(get_utf_string(td::Slice(data, data_size))); - //td::find_mentions(get_utf_string(td::Slice(data, data_size))); - return 0; -} diff --git a/libs/tdlib/td/test/http.cpp b/libs/tdlib/td/test/http.cpp deleted file mode 100644 index 98c94b2e8a..0000000000 --- a/libs/tdlib/td/test/http.cpp +++ /dev/null @@ -1,373 +0,0 @@ -// -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -#include "td/utils/tests.h" - -#include "td/net/HttpChunkedByteFlow.h" -#include "td/net/HttpHeaderCreator.h" -#include "td/net/HttpQuery.h" -#include "td/net/HttpReader.h" - -#include "td/utils/AesCtrByteFlow.h" -#include "td/utils/base64.h" -#include "td/utils/buffer.h" -#include "td/utils/BufferedFd.h" -#include "td/utils/ByteFlow.h" -#include "td/utils/crypto.h" -#include "td/utils/format.h" -#include "td/utils/Gzip.h" -#include "td/utils/GzipByteFlow.h" -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/port/Fd.h" -#include "td/utils/port/FileFd.h" -#include "td/utils/port/path.h" -#include "td/utils/port/thread_local.h" -#include "td/utils/Random.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" - -#include "test/data.h" - -#include <algorithm> -#include <cstdlib> -#include <limits> - -REGISTER_TESTS(http) - -using namespace td; - -static string make_chunked(string str) { - auto v = rand_split(str); - string res; - for (auto &s : v) { - res += PSTRING() << format::as_hex_dump(int(s.size())); - res += "\r\n"; - res += s; - res += "\r\n"; - } - res += "0\r\n\r\n"; - return res; -} - -static string gen_http_content() { - int t = Random::fast(0, 2); - int len; - if (t == 0) { - len = Random::fast(1, 10); - } else if (t == 1) { - len = Random::fast(100, 200); - } else { - len = Random::fast(1000, 20000); - } - return rand_string(std::numeric_limits<char>::min(), std::numeric_limits<char>::max(), len); -} - -static string make_http_query(string content, bool is_chunked, bool is_gzip, double gzip_k = 5, - string zip_override = "") { - HttpHeaderCreator hc; - hc.init_post("/"); - hc.add_header("jfkdlsahhjk", rand_string('a', 'z', Random::fast(1, 2000))); - if (is_gzip) { - BufferSlice zip; - if (zip_override.empty()) { - zip = gzencode(content, gzip_k); - } else { - zip = BufferSlice(zip_override); - } - if (!zip.empty()) { - hc.add_header("content-encoding", "gzip"); - content = zip.as_slice().str(); - } - } - if (is_chunked) { - hc.add_header("transfer-encoding", "chunked"); - content = make_chunked(content); - } else { - hc.set_content_size(content.size()); - } - string res; - auto r_header = hc.finish(); - CHECK(r_header.is_ok()); - res += r_header.ok().str(); - res += content; - return res; -} - -static string rand_http_query(string content) { - bool is_chunked = Random::fast(0, 1) == 0; - bool is_gzip = Random::fast(0, 1) == 0; - return make_http_query(std::move(content), is_chunked, is_gzip); -} - -static string join(const std::vector<string> &v) { - string res; - for (auto &s : v) { - res += s; - } - return res; -} - -TEST(Http, stack_overflow) { - ChainBufferWriter writer; - BufferSlice slice(string(256, 'A')); - for (int i = 0; i < 1000000; i++) { - ChainBufferWriter tmp_writer; - writer.append(slice.clone()); - } - { - auto reader = writer.extract_reader(); - reader.sync_with_writer(); - } -} - -TEST(Http, reader) { -#if TD_ANDROID || TD_TIZEN - return; -#endif - clear_thread_locals(); - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(INFO)); - auto start_mem = BufferAllocator::get_buffer_mem(); - { - auto input_writer = ChainBufferWriter::create_empty(); - auto input = input_writer.extract_reader(); - HttpReader reader; - int max_post_size = 10000; - reader.init(&input, max_post_size, 0); - - std::srand(4); - std::vector<string> contents(1000); - std::generate(contents.begin(), contents.end(), gen_http_content); - auto v = td::transform(contents, rand_http_query); - auto vec_str = rand_split(join(v)); - - HttpQuery q; - std::vector<string> res; - for (auto &str : vec_str) { - input_writer.append(str); - input.sync_with_writer(); - while (true) { - auto r_state = reader.read_next(&q); - LOG_IF(ERROR, r_state.is_error()) << r_state.error() << tag("ok", res.size()); - ASSERT_TRUE(r_state.is_ok()); - auto state = r_state.ok(); - if (state == 0) { - if (q.files_.empty()) { - ASSERT_TRUE(td::narrow_cast<int>(q.content_.size()) <= max_post_size); - auto expected = contents[res.size()]; - ASSERT_EQ(expected, q.content_.str()); - res.push_back(q.content_.str()); - } else { - auto r_fd = FileFd::open(q.files_[0].temp_file_name, FileFd::Read); - ASSERT_TRUE(r_fd.is_ok()); - auto fd = r_fd.move_as_ok(); - string content(td::narrow_cast<size_t>(q.files_[0].size), '\0'); - auto r_size = fd.read(MutableSlice(content)); - ASSERT_TRUE(r_size.is_ok()); - ASSERT_TRUE(r_size.ok() == content.size()); - ASSERT_TRUE(td::narrow_cast<int>(content.size()) > max_post_size); - ASSERT_EQ(contents[res.size()], content); - res.push_back(content); - fd.close(); - } - } else { - break; - } - } - } - ASSERT_EQ(contents.size(), res.size()); - ASSERT_EQ(contents, res); - } - clear_thread_locals(); - ASSERT_EQ(start_mem, BufferAllocator::get_buffer_mem()); -} - -TEST(Http, gzip_bomb) { -#if TD_ANDROID || TD_TIZEN || TD_EMSCRIPTEN // the test should be disabled on low-memory systems - return; -#endif - auto gzip_bomb_str = - gzdecode(gzdecode(base64url_decode(Slice(gzip_bomb, gzip_bomb_size)).ok()).as_slice()).as_slice().str(); - - auto query = make_http_query("", false, true, 0.01, gzip_bomb_str); - auto parts = rand_split(query); - auto input_writer = ChainBufferWriter::create_empty(); - auto input = input_writer.extract_reader(); - HttpReader reader; - HttpQuery q; - reader.init(&input, 100000000, 0); - for (auto &part : parts) { - input_writer.append(part); - input.sync_with_writer(); - auto r_state = reader.read_next(&q); - if (r_state.is_error()) { - LOG(INFO) << r_state.error(); - return; - } - ASSERT_TRUE(r_state.ok() != 0); - } -} - -TEST(Http, aes_ctr_encode_decode_flow) { - auto str = rand_string('a', 'z', 1000000); - auto parts = rand_split(str); - auto input_writer = ChainBufferWriter::create_empty(); - auto input = input_writer.extract_reader(); - ByteFlowSource source(&input); - UInt256 key; - UInt128 iv; - Random::secure_bytes(key.raw, sizeof(key)); - Random::secure_bytes(iv.raw, sizeof(iv)); - AesCtrByteFlow aes_encode; - aes_encode.init(key, iv); - AesCtrByteFlow aes_decode; - aes_decode.init(key, iv); - ByteFlowSink sink; - source >> aes_encode >> aes_decode >> sink; - - ASSERT_TRUE(!sink.is_ready()); - for (auto &part : parts) { - input_writer.append(part); - source.wakeup(); - } - ASSERT_TRUE(!sink.is_ready()); - source.close_input(Status::OK()); - ASSERT_TRUE(sink.is_ready()); - LOG_IF(ERROR, sink.status().is_error()) << sink.status(); - ASSERT_TRUE(sink.status().is_ok()); - ASSERT_EQ(str, sink.result()->move_as_buffer_slice().as_slice().str()); -} - -TEST(Http, aes_file_encryption) { - auto str = rand_string('a', 'z', 1000000); - CSlice name = "test_encryption"; - unlink(name).ignore(); - UInt256 key; - UInt128 iv; - Random::secure_bytes(key.raw, sizeof(key)); - Random::secure_bytes(iv.raw, sizeof(iv)); - - { - BufferedFdBase<FileFd> fd(FileFd::open(name, FileFd::Write | FileFd::Create).move_as_ok()); - - auto parts = rand_split(str); - - ChainBufferWriter output_writer; - auto output_reader = output_writer.extract_reader(); - ByteFlowSource source(&output_reader); - AesCtrByteFlow aes_encode; - aes_encode.init(key, iv); - ByteFlowSink sink; - - source >> aes_encode >> sink; - fd.set_output_reader(sink.get_output()); - - for (auto &part : parts) { - output_writer.append(part); - source.wakeup(); - fd.flush_write().ensure(); - } - fd.close(); - } - - { - BufferedFdBase<FileFd> fd(FileFd::open(name, FileFd::Read).move_as_ok()); - - ChainBufferWriter input_writer; - auto input_reader = input_writer.extract_reader(); - ByteFlowSource source(&input_reader); - AesCtrByteFlow aes_encode; - aes_encode.init(key, iv); - ByteFlowSink sink; - source >> aes_encode >> sink; - fd.set_input_writer(&input_writer); - - fd.update_flags(Fd::Flag::Read); - while (can_read(fd)) { - fd.flush_read(4096).ensure(); - source.wakeup(); - } - - fd.close(); - - source.close_input(Status::OK()); - ASSERT_TRUE(sink.is_ready()); - LOG_IF(ERROR, sink.status().is_error()) << sink.status(); - ASSERT_TRUE(sink.status().is_ok()); - auto result = sink.result()->move_as_buffer_slice().as_slice().str(); - ASSERT_EQ(str, result); - } -} - -TEST(Http, chunked_flow) { - auto str = rand_string('a', 'z', 100); - auto parts = rand_split(make_chunked(str)); - auto input_writer = ChainBufferWriter::create_empty(); - auto input = input_writer.extract_reader(); - ByteFlowSource source(&input); - HttpChunkedByteFlow chunked_flow; - ByteFlowSink sink; - source >> chunked_flow >> sink; - - for (auto &part : parts) { - input_writer.append(part); - source.wakeup(); - } - source.close_input(Status::OK()); - ASSERT_TRUE(sink.is_ready()); - LOG_IF(ERROR, sink.status().is_error()) << sink.status(); - ASSERT_TRUE(sink.status().is_ok()); - auto res = sink.result()->move_as_buffer_slice().as_slice().str(); - ASSERT_EQ(str.size(), res.size()); - ASSERT_EQ(str, res); -} - -TEST(Http, chunked_flow_error) { - auto str = rand_string('a', 'z', 100000); - for (int d = 1; d < 100; d += 10) { - auto new_str = make_chunked(str); - new_str.resize(str.size() - d); - auto parts = rand_split(new_str); - auto input_writer = ChainBufferWriter::create_empty(); - auto input = input_writer.extract_reader(); - ByteFlowSource source(&input); - HttpChunkedByteFlow chunked_flow; - ByteFlowSink sink; - source >> chunked_flow >> sink; - - for (auto &part : parts) { - input_writer.append(part); - source.wakeup(); - } - ASSERT_TRUE(!sink.is_ready()); - source.close_input(Status::OK()); - ASSERT_TRUE(sink.is_ready()); - ASSERT_TRUE(!sink.status().is_ok()); - } -} - -TEST(Http, gzip_chunked_flow) { - auto str = rand_string('a', 'z', 1000000); - auto parts = rand_split(make_chunked(gzencode(str).as_slice().str())); - - auto input_writer = ChainBufferWriter::create_empty(); - auto input = input_writer.extract_reader(); - ByteFlowSource source(&input); - HttpChunkedByteFlow chunked_flow; - GzipByteFlow gzip_flow(Gzip::Decode); - ByteFlowSink sink; - source >> chunked_flow >> gzip_flow >> sink; - - for (auto &part : parts) { - input_writer.append(part); - source.wakeup(); - } - source.close_input(Status::OK()); - ASSERT_TRUE(sink.is_ready()); - LOG_IF(ERROR, sink.status().is_error()) << sink.status(); - ASSERT_TRUE(sink.status().is_ok()); - ASSERT_EQ(str, sink.result()->move_as_buffer_slice().as_slice().str()); -} diff --git a/libs/tdlib/td/test/main.cpp b/libs/tdlib/td/test/main.cpp deleted file mode 100644 index 0ef46c75b2..0000000000 --- a/libs/tdlib/td/test/main.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -#include "td/utils/tests.h" - -#include "td/utils/logging.h" - -#include <cstring> - -#if TD_EMSCRIPTEN -#include <emscripten.h> -#endif - -int main(int argc, char **argv) { - // TODO port OptionsParser to Windows - for (int i = 1; i < argc; i++) { - if (!std::strcmp(argv[i], "--filter")) { - CHECK(i + 1 < argc); - td::Test::add_substr_filter(argv[++i]); - } - if (!std::strcmp(argv[i], "--stress")) { - td::Test::set_stress_flag(true); - } - } -#if TD_EMSCRIPTEN - emscripten_set_main_loop( - [] { - if (!td::Test::run_all_step()) { - emscripten_cancel_main_loop(); - } - }, - 10, 0); -#else - td::Test::run_all(); -#endif - return 0; -} diff --git a/libs/tdlib/td/test/message_entities.cpp b/libs/tdlib/td/test/message_entities.cpp deleted file mode 100644 index 473a87140a..0000000000 --- a/libs/tdlib/td/test/message_entities.cpp +++ /dev/null @@ -1,529 +0,0 @@ -// -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 -// -// 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/MessageEntity.h" - -#include "td/utils/format.h" -#include "td/utils/logging.h" -#include "td/utils/tests.h" - -REGISTER_TESTS(message_entities); - -using namespace td; - -static void check_mention(string str, std::vector<string> expected) { - auto result_slice = find_mentions(str); - std::vector<string> result; - for (auto &it : result_slice) { - result.push_back(it.str()); - } - if (result != expected) { - LOG(FATAL) << tag("text", str) << tag("got", format::as_array(result)) - << tag("expected", format::as_array(expected)); - } -} - -TEST(MessageEntities, mention) { - check_mention("@mention", {"@mention"}); - check_mention("@mention ", {"@mention"}); - check_mention(" @mention", {"@mention"}); - check_mention(" @mention ", {"@mention"}); - check_mention("@abc @xyz @abc @xyz @xxx@yyy @ttt", {}); - check_mention("@abcde @xyzxy @abcde @xyzxy @xxxxx@yyyyy @ttttt", - {"@abcde", "@xyzxy", "@abcde", "@xyzxy", "@xxxxx", "@ttttt"}); - check_mention("no@mention", {}); - check_mention("@n", {}); - check_mention("@abcdefghijklmnopqrstuvwxyz123456", {"@abcdefghijklmnopqrstuvwxyz123456"}); - check_mention("@abcdefghijklmnopqrstuvwxyz1234567", {}); - check_mention("нет@mention", {}); - check_mention("@ya @gif @wiki @vid @bing @pic @bold @imdb @coub @like @vote @giff @cap ya cap @y @yar @bingg @bin", - {"@ya", "@gif", "@wiki", "@vid", "@bing", "@pic", "@bold", "@imdb", "@coub", "@like", "@vote", "@giff", - "@cap", "@bingg"}); -}; - -static void check_bot_command(string str, std::vector<string> expected) { - auto result_slice = find_bot_commands(str); - std::vector<string> result; - for (auto &it : result_slice) { - result.push_back(it.str()); - } - if (result != expected) { - LOG(FATAL) << tag("text", str) << tag("got", format::as_array(result)) - << tag("expected", format::as_array(expected)); - } -} - -TEST(MessageEntities, bot_command) { - // 1..64@3..32 - check_bot_command("/abc", {"/abc"}); - check_bot_command(" /abc", {"/abc"}); - check_bot_command("/abc ", {"/abc"}); - check_bot_command(" /abc ", {"/abc"}); - check_bot_command("/a@abc", {"/a@abc"}); - check_bot_command("/a@b", {}); - check_bot_command("/@bfdsa", {}); - check_bot_command("/test/", {}); -} - -static void check_hashtag(string str, std::vector<string> expected) { - auto result_slice = find_hashtags(str); - std::vector<string> result; - for (auto &it : result_slice) { - result.push_back(it.str()); - } - if (result != expected) { - LOG(FATAL) << tag("text", str) << tag("got", format::as_array(result)) - << tag("expected", format::as_array(expected)); - } -} - -TEST(MessageEntities, hashtag) { - check_hashtag("", {}); - check_hashtag("#", {}); - check_hashtag("##", {}); - check_hashtag("###", {}); - check_hashtag("#a", {"#a"}); - check_hashtag(" #a", {"#a"}); - check_hashtag("#a ", {"#a"}); - check_hashtag(" #я ", {"#я"}); - check_hashtag(" я#a ", {}); - check_hashtag(" #a# ", {}); - check_hashtag(" #123 ", {}); - check_hashtag(" #123a ", {"#123a"}); - check_hashtag(" #a123 ", {"#a123"}); - check_hashtag(" #123a# ", {}); - check_hashtag(" #" + string(300, '1'), {}); - check_hashtag(" #" + string(256, '1'), {}); - check_hashtag(" #" + string(256, '1') + "a ", {}); - check_hashtag(" #" + string(255, '1') + "a", {"#" + string(255, '1') + "a"}); - check_hashtag(" #" + string(255, '1') + "Я", {"#" + string(255, '1') + "Я"}); - check_hashtag(" #" + string(255, '1') + "a" + string(255, 'b') + "# ", {}); - check_hashtag("#a#b #c #d", {"#c", "#d"}); - check_hashtag("#test", {"#test"}); - check_hashtag(u8"\U0001F604\U0001F604\U0001F604\U0001F604 \U0001F604\U0001F604\U0001F604#" + string(200, '1') + - "ООО" + string(200, '2'), - {"#" + string(200, '1') + "ООО" + string(53, '2')}); - check_hashtag(u8"#a\u2122", {"#a"}); -} - -static void check_cashtag(string str, std::vector<string> expected) { - auto result_slice = find_cashtags(str); - std::vector<string> result; - for (auto &it : result_slice) { - result.push_back(it.str()); - } - if (result != expected) { - LOG(FATAL) << tag("text", str) << tag("got", format::as_array(result)) - << tag("expected", format::as_array(expected)); - } -} - -TEST(MessageEntities, cashtag) { - check_cashtag("", {}); - check_cashtag("$", {}); - check_cashtag("$$", {}); - check_cashtag("$$$", {}); - check_cashtag("$a", {}); - check_cashtag(" $a", {}); - check_cashtag("$a ", {}); - check_cashtag(" $я ", {}); - check_cashtag("$ab", {}); - check_cashtag("$abc", {}); - check_cashtag("$", {}); - check_cashtag("$A", {}); - check_cashtag("$AB", {}); - check_cashtag("$АBC", {}); - check_cashtag("$АВС", {}); - check_cashtag("$ABC", {"$ABC"}); - check_cashtag("$ABCD", {"$ABCD"}); - check_cashtag("$ABCDE", {"$ABCDE"}); - check_cashtag("$ABCDEF", {"$ABCDEF"}); - check_cashtag("$ABCDEFG", {"$ABCDEFG"}); - check_cashtag("$ABCDEFGH", {"$ABCDEFGH"}); - check_cashtag("$ABCDEFGHJ", {}); - check_cashtag("$ABCDEFGH1", {}); - check_cashtag(" $XYZ", {"$XYZ"}); - check_cashtag("$XYZ ", {"$XYZ"}); - check_cashtag(" $XYZ ", {"$XYZ"}); - check_cashtag(" $$XYZ ", {}); - check_cashtag(" $XYZ$ ", {}); - check_cashtag(" $ABC1 ", {}); - check_cashtag(" $1ABC ", {}); - check_cashtag(" 1$ABC ", {}); - check_cashtag(" А$ABC ", {}); - check_cashtag("$ABC$DEF $GHI $KLM", {"$GHI", "$KLM"}); - check_cashtag("$TEST", {"$TEST"}); - check_cashtag(u8"$ABC\u2122", {"$ABC"}); - check_cashtag(u8"\u2122$ABC", {"$ABC"}); - check_cashtag(u8"\u2122$ABC\u2122", {"$ABC"}); -} - -static void check_is_email_address(string str, bool expected) { - bool result = is_email_address(str); - LOG_IF(FATAL, result != expected) << "Expected " << expected << " as result of is_email_address(" << str << ")"; -} - -TEST(MessageEntities, is_email_address) { - check_is_email_address("telegram.org", false); - check_is_email_address("security@telegram.org", true); - check_is_email_address("security.telegram.org", false); - check_is_email_address("", false); - check_is_email_address("@", false); - check_is_email_address("A@a.a.a.ab", true); - check_is_email_address("A@a.ab", true); - check_is_email_address("Test@aa.aa.aa.aa", true); - check_is_email_address("Test@test.abd", true); - check_is_email_address("a@a.a.a.ab", true); - check_is_email_address("test@test.abd", true); - check_is_email_address("test@test.com", true); - check_is_email_address("test.abd", false); - check_is_email_address("a.ab", false); - check_is_email_address("a.bc@d.ef", true); - - vector<string> bad_userdatas = {"", - "a.a.a.a.a.a.a.a.a.a.a.a", - "+.+.+.+.+.+", - "*.a.a", - "a.*.a", - "a.a.*", - "a.a.", - "a.a.abcdefghijklmnopqrstuvwxyz0123456789", - "a.abcdefghijklmnopqrstuvwxyz0.a", - "abcdefghijklmnopqrstuvwxyz0.a.a"}; - vector<string> good_userdatas = {"a.a.a.a.a.a.a.a.a.a.a", - "a+a+a+a+a+a+a+a+a+a+a", - "+.+.+.+.+._", - "aozAQZ0-5-9_+-aozAQZ0-5-9_.aozAQZ0-5-9_.-._.+-", - "a.a.a", - "a.a.abcdefghijklmnopqrstuvwxyz012345678", - "a.abcdefghijklmnopqrstuvwxyz.a", - "a..a", - "abcdefghijklmnopqrstuvwxyz.a.a", - ".a.a"}; - - vector<string> bad_domains = {"", - ".", - "abc", - "localhost", - "a.a.a.a.a.a.a.ab", - ".......", - "a.a.a.a.a.a+ab", - "a+a.a.a.a.a.ab", - "a.a.a.a.a.a.a", - "a.a.a.a.a.a.abcdefg", - "a.a.a.a.a.a.ab0yz", - "a.a.a.a.a.a.ab9yz", - "a.a.a.a.a.a.ab-yz", - "a.a.a.a.a.a.ab_yz", - "a.a.a.a.a.a.ab*yz", - ".ab", - ".a.ab", - "a..ab", - "a.a.a..a.ab", - ".a.a.a.a.ab", - "abcdefghijklmnopqrstuvwxyz01234.ab", - "ab0cd.abd.aA*sd.0.9.0-9.ABOYZ", - "ab*cd.abd.aAasd.0.9.0-9.ABOYZ", - "ab0cd.abd.aAasd.0.9.0*9.ABOYZ", - "*b0cd.ab_d.aA-sd.0.9.0-9.ABOYZ", - "ab0c*.ab_d.aA-sd.0.9.0-9.ABOYZ", - "ab0cd.ab_d.aA-sd.0.9.0-*.ABOYZ", - "ab0cd.ab_d.aA-sd.0.9.*-9.ABOYZ", - "-b0cd.ab_d.aA-sd.0.9.0-9.ABOYZ", - "ab0c-.ab_d.aA-sd.0.9.0-9.ABOYZ", - "ab0cd.ab_d.aA-sd.-.9.0-9.ABOYZ", - "ab0cd.ab_d.aA-sd.0.9.--9.ABOYZ", - "ab0cd.ab_d.aA-sd.0.9.0--.ABOYZ", - "_b0cd.ab_d.aA-sd.0.9.0-9.ABOYZ", - "ab0c_.ab_d.aA-sd.0.9.0-9.ABOYZ", - "ab0cd.ab_d.aA-sd._.9.0-9.ABOYZ", - "ab0cd.ab_d.aA-sd.0.9._-9.ABOYZ", - "ab0cd.ab_d.aA-sd.0.9.0-_.ABOYZ", - "-.ab_d.aA-sd.0.9.0-9.ABOYZ", - "ab0cd.ab_d.-.0.9.0-9.ABOYZ", - "ab0cd.ab_d.aA-sd.0.9.-.ABOYZ", - "_.ab_d.aA-sd.0.9.0-9.ABOYZ", - "ab0cd.ab_d._.0.9.0-9.ABOYZ", - "ab0cd.ab_d.aA-sd.0.9._.ABOYZ"}; - vector<string> good_domains = {"a.a.a.a.a.a.ab", - "a.a.a.a.a.a.abcdef", - "a.a.a.a.a.a.aboyz", - "a.a.a.a.a.a.ABOYZ", - "a.a.a.a.a.a.AbOyZ", - "abcdefghijklmnopqrstuvwxyz0123.ab", - "ab0cd.ab_d.aA-sd.0.9.0-9.ABOYZ", - "A.Z.aA-sd.a.z.0-9.ABOYZ"}; - - for (auto &userdata : bad_userdatas) { - for (auto &domain : bad_domains) { - check_is_email_address(userdata + '@' + domain, false); - check_is_email_address(userdata + domain, false); - } - for (auto &domain : good_domains) { - check_is_email_address(userdata + '@' + domain, false); - check_is_email_address(userdata + domain, false); - } - } - for (auto &userdata : good_userdatas) { - for (auto &domain : bad_domains) { - check_is_email_address(userdata + '@' + domain, false); - check_is_email_address(userdata + domain, false); - } - for (auto &domain : good_domains) { - check_is_email_address(userdata + '@' + domain, true); - check_is_email_address(userdata + domain, false); - } - } -} - -static void check_url(string str, std::vector<string> expected_urls, - std::vector<string> expected_email_addresses = {}) { - auto result_slice = find_urls(str); - std::vector<string> result_urls; - std::vector<string> result_email_addresses; - for (auto &it : result_slice) { - if (!it.second) { - result_urls.push_back(it.first.str()); - } else { - result_email_addresses.push_back(it.first.str()); - } - } - if (result_urls != expected_urls) { - LOG(FATAL) << tag("text", str) << tag("got", format::as_array(result_urls)) - << tag("expected", format::as_array(expected_urls)); - } - if (result_email_addresses != expected_email_addresses) { - LOG(FATAL) << tag("text", str) << tag("got", format::as_array(result_email_addresses)) - << tag("expected", format::as_array(expected_email_addresses)); - } -} - -TEST(MessageEntities, url) { - check_url("telegram.org", {"telegram.org"}); - check_url("(telegram.org)", {"telegram.org"}); - check_url("\ntelegram.org)", {"telegram.org"}); - check_url(" telegram.org)", {"telegram.org"}); - check_url(".telegram.org)", {}); - check_url("()telegram.org/?q=()", {"telegram.org/?q=()"}); - check_url("\"telegram.org\"", {"telegram.org"}); - check_url(" telegram. org. www. com... telegram.org... ...google.com...", {"telegram.org"}); - check_url(" telegram.org ", {"telegram.org"}); - check_url("Такой сайт: http://www.google.com или такой telegram.org ", {"http://www.google.com", "telegram.org"}); - check_url(" telegram.org. ", {"telegram.org"}); - check_url("http://google,.com", {}); - check_url("http://telegram.org/?asd=123#123.", {"http://telegram.org/?asd=123#123"}); - check_url("[http://google.com](test)", {"http://google.com"}); - check_url("", {}); - check_url(".", {}); - check_url("http://@google.com", {}); - check_url("http://@goog.com", {}); // TODO: server fix - check_url("http://@@google.com", {"http://@@google.com"}); - check_url("http://a@google.com", {"http://a@google.com"}); - check_url("http://test@google.com", {"http://test@google.com"}); - check_url("google.com:᪉᪉᪉᪉᪉", {"google.com"}); - check_url("https://telegram.org", {"https://telegram.org"}); - check_url("http://telegram.org", {"http://telegram.org"}); - check_url("ftp://telegram.org", {"ftp://telegram.org"}); - check_url("ftps://telegram.org", {}); - check_url("sftp://telegram.org", {"sftp://telegram.org"}); - check_url("hTtPs://telegram.org", {"hTtPs://telegram.org"}); - check_url("HTTP://telegram.org", {"HTTP://telegram.org"}); - check_url("аHTTP://telegram.org", {"HTTP://telegram.org"}); - check_url("sHTTP://telegram.org", {}); - check_url("://telegram.org", {}); - check_url("google.com:᪀᪀", {"google.com"}); - check_url( - "http://" - "abcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkab" - "cdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcd" - "efghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdef" - "ghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefgh" - "ijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghij" - "kabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijka" - "bcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabc" - "defghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijk.com", - {}); - check_url("http:// .com", {}); - check_url("URL: .com", {}); - check_url("URL: .com", {}); - check_url(".com", {}); - check_url("http:// .", {}); - check_url("http://.", {}); - check_url("http://.com", {}); - check_url("http:// .", {}); - check_url(",ahttp://google.com", {"http://google.com"}); - check_url(".ahttp://google.com", {}); - check_url("http://1.0", {}); - check_url("http://a.0", {}); - check_url("http://a.a", {}); - check_url("google.com:1#ab c", {"google.com:1#ab"}); - check_url("google.com:1#", {"google.com:1#"}); - check_url("google.com:1#1", {"google.com:1#1"}); - check_url("google.com:00000001/abs", {"google.com:00000001/abs"}); - check_url("google.com:000000065535/abs", {"google.com:000000065535/abs"}); - check_url("google.com:000000065536/abs", {"google.com"}); - check_url("google.com:000000080/abs", {"google.com:000000080/abs"}); - check_url("google.com:0000000/abs", {"google.com"}); - check_url("google.com:0/abs", {"google.com"}); - check_url("google.com:/abs", {"google.com"}); - check_url("google.com:65535", {"google.com:65535"}); - check_url("google.com:65536", {"google.com"}); - check_url("google.com:99999", {"google.com"}); - check_url("google.com:100000", {"google.com"}); - check_url("127.001", {}); - check_url("127.0.0.1", {"127.0.0.1"}); - check_url("127.0.0.01", {}); - check_url("127.0.0.256", {}); - check_url("127.0.0.300", {}); - check_url("127.0.0.1000", {}); - check_url("127.0.0.260", {}); - check_url("1.0", {}); - check_url("www.🤙.tk", {"www.🤙.tk"}); - check_url("a.ab", {}); - check_url("test.abd", {}); - check_url("ТеСт.Москва", {}); - check_url("ТеСт.МоСкВΑ", {}); - check_url("ТеСт.МоСкВа", {"ТеСт.МоСкВа"}); - check_url("ТеСт.МоСкВач", {}); - check_url("http://ÀТеСт.МоСкВач", {"http://ÀТеСт.МоСкВач"}); - check_url("ÀÁ.com. ÀÁ.com.", {"ÀÁ.com", "ÀÁ.com"}); - check_url("ÀÁ.com,ÀÁ.com.", {"ÀÁ.com", "ÀÁ.com"}); - check_url("teiegram.org", {}); - check_url("http://test.google.com/?q=abc()}[]def", {"http://test.google.com/?q=abc()"}); - check_url("http://test.google.com/?q=abc([{)]}def", {"http://test.google.com/?q=abc([{)]}def"}); - check_url("http://test.google.com/?q=abc(){}]def", {"http://test.google.com/?q=abc(){}"}); - check_url("http://test.google.com/?q=abc){}[]def", {"http://test.google.com/?q=abc"}); - check_url("http://test.google.com/?q=abc(){}[]def", {"http://test.google.com/?q=abc(){}[]def"}); - check_url("http://test-.google.com", {}); - check_url("http://test_.google.com", {"http://test_.google.com"}); - check_url("http://google_.com", {}); - check_url("http://google._com_", {}); - check_url("http://[2001:4860:0:2001::68]/", {}); // TODO - check_url("test.abd", {}); - check_url("/.b/..a @.....@/. a.ba", {"a.ba"}); - check_url("bbbbbbbbbbbbbb.@.@", {}); - check_url("http://google.com/", {"http://google.com/"}); - check_url("http://google.com?", {"http://google.com"}); - check_url("http://google.com#", {"http://google.com#"}); - check_url("http://google.com/?", {"http://google.com/"}); - check_url("https://www.google.com/ab,", {"https://www.google.com/ab"}); - check_url("@.", {}); - check_url( - "a.b.google.com dfsknnfs gsdfgsg http://códuia.de/ dffdg,\" 12)(cpia.de/())(\" http://гришка.рф/ sdufhdf " - "http://xn--80afpi2a3c.xn--p1ai/ I have a good time.Thanks, guys!\n\n(hdfughidufhgdis)go#ogle.com гришка.рф " - "hsighsdf gi почта.рф\n\n✪df.ws/123 " - "xn--80afpi2a3c.xn--p1ai\n\nhttp://foo.com/blah_blah\nhttp://foo.com/blah_blah/\n(Something like " - "http://foo.com/blah_blah)\nhttp://foo.com/blah_blah_(wikipedi8989a_Вася)\n(Something like " - "http://foo.com/blah_blah_(Стакан_007))\nhttp://foo.com/blah_blah.\nhttp://foo.com/blah_blah/.\n<http://foo.com/" - "blah_blah>\n<http://fo@@@@@@@@@^%#*@^&@$#*@#%^*&!^#o.com/blah_blah/>\nhttp://foo.com/blah_blah,\nhttp://" - "www.example.com/wpstyle/?p=364.\nhttp://✪df.ws/123\nrdar://1234\nrdar:/1234\nhttp://" - "userid:password@example.com:8080\nhttp://userid@example.com\nhttp://userid@example.com:8080\nhttp://" - "userid:password@example.com\nhttp://example.com:8080 " - "x-yojimbo-item://6303E4C1-xxxx-45A6-AB9D-3A908F59AE0E\nmessage://" - "%3c330e7f8409726r6a4ba78dkf1fd71420c1bf6ff@mail.gmail.com%3e\nhttp://➡️.ws/䨹\nwww.➡️.ws/" - "䨹\n<tag>http://example.com</tag>\nJust a www.example.com " - "link.\n\n➡️.ws/" - "䨹\n\nabcdefghijklmnopqrstuvwxyz0123456789qwe_sdfsdf.aweawe-sdfs.com\nwww.🤙.tk:1\ngoogle.com:" - "᪉᪉᪉᪉\ngoogle." - "com:᪀᪀\nhttp:// .com\nURL: .com\nURL: " - ".com\n\ngoogle.com?qwe\ngoogle.com#qwe\ngoogle.com/?\ngoogle.com/#\ngoogle.com?\ngoogle.com#\n", - {"a.b.google.com", - "http://códuia.de/", - "cpia.de/()", - "http://гришка.рф/", - "http://xn--80afpi2a3c.xn--p1ai/", - "гришка.рф", - "почта.рф", - "✪df.ws/123", - "xn--80afpi2a3c.xn--p1ai", - "http://foo.com/blah_blah", - "http://foo.com/blah_blah/", - "http://foo.com/blah_blah", - "http://foo.com/blah_blah_(wikipedi8989a_Вася)", - "http://foo.com/blah_blah_(Стакан_007)", - "http://foo.com/blah_blah", - "http://foo.com/blah_blah/", - "http://foo.com/blah_blah", - "http://foo.com/blah_blah", - "http://www.example.com/wpstyle/?p=364", - "http://✪df.ws/123", - "http://userid:password@example.com:8080", - "http://userid@example.com", - "http://userid@example.com:8080", - "http://userid:password@example.com", - "http://example.com:8080", - "http://➡️.ws/䨹", - "www.➡️.ws/䨹", - "http://example.com", - "www.example.com", - "➡️.ws/䨹", - "abcdefghijklmnopqrstuvwxyz0123456789qwe_sdfsdf.aweawe-sdfs.com", - "www.🤙.tk:1", - "google.com", - "google.com", - "google.com?qwe", - "google.com#qwe", - "google.com/", - "google.com/#", - "google.com", - "google.com#"}); - check_url("https://t.…", {}); - check_url("('http://telegram.org/a-b/?br=ie&lang=en',)", {"http://telegram.org/a-b/?br=ie&lang=en"}); - check_url("https://ai.telegram.org/bot%20bot/test-...", {"https://ai.telegram.org/bot%20bot/test-"}); - check_url("a.bc@c.com", {}, {"a.bc@c.com"}); - check_url("https://a.bc@c.com", {"https://a.bc@c.com"}); - check_url("https://a.de[bc@c.com", {"https://a.de"}, {"bc@c.com"}); - check_url("https://a.de/bc@c.com", {"https://a.de/bc@c.com"}); - check_url("https://a.de]bc@c.com", {"https://a.de"}, {"bc@c.com"}); - check_url("https://a.de{bc@c.com", {"https://a.de"}, {"bc@c.com"}); - check_url("https://a.de}bc@c.com", {"https://a.de"}, {"bc@c.com"}); - check_url("https://a.de(bc@c.com", {"https://a.de"}, {"bc@c.com"}); - check_url("https://a.de)bc@c.com", {"https://a.de"}, {"bc@c.com"}); - check_url("https://a.de\\bc@c.com", {"https://a.de\\bc@c.com"}); - check_url("https://a.de'bc@c.com", {"https://a.de"}, {"bc@c.com"}); - check_url("https://a.de`bc@c.com", {"https://a.de"}, {"bc@c.com"}); - check_url("https://a.bc:de.fg@c.com", {"https://a.bc:de.fg@c.com"}); - check_url("https://a:h.bc:de.fg@c.com", {"https://a:h.bc:de.fg@c.com"}); - check_url("https://abc@c.com", {"https://abc@c.com"}); - check_url("https://de[bc@c.com", {}, {"bc@c.com"}); - check_url("https://de/bc@c.com", {}); - check_url("https://de]bc@c.com", {}, {"bc@c.com"}); - check_url("https://de{bc@c.com", {}, {"bc@c.com"}); - check_url("https://de}bc@c.com", {}, {"bc@c.com"}); - check_url("https://de(bc@c.com", {}, {"bc@c.com"}); - check_url("https://de)bc@c.com", {}, {"bc@c.com"}); - check_url("https://de\\bc@c.com", {"https://de\\bc@c.com"}); - check_url("https://de'bc@c.com", {}, {"bc@c.com"}); - check_url("https://de`bc@c.com", {}, {"bc@c.com"}); - check_url("https://bc:defg@c.com", {"https://bc:defg@c.com"}); - check_url("https://a:hbc:defg@c.com", {"https://a:hbc:defg@c.com"}); - check_url("https://a.bc@test.com:cd.com", {"https://a.bc@test.com", "cd.com"}); - check_url("telegram.Org", {}); - check_url("telegram.ORG", {"telegram.ORG"}); - check_url("a.b.c.com.a.b.c", {}); - check_url("File '/usr/views.py'", {}); // TODO server fix - check_url("@views.py'", {}); // TODO server fix - check_url("#views.py'", {}); // TODO server fix - check_url("/views.py'", {}); // TODO server fix - check_url(".views.py", {}); - check_url("'views.py'", {"views.py"}); - check_url("bug.http://test.com/test/+#", {}); // TODO {"http://test.com/test/+#"} - check_url("//AB.C.D.E.F.GH//", {}); - check_url("<http://www.ics.uci.edu/pub/ietf/uri/historical.html#WARNING>", - {"http://www.ics.uci.edu/pub/ietf/uri/historical.html#WARNING"}); - check_url("Look :test@example.com", {":test@example.com"}, {}); // TODO {}, {"test@example.com"} - check_url("http://test.com#a", {"http://test.com#a"}); - check_url("http://test.com#", {"http://test.com#"}); - check_url("http://test.com?#", {"http://test.com?#"}); - check_url("http://test.com/?#", {"http://test.com/?#"}); - check_url("https://t.me/abcdef…", {"https://t.me/abcdef"}); - check_url("https://t.me…", {"https://t.me"}); - check_url("https://t.m…", {}); - check_url("https://t.…", {}); - check_url("https://t…", {}); - check_url("👉http://ab.com/cdefgh-1IJ", {"http://ab.com/cdefgh-1IJ"}); - check_url("...👉http://ab.com/cdefgh-1IJ", {}); // TODO -} diff --git a/libs/tdlib/td/test/mtproto.cpp b/libs/tdlib/td/test/mtproto.cpp deleted file mode 100644 index 7702a1e37b..0000000000 --- a/libs/tdlib/td/test/mtproto.cpp +++ /dev/null @@ -1,347 +0,0 @@ -// -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -#include "td/utils/tests.h" - -#include "td/actor/actor.h" -#include "td/actor/PromiseFuture.h" - -#include "td/mtproto/crypto.h" -#include "td/mtproto/Handshake.h" -#include "td/mtproto/HandshakeActor.h" -#include "td/mtproto/HandshakeConnection.h" -#include "td/mtproto/PingConnection.h" -#include "td/mtproto/RawConnection.h" - -#include "td/net/Socks5.h" - -#include "td/telegram/ConfigManager.h" -#include "td/telegram/net/PublicRsaKeyShared.h" - -#include "td/utils/logging.h" -#include "td/utils/port/IPAddress.h" -#include "td/utils/port/SocketFd.h" -#include "td/utils/Status.h" - -REGISTER_TESTS(mtproto); - -using namespace td; -using namespace mtproto; - -#if !TD_WINDOWS && !TD_EMSCRIPTEN // TODO -TEST(Mtproto, config) { - ConcurrentScheduler sched; - int threads_n = 0; - sched.init(threads_n); - - int cnt = 3; - { - auto guard = sched.get_current_guard(); - get_simple_config_azure(PromiseCreator::lambda([&](Result<SimpleConfig> r_simple_config) { - LOG(ERROR) << to_string(r_simple_config.ok()); - if (--cnt == 0) { - Scheduler::instance()->finish(); - } - })) - .release(); - - get_simple_config_google_app(PromiseCreator::lambda([&](Result<SimpleConfig> r_simple_config) { - LOG(ERROR) << to_string(r_simple_config.ok()); - if (--cnt == 0) { - Scheduler::instance()->finish(); - } - })) - .release(); - - get_simple_config_google_dns(PromiseCreator::lambda([&](Result<SimpleConfig> r_simple_config) { - LOG(ERROR) << to_string(r_simple_config.ok()); - if (--cnt == 0) { - Scheduler::instance()->finish(); - } - })) - .release(); - } - sched.start(); - while (sched.run_main(10)) { - // empty; - } - sched.finish(); -} -#endif - -TEST(Mtproto, encrypted_config) { - string data = - " LQ2 \b\n\tru6xVXpHHckW4eQWK0X3uThupVOor5sXT8t298IjDksYeUseQTOIrnUqiQj7o" - "+ZgPfhnfe+lfcQA+naax9akgllimjlJtL5riTf3O7iqZSnJ614qmCucxqqVTbXk/" - "hY2KaJTtsMqk7cShJjM3aQ4DD40h2InTaG7uyVO2q7K0GMUTeY3AM0Rt1lUjKHLD" - "g4RwjTzZaG8TwfgL/mZ7jsvgTTTATPWKUo7SmxQ9Hsj+07NMGqr6JKZS6aiU1Knz" - "VGCZ3OJEyRYocktN4HjaLpkguilaHWlVM2UNFUd5a+ajfLIiiKlH0FRC3XZ12CND" - "Y+NBjv0I57N2O4fBfswTlA== "; - auto config = decode_config(data).move_as_ok(); -} - -class TestPingActor : public Actor { - public: - TestPingActor(IPAddress ip_address, Status *result) : ip_address_(ip_address), result_(result) { - } - - private: - IPAddress ip_address_; - std::unique_ptr<mtproto::PingConnection> ping_connection_; - Status *result_; - - void start_up() override { - ping_connection_ = std::make_unique<mtproto::PingConnection>(std::make_unique<mtproto::RawConnection>( - SocketFd::open(ip_address_).move_as_ok(), mtproto::TransportType::Tcp, nullptr)); - - ping_connection_->get_pollable().set_observer(this); - subscribe(ping_connection_->get_pollable()); - set_timeout_in(10); - yield(); - } - void tear_down() override { - unsubscribe_before_close(ping_connection_->get_pollable()); - ping_connection_->close(); - Scheduler::instance()->finish(); - } - - void loop() override { - auto status = ping_connection_->flush(); - if (status.is_error()) { - *result_ = std::move(status); - return stop(); - } - if (ping_connection_->was_pong()) { - LOG(ERROR) << "GOT PONG"; - return stop(); - } - } - - void timeout_expired() override { - *result_ = Status::Error("Timeout expired"); - stop(); - } -}; - -static IPAddress get_default_ip_address() { - IPAddress ip_address; - ip_address.init_ipv4_port("149.154.167.40", 80).ensure(); - return ip_address; -} - -class Mtproto_ping : public td::Test { - public: - using Test::Test; - bool step() final { - if (!is_inited_) { - sched_.init(0); - sched_.create_actor_unsafe<TestPingActor>(0, "Pinger", get_default_ip_address(), &result_).release(); - sched_.start(); - is_inited_ = true; - } - - bool ret = sched_.run_main(10); - if (ret) { - return true; - } - sched_.finish(); - if (result_.is_error()) { - LOG(ERROR) << result_; - } - ASSERT_TRUE(result_.is_ok()); - return false; - } - - private: - bool is_inited_ = false; - ConcurrentScheduler sched_; - Status result_; -}; -Mtproto_ping mtproto_ping("Mtproto_ping"); - -class Context : public AuthKeyHandshakeContext { - public: - DhCallback *get_dh_callback() override { - return nullptr; - } - PublicRsaKeyInterface *get_public_rsa_key_interface() override { - return &public_rsa_key; - } - - private: - PublicRsaKeyShared public_rsa_key{DcId::empty()}; -}; - -class HandshakeTestActor : public Actor { - public: - explicit HandshakeTestActor(Status *result) : result_(result) { - } - - private: - Status *result_; - bool wait_for_raw_connection_ = false; - std::unique_ptr<RawConnection> raw_connection_; - bool wait_for_handshake_ = false; - std::unique_ptr<AuthKeyHandshake> handshake_; - Status status_; - bool wait_for_result_ = false; - - void tear_down() override { - if (raw_connection_) { - raw_connection_->close(); - } - finish(Status::Error("Interrupted")); - } - void loop() override { - if (!wait_for_raw_connection_ && !raw_connection_) { - raw_connection_ = std::make_unique<mtproto::RawConnection>(SocketFd::open(get_default_ip_address()).move_as_ok(), - mtproto::TransportType::Tcp, nullptr); - } - if (!wait_for_handshake_ && !handshake_) { - handshake_ = std::make_unique<AuthKeyHandshake>(0); - } - if (raw_connection_ && handshake_) { - if (wait_for_result_) { - wait_for_result_ = false; - if (status_.is_error()) { - finish(std::move(status_)); - return stop(); - } - if (!handshake_->is_ready_for_finish()) { - finish(Status::Error("Key is not ready..")); - return stop(); - } - finish(Status::OK()); - return stop(); - } - - wait_for_result_ = true; - create_actor<HandshakeActor>( - "HandshakeActor", std::move(handshake_), std::move(raw_connection_), std::make_unique<Context>(), 10.0, - PromiseCreator::lambda([self = actor_id(this)](Result<std::unique_ptr<RawConnection>> raw_connection) { - send_closure(self, &HandshakeTestActor::got_connection, std::move(raw_connection), 1); - }), - PromiseCreator::lambda([self = actor_id(this)](Result<std::unique_ptr<AuthKeyHandshake>> handshake) { - send_closure(self, &HandshakeTestActor::got_handshake, std::move(handshake), 1); - })) - .release(); - wait_for_raw_connection_ = true; - wait_for_handshake_ = true; - } - } - - void got_connection(Result<std::unique_ptr<RawConnection>> r_raw_connection, int32 dummy) { - CHECK(wait_for_raw_connection_); - wait_for_raw_connection_ = false; - if (r_raw_connection.is_ok()) { - raw_connection_ = r_raw_connection.move_as_ok(); - status_ = Status::OK(); - } else { - status_ = r_raw_connection.move_as_error(); - } - // TODO: save error - loop(); - } - - void got_handshake(Result<std::unique_ptr<AuthKeyHandshake>> r_handshake, int32 dummy) { - CHECK(wait_for_handshake_); - wait_for_handshake_ = false; - CHECK(r_handshake.is_ok()); - handshake_ = r_handshake.move_as_ok(); - loop(); - } - - void finish(Status status) { - if (!result_) { - return; - } - *result_ = std::move(status); - result_ = nullptr; - Scheduler::instance()->finish(); - } -}; - -class Mtproto_handshake : public td::Test { - public: - using Test::Test; - bool step() final { - if (!is_inited_) { - sched_.init(0); - sched_.create_actor_unsafe<HandshakeTestActor>(0, "HandshakeTestActor", &result_).release(); - sched_.start(); - is_inited_ = true; - } - - bool ret = sched_.run_main(10); - if (ret) { - return true; - } - sched_.finish(); - if (result_.is_error()) { - LOG(ERROR) << result_; - } - ASSERT_TRUE(result_.is_ok()); - return false; - } - - private: - bool is_inited_ = false; - ConcurrentScheduler sched_; - Status result_; -}; -Mtproto_handshake mtproto_handshake("Mtproto_handshake"); - -class Socks5TestActor : public Actor { - public: - void start_up() override { - auto promise = PromiseCreator::lambda([actor_id = actor_id(this)](Result<SocketFd> res) { - send_closure(actor_id, &Socks5TestActor::on_result, std::move(res), false); - }); - - class Callback : public Socks5::Callback { - public: - explicit Callback(Promise<SocketFd> promise) : promise_(std::move(promise)) { - } - void set_result(Result<SocketFd> result) override { - promise_.set_result(std::move(result)); - } - void on_connected() override { - } - - private: - Promise<SocketFd> promise_; - }; - - IPAddress socks5_ip; - socks5_ip.init_ipv4_port("131.191.89.104", 43077).ensure(); - IPAddress mtproto_ip = get_default_ip_address(); - - auto r_socket = SocketFd::open(socks5_ip); - create_actor<Socks5>("socks5", r_socket.move_as_ok(), mtproto_ip, "", "", - std::make_unique<Callback>(std::move(promise)), actor_shared()) - .release(); - } - - private: - void on_result(Result<SocketFd> res, bool dummy) { - res.ensure(); - Scheduler::instance()->finish(); - } -}; - -TEST(Mtproto, socks5) { - return; - ConcurrentScheduler sched; - int threads_n = 0; - sched.init(threads_n); - - sched.create_actor_unsafe<Socks5TestActor>(0, "Socks5TestActor").release(); - sched.start(); - while (sched.run_main(10)) { - // empty; - } - sched.finish(); -} diff --git a/libs/tdlib/td/test/secret.cpp b/libs/tdlib/td/test/secret.cpp deleted file mode 100644 index 2abed9787b..0000000000 --- a/libs/tdlib/td/test/secret.cpp +++ /dev/null @@ -1,1056 +0,0 @@ -// -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 -// -// 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/actor/PromiseFuture.h" - -#include "td/db/binlog/detail/BinlogEventsProcessor.h" - -#include "td/mtproto/crypto.h" -#include "td/mtproto/utils.h" - -#include "td/telegram/Global.h" -#include "td/telegram/MessageId.h" -#include "td/telegram/SecretChatActor.h" -#include "td/telegram/SecretChatId.h" - -#include "td/telegram/secret_api.h" -#include "td/telegram/telegram_api.h" - -#include "td/tl/tl_object_parse.h" -#include "td/tl/tl_object_store.h" - -#include "td/utils/base64.h" -#include "td/utils/buffer.h" -#include "td/utils/crypto.h" -#include "td/utils/format.h" -#include "td/utils/Gzip.h" -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/Random.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" -#include "td/utils/tests.h" -#include "td/utils/tl_helpers.h" -#include "td/utils/tl_parsers.h" -#include "td/utils/tl_storers.h" - -#include <cstdio> -#include <ctime> -#include <limits> -#include <map> -#include <memory> - -REGISTER_TESTS(secret); - -namespace my_api { - -using namespace td; - -//messages_getDhConfig -class messages_getDhConfig { - public: - int32 version_; - int32 random_length_; - - messages_getDhConfig() = default; - - messages_getDhConfig(int32 version_, int32 random_length_); - - static const int32 ID = 651135312; - - explicit messages_getDhConfig(TlBufferParser &p) -#define FAIL(error) p.set_error(error) - : version_(TlFetchInt::parse(p)) - , random_length_(TlFetchInt::parse(p)) -#undef FAIL - { - } -}; - -//InputUser -class InputUser { - public: - static tl_object_ptr<InputUser> fetch(TlBufferParser &p); -}; - -class inputUser final : public InputUser { - public: - int32 user_id_; - int64 access_hash_; - - static const int32 ID = -668391402; - inputUser() = default; - - explicit inputUser(TlBufferParser &p) -#define FAIL(error) p.set_error(error) - : user_id_(TlFetchInt::parse(p)) - , access_hash_(TlFetchLong::parse(p)) -#undef FAIL - { - } -}; -tl_object_ptr<InputUser> InputUser::fetch(TlBufferParser &p) { -#define FAIL(error) \ - p.set_error(error); \ - return nullptr; - int constructor = p.fetch_int(); - switch (constructor) { - case inputUser::ID: - return make_tl_object<inputUser>(p); - default: - FAIL(PSTRING() << "Unknown constructor found " << format::as_hex(constructor)); - } -#undef FAIL -} - -class messages_requestEncryption final { - public: - tl_object_ptr<InputUser> user_id_; - int32 random_id_; - BufferSlice g_a_; - - static const int32 ID = -162681021; - messages_requestEncryption(); - - explicit messages_requestEncryption(TlBufferParser &p) -#define FAIL(error) p.set_error(error) - : user_id_(TlFetchObject<InputUser>::parse(p)) - , random_id_(TlFetchInt::parse(p)) - , g_a_(TlFetchBytes<BufferSlice>::parse(p)) -#undef FAIL - { - } -}; - -class inputEncryptedChat final { - public: - int32 chat_id_; - int64 access_hash_; - - inputEncryptedChat() = default; - - static const int32 ID = -247351839; - explicit inputEncryptedChat(TlBufferParser &p) -#define FAIL(error) p.set_error(error) - : chat_id_(TlFetchInt::parse(p)) - , access_hash_(TlFetchLong::parse(p)) -#undef FAIL - { - } - static tl_object_ptr<inputEncryptedChat> fetch(TlBufferParser &p) { - return make_tl_object<inputEncryptedChat>(p); - } -}; - -class messages_acceptEncryption final { - public: - tl_object_ptr<inputEncryptedChat> peer_; - BufferSlice g_b_; - int64 key_fingerprint_; - - messages_acceptEncryption() = default; - - static const int32 ID = 1035731989; - - explicit messages_acceptEncryption(TlBufferParser &p) -#define FAIL(error) p.set_error(error) - : peer_(TlFetchBoxed<TlFetchObject<inputEncryptedChat>, -247351839>::parse(p)) - , g_b_(TlFetchBytes<BufferSlice>::parse(p)) - , key_fingerprint_(TlFetchLong::parse(p)) -#undef FAIL - { - } -}; - -class messages_sendEncryptedService final { - public: - tl_object_ptr<inputEncryptedChat> peer_; - int64 random_id_; - BufferSlice data_; - - messages_sendEncryptedService() = default; - static const int32 ID = 852769188; - explicit messages_sendEncryptedService(TlBufferParser &p) -#define FAIL(error) p.set_error(error) - : peer_(TlFetchBoxed<TlFetchObject<inputEncryptedChat>, -247351839>::parse(p)) - , random_id_(TlFetchLong::parse(p)) - , data_(TlFetchBytes<BufferSlice>::parse(p)) -#undef FAIL - { - } -}; - -class messages_sendEncrypted final { - public: - tl_object_ptr<inputEncryptedChat> peer_; - int64 random_id_; - BufferSlice data_; - - messages_sendEncrypted() = default; - static const int32 ID = -1451792525; - - explicit messages_sendEncrypted(TlBufferParser &p) -#define FAIL(error) p.set_error(error) - : peer_(TlFetchBoxed<TlFetchObject<inputEncryptedChat>, -247351839>::parse(p)) - , random_id_(TlFetchLong::parse(p)) - , data_(TlFetchBytes<BufferSlice>::parse(p)) -#undef FAIL - { - } -}; - -template <class F> -static void downcast_call(TlBufferParser &p, F &&f) { - auto id = p.fetch_int(); - switch (id) { - case messages_getDhConfig::ID: - return f(*make_tl_object<messages_getDhConfig>(p)); - case messages_requestEncryption::ID: - return f(*make_tl_object<messages_requestEncryption>(p)); - case messages_acceptEncryption::ID: - return f(*make_tl_object<messages_acceptEncryption>(p)); - case messages_sendEncrypted::ID: - return f(*make_tl_object<messages_sendEncrypted>(p)); - case messages_sendEncryptedService::ID: - return f(*make_tl_object<messages_sendEncryptedService>(p)); - default: - CHECK(0) << id; - UNREACHABLE(); - } -} - -class messages_dhConfig final { - public: - int32 g_; - BufferSlice p_; - int32 version_; - BufferSlice random_; - - messages_dhConfig() = default; - - messages_dhConfig(int32 g_, BufferSlice &&p_, int32 version_, BufferSlice &&random_) - : g_(g_), p_(std::move(p_)), version_(version_), random_(std::move(random_)) { - } - - static const int32 ID = 740433629; - int32 get_id() const { - return ID; - } - - void store(TlStorerCalcLength &s) const { - (void)sizeof(s); - TlStoreBinary::store(g_, s); - TlStoreString::store(p_, s); - TlStoreBinary::store(version_, s); - TlStoreString::store(random_, s); - } - void store(TlStorerUnsafe &s) const { - (void)sizeof(s); - TlStoreBinary::store(g_, s); - TlStoreString::store(p_, s); - TlStoreBinary::store(version_, s); - TlStoreString::store(random_, s); - } -}; - -class encryptedChat final { - public: - int32 id_; - int64 access_hash_; - int32 date_; - int32 admin_id_; - int32 participant_id_; - BufferSlice g_a_or_b_; - int64 key_fingerprint_; - - encryptedChat() = default; - - encryptedChat(int32 id_, int64 access_hash_, int32 date_, int32 admin_id_, int32 participant_id_, - BufferSlice &&g_a_or_b_, int64 key_fingerprint_) - : id_(id_) - , access_hash_(access_hash_) - , date_(date_) - , admin_id_(admin_id_) - , participant_id_(participant_id_) - , g_a_or_b_(std::move(g_a_or_b_)) - , key_fingerprint_(key_fingerprint_) { - } - - static const int32 ID = -94974410; - int32 get_id() const { - return ID; - } - - void store(TlStorerCalcLength &s) const { - (void)sizeof(s); - TlStoreBinary::store(id_, s); - TlStoreBinary::store(access_hash_, s); - TlStoreBinary::store(date_, s); - TlStoreBinary::store(admin_id_, s); - TlStoreBinary::store(participant_id_, s); - TlStoreString::store(g_a_or_b_, s); - TlStoreBinary::store(key_fingerprint_, s); - } - - void store(TlStorerUnsafe &s) const { - (void)sizeof(s); - TlStoreBinary::store(id_, s); - TlStoreBinary::store(access_hash_, s); - TlStoreBinary::store(date_, s); - TlStoreBinary::store(admin_id_, s); - TlStoreBinary::store(participant_id_, s); - TlStoreString::store(g_a_or_b_, s); - TlStoreBinary::store(key_fingerprint_, s); - } -}; - -class messages_sentEncryptedMessage final { - public: - int32 date_; - - messages_sentEncryptedMessage() = default; - - explicit messages_sentEncryptedMessage(int32 date_) : date_(date_) { - } - - static const int32 ID = 1443858741; - int32 get_id() const { - return ID; - } - - void store(TlStorerCalcLength &s) const { - (void)sizeof(s); - TlStoreBinary::store(date_, s); - } - - void store(TlStorerUnsafe &s) const { - (void)sizeof(s); - TlStoreBinary::store(date_, s); - } -}; - -} // namespace my_api - -namespace td { -static int32 g = 3; -static string prime_base64 = - "xxyuucaxyQSObFIvcPE_c5gNQCOOPiHBSTTQN1Y9kw9IGYoKp8FAWCKUk9IlMPTb-jNvbgrJJROVQ67UTM58NyD9UfaUWHBaxozU_mtrE6vcl0ZRKW" - "kyhFTxj6-MWV9kJHf-lrsqlB1bzR1KyMxJiAcI-ps3jjxPOpBgvuZ8-aSkppWBEFGQfhYnU7VrD2tBDbp02KhLKhSzFE4O8ShHVP0X7ZUNWWW0ud1G" - "WC2xF40WnGvEZbDW_5yjko_vW5rk5Bj8Feg-vqD4f6n_Xu1wBQ3tKEn0e_lZ2VaFDOkphR8NgRX2NbEF7i5OFdBLJFS_b0-t8DSxBAMRnNjjuS_MW" - "w"; - -class FakeDhCallback : public DhCallback { - public: - int is_good_prime(Slice prime_str) const override { - auto it = cache.find(prime_str.str()); - if (it == cache.end()) { - return -1; - } - return it->second; - } - void add_good_prime(Slice prime_str) const override { - cache[prime_str.str()] = 1; - } - void add_bad_prime(Slice prime_str) const override { - cache[prime_str.str()] = 0; - } - mutable std::map<string, int> cache; -}; - -class FakeBinlog - : public BinlogInterface - , public Actor { - public: - FakeBinlog() { - register_actor("FakeBinlog", this).release(); - } - void force_sync(Promise<> promise) override { - if (pending_events_.empty()) { - pending_events_.emplace_back(); - } - pending_events_.back().promises_.push_back(std::move(promise)); - pending_events_.back().sync_flag = true; - request_sync(); - } - void request_sync() { - if (!has_request_sync) { - has_request_sync = true; - if (Random::fast(0, 4) == 0) { - set_timeout_in(Random::fast(0, 99) / 100.0 * 0.005 + 0.001); - } else { - yield(); - } - } - } - void force_flush() override { - } - - uint64 next_id() override { - auto res = last_id_; - last_id_++; - return res; - } - uint64 next_id(int32 shift) override { - auto res = last_id_; - last_id_ += shift; - return res; - } - template <class F> - void for_each(const F &f) { - events_processor_.for_each([&](auto &x) { - LOG(INFO) << "REPLAY: " << x.id_; - f(x); - }); - } - - void restart() { - has_request_sync = false; - cancel_timeout(); - for (auto &pending : pending_events_) { - auto &event = pending.event; - if (!event.empty()) { - // LOG(ERROR) << "FORGET EVENT: " << event.id_ << " " << event; - } - } - pending_events_.clear(); - } - - void change_key(DbKey key, Promise<> promise) override { - } - - protected: - void close_impl(Promise<> promise) override { - } - void close_and_destroy_impl(Promise<> promise) override { - } - void add_raw_event_impl(uint64 id, BufferSlice &&raw_event, Promise<> promise) override { - auto event = BinlogEvent(std::move(raw_event)); - LOG(INFO) << "ADD EVENT: " << event.id_ << " " << event; - pending_events_.emplace_back(); - pending_events_.back().event = std::move(event); - pending_events_.back().promises_.push_back(std::move(promise)); - } - void do_force_sync() { - if (pending_events_.empty()) { - return; - } - cancel_timeout(); - has_request_sync = false; - auto pos = static_cast<size_t>(Random::fast_uint64() % pending_events_.size()); - // pos = pending_events_.size() - 1; - std::vector<Promise<>> promises; - for (size_t i = 0; i <= pos; i++) { - auto &pending = pending_events_[i]; - auto event = std::move(pending.event); - if (!event.empty()) { - LOG(INFO) << "SAVE EVENT: " << event.id_ << " " << event; - events_processor_.add_event(std::move(event)); - } - append(promises, std::move(pending.promises_)); - } - pending_events_.erase(pending_events_.begin(), pending_events_.begin() + pos + 1); - for (auto &promise : promises) { - promise.set_value(Unit()); - } - - for (auto &event : pending_events_) { - if (event.sync_flag) { - request_sync(); - break; - } - } - } - void timeout_expired() override { - do_force_sync(); - } - void wakeup() override { - if (has_request_sync) { - do_force_sync(); - } - } - bool has_request_sync = false; - uint64 last_id_ = 1; - detail::BinlogEventsProcessor events_processor_; - - struct PendingEvent { - BinlogEvent event; - bool sync_flag = false; - std::vector<Promise<>> promises_; - }; - - std::vector<PendingEvent> pending_events_; -}; - -using FakeKeyValue = BinlogKeyValue<BinlogInterface>; -class OldFakeKeyValue : public KeyValueSyncInterface { - SeqNo set(string key, string value) override { - kv_[key] = value; - return 0; - } - - SeqNo erase(const string &key) override { - kv_.erase(key); - return 0; - } - - bool isset(const string &key) override { - return kv_.count(key) > 0; - } - - string get(const string &key) override { - auto it = kv_.find(key); - if (it != kv_.end()) { - return it->second; - } - return string(); - } - - private: - std::map<string, string> kv_; -}; - -class Master; -class FakeSecretChatContext : public SecretChatActor::Context { - public: - FakeSecretChatContext(std::shared_ptr<BinlogInterface> binlog, std::shared_ptr<KeyValueSyncInterface> key_value, - std::shared_ptr<bool> close_flag, ActorShared<Master> master) - : binlog_(std::move(binlog)) - , key_value_(std::move(key_value)) - , close_flag_(std::move(close_flag)) - , master_(std::move(master)) { - secret_chat_db_ = std::make_unique<SecretChatDb>(key_value_, 1); - net_query_creator_.stop_check(); // :( - } - DhCallback *dh_callback() override { - return &fake_dh_callback_; - } - NetQueryCreator &net_query_creator() override { - return net_query_creator_; - } - int32 unix_time() override { - return static_cast<int32>(std::time(nullptr)); - } - bool close_flag() override { - return *close_flag_; - } - BinlogInterface *binlog() override { - return binlog_.get(); - } - SecretChatDb *secret_chat_db() override { - return secret_chat_db_.get(); - } - std::shared_ptr<DhConfig> dh_config() override { - static auto config = [] { - DhConfig dh_config; - dh_config.version = 12; - dh_config.g = g; - dh_config.prime = base64url_decode(prime_base64).move_as_ok(); - return std::make_shared<DhConfig>(dh_config); - }(); - - return config; - } - void set_dh_config(std::shared_ptr<DhConfig> dh_config) override { - // empty - } - - bool get_config_option_boolean(const string &name) const override { - return false; - } - - // We don't want to expose the whole NetQueryDispatcher, MessagesManager and ContactsManager. - // So it is more clear which parts of MessagesManager is really used. And it is much easier to create tests. - void send_net_query(NetQueryPtr query, ActorShared<NetQueryCallback> callback, bool ordered) override; - - void on_update_secret_chat(int64 access_hash, UserId user_id, SecretChatState state, bool is_outbound, int32 ttl, - int32 date, string key_hash, int32 layer) override { - } - - void on_inbound_message(UserId user_id, MessageId message_id, int32 date, - tl_object_ptr<telegram_api::encryptedFile> file, - tl_object_ptr<secret_api::decryptedMessage> message, Promise<>) override; - - void on_send_message_error(int64 random_id, Status error, Promise<>) override; - void on_send_message_ack(int64 random_id) override; - void on_send_message_ok(int64 random_id, MessageId message_id, int32 date, - tl_object_ptr<telegram_api::EncryptedFile> file, Promise<>) override; - void on_delete_messages(std::vector<int64> random_id, Promise<>) override; - void on_flush_history(MessageId, Promise<>) override; - void on_read_message(int64, Promise<>) override; - - void on_screenshot_taken(UserId user_id, MessageId message_id, int32 date, int64 random_id, - Promise<> promise) override { - } - void on_set_ttl(UserId user_id, MessageId message_id, int32 date, int32 ttl, int64 random_id, - Promise<> promise) override { - } - - private: - FakeDhCallback fake_dh_callback_; - static NetQueryCreator net_query_creator_; - std::shared_ptr<BinlogInterface> binlog_; - std::shared_ptr<KeyValueSyncInterface> key_value_; - std::shared_ptr<bool> close_flag_; - ActorShared<Master> master_; - - std::shared_ptr<SecretChatDb> secret_chat_db_; -}; -NetQueryCreator FakeSecretChatContext::net_query_creator_; - -class Master : public Actor { - public: - explicit Master(Status *status) : status_(status) { - } - class SecretChatProxy : public Actor { - public: - SecretChatProxy(string name, ActorShared<Master> parent) : name_(std::move(name)) { - binlog_ = std::make_shared<FakeBinlog>(); - key_value_ = std::make_shared<FakeKeyValue>(); - key_value_->external_init_begin(LogEvent::HandlerType::BinlogPmcMagic); - key_value_->external_init_finish(binlog_); - close_flag_ = std::make_shared<bool>(false); - parent_ = parent.get(); - parent_token_ = parent.token(); - actor_ = create_actor<SecretChatActor>( - "SecretChat " + name_, 123, - std::make_unique<FakeSecretChatContext>(binlog_, key_value_, close_flag_, std::move(parent)), true); - on_binlog_replay_finish(); - } - - ActorOwn<SecretChatActor> actor_; - - void add_inbound_message(int32 chat_id, BufferSlice data, uint64 crc) { - CHECK(crc64(data.as_slice()) == crc); - auto event = std::make_unique<logevent::InboundSecretMessage>(); - event->qts = 0; - event->chat_id = chat_id; - event->date = 0; - event->encrypted_message = std::move(data); - event->qts_ack = PromiseCreator::lambda( - [actor_id = actor_id(this), chat_id, data = event->encrypted_message.copy(), crc](Result<> result) mutable { - if (result.is_ok()) { - LOG(INFO) << "FINISH add_inbound_message " << tag("crc", crc); - return; - } - LOG(INFO) << "RESEND add_inbound_message " << tag("crc", crc) << result.error(); - send_closure(actor_id, &SecretChatProxy::add_inbound_message, chat_id, std::move(data), crc); - }); - - add_event(Event::delayed_closure(&SecretChatActor::add_inbound_message, std::move(event))); - } - - void send_message(tl_object_ptr<secret_api::decryptedMessage> message) { - BufferSlice serialized_message(serialize(*message)); - auto resend_promise = PromiseCreator::lambda( - [actor_id = actor_id(this), serialized_message = std::move(serialized_message)](Result<> result) mutable { - TlBufferParser parser(&serialized_message); - auto message = secret_api::decryptedMessage::fetch(parser); - if (result.is_ok()) { - LOG(INFO) << "FINISH send_message " << tag("message", to_string(message)); - return; - } - LOG(INFO) << "RESEND send_message " << tag("message", to_string(message)) << result.error(); - CHECK(serialize(*message) == serialized_message.as_slice()); - send_closure(actor_id, &SecretChatProxy::send_message, std::move(message)); - }); - auto sync_promise = PromiseCreator::lambda([actor_id = actor_id(this), generation = this->binlog_generation_, - resend_promise = std::move(resend_promise)](Result<> result) mutable { - if (result.is_error()) { - resend_promise.set_error(result.move_as_error()); - return; - } - send_closure(actor_id, &SecretChatProxy::sync_binlog, generation, std::move(resend_promise)); - }); - - add_event( - Event::delayed_closure(&SecretChatActor::send_message, std::move(message), nullptr, std::move(sync_promise))); - } - int32 binlog_generation_ = 0; - void sync_binlog(int32 binlog_generation, Promise<> promise) { - if (binlog_generation != binlog_generation_) { - return promise.set_error(Status::Error("binlog generation mismatch")); - } - binlog_->force_sync(std::move(promise)); - } - void on_closed() { - LOG(INFO) << "CLOSED"; - ready_ = false; - *close_flag_ = false; - - key_value_ = std::make_shared<FakeKeyValue>(); - key_value_->external_init_begin(LogEvent::HandlerType::BinlogPmcMagic); - - std::vector<BinlogEvent> events; - binlog_generation_++; - binlog_->restart(); - binlog_->for_each([&](const BinlogEvent &event) { - if (event.type_ == LogEvent::HandlerType::BinlogPmcMagic) { - key_value_->external_init_handle(event); - } else { - events.push_back(event.clone()); - } - }); - - key_value_->external_init_finish(binlog_); - - actor_ = create_actor<SecretChatActor>( - "SecretChat " + name_, 123, - std::make_unique<FakeSecretChatContext>(binlog_, key_value_, close_flag_, - ActorShared<Master>(parent_, parent_token_)), - true); - - for (auto &event : events) { - CHECK(event.type_ == LogEvent::HandlerType::SecretChats); - auto r_message = logevent::SecretChatEvent::from_buffer_slice(event.data_as_buffer_slice()); - LOG_IF(FATAL, r_message.is_error()) << "Failed to deserialize event: " << r_message.error(); - auto message = r_message.move_as_ok(); - message->set_logevent_id(event.id_); - LOG(INFO) << "Process binlog event " << *message; - switch (message->get_type()) { - case logevent::SecretChatEvent::Type::InboundSecretMessage: - send_closure_later(actor_, &SecretChatActor::replay_inbound_message, - std::unique_ptr<logevent::InboundSecretMessage>( - static_cast<logevent::InboundSecretMessage *>(message.release()))); - break; - case logevent::SecretChatEvent::Type::OutboundSecretMessage: - send_closure_later(actor_, &SecretChatActor::replay_outbound_message, - std::unique_ptr<logevent::OutboundSecretMessage>( - static_cast<logevent::OutboundSecretMessage *>(message.release()))); - break; - default: - UNREACHABLE(); - } - }; - start_test(); - on_binlog_replay_finish(); - } - void on_binlog_replay_finish() { - ready_ = true; - LOG(INFO) << "on_binlog_replay_finish!"; - send_closure(actor_, &SecretChatActor::binlog_replay_finish); - for (auto &event : pending_events_) { - send_event(actor_, std::move(event)); - } - pending_events_.clear(); - } - void start_test() { - set_timeout_in(Random::fast(50, 99) * 0.3 / 50); - events_cnt_ = 0; - } - - private: - string name_; - - ActorId<Master> parent_; - uint64 parent_token_; - std::shared_ptr<FakeBinlog> binlog_; - std::shared_ptr<FakeKeyValue> key_value_; - std::shared_ptr<bool> close_flag_; - int events_cnt_ = 0; - - std::vector<Event> pending_events_; - bool ready_ = false; - - bool is_active() { - return !actor_.empty() && ready_; - } - void add_event(Event event) { - events_cnt_++; - if (is_active()) { - LOG(INFO) << "EMIT"; - send_event(actor_, std::move(event)); - } else { - LOG(INFO) << "DELAY"; - pending_events_.push_back(std::move(event)); - } - } - - int32 bad_cnt_ = 0; - void timeout_expired() override { - LOG(INFO) << "TIMEOUT EXPIRED"; - if (events_cnt_ < 4) { - bad_cnt_++; - CHECK(bad_cnt_ < 10); - } else { - bad_cnt_ = 0; - } - *close_flag_ = true; - actor_.reset(); - } - }; - - auto &get_by_id(uint64 id) { - if (id == 1) { - return alice_; - } else { - return bob_; - } - } - auto &from() { - return get_by_id(get_link_token()); - } - auto &to() { - return get_by_id(3 - get_link_token()); - } - void start_up() override { - set_context(std::make_shared<Global>()); - alice_ = create_actor<SecretChatProxy>("SecretChatProxy alice", "alice", actor_shared(this, 1)); - bob_ = create_actor<SecretChatProxy>("SecretChatProxy bob", "bob", actor_shared(this, 2)); - send_closure(alice_->get_actor_unsafe()->actor_, &SecretChatActor::create_chat, 2, 0, 123, - PromiseCreator::lambda([actor_id = actor_id(this)](Result<SecretChatId> res) { - send_closure(actor_id, &Master::got_secret_chat_id, std::move(res), 0); - })); - } - void got_secret_chat_id(Result<SecretChatId> res, int) { // second parameter is needed to workaround clang bug - CHECK(res.is_ok()); - auto id = res.move_as_ok(); - LOG(INFO) << "SecretChatId = " << id; - } - bool can_fail(NetQueryPtr &query) { - static int cnt = 20; - if (cnt > 0) { - cnt--; - return false; - } - if (query->tl_constructor() == telegram_api::messages_sendEncrypted::ID || - query->tl_constructor() == telegram_api::messages_sendEncryptedFile::ID) { - return true; - } - return false; - } - void send_net_query(NetQueryPtr query, ActorShared<NetQueryCallback> callback, bool ordered) { - if (can_fail(query) && Random::fast(0, 1) == 0) { - LOG(INFO) << "Fail query " << query; - auto resend_promise = - PromiseCreator::lambda([id = actor_shared(this, get_link_token()), callback_actor = callback.get(), - callback_token = callback.token()](Result<NetQueryPtr> r_net_query) mutable { - if (r_net_query.is_error()) { - id.release(); - return; - } - send_closure(std::move(id), &Master::send_net_query, r_net_query.move_as_ok(), - ActorShared<NetQueryCallback>(callback_actor, callback_token), true); - }); - query->set_error(Status::Error(429, "Test error")); - send_closure(std::move(callback), &NetQueryCallback::on_result_resendable, std::move(query), - std::move(resend_promise)); - return; - } else { - LOG(INFO) << "Do not fail " << query; - } - auto query_slice = query->query().clone(); - if (query->gzip_flag() == NetQuery::GzipFlag::On) { - query_slice = gzdecode(query_slice.as_slice()); - } - TlBufferParser parser(&query_slice); - //auto object = telegram_api::Function::fetch(parser); - //LOG(INFO) << query_slice.size(); - //parser.get_status().ensure(); - my_api::downcast_call(parser, [&](auto &object) { - this->process_net_query(std::move(object), std::move(query), std::move(callback)); - }); - } - template <class T> - void process_net_query(T &&object, NetQueryPtr query, ActorShared<NetQueryCallback> callback) { - LOG(FATAL) << "Unsupported query: " << to_string(object); - } - void process_net_query(my_api::messages_getDhConfig &&get_dh_config, NetQueryPtr net_query, - ActorShared<NetQueryCallback> callback) { - //LOG(INFO) << "Got 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<my_api::messages_dhConfig>(config); - BufferSlice answer(storer.size()); - storer.store(answer.as_slice().ubegin()); - net_query->set_ok(std::move(answer)); - send_closure(std::move(callback), &NetQueryCallback::on_result, std::move(net_query)); - } - void process_net_query(my_api::messages_requestEncryption &&request_encryption, NetQueryPtr net_query, - ActorShared<NetQueryCallback> callback) { - CHECK(get_link_token() == 1); - send_closure(alice_->get_actor_unsafe()->actor_, &SecretChatActor::update_chat, - make_tl_object<telegram_api::encryptedChatWaiting>(123, 321, 0, 1, 2)); - send_closure( - bob_->get_actor_unsafe()->actor_, &SecretChatActor::update_chat, - make_tl_object<telegram_api::encryptedChatRequested>(123, 321, 0, 1, 2, request_encryption.g_a_.clone())); - net_query->clear(); - } - void process_net_query(my_api::messages_acceptEncryption &&request_encryption, NetQueryPtr net_query, - ActorShared<NetQueryCallback> callback) { - CHECK(get_link_token() == 2); - send_closure(alice_->get_actor_unsafe()->actor_, &SecretChatActor::update_chat, - make_tl_object<telegram_api::encryptedChat>(123, 321, 0, 1, 2, request_encryption.g_b_.clone(), - request_encryption.key_fingerprint_)); - - my_api::encryptedChat encrypted_chat(123, 321, 0, 1, 2, BufferSlice(), request_encryption.key_fingerprint_); - auto storer = TLObjectStorer<my_api::encryptedChat>(encrypted_chat); - BufferSlice answer(storer.size()); - storer.store(answer.as_slice().ubegin()); - net_query->set_ok(std::move(answer)); - send_closure(std::move(callback), &NetQueryCallback::on_result, std::move(net_query)); - send_closure(alice_, &SecretChatProxy::start_test); - send_closure(bob_, &SecretChatProxy::start_test); - send_ping(1, 5000); - set_timeout_in(1); - } - void timeout_expired() override { - send_message(1, "oppa"); - send_message(2, "appo"); - set_timeout_in(1); - } - void send_ping(int id, int cnt) { - if (cnt % 200 == 0) { - LOG(ERROR) << "send ping " << tag("id", id) << tag("cnt", cnt); - } else { - LOG(INFO) << "send ping " << tag("id", id) << tag("cnt", cnt); - } - string text = PSTRING() << "PING: " << cnt; - send_message(id, std::move(text)); - } - void send_message(int id, string text) { - auto random_id = Random::secure_int64(); - LOG(INFO) << "send message: " << tag("id", id) << tag("text", text) << tag("random_id", random_id); - sent_messages_[random_id] = Message{id, text}; - send_closure(get_by_id(id), &SecretChatProxy::send_message, - secret_api::make_object<secret_api::decryptedMessage>(0, random_id, 0, text, Auto(), Auto(), Auto(), - Auto(), 0)); - } - void process_net_query(my_api::messages_sendEncryptedService &&message, NetQueryPtr net_query, - ActorShared<NetQueryCallback> callback) { - process_net_query_send_enrypted(std::move(message.data_), std::move(net_query), std::move(callback)); - } - void process_net_query(my_api::messages_sendEncrypted &&message, NetQueryPtr net_query, - ActorShared<NetQueryCallback> callback) { - process_net_query_send_enrypted(std::move(message.data_), std::move(net_query), std::move(callback)); - } - void process_net_query_send_enrypted(BufferSlice data, NetQueryPtr net_query, - ActorShared<NetQueryCallback> callback) { - my_api::messages_sentEncryptedMessage sent_message; - sent_message.date_ = 0; - auto storer = TLObjectStorer<my_api::messages_sentEncryptedMessage>(sent_message); - BufferSlice answer(storer.size()); - storer.store(answer.as_slice().ubegin()); - net_query->set_ok(std::move(answer)); - send_closure(std::move(callback), &NetQueryCallback::on_result, std::move(net_query)); - - // We can't loose updates yet :( - auto crc = crc64(data.as_slice()); - LOG(INFO) << "send SecretChatProxy::add_inbound_message" << tag("crc", crc); - send_closure(to(), &SecretChatProxy::add_inbound_message, narrow_cast<int32>(3 - get_link_token()), std::move(data), - crc); - } - - int32 last_ping_ = std::numeric_limits<int32>::max(); - void on_inbound_message(string message, Promise<> promise) { - promise.set_value(Unit()); - LOG(INFO) << "GOT INBOUND MESSAGE: " << message << " " << get_link_token(); - int32 cnt; - int x = std::sscanf(message.c_str(), "PING: %d", &cnt); - if (x != 1) { - return; - } - if (cnt == 0) { - Scheduler::instance()->finish(); - *status_ = Status::OK(); - return; - } - if (cnt >= last_ping_) { - return; - } - last_ping_ = cnt; - send_ping(narrow_cast<int32>(get_link_token()), cnt - 1); - } - void on_send_message_error(int64 random_id, Status error, Promise<> promise) { - promise.set_value(Unit()); - LOG(INFO) << "on_send_message_error: " << tag("random_id", random_id) << error; - auto it = sent_messages_.find(random_id); - if (it == sent_messages_.end()) { - LOG(INFO) << "TODO: try fix errors about message after it is sent"; - return; - } - CHECK(it != sent_messages_.end()); - auto message = it->second; - // sent_messages_.erase(it); - send_message(message.id, message.text); - } - void on_send_message_ok(int64 random_id, Promise<> promise) { - promise.set_value(Unit()); - LOG(INFO) << "on_send_message_ok: " << tag("random_id", random_id); - auto it = sent_messages_.find(random_id); - if (it == sent_messages_.end()) { - LOG(INFO) << "TODO: try fix errors about message after it is sent"; - return; - } - CHECK(it != sent_messages_.end()); - // sent_messages_.erase(it); - } - - private: - Status *status_; - ActorOwn<SecretChatProxy> alice_; - ActorOwn<SecretChatProxy> bob_; - struct Message { - int32 id; - string text; - }; - std::map<int64, Message> sent_messages_; - - void hangup_shared() override { - LOG(INFO) << "GOT HANGUP: " << get_link_token(); - send_closure(from(), &SecretChatProxy::on_closed); - } -}; - -void FakeSecretChatContext::send_net_query(NetQueryPtr query, ActorShared<NetQueryCallback> callback, bool ordered) { - send_closure(master_, &Master::send_net_query, std::move(query), std::move(callback), ordered); -} -void FakeSecretChatContext::on_inbound_message(UserId user_id, MessageId message_id, int32 date, - tl_object_ptr<telegram_api::encryptedFile> file, - tl_object_ptr<secret_api::decryptedMessage> message, Promise<> promise) { - send_closure(master_, &Master::on_inbound_message, message->message_, std::move(promise)); -} -void FakeSecretChatContext::on_send_message_error(int64 random_id, Status error, Promise<> promise) { - send_closure(master_, &Master::on_send_message_error, random_id, std::move(error), std::move(promise)); -} -void FakeSecretChatContext::on_send_message_ack(int64 random_id) { -} -void FakeSecretChatContext::on_send_message_ok(int64 random_id, MessageId message_id, int32 date, - tl_object_ptr<telegram_api::EncryptedFile> file, Promise<> promise) { - send_closure(master_, &Master::on_send_message_ok, random_id, std::move(promise)); -} -void FakeSecretChatContext::on_delete_messages(std::vector<int64> random_id, Promise<> promise) { - promise.set_value(Unit()); -} -void FakeSecretChatContext::on_flush_history(MessageId, Promise<> promise) { - promise.set_error(Status::Error("unsupported")); -} -void FakeSecretChatContext::on_read_message(int64, Promise<> promise) { - promise.set_error(Status::Error("unsupported")); -} - -TEST(Secret, go) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - ConcurrentScheduler sched; - int threads_n = 0; - sched.init(threads_n); - - Status result; - sched.create_actor_unsafe<Master>(0, "HandshakeTestActor", &result).release(); - sched.start(); - while (sched.run_main(10)) { - // empty; - } - sched.finish(); - - if (result.is_error()) { - LOG(ERROR) << result; - } - ASSERT_TRUE(result.is_ok()); -} - -} // namespace td diff --git a/libs/tdlib/td/test/string_cleaning.cpp b/libs/tdlib/td/test/string_cleaning.cpp deleted file mode 100644 index 6fbd8150a4..0000000000 --- a/libs/tdlib/td/test/string_cleaning.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 -// -// 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/Slice.h" -#include "td/utils/tests.h" - -REGISTER_TESTS(string_cleaning); - -using namespace td; - -TEST(StringCleaning, clean_name) { - ASSERT_EQ("@mention", clean_name("@mention", 1000000)); - ASSERT_EQ("@mention", clean_name(" @mention ", 1000000)); - ASSERT_EQ("@MENTION", clean_name("@MENTION", 1000000)); - ASSERT_EQ("ЛШТШФУМ", clean_name("ЛШТШФУМ", 1000000)); - ASSERT_EQ("....", clean_name("....", 1000000)); - ASSERT_EQ(". ASD ..", clean_name(". ASD ..", 1000000)); - ASSERT_EQ(". ASD", clean_name(". ASD ..", 10)); - ASSERT_EQ(". ASD", clean_name(".\n\n\nASD\n\n\n..", 10)); - ASSERT_EQ("", clean_name("\n\n\n\n\n\n", 1000000)); - ASSERT_EQ("", clean_name("\xC2\xA0\xC2\xA0\xC2\xA0\xC2\xA0\xC2\xA0\n\n\n\n\n\n \n\xC2\xA0 \xC2\xA0 \n", 100000)); - ASSERT_EQ("abc", clean_name("\xC2\xA0\xC2\xA0" - "abc\xC2\xA0\xC2\xA0\xC2\xA0\xC2\xA0", - 1000000)); -}; - -TEST(StringCleaning, clean_username) { - ASSERT_EQ("@mention", clean_username("@mention")); - ASSERT_EQ("@mention", clean_username(" @mention ")); - ASSERT_EQ("@mention", clean_username("@MENTION")); - ASSERT_EQ("ЛШТШФУМ", clean_username("ЛШТШФУМ")); - ASSERT_EQ("", clean_username("....")); - ASSERT_EQ("asd", clean_username(". ASD ..")); -}; - -static void check_clean_input_string(string str, string expected, bool expected_result) { - auto result = clean_input_string(str); - ASSERT_EQ(expected_result, result); - if (result) { - ASSERT_EQ(expected, str); - } -} - -TEST(StringCleaning, clean_input_string) { - check_clean_input_string("/abc", "/abc", true); - check_clean_input_string(string(50000, 'a'), string(34996, 'a'), true); - check_clean_input_string("\xff", "", false); - check_clean_input_string("\xc0\x80", "", false); - check_clean_input_string("\xd0", "", false); - check_clean_input_string("\xe0\xaf", "", false); - check_clean_input_string("\xf0\xa6", "", false); - check_clean_input_string("\xf0\xa6\x88", "", false); - check_clean_input_string("\xf4\x8f\xbf\xbf", "\xf4\x8f\xbf\xbf", true); - check_clean_input_string("\xf4\x8f\xbf\xc0", "", false); - check_clean_input_string("\r\r\r\r\r\r\r", "", true); - check_clean_input_string("\r\n\r\n\r\n\r\n\r\n\r\n\r", "\n\n\n\n\n\n", true); - check_clean_input_string(Slice("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" - "\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21") - .str(), - " \x0a \x21", true); - check_clean_input_string( - "\xe2\x80\xa7\xe2\x80\xa8\xe2\x80\xa9\xe2\x80\xaa\xe2\x80\xab\xe2\x80\xac\xe2\x80\xad\xe2\x80\xae\xe2\x80\xaf", - "\xe2\x80\xa7\xe2\x80\xaf", true); - check_clean_input_string("\xcc\xb3\xcc\xbf\xcc\x8a", "", true); -} - -static void check_strip_empty_characters(string str, size_t max_length, string expected) { - ASSERT_EQ(expected, strip_empty_characters(str, max_length)); -} - -TEST(StringCleaning, strip_empty_characters) { - check_strip_empty_characters("/abc", 4, "/abc"); - check_strip_empty_characters("/abc", 3, "/ab"); - check_strip_empty_characters("/abc", 0, ""); - check_strip_empty_characters("/abc", 10000000, "/abc"); - string spaces = - u8"\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u200B\u202F\u205F\u3000\uFEFF" - u8"\uFFFC\uFFFC"; - string spaces_replace = " "; - string empty = "\xE2\x80\x8C\xE2\x80\x8D\xE2\x80\xAE\xC2\xA0\xC2\xA0"; - - check_strip_empty_characters(spaces, 1000000, ""); - check_strip_empty_characters(empty, 1000000, ""); - check_strip_empty_characters(empty + "a", 1000000, empty + "a"); - check_strip_empty_characters(spaces + empty + spaces + "abc" + spaces, 1000000, empty + spaces_replace + "abc"); - check_strip_empty_characters(spaces + spaces + empty + spaces + spaces + empty + empty, 1000000, - empty + spaces_replace + spaces_replace + empty + empty); - check_strip_empty_characters("\r\r\r\r\r\r\r", 1000000, ""); - check_strip_empty_characters("\r\n\r\n\r\n\r\n\r\n\r\n\r", 1000000, ""); - check_strip_empty_characters(Slice(" \t\r\n\0\va\v\0\n\r\t ").str(), 1000000, "a"); - check_strip_empty_characters( - Slice("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" - "\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21") - .str(), - 1000000, - "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" - "\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21"); - check_strip_empty_characters("\xcc\xb3\xcc\xbf\xcc\x8a", 2, "\xcc\xb3\xcc\xbf"); - check_strip_empty_characters( - "\xe2\x80\xa7\xe2\x80\xa8\xe2\x80\xa9\xe2\x80\xaa\xe2\x80\xab\xe2\x80\xac\xe2\x80\xad\xe2\x80\xae", 3, - "\xe2\x80\xa7\xe2\x80\xa8\xe2\x80\xa9"); -} diff --git a/libs/tdlib/td/test/tdclient.cpp b/libs/tdlib/td/test/tdclient.cpp deleted file mode 100644 index 7cef0fcbc0..0000000000 --- a/libs/tdlib/td/test/tdclient.cpp +++ /dev/null @@ -1,837 +0,0 @@ -// -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 -// -// 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 "data.h" - -#include "td/actor/PromiseFuture.h" - -#include "td/telegram/ClientActor.h" - -#include "td/telegram/td_api.h" - -#include "td/utils/base64.h" -#include "td/utils/BufferedFd.h" -#include "td/utils/filesystem.h" -#include "td/utils/format.h" -#include "td/utils/logging.h" -#include "td/utils/misc.h" -#include "td/utils/port/FileFd.h" -#include "td/utils/port/path.h" -#include "td/utils/Random.h" -#include "td/utils/Slice.h" -#include "td/utils/Status.h" -#include "td/utils/tests.h" - -#include <cstdio> -#include <functional> -#include <map> -#include <memory> -#include <utility> - -REGISTER_TESTS(tdclient); - -namespace td { - -template <class T> -static void check_td_error(T &result) { - CHECK(result->get_id() != td_api::error::ID) << to_string(result); -} - -static void rmrf(CSlice path) { - td::walk_path(path, [](CSlice path, bool is_dir) { - if (is_dir) { - td::rmdir(path).ignore(); - } else { - td::unlink(path).ignore(); - } - }); -} - -class TestClient : public Actor { - public: - explicit TestClient(string name) : name_(std::move(name)) { - } - struct Update { - uint64 id; - tl_object_ptr<td_api::Object> object; - Update(uint64 id, tl_object_ptr<td_api::Object> object) : id(id), object(std::move(object)) { - } - }; - class Listener { - public: - Listener() = default; - Listener(const Listener &) = delete; - Listener &operator=(const Listener &) = delete; - Listener(Listener &&) = delete; - Listener &operator=(Listener &&) = delete; - virtual ~Listener() = default; - virtual void start_listen(TestClient *client) { - } - virtual void stop_listen() { - } - virtual void on_update(std::shared_ptr<Update> update) = 0; - }; - void close(Promise<> close_promise) { - close_promise_ = std::move(close_promise); - td_.reset(); - } - - unique_ptr<TdCallback> make_td_callback() { - class TdCallbackImpl : public TdCallback { - public: - explicit TdCallbackImpl(ActorId<TestClient> client) : client_(client) { - } - void on_result(uint64 id, tl_object_ptr<td_api::Object> result) override { - send_closure(client_, &TestClient::on_result, id, std::move(result)); - } - void on_error(uint64 id, tl_object_ptr<td_api::error> error) override { - send_closure(client_, &TestClient::on_error, id, std::move(error)); - } - void on_closed() override { - send_closure(client_, &TestClient::on_closed); - } - - private: - ActorId<TestClient> client_; - }; - return make_unique<TdCallbackImpl>(actor_id(this)); - } - - void add_listener(std::unique_ptr<Listener> listener) { - auto *ptr = listener.get(); - listeners_.push_back(std::move(listener)); - ptr->start_listen(this); - } - void remove_listener(Listener *listener) { - pending_remove_.push_back(listener); - } - void do_pending_remove_listeners() { - for (auto listener : pending_remove_) { - do_remove_listener(listener); - } - pending_remove_.clear(); - } - void do_remove_listener(Listener *listener) { - for (size_t i = 0; i < listeners_.size(); i++) { - if (listeners_[i].get() == listener) { - listener->stop_listen(); - listeners_.erase(listeners_.begin() + i); - break; - } - } - } - - void on_result(uint64 id, tl_object_ptr<td_api::Object> result) { - on_update(std::make_shared<Update>(id, std::move(result))); - } - void on_error(uint64 id, tl_object_ptr<td_api::error> error) { - on_update(std::make_shared<Update>(id, std::move(error))); - } - void on_update(std::shared_ptr<Update> update) { - for (auto &listener : listeners_) { - listener->on_update(update); - } - do_pending_remove_listeners(); - } - - void on_closed() { - stop(); - } - - void start_up() override { - rmrf(name_); - set_context(std::make_shared<td::ActorContext>()); - set_tag(name_); - LOG(INFO) << "START UP!"; - - td_ = create_actor<ClientActor>("Td-proxy", make_td_callback()); - } - - ActorOwn<ClientActor> td_; - - string name_; - - private: - std::vector<std::unique_ptr<Listener>> listeners_; - std::vector<Listener *> pending_remove_; - - Promise<> close_promise_; -}; - -class Task : public TestClient::Listener { - public: - void on_update(std::shared_ptr<TestClient::Update> update) override { - auto it = sent_queries_.find(update->id); - if (it != sent_queries_.end()) { - it->second(std::move(update->object)); - sent_queries_.erase(it); - } - process_update(update); - } - void start_listen(TestClient *client) override { - client_ = client; - start_up(); - } - virtual void process_update(std::shared_ptr<TestClient::Update> update) { - } - - template <class F> - void send_query(tl_object_ptr<td_api::Function> function, F callback) { - auto id = current_query_id_++; - sent_queries_[id] = std::forward<F>(callback); - send_closure(client_->td_, &ClientActor::request, id, std::move(function)); - } - - protected: - std::map<uint64, std::function<void(tl_object_ptr<td_api::Object>)>> sent_queries_; - TestClient *client_; - uint64 current_query_id_ = 1; - - virtual void start_up() { - } - void stop() { - client_->remove_listener(this); - } -}; - -class DoAuthentication : public Task { - public: - DoAuthentication(string name, string phone, string code, Promise<> promise) - : name_(std::move(name)), phone_(std::move(phone)), code_(std::move(code)), promise_(std::move(promise)) { - } - void start_up() override { - send_query(make_tl_object<td_api::getAuthorizationState>(), - [this](auto res) { this->process_authorization_state(std::move(res)); }); - } - void process_authorization_state(tl_object_ptr<td_api::Object> authorization_state) { - start_flag_ = true; - tl_object_ptr<td_api::Function> function; - switch (authorization_state->get_id()) { - case td_api::authorizationStateWaitEncryptionKey::ID: - function = make_tl_object<td_api::checkDatabaseEncryptionKey>(); - break; - case td_api::authorizationStateWaitPhoneNumber::ID: - function = make_tl_object<td_api::setAuthenticationPhoneNumber>(phone_, false, true); - break; - case td_api::authorizationStateWaitCode::ID: - function = make_tl_object<td_api::checkAuthenticationCode>(code_, name_, ""); - break; - case td_api::authorizationStateWaitTdlibParameters::ID: { - auto parameters = td_api::make_object<td_api::tdlibParameters>(); - parameters->use_test_dc_ = true; - parameters->database_directory_ = name_ + TD_DIR_SLASH; - parameters->use_message_database_ = true; - parameters->use_secret_chats_ = true; - parameters->api_id_ = 94575; - parameters->api_hash_ = "a3406de8d171bb422bb6ddf3bbd800e2"; - parameters->system_language_code_ = "en"; - parameters->device_model_ = "Desktop"; - parameters->system_version_ = "Unknown"; - parameters->application_version_ = "tdclient-test"; - parameters->ignore_file_names_ = false; - parameters->enable_storage_optimizer_ = true; - function = td_api::make_object<td_api::setTdlibParameters>(std::move(parameters)); - break; - } - case td_api::authorizationStateReady::ID: - on_authorization_ready(); - return; - default: - CHECK(false) << "Unexpected authorization state " << to_string(authorization_state); - } - send_query(std::move(function), [this](auto res) { CHECK(res->get_id() == td_api::ok::ID) << to_string(res); }); - } - void on_authorization_ready() { - LOG(INFO) << "GOT AUTHORIZED"; - stop(); - } - - private: - string name_; - string phone_; - string code_; - Promise<> promise_; - bool start_flag_{false}; - void process_update(std::shared_ptr<TestClient::Update> update) override { - if (!start_flag_) { - return; - } - if (!update->object) { - return; - } - if (update->object->get_id() == td_api::updateAuthorizationState::ID) { - auto o = std::move(update->object); - process_authorization_state(std::move(static_cast<td_api::updateAuthorizationState &>(*o).authorization_state_)); - } - } -}; - -class SetUsername : public Task { - public: - SetUsername(string username, Promise<> promise) : username_(std::move(username)), promise_(std::move(promise)) { - } - - private: - string username_; - Promise<> promise_; - int32 self_id_; - string tag_; - - void start_up() override { - send_query(make_tl_object<td_api::getMe>(), [this](auto res) { this->process_me_user(std::move(res)); }); - } - - void process_me_user(tl_object_ptr<td_api::Object> res) { - CHECK(res->get_id() == td_api::user::ID); - auto user = move_tl_object_as<td_api::user>(res); - self_id_ = user->id_; - if (user->username_ != username_) { - LOG(INFO) << "SET USERNAME: " << username_; - send_query(make_tl_object<td_api::setUsername>(username_), [this](auto res) { - CHECK(res->get_id() == td_api::ok::ID); - this->send_self_message(); - }); - } else { - send_self_message(); - } - } - void send_self_message() { - tag_ = PSTRING() << format::as_hex(Random::secure_int64()); - - send_query(make_tl_object<td_api::createPrivateChat>(self_id_, false), [this](auto res) { - CHECK(res->get_id() == td_api::chat::ID); - auto chat = move_tl_object_as<td_api::chat>(res); - this->send_query( - make_tl_object<td_api::sendMessage>( - chat->id_, 0, false, false, nullptr, - make_tl_object<td_api::inputMessageText>( - make_tl_object<td_api::formattedText>(PSTRING() << tag_ << " INIT", Auto()), false, false)), - [](auto res) {}); - }); - } - - void process_update(std::shared_ptr<TestClient::Update> update) override { - if (!update->object) { - return; - } - if (update->object->get_id() == td_api::updateMessageSendSucceeded::ID) { - auto updateNewMessage = move_tl_object_as<td_api::updateMessageSendSucceeded>(update->object); - auto &message = updateNewMessage->message_; - if (message->content_->get_id() == td_api::messageText::ID) { - auto messageText = move_tl_object_as<td_api::messageText>(message->content_); - auto text = messageText->text_->text_; - if (text.substr(0, tag_.size()) == tag_) { - LOG(INFO) << "GOT SELF MESSAGE"; - return stop(); - } - } - } - } -}; - -class CheckTestA : public Task { - public: - CheckTestA(string tag, Promise<> promise) : tag_(std::move(tag)), promise_(std::move(promise)) { - } - - private: - string tag_; - Promise<> promise_; - string previous_text_; - int cnt_ = 20; - void process_update(std::shared_ptr<TestClient::Update> update) override { - if (update->object->get_id() == td_api::updateNewMessage::ID) { - auto updateNewMessage = move_tl_object_as<td_api::updateNewMessage>(update->object); - auto &message = updateNewMessage->message_; - if (message->content_->get_id() == td_api::messageText::ID) { - auto messageText = move_tl_object_as<td_api::messageText>(message->content_); - auto text = messageText->text_->text_; - if (text.substr(0, tag_.size()) == tag_) { - CHECK(text > previous_text_) << tag("now", text) << tag("previous", previous_text_); - previous_text_ = text; - cnt_--; - LOG(INFO) << "GOT " << tag("text", text) << tag("left", cnt_); - if (cnt_ == 0) { - return stop(); - } - } - } - } - } -}; - -class TestA : public Task { - public: - TestA(string tag, string username) : tag_(std::move(tag)), username_(std::move(username)) { - } - void start_up() override { - send_query(make_tl_object<td_api::searchPublicChat>(username_), [this](auto res) { - CHECK(res->get_id() == td_api::chat::ID); - auto chat = move_tl_object_as<td_api::chat>(res); - for (int i = 0; i < 20; i++) { - this->send_query(make_tl_object<td_api::sendMessage>( - chat->id_, 0, false, false, nullptr, - make_tl_object<td_api::inputMessageText>( - make_tl_object<td_api::formattedText>(PSTRING() << tag_ << " " << (1000 + i), Auto()), - false, false)), - [&](auto res) { this->stop(); }); - } - }); - } - - private: - string tag_; - string username_; -}; - -class TestSecretChat : public Task { - public: - TestSecretChat(string tag, string username) : tag_(std::move(tag)), username_(std::move(username)) { - } - - void start_up() override { - auto f = [this](auto res) { - CHECK(res->get_id() == td_api::chat::ID); - auto chat = move_tl_object_as<td_api::chat>(res); - this->chat_id_ = chat->id_; - this->secret_chat_id_ = move_tl_object_as<td_api::chatTypeSecret>(chat->type_)->secret_chat_id_; - }; - send_query(make_tl_object<td_api::searchPublicChat>(username_), [this, f = std::move(f)](auto res) mutable { - CHECK(res->get_id() == td_api::chat::ID); - auto chat = move_tl_object_as<td_api::chat>(res); - CHECK(chat->type_->get_id() == td_api::chatTypePrivate::ID); - auto info = move_tl_object_as<td_api::chatTypePrivate>(chat->type_); - this->send_query(make_tl_object<td_api::createNewSecretChat>(info->user_id_), std::move(f)); - }); - } - - void process_update(std::shared_ptr<TestClient::Update> update) override { - if (!update->object) { - return; - } - if (update->object->get_id() == td_api::updateSecretChat::ID) { - auto update_secret_chat = move_tl_object_as<td_api::updateSecretChat>(update->object); - if (update_secret_chat->secret_chat_->id_ != secret_chat_id_ || - update_secret_chat->secret_chat_->state_->get_id() != td_api::secretChatStateReady::ID) { - return; - } - LOG(INFO) << "SEND ENCRYPTED MESSAGES"; - for (int i = 0; i < 20; i++) { - send_query(make_tl_object<td_api::sendMessage>( - chat_id_, 0, false, false, nullptr, - make_tl_object<td_api::inputMessageText>( - make_tl_object<td_api::formattedText>(PSTRING() << tag_ << " " << (1000 + i), Auto()), false, - false)), - [](auto res) {}); - } - } - } - - private: - string tag_; - string username_; - int64 secret_chat_id_ = 0; - int64 chat_id_ = 0; -}; - -class TestFileGenerated : public Task { - public: - TestFileGenerated(string tag, string username) : tag_(std::move(tag)), username_(std::move(username)) { - } - - void start_up() override { - } - - void process_update(std::shared_ptr<TestClient::Update> update) override { - if (!update->object) { - return; - } - if (update->object->get_id() == td_api::updateNewMessage::ID) { - auto updateNewMessage = move_tl_object_as<td_api::updateNewMessage>(update->object); - auto &message = updateNewMessage->message_; - chat_id_ = message->chat_id_; - if (message->content_->get_id() == td_api::messageText::ID) { - auto messageText = move_tl_object_as<td_api::messageText>(message->content_); - auto text = messageText->text_->text_; - if (text.substr(0, tag_.size()) == tag_) { - if (text.substr(tag_.size() + 1) == "ONE_FILE") { - return one_file(); - } - } - } - } else if (update->object->get_id() == td_api::updateFileGenerationStart::ID) { - auto info = move_tl_object_as<td_api::updateFileGenerationStart>(update->object); - generate_file(info->generation_id_, info->original_path_, info->destination_path_, info->conversion_); - } else if (update->object->get_id() == td_api::updateFile::ID) { - auto file = move_tl_object_as<td_api::updateFile>(update->object); - LOG(INFO) << to_string(file); - } - } - void one_file() { - LOG(ERROR) << "Start ONE_FILE test"; - string file_path = string("test_documents") + TD_DIR_SLASH + "a.txt"; - mkpath(file_path).ensure(); - auto raw_file = - FileFd::open(file_path, FileFd::Flags::Create | FileFd::Flags::Truncate | FileFd::Flags::Write).move_as_ok(); - auto file = BufferedFd<FileFd>(std::move(raw_file)); - for (int i = 1; i < 100000; i++) { - file.write(PSLICE() << i << "\n").ensure(); - } - file.flush_write().ensure(); // important - file.close(); - this->send_query(make_tl_object<td_api::sendMessage>( - chat_id_, 0, false, false, nullptr, - make_tl_object<td_api::inputMessageDocument>( - make_tl_object<td_api::inputFileGenerated>(file_path, "square", 0), - make_tl_object<td_api::inputThumbnail>( - make_tl_object<td_api::inputFileGenerated>(file_path, "thumbnail", 0), 0, 0), - make_tl_object<td_api::formattedText>(tag_, Auto()))), - [](auto res) { check_td_error(res); }); - - this->send_query( - make_tl_object<td_api::sendMessage>(chat_id_, 0, false, false, nullptr, - make_tl_object<td_api::inputMessageDocument>( - make_tl_object<td_api::inputFileGenerated>(file_path, "square", 0), - nullptr, make_tl_object<td_api::formattedText>(tag_, Auto()))), - [](auto res) { check_td_error(res); }); - } - - friend class GenerateFile; - class GenerateFile : public Actor { - public: - GenerateFile(Task *parent, int64 id, string original_path, string destination_path, string conversion) - : parent_(parent) - , id_(id) - , original_path_(std::move(original_path)) - , destination_path_(std::move(destination_path)) - , conversion_(std::move(conversion)) { - } - - private: - Task *parent_; - int64 id_; - string original_path_; - string destination_path_; - string conversion_; - - FILE *from = nullptr; - FILE *to = nullptr; - - void start_up() override { - from = std::fopen(original_path_.c_str(), "rb"); - CHECK(from); - to = std::fopen(destination_path_.c_str(), "wb"); - CHECK(to); - yield(); - } - void loop() override { - int cnt = 0; - while (true) { - uint32 x; - auto r = std::fscanf(from, "%u", &x); - if (r != 1) { - return stop(); - } - std::fprintf(to, "%u\n", x * x); - if (++cnt >= 10000) { - break; - } - } - auto ready = std::ftell(to); - LOG(ERROR) << "READY: " << ready; - parent_->send_query(make_tl_object<td_api::setFileGenerationProgress>( - id_, 1039823 /*yeah, exact size of this file*/, narrow_cast<int32>(ready)), - [](auto result) { check_td_error(result); }); - set_timeout_in(0.02); - } - void tear_down() override { - std::fclose(from); - std::fclose(to); - parent_->send_query(make_tl_object<td_api::finishFileGeneration>(id_, nullptr), - [](auto result) { check_td_error(result); }); - } - }; - void generate_file(int64 id, string original_path, string destination_path, string conversion) { - LOG(ERROR) << "Generate file " << tag("id", id) << tag("original_path", original_path) - << tag("destination_path", destination_path) << tag("conversion", conversion); - if (conversion == "square") { - create_actor<GenerateFile>("GenerateFile", this, id, original_path, destination_path, conversion).release(); - } else if (conversion == "thumbnail") { - write_file(destination_path, base64url_decode(Slice(thumbnail, thumbnail_size)).ok()).ensure(); - this->send_query(make_tl_object<td_api::finishFileGeneration>(id, nullptr), - [](auto result) { check_td_error(result); }); - } else { - LOG(FATAL) << "unknown " << tag("conversion", conversion); - } - } - - private: - string tag_; - string username_; - int64 chat_id_ = 0; -}; - -class CheckTestC : public Task { - public: - CheckTestC(string username, string tag, Promise<> promise) - : username_(std::move(username)), tag_(std::move(tag)), promise_(std::move(promise)) { - } - - void start_up() override { - send_query(make_tl_object<td_api::searchPublicChat>(username_), [this](auto res) { - CHECK(res->get_id() == td_api::chat::ID); - auto chat = move_tl_object_as<td_api::chat>(res); - chat_id_ = chat->id_; - this->one_file(); - }); - } - - private: - string username_; - string tag_; - Promise<> promise_; - int64 chat_id_; - - void one_file() { - this->send_query( - make_tl_object<td_api::sendMessage>( - chat_id_, 0, false, false, nullptr, - make_tl_object<td_api::inputMessageText>( - make_tl_object<td_api::formattedText>(PSTRING() << tag_ << " ONE_FILE", Auto()), false, false)), - [](auto res) { check_td_error(res); }); - } - - void process_update(std::shared_ptr<TestClient::Update> update) override { - if (!update->object) { - return; - } - if (update->object->get_id() == td_api::updateNewMessage::ID) { - auto updateNewMessage = move_tl_object_as<td_api::updateNewMessage>(update->object); - auto &message = updateNewMessage->message_; - if (message->content_->get_id() == td_api::messageDocument::ID) { - auto messageDocument = move_tl_object_as<td_api::messageDocument>(message->content_); - 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_); - this->send_query(make_tl_object<td_api::downloadFile>(file_id_to_check_, 1), - [](auto res) { check_td_error(res); }); - } - } - } else if (update->object->get_id() == td_api::updateFile::ID) { - auto updateFile = move_tl_object_as<td_api::updateFile>(update->object); - if (updateFile->file_->id_ == file_id_to_check_ && (updateFile->file_->local_->is_downloading_completed_)) { - check_file(updateFile->file_->local_->path_); - } - } - } - - void check_file(CSlice path) { - FILE *from = std::fopen(path.c_str(), "rb"); - CHECK(from); - uint32 x; - uint32 y = 1; - while (std::fscanf(from, "%u", &x) == 1) { - CHECK(x == y * y); - y++; - } - std::fclose(from); - stop(); - } - int32 file_id_to_check_ = 0; -}; - -class LoginTestActor : public Actor { - public: - explicit LoginTestActor(Status *status) : status_(status) { - *status_ = Status::OK(); - } - - private: - Status *status_; - ActorOwn<TestClient> alice_; - ActorOwn<TestClient> bob_; - - string alice_phone_ = "9996636437"; - string bob_phone_ = "9996636438"; - string alice_username_ = "alice_" + alice_phone_; - string bob_username_ = "bob_" + bob_phone_; - - string stage_name_; - - void begin_stage(string stage_name, double timeout) { - LOG(WARNING) << "Begin stage '" << stage_name << "'"; - stage_name_ = std::move(stage_name); - set_timeout_in(timeout); - } - - void start_up() override { - begin_stage("Logging in", 160); - alice_ = create_actor<TestClient>("AliceClient", "alice"); - bob_ = create_actor<TestClient>("BobClient", "bob"); - - send_closure(alice_, &TestClient::add_listener, - std::make_unique<DoAuthentication>( - "alice", alice_phone_, "33333", - PromiseCreator::event(self_closure(this, &LoginTestActor::start_up_fence_dec)))); - - send_closure(bob_, &TestClient::add_listener, - std::make_unique<DoAuthentication>( - "bob", bob_phone_, "33333", - PromiseCreator::event(self_closure(this, &LoginTestActor::start_up_fence_dec)))); - } - - int start_up_fence_ = 3; - void start_up_fence_dec() { - --start_up_fence_; - if (start_up_fence_ == 0) { - init(); - } else if (start_up_fence_ == 1) { - return init(); - class WaitActor : public Actor { - public: - WaitActor(double timeout, Promise<> promise) : timeout_(timeout), promise_(std::move(promise)) { - } - void start_up() override { - set_timeout_in(timeout_); - } - void timeout_expired() override { - stop(); - } - - private: - double timeout_; - Promise<> promise_; - }; - create_actor<WaitActor>("WaitActor", 2, - PromiseCreator::event(self_closure(this, &LoginTestActor::start_up_fence_dec))) - .release(); - } - } - - void init() { - send_closure(alice_, &TestClient::add_listener, - std::make_unique<SetUsername>( - alice_username_, PromiseCreator::event(self_closure(this, &LoginTestActor::init_fence_dec)))); - send_closure(bob_, &TestClient::add_listener, - std::make_unique<SetUsername>( - bob_username_, PromiseCreator::event(self_closure(this, &LoginTestActor::init_fence_dec)))); - } - - int init_fence_ = 2; - void init_fence_dec() { - if (--init_fence_ == 0) { - test_a(); - } - } - - int32 test_a_fence_ = 2; - void test_a_fence() { - if (--test_a_fence_ == 0) { - test_b(); - } - } - - void test_a() { - begin_stage("Ready to create chats", 80); - string alice_tag = PSTRING() << format::as_hex(Random::secure_int64()); - string bob_tag = PSTRING() << format::as_hex(Random::secure_int64()); - - send_closure(bob_, &TestClient::add_listener, - std::make_unique<CheckTestA>( - alice_tag, PromiseCreator::event(self_closure(this, &LoginTestActor::test_a_fence)))); - send_closure(alice_, &TestClient::add_listener, - std::make_unique<CheckTestA>( - bob_tag, PromiseCreator::event(self_closure(this, &LoginTestActor::test_a_fence)))); - - send_closure(alice_, &TestClient::add_listener, std::make_unique<TestA>(alice_tag, bob_username_)); - send_closure(bob_, &TestClient::add_listener, std::make_unique<TestA>(bob_tag, alice_username_)); - // send_closure(alice_, &TestClient::add_listener, std::make_unique<TestChat>(bob_username_)); - } - - void timeout_expired() override { - LOG(FATAL) << "Timeout expired in stage '" << stage_name_ << "'"; - } - - int32 test_b_fence_ = 1; - void test_b_fence() { - if (--test_b_fence_ == 0) { - test_c(); - } - } - - int32 test_c_fence_ = 1; - void test_c_fence() { - if (--test_c_fence_ == 0) { - finish(); - } - } - - void test_b() { - begin_stage("Create secret chat", 40); - string tag = PSTRING() << format::as_hex(Random::secure_int64()); - - send_closure( - bob_, &TestClient::add_listener, - std::make_unique<CheckTestA>(tag, PromiseCreator::event(self_closure(this, &LoginTestActor::test_b_fence)))); - send_closure(alice_, &TestClient::add_listener, std::make_unique<TestSecretChat>(tag, bob_username_)); - } - - void test_c() { - begin_stage("Send generated file", 240); - string tag = PSTRING() << format::as_hex(Random::secure_int64()); - - send_closure(bob_, &TestClient::add_listener, - std::make_unique<CheckTestC>( - alice_username_, tag, PromiseCreator::event(self_closure(this, &LoginTestActor::test_c_fence)))); - send_closure(alice_, &TestClient::add_listener, std::make_unique<TestFileGenerated>(tag, bob_username_)); - } - - int32 finish_fence_ = 2; - void finish_fence() { - finish_fence_--; - if (finish_fence_ == 0) { - Scheduler::instance()->finish(); - stop(); - } - } - void finish() { - send_closure(alice_, &TestClient::close, PromiseCreator::event(self_closure(this, &LoginTestActor::finish_fence))); - send_closure(bob_, &TestClient::close, PromiseCreator::event(self_closure(this, &LoginTestActor::finish_fence))); - } -}; - -class Tdclient_login : public td::Test { - public: - using Test::Test; - bool step() final { - if (!is_inited_) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(DEBUG) + 2); - sched_.init(4); - sched_.create_actor_unsafe<LoginTestActor>(0, "LoginTestActor", &result_).release(); - sched_.start(); - is_inited_ = true; - } - - bool ret = sched_.run_main(10); - if (ret) { - return true; - } - sched_.finish(); - if (result_.is_error()) { - LOG(ERROR) << result_; - } - ASSERT_TRUE(result_.is_ok()); - return false; - } - - private: - bool is_inited_ = false; - ConcurrentScheduler sched_; - Status result_; -}; -Tdclient_login Tdclient_login("Tdclient_login"); -}; // namespace td diff --git a/libs/tdlib/td/test/tests_runner.cpp b/libs/tdlib/td/test/tests_runner.cpp deleted file mode 100644 index 0edb186f0a..0000000000 --- a/libs/tdlib/td/test/tests_runner.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 -// -// 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 "test/tests_runner.h" - -#include "test/TestsRunner.h" - -extern "C" { -void tests_runner_init(const char *dir) { - td::TestsRunner::init(dir); -} -void run_all_tests() { - td::TestsRunner::run_all_tests(); -} -} diff --git a/libs/tdlib/td/test/tests_runner.h b/libs/tdlib/td/test/tests_runner.h deleted file mode 100644 index 3de566858b..0000000000 --- a/libs/tdlib/td/test/tests_runner.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 -// -// 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) -// -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -void tests_runner_init(const char *dir); -void run_all_tests(); - -#ifdef __cplusplus -} -#endif |