From 0ece30dc7c0e34b4c5911969b8fa99c33c6d023c Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 30 Nov 2022 17:48:47 +0300 Subject: Telegram: update for TDLIB --- protocols/Telegram/tdlib/td/tdutils/test/List.cpp | 169 ++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 protocols/Telegram/tdlib/td/tdutils/test/List.cpp (limited to 'protocols/Telegram/tdlib/td/tdutils/test/List.cpp') diff --git a/protocols/Telegram/tdlib/td/tdutils/test/List.cpp b/protocols/Telegram/tdlib/td/tdutils/test/List.cpp new file mode 100644 index 0000000000..02ab080d89 --- /dev/null +++ b/protocols/Telegram/tdlib/td/tdutils/test/List.cpp @@ -0,0 +1,169 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// +// 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/common.h" +#include "td/utils/List.h" +#include "td/utils/MovableValue.h" +#include "td/utils/port/thread.h" +#include "td/utils/Random.h" +#include "td/utils/tests.h" +#include "td/utils/TsList.h" + +#include +#include +#include +#include + +struct ListData { + td::MovableValue value_; + td::MovableValue in_list_; + + ListData() = default; + ListData(td::uint64 value, bool in_list) : value_(value), in_list_(in_list) { + } +}; + +struct Node final : public td::ListNode { + Node() = default; + explicit Node(ListData data) : data_(std::move(data)) { + } + + ListData data_; +}; + +static ListData &get_data(Node &node) { + return node.data_; +} + +static ListData &get_data(td::TsListNode &node) { + return node.get_data_unsafe(); +} + +static std::unique_lock lock(td::ListNode &node) { + return {}; +} + +static std::unique_lock lock(td::TsListNode &node) { + return node.lock(); +} + +template +static void do_run_list_test(ListRootT &root, std::atomic &id) { + td::vector nodes; + + td::Random::Xorshift128plus rnd(123); + + auto next_id = [&] { + return ++id; + }; + auto add_node = [&] { + if (nodes.size() >= 20) { + return; + } + nodes.push_back(NodeT({next_id(), false})); + }; + auto pop_node = [&] { + if (nodes.empty()) { + return; + } + nodes.pop_back(); + }; + auto random_node_index = [&] { + CHECK(!nodes.empty()); + return rnd.fast(0, static_cast(nodes.size()) - 1); + }; + + auto link_node = [&] { + if (nodes.empty()) { + return; + } + auto i = random_node_index(); + nodes[i].remove(); + get_data(nodes[i]) = ListData(next_id(), true); + root.put(&nodes[i]); + }; + auto unlink_node = [&] { + if (nodes.empty()) { + return; + } + auto i = random_node_index(); + nodes[i].remove(); + get_data(nodes[i]).in_list_ = false; + }; + auto swap_nodes = [&] { + if (nodes.empty()) { + return; + } + auto i = random_node_index(); + auto j = random_node_index(); + std::swap(nodes[i], nodes[j]); + }; + auto set_node = [&] { + if (nodes.empty()) { + return; + } + auto i = random_node_index(); + auto j = random_node_index(); + nodes[i] = std::move(nodes[j]); + }; + auto validate = [&] { + std::multiset in_list; + std::multiset not_in_list; + for (auto &node : nodes) { + if (get_data(node).in_list_.get()) { + in_list.insert(get_data(node).value_.get()); + } else { + not_in_list.insert(get_data(node).value_.get()); + } + } + auto guard = lock(root); + for (auto *begin = root.begin(), *end = root.end(); begin != end; begin = begin->get_next()) { + auto &data = get_data(*static_cast(begin)); + CHECK(data.in_list_.get()); + CHECK(data.value_.get() != 0); + auto it = in_list.find(data.value_.get()); + if (it != in_list.end()) { + in_list.erase(it); + } else { + ASSERT_EQ(0u, not_in_list.count(data.value_.get())); + } + } + ASSERT_EQ(0u, in_list.size()); + }; + td::RandomSteps steps( + {{add_node, 3}, {pop_node, 1}, {unlink_node, 1}, {link_node, 3}, {swap_nodes, 1}, {set_node, 1}, {validate, 1}}); + for (int i = 0; i < 10000; i++) { + steps.step(rnd); + } +} + +TEST(Misc, List) { + td::ListNode root; + std::atomic id{0}; + for (std::size_t i = 0; i < 4; i++) { + do_run_list_test(root, id); + } +} + +TEST(Misc, TsList) { + td::TsList root; + std::atomic id{0}; + for (std::size_t i = 0; i < 4; i++) { + do_run_list_test, td::TsList, td::TsListNode>(root, id); + } +} + +#if !TD_THREAD_UNSUPPORTED +TEST(Misc, TsListConcurrent) { + td::TsList root; + td::vector threads; + std::atomic id{0}; + for (std::size_t i = 0; i < 4; i++) { + threads.emplace_back( + [&] { do_run_list_test, td::TsList, td::TsListNode>(root, id); }); + } +} +#endif -- cgit v1.2.3