mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
pow-testgiver support
This commit is contained in:
parent
dbde9c1c40
commit
f064b1047a
257 changed files with 6665 additions and 2608 deletions
179
tdutils/test/List.cpp
Normal file
179
tdutils/test/List.cpp
Normal file
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
|
||||
#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 <atomic>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
struct ListData {
|
||||
td::MovableValue<td::uint64> value;
|
||||
td::MovableValue<bool> in_list;
|
||||
|
||||
ListData() = default;
|
||||
ListData(td::uint64 value, bool in_list) : value(value), in_list(in_list) {
|
||||
}
|
||||
};
|
||||
|
||||
struct Node : 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<ListData> &node) {
|
||||
return node.get_data_unsafe();
|
||||
}
|
||||
|
||||
static std::unique_lock<std::mutex> lock(td::ListNode &node) {
|
||||
return {};
|
||||
}
|
||||
|
||||
static std::unique_lock<std::mutex> lock(td::TsListNode<ListData> &node) {
|
||||
return node.lock();
|
||||
}
|
||||
|
||||
template <class ListNodeT, class ListRootT, class NodeT>
|
||||
static void do_run_list_test(ListRootT &root, std::atomic<td::uint64> &id) {
|
||||
td::vector<NodeT> nodes;
|
||||
|
||||
td::Random::Xorshift128plus rnd(123);
|
||||
|
||||
auto next_id = [&] {
|
||||
return ++id;
|
||||
};
|
||||
auto add_node = [&] {
|
||||
if (nodes.size() >= 20) {
|
||||
return;
|
||||
}
|
||||
nodes.emplace_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<int>(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<td::uint64> in_list, 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<NodeT *>(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<td::uint64> id{0};
|
||||
for (std::size_t i = 0; i < 4; i++) {
|
||||
do_run_list_test<td::ListNode, td::ListNode, Node>(root, id);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Misc, TsList) {
|
||||
td::TsList<ListData> root;
|
||||
std::atomic<td::uint64> id{0};
|
||||
for (std::size_t i = 0; i < 4; i++) {
|
||||
do_run_list_test<td::TsListNode<ListData>, td::TsList<ListData>, td::TsListNode<ListData>>(root, id);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Misc, TsListConcurrent) {
|
||||
td::TsList<ListData> root;
|
||||
td::vector<td::thread> threads;
|
||||
std::atomic<td::uint64> id{0};
|
||||
for (std::size_t i = 0; i < 4; i++) {
|
||||
threads.emplace_back(
|
||||
[&] { do_run_list_test<td::TsListNode<ListData>, td::TsList<ListData>, td::TsListNode<ListData>>(root, id); });
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue