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
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
#include "td/utils/benchmark.h"
|
||||
#include "td/utils/ConcurrentHashTable.h"
|
||||
#include "td/utils/misc.h"
|
||||
#include "td/utils/port/thread.h"
|
||||
#include "td/utils/SpinLock.h"
|
||||
#include "td/utils/tests.h"
|
||||
|
@ -198,17 +199,17 @@ class HashMapBenchmark : public td::Benchmark {
|
|||
|
||||
size_t threads_n = 16;
|
||||
int mod_;
|
||||
static constexpr size_t mul_ = 7273; //1000000000 + 7;
|
||||
static constexpr size_t MUL = 7273; //1000000000 + 7;
|
||||
int n_;
|
||||
|
||||
public:
|
||||
explicit HashMapBenchmark(size_t threads_n) : threads_n(threads_n) {
|
||||
}
|
||||
std::string get_description() const override {
|
||||
return hash_map->get_name();
|
||||
return HashMap::get_name();
|
||||
}
|
||||
void start_up_n(int n) override {
|
||||
n *= (int)threads_n;
|
||||
n *= static_cast<int>(threads_n);
|
||||
n_ = n;
|
||||
hash_map = td::make_unique<HashMap>(n * 2);
|
||||
}
|
||||
|
@ -222,8 +223,8 @@ class HashMapBenchmark : public td::Benchmark {
|
|||
size_t r = n * (i + 1) / threads_n;
|
||||
threads.emplace_back([l, r, this] {
|
||||
for (size_t i = l; i < r; i++) {
|
||||
auto x = int((i + 1) * mul_ % n_) + 3;
|
||||
auto y = int(i + 2);
|
||||
auto x = td::narrow_cast<int>((i + 1) * MUL % n_) + 3;
|
||||
auto y = td::narrow_cast<int>(i + 2);
|
||||
hash_map->insert(x, y);
|
||||
}
|
||||
});
|
||||
|
@ -235,8 +236,8 @@ class HashMapBenchmark : public td::Benchmark {
|
|||
|
||||
void tear_down() override {
|
||||
for (int i = 0; i < n_; i++) {
|
||||
auto x = int((i + 1) * mul_ % n_) + 3;
|
||||
auto y = int(i + 2);
|
||||
auto x = td::narrow_cast<int>((i + 1) * MUL % n_) + 3;
|
||||
auto y = td::narrow_cast<int>(i + 2);
|
||||
ASSERT_EQ(y, hash_map->find(x, -1));
|
||||
}
|
||||
queries.clear();
|
||||
|
|
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); });
|
||||
}
|
||||
}
|
95
tdutils/test/OptionParser.cpp
Normal file
95
tdutils/test/OptionParser.cpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
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/misc.h"
|
||||
#include "td/utils/OptionParser.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/Status.h"
|
||||
#include "td/utils/tests.h"
|
||||
|
||||
TEST(OptionParser, run) {
|
||||
td::OptionParser options;
|
||||
options.set_description("test description");
|
||||
|
||||
td::string exename = "exename";
|
||||
td::vector<td::string> args;
|
||||
auto run_option_parser = [&](td::string command_line) {
|
||||
args = td::full_split(command_line, ' ');
|
||||
td::vector<char *> argv;
|
||||
argv.push_back(&exename[0]);
|
||||
for (auto &arg : args) {
|
||||
argv.push_back(&arg[0]);
|
||||
}
|
||||
return options.run(static_cast<int>(argv.size()), &argv[0]);
|
||||
};
|
||||
|
||||
td::uint64 chosen_options = 0;
|
||||
td::vector<td::string> chosen_parameters;
|
||||
auto test_success = [&](td::string command_line, td::uint64 expected_options,
|
||||
td::vector<td::string> expected_parameters, td::vector<td::string> expected_result) {
|
||||
chosen_options = 0;
|
||||
chosen_parameters.clear();
|
||||
auto result = run_option_parser(command_line);
|
||||
ASSERT_TRUE(result.is_ok());
|
||||
ASSERT_EQ(expected_options, chosen_options);
|
||||
ASSERT_EQ(expected_parameters, chosen_parameters);
|
||||
ASSERT_EQ(expected_result.size(), result.ok().size());
|
||||
for (size_t i = 0; i < expected_result.size(); i++) {
|
||||
ASSERT_STREQ(expected_result[i], td::string(result.ok()[i]));
|
||||
}
|
||||
};
|
||||
auto test_fail = [&](td::string command_line) {
|
||||
auto result = run_option_parser(command_line);
|
||||
ASSERT_TRUE(result.is_error());
|
||||
};
|
||||
|
||||
options.add_option('q', "", "", [&] { chosen_options += 1; });
|
||||
options.add_option('\0', "http-port2", "", [&] { chosen_options += 10; });
|
||||
options.add_option('p', "http-port", "", [&](td::Slice parameter) {
|
||||
chosen_options += 100;
|
||||
chosen_parameters.push_back(parameter.str());
|
||||
});
|
||||
options.add_option('v', "test", "", [&] { chosen_options += 1000; });
|
||||
|
||||
test_fail("-http-port2");
|
||||
test_success("-", 0, {}, {"-"});
|
||||
test_fail("--http-port");
|
||||
test_fail("--http-port3");
|
||||
test_fail("--http-por");
|
||||
test_fail("--http-port2=1");
|
||||
test_fail("--q");
|
||||
test_fail("-qvp");
|
||||
test_fail("-p");
|
||||
test_fail("-u");
|
||||
test_success("-q", 1, {}, {});
|
||||
test_success("-vvvvvvvvvv", 10000, {}, {});
|
||||
test_success("-qpv", 101, {"v"}, {});
|
||||
test_success("-qp -v", 101, {"-v"}, {});
|
||||
test_success("-qp --http-port2", 101, {"--http-port2"}, {});
|
||||
test_success("-qp -- -v", 1101, {"--"}, {});
|
||||
test_success("-qvqvpqv", 2102, {"qv"}, {});
|
||||
test_success("aba --http-port2 caba --http-port2 dabacaba", 20, {}, {"aba", "caba", "dabacaba"});
|
||||
test_success("das -pqwerty -- -v asd --http-port", 100, {"qwerty"}, {"das", "-v", "asd", "--http-port"});
|
||||
test_success("-p option --http-port option2 --http-port=option3 --http-port=", 400,
|
||||
{"option", "option2", "option3", ""}, {});
|
||||
test_success("", 0, {}, {});
|
||||
test_success("a", 0, {}, {"a"});
|
||||
test_success("", 0, {}, {});
|
||||
}
|
|
@ -16,66 +16,71 @@
|
|||
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "td/utils/tests.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/port/thread.h"
|
||||
#include "td/utils/SharedSlice.h"
|
||||
#include "td/utils/tests.h"
|
||||
|
||||
using namespace td;
|
||||
char disable_linker_warning_about_empty_file_tdutils_test_shared_slice_cpp TD_UNUSED;
|
||||
|
||||
#if !TD_THREAD_UNSUPPORTED
|
||||
TEST(SharedSlice, Hands) {
|
||||
{
|
||||
SharedSlice h("hello");
|
||||
td::SharedSlice h("hello");
|
||||
ASSERT_EQ("hello", h.as_slice());
|
||||
// auto g = h; // CE
|
||||
auto g = h.clone();
|
||||
ASSERT_EQ("hello", h.as_slice());
|
||||
ASSERT_EQ("hello", g.as_slice());
|
||||
}
|
||||
|
||||
{
|
||||
SharedSlice h("hello");
|
||||
UniqueSharedSlice g(std::move(h));
|
||||
td::SharedSlice h("hello");
|
||||
td::UniqueSharedSlice g(std::move(h));
|
||||
ASSERT_EQ("", h.as_slice());
|
||||
ASSERT_EQ("hello", g.as_slice());
|
||||
}
|
||||
{
|
||||
SharedSlice h("hello");
|
||||
SharedSlice t = h.clone();
|
||||
UniqueSharedSlice g(std::move(h));
|
||||
td::SharedSlice h("hello");
|
||||
td::SharedSlice t = h.clone();
|
||||
td::UniqueSharedSlice g(std::move(h));
|
||||
ASSERT_EQ("", h.as_slice());
|
||||
ASSERT_EQ("hello", g.as_slice());
|
||||
ASSERT_EQ("hello", t.as_slice());
|
||||
}
|
||||
|
||||
{
|
||||
UniqueSharedSlice g(5);
|
||||
td::UniqueSharedSlice g(5);
|
||||
g.as_mutable_slice().copy_from("hello");
|
||||
SharedSlice h(std::move(g));
|
||||
td::SharedSlice h(std::move(g));
|
||||
ASSERT_EQ("hello", h);
|
||||
ASSERT_EQ("", g);
|
||||
}
|
||||
|
||||
{
|
||||
UniqueSlice h("hello");
|
||||
UniqueSlice g(std::move(h));
|
||||
td::UniqueSlice h("hello");
|
||||
td::UniqueSlice g(std::move(h));
|
||||
ASSERT_EQ("", h.as_slice());
|
||||
ASSERT_EQ("hello", g.as_slice());
|
||||
}
|
||||
|
||||
{
|
||||
SecureString h("hello");
|
||||
SecureString g(std::move(h));
|
||||
td::SecureString h("hello");
|
||||
td::SecureString g(std::move(h));
|
||||
ASSERT_EQ("", h.as_slice());
|
||||
ASSERT_EQ("hello", g.as_slice());
|
||||
}
|
||||
|
||||
{
|
||||
Stage stage;
|
||||
SharedSlice a, b;
|
||||
std::vector<td::thread> threads(2);
|
||||
td::Stage stage;
|
||||
td::SharedSlice a, b;
|
||||
td::vector<td::thread> threads(2);
|
||||
for (int i = 0; i < 2; i++) {
|
||||
threads[i] = td::thread([i, &stage, &a, &b] {
|
||||
for (int j = 0; j < 10000; j++) {
|
||||
if (i == 0) {
|
||||
a = SharedSlice("hello");
|
||||
a = td::SharedSlice("hello");
|
||||
b = a.clone();
|
||||
}
|
||||
stage.wait((2 * j + 1) * 2);
|
||||
|
@ -83,7 +88,7 @@ TEST(SharedSlice, Hands) {
|
|||
ASSERT_EQ('h', a[0]);
|
||||
a.clear();
|
||||
} else {
|
||||
UniqueSharedSlice c(std::move(b));
|
||||
td::UniqueSharedSlice c(std::move(b));
|
||||
c.as_mutable_slice()[0] = '!';
|
||||
}
|
||||
stage.wait((2 * j + 2) * 2);
|
||||
|
@ -95,3 +100,4 @@ TEST(SharedSlice, Hands) {
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,30 +1,22 @@
|
|||
/*
|
||||
This file is part of TON Blockchain source code.
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU 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 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 is distributed in the hope that it will be useful,
|
||||
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 General Public License for more details.
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with TON Blockchain. If not, see <http://www.gnu.org/licenses/>.
|
||||
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/>.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
You must obey the GNU General Public License in all respects for all
|
||||
of the code used other than OpenSSL. If you modify file(s) with this
|
||||
exception, you may extend this exception to your version of the file(s),
|
||||
but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. If you delete this exception statement
|
||||
from all source files in the program, then also delete it here.
|
||||
|
||||
Copyright 2019-2020 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
|
||||
#include "td/utils/tests.h"
|
||||
#include "td/utils/benchmark.h"
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "td/utils/common.h"
|
||||
#include "td/utils/crypto.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/Random.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/tests.h"
|
||||
#include "td/utils/UInt.h"
|
||||
|
@ -30,6 +31,29 @@
|
|||
static td::vector<td::string> strings{"", "1", "short test string", td::string(1000000, 'a')};
|
||||
|
||||
#if TD_HAVE_OPENSSL
|
||||
#if TD_HAVE_ZLIB
|
||||
TEST(Crypto, Aes) {
|
||||
td::Random::Xorshift128plus rnd(123);
|
||||
td::UInt256 key;
|
||||
rnd.bytes(as_slice(key));
|
||||
td::string plaintext(16, '\0');
|
||||
td::string encrypted(16, '\0');
|
||||
td::string decrypted(16, '\0');
|
||||
rnd.bytes(plaintext);
|
||||
|
||||
td::AesState encryptor;
|
||||
encryptor.init(as_slice(key), true);
|
||||
td::AesState decryptor;
|
||||
decryptor.init(as_slice(key), false);
|
||||
|
||||
encryptor.encrypt(td::as_slice(plaintext).ubegin(), td::as_slice(encrypted).ubegin(), 16);
|
||||
decryptor.decrypt(td::as_slice(encrypted).ubegin(), td::as_slice(decrypted).ubegin(), 16);
|
||||
|
||||
CHECK(decrypted == plaintext);
|
||||
CHECK(decrypted != encrypted);
|
||||
CHECK(td::crc32(encrypted) == 178892237);
|
||||
}
|
||||
|
||||
TEST(Crypto, AesCtrState) {
|
||||
td::vector<td::uint32> answers1{0u, 1141589763u, 596296607u, 3673001485u, 2302125528u,
|
||||
330967191u, 2047392231u, 3537459563u, 307747798u, 2149598133u};
|
||||
|
@ -63,7 +87,7 @@ TEST(Crypto, AesCtrState) {
|
|||
ASSERT_EQ(answers1[i], td::crc32(t));
|
||||
state.init(as_slice(key), as_slice(iv));
|
||||
state.decrypt(t, t);
|
||||
ASSERT_STREQ(s, t);
|
||||
ASSERT_STREQ(td::base64_encode(s), td::base64_encode(t));
|
||||
|
||||
for (auto &c : iv.raw) {
|
||||
c = 0xFF;
|
||||
|
@ -76,6 +100,82 @@ TEST(Crypto, AesCtrState) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST(Crypto, AesIgeState) {
|
||||
td::vector<td::uint32> answers1{0u, 2045698207u, 2423540300u, 525522475u, 1545267325u};
|
||||
|
||||
std::size_t i = 0;
|
||||
for (auto length : {0, 16, 32, 256, 1024}) {
|
||||
td::uint32 seed = length;
|
||||
td::string s(length, '\0');
|
||||
for (auto &c : s) {
|
||||
seed = seed * 123457567u + 987651241u;
|
||||
c = static_cast<char>((seed >> 23) & 255);
|
||||
}
|
||||
|
||||
td::UInt256 key;
|
||||
for (auto &c : key.raw) {
|
||||
seed = seed * 123457567u + 987651241u;
|
||||
c = (seed >> 23) & 255;
|
||||
}
|
||||
td::UInt256 iv;
|
||||
for (auto &c : iv.raw) {
|
||||
seed = seed * 123457567u + 987651241u;
|
||||
c = (seed >> 23) & 255;
|
||||
}
|
||||
|
||||
td::AesIgeState state;
|
||||
state.init(as_slice(key), as_slice(iv), true);
|
||||
td::string t(length, '\0');
|
||||
state.encrypt(s, t);
|
||||
|
||||
ASSERT_EQ(answers1[i], td::crc32(t));
|
||||
|
||||
state.init(as_slice(key), as_slice(iv), false);
|
||||
state.decrypt(t, t);
|
||||
ASSERT_STREQ(td::base64_encode(s), td::base64_encode(t));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Crypto, AesCbcState) {
|
||||
td::vector<td::uint32> answers1{0u, 3617355989u, 3449188102u, 186999968u, 4244808847u};
|
||||
|
||||
std::size_t i = 0;
|
||||
for (auto length : {0, 16, 32, 256, 1024}) {
|
||||
td::uint32 seed = length;
|
||||
td::string s(length, '\0');
|
||||
for (auto &c : s) {
|
||||
seed = seed * 123457567u + 987651241u;
|
||||
c = static_cast<char>((seed >> 23) & 255);
|
||||
}
|
||||
|
||||
td::UInt256 key;
|
||||
for (auto &c : key.raw) {
|
||||
seed = seed * 123457567u + 987651241u;
|
||||
c = (seed >> 23) & 255;
|
||||
}
|
||||
td::UInt128 iv;
|
||||
for (auto &c : iv.raw) {
|
||||
seed = seed * 123457567u + 987651241u;
|
||||
c = (seed >> 23) & 255;
|
||||
}
|
||||
|
||||
td::AesCbcState state(as_slice(key), as_slice(iv));
|
||||
//state.init(as_slice(key), as_slice(iv), true);
|
||||
td::string t(length, '\0');
|
||||
state.encrypt(s, t);
|
||||
|
||||
ASSERT_EQ(answers1[i], td::crc32(t));
|
||||
|
||||
//state.init(as_slice(key), as_slice(iv), false);
|
||||
state = td::AesCbcState(as_slice(key), as_slice(iv));
|
||||
state.decrypt(t, t);
|
||||
ASSERT_STREQ(td::base64_encode(s), td::base64_encode(t));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(Crypto, Sha256State) {
|
||||
for (auto length : {0, 1, 31, 32, 33, 9999, 10000, 10001, 999999, 1000001}) {
|
||||
auto s = td::rand_string(std::numeric_limits<char>::min(), std::numeric_limits<char>::max(), length);
|
||||
|
@ -97,8 +197,8 @@ TEST(Crypto, Sha256State) {
|
|||
}
|
||||
|
||||
TEST(Crypto, PBKDF) {
|
||||
td::vector<td::string> passwords{"", "qwerty", std::string(1000, 'a')};
|
||||
td::vector<td::string> salts{"", "qwerty", std::string(1000, 'a')};
|
||||
td::vector<td::string> passwords{"", "qwerty", td::string(1000, 'a')};
|
||||
td::vector<td::string> salts{"", "qwerty", td::string(1000, 'a')};
|
||||
td::vector<int> iteration_counts{1, 2, 1000};
|
||||
td::vector<td::Slice> answers{
|
||||
"984LZT0tcqQQjPWr6RL/3Xd2Ftu7J6cOggTzri0Pb60=", "lzmEEdaupDp3rO+SImq4J41NsGaL0denanJfdoCsRcU=",
|
||||
|
@ -199,7 +299,7 @@ TEST(Crypto, crc32c_benchmark) {
|
|||
public:
|
||||
explicit Crc32cExtendBenchmark(size_t chunk_size) : chunk_size_(chunk_size) {
|
||||
}
|
||||
std::string get_description() const override {
|
||||
td::string get_description() const override {
|
||||
return PSTRING() << "Crc32c with chunk_size=" << chunk_size_;
|
||||
}
|
||||
void start_up_n(int n) override {
|
||||
|
@ -209,7 +309,7 @@ TEST(Crypto, crc32c_benchmark) {
|
|||
} else {
|
||||
cnt_ = 1;
|
||||
}
|
||||
data_ = std::string(n, 'a');
|
||||
data_ = td::string(n, 'a');
|
||||
}
|
||||
void run(int n) override {
|
||||
td::uint32 res = 0;
|
||||
|
@ -226,7 +326,7 @@ TEST(Crypto, crc32c_benchmark) {
|
|||
|
||||
private:
|
||||
size_t chunk_size_;
|
||||
std::string data_;
|
||||
td::string data_;
|
||||
int cnt_;
|
||||
};
|
||||
bench(Crc32cExtendBenchmark(2));
|
||||
|
|
|
@ -17,38 +17,43 @@
|
|||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "td/utils/filesystem.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/tests.h"
|
||||
|
||||
TEST(Misc, clean_filename) {
|
||||
using td::clean_filename;
|
||||
ASSERT_STREQ(clean_filename("-1234567"), "-1234567");
|
||||
ASSERT_STREQ(clean_filename(".git"), "git");
|
||||
ASSERT_STREQ(clean_filename("../../.git"), "git");
|
||||
ASSERT_STREQ(clean_filename(".././.."), "");
|
||||
ASSERT_STREQ(clean_filename("../"), "");
|
||||
ASSERT_STREQ(clean_filename(".."), "");
|
||||
ASSERT_STREQ(clean_filename("test/git/ as dsa . a"), "as dsa.a");
|
||||
ASSERT_STREQ(clean_filename(" . "), "");
|
||||
ASSERT_STREQ(clean_filename("!@#$%^&*()_+-=[]{;|:\"}'<>?,.`~"), "!@#$%^ ()_+-=[]{; } ,.~");
|
||||
ASSERT_STREQ(clean_filename("!@#$%^&*()_+-=[]{}\\|:\";'<>?,.`~"), "; ,.~");
|
||||
ASSERT_STREQ(clean_filename("عرفها بعد قد. هذا مع تاريخ اليميني واندونيسيا،, لعدم تاريخ لهيمنة الى"),
|
||||
"عرفها بعد قد.هذا مع تاريخ اليميني");
|
||||
ASSERT_STREQ(
|
||||
clean_filename(
|
||||
"012345678901234567890123456789012345678901234567890123456789adsasdasdsaa.01234567890123456789asdasdasdasd"),
|
||||
"012345678901234567890123456789012345678901234567890123456789.01234567890123456789");
|
||||
ASSERT_STREQ(clean_filename("01234567890123456789012345678901234567890123456789<>*?: <>*?:0123456789adsasdasdsaa. "
|
||||
"0123456789`<><<>><><>0123456789asdasdasdasd"),
|
||||
"01234567890123456789012345678901234567890123456789.0123456789");
|
||||
ASSERT_STREQ(clean_filename("01234567890123456789012345678901234567890123456789<>*?: <>*?:0123456789adsasdasdsaa. "
|
||||
"0123456789`<><><>0123456789asdasdasdasd"),
|
||||
"01234567890123456789012345678901234567890123456789.0123456789 012");
|
||||
ASSERT_STREQ(clean_filename("C:/document.tar.gz"), "document.tar.gz");
|
||||
ASSERT_STREQ(clean_filename("test...."), "test");
|
||||
ASSERT_STREQ(clean_filename("....test"), "test");
|
||||
ASSERT_STREQ(clean_filename("test.exe...."), "test.exe"); // extension has changed
|
||||
ASSERT_STREQ(clean_filename("test.exe01234567890123456789...."),
|
||||
"test.exe01234567890123456789"); // extension may be more then 20 characters
|
||||
ASSERT_STREQ(clean_filename("....test....asdf"), "test.asdf");
|
||||
ASSERT_STREQ(clean_filename("കറുപ്പ്.txt"), "കറപപ.txt");
|
||||
static void test_clean_filename(td::CSlice name, td::Slice result) {
|
||||
ASSERT_STREQ(td::clean_filename(name), result);
|
||||
}
|
||||
|
||||
TEST(Misc, clean_filename) {
|
||||
test_clean_filename("-1234567", "-1234567");
|
||||
test_clean_filename(".git", "git");
|
||||
test_clean_filename("../../.git", "git");
|
||||
test_clean_filename(".././..", "");
|
||||
test_clean_filename("../", "");
|
||||
test_clean_filename("..", "");
|
||||
test_clean_filename("test/git/ as dsa . a", "as dsa.a");
|
||||
test_clean_filename(" . ", "");
|
||||
test_clean_filename("!@#$%^&*()_+-=[]{;|:\"}'<>?,.`~", "!@#$%^ ()_+-=[]{; } ,.~");
|
||||
test_clean_filename("!@#$%^&*()_+-=[]{}\\|:\";'<>?,.`~", "; ,.~");
|
||||
test_clean_filename("عرفها بعد قد. هذا مع تاريخ اليميني واندونيسيا،, لعدم تاريخ لهيمنة الى",
|
||||
"عرفها بعد قد.هذا مع تاريخ اليميني");
|
||||
test_clean_filename(
|
||||
"012345678901234567890123456789012345678901234567890123456789adsasdasdsaa.01234567890123456789asdasdasdasd",
|
||||
"012345678901234567890123456789012345678901234567890123456789.01234567890123456789");
|
||||
test_clean_filename(
|
||||
"01234567890123456789012345678901234567890123456789<>*?: <>*?:0123456789adsasdasdsaa. "
|
||||
"0123456789`<><<>><><>0123456789asdasdasdasd",
|
||||
"01234567890123456789012345678901234567890123456789.0123456789");
|
||||
test_clean_filename(
|
||||
"01234567890123456789012345678901234567890123456789<>*?: <>*?:0123456789adsasdasdsaa. "
|
||||
"0123456789`<><><>0123456789asdasdasdasd",
|
||||
"01234567890123456789012345678901234567890123456789.0123456789 012");
|
||||
test_clean_filename("C:/document.tar.gz", "document.tar.gz");
|
||||
test_clean_filename("test....", "test");
|
||||
test_clean_filename("....test", "test");
|
||||
test_clean_filename("test.exe....", "test.exe"); // extension has changed
|
||||
test_clean_filename("test.exe01234567890123456789....",
|
||||
"test.exe01234567890123456789"); // extension may be more than 20 characters
|
||||
test_clean_filename("....test....asdf", "test.asdf");
|
||||
test_clean_filename("കറുപ്പ്.txt", "കറപപ.txt");
|
||||
}
|
||||
|
|
|
@ -18,33 +18,40 @@
|
|||
*/
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/ByteFlow.h"
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/Gzip.h"
|
||||
#include "td/utils/GzipByteFlow.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/Status.h"
|
||||
#include "td/utils/tests.h"
|
||||
#include "td/utils/Time.h"
|
||||
|
||||
static void encode_decode(td::string s) {
|
||||
auto r = td::gzencode(s, 2);
|
||||
ASSERT_TRUE(!r.empty());
|
||||
if (r.empty()) {
|
||||
return;
|
||||
}
|
||||
auto new_s = td::gzdecode(r.as_slice());
|
||||
ASSERT_TRUE(!new_s.empty());
|
||||
if (new_s.empty()) {
|
||||
return;
|
||||
}
|
||||
ASSERT_EQ(s, new_s.as_slice().str());
|
||||
ASSERT_EQ(s, td::gzdecode(r.as_slice()));
|
||||
}
|
||||
|
||||
TEST(Gzip, gzencode_gzdecode) {
|
||||
auto str = td::rand_string(0, 127, 1000);
|
||||
encode_decode(str);
|
||||
str = td::rand_string('a', 'z', 1000000);
|
||||
encode_decode(str);
|
||||
str = td::string(1000000, 'a');
|
||||
encode_decode(str);
|
||||
encode_decode(td::rand_string(0, 255, 1000));
|
||||
encode_decode(td::rand_string('a', 'z', 1000000));
|
||||
encode_decode(td::string(1000000, 'a'));
|
||||
}
|
||||
|
||||
static void test_gzencode(td::string s) {
|
||||
auto begin_time = td::Time::now();
|
||||
auto r = td::gzencode(s, td::max(2, static_cast<int>(100 / s.size())));
|
||||
ASSERT_TRUE(!r.empty());
|
||||
LOG(INFO) << "Encoded string of size " << s.size() << " in " << (td::Time::now() - begin_time)
|
||||
<< " with compression ratio " << static_cast<double>(r.size()) / static_cast<double>(s.size());
|
||||
}
|
||||
|
||||
TEST(Gzip, gzencode) {
|
||||
for (size_t len = 1; len <= 10000000; len *= 10) {
|
||||
test_gzencode(td::rand_string('a', 'a', len));
|
||||
test_gzencode(td::rand_string('a', 'z', len));
|
||||
test_gzencode(td::rand_string(0, 255, len));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Gzip, flow) {
|
||||
|
@ -54,8 +61,8 @@ TEST(Gzip, flow) {
|
|||
td::ChainBufferWriter input_writer;
|
||||
auto input = input_writer.extract_reader();
|
||||
td::ByteFlowSource source(&input);
|
||||
td::GzipByteFlow gzip_flow(td::Gzip::Encode);
|
||||
gzip_flow = td::GzipByteFlow(td::Gzip::Encode);
|
||||
td::GzipByteFlow gzip_flow(td::Gzip::Mode::Encode);
|
||||
gzip_flow = td::GzipByteFlow(td::Gzip::Mode::Encode);
|
||||
td::ByteFlowSink sink;
|
||||
|
||||
source >> gzip_flow >> sink;
|
||||
|
@ -75,14 +82,15 @@ TEST(Gzip, flow) {
|
|||
}
|
||||
TEST(Gzip, flow_error) {
|
||||
auto str = td::rand_string('a', 'z', 1000000);
|
||||
auto zip = td::gzencode(str).as_slice().str();
|
||||
auto zip = td::gzencode(str, 0.9).as_slice().str();
|
||||
ASSERT_TRUE(!zip.empty());
|
||||
zip.resize(zip.size() - 1);
|
||||
auto parts = td::rand_split(zip);
|
||||
|
||||
auto input_writer = td::ChainBufferWriter();
|
||||
auto input = input_writer.extract_reader();
|
||||
td::ByteFlowSource source(&input);
|
||||
td::GzipByteFlow gzip_flow(td::Gzip::Decode);
|
||||
td::GzipByteFlow gzip_flow(td::Gzip::Mode::Decode);
|
||||
td::ByteFlowSink sink;
|
||||
|
||||
source >> gzip_flow >> sink;
|
||||
|
@ -104,10 +112,10 @@ TEST(Gzip, encode_decode_flow) {
|
|||
td::ChainBufferWriter input_writer;
|
||||
auto input = input_writer.extract_reader();
|
||||
td::ByteFlowSource source(&input);
|
||||
td::GzipByteFlow gzip_encode_flow(td::Gzip::Encode);
|
||||
td::GzipByteFlow gzip_decode_flow(td::Gzip::Decode);
|
||||
td::GzipByteFlow gzip_encode_flow2(td::Gzip::Encode);
|
||||
td::GzipByteFlow gzip_decode_flow2(td::Gzip::Decode);
|
||||
td::GzipByteFlow gzip_encode_flow(td::Gzip::Mode::Encode);
|
||||
td::GzipByteFlow gzip_decode_flow(td::Gzip::Mode::Decode);
|
||||
td::GzipByteFlow gzip_encode_flow2(td::Gzip::Mode::Encode);
|
||||
td::GzipByteFlow gzip_decode_flow2(td::Gzip::Mode::Decode);
|
||||
td::ByteFlowSink sink;
|
||||
source >> gzip_encode_flow >> gzip_decode_flow >> gzip_encode_flow2 >> gzip_decode_flow2 >> sink;
|
||||
|
||||
|
|
|
@ -22,26 +22,23 @@
|
|||
#include "td/utils/Heap.h"
|
||||
#include "td/utils/Random.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
REGISTER_TESTS(heap)
|
||||
|
||||
using namespace td;
|
||||
|
||||
TEST(Heap, sort_random_perm) {
|
||||
int n = 1000000;
|
||||
std::vector<int> v(n);
|
||||
|
||||
td::vector<int> v(n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
v[i] = i;
|
||||
}
|
||||
td::Random::Xorshift128plus rnd(123);
|
||||
td::random_shuffle(as_mutable_span(v), rnd);
|
||||
std::vector<HeapNode> nodes(n);
|
||||
KHeap<int> kheap;
|
||||
td::random_shuffle(td::as_mutable_span(v), rnd);
|
||||
std::vector<td::HeapNode> nodes(n);
|
||||
td::KHeap<int> kheap;
|
||||
for (int i = 0; i < n; i++) {
|
||||
kheap.insert(v[i], &nodes[i]);
|
||||
}
|
||||
|
@ -62,7 +59,7 @@ class CheckedHeap {
|
|||
nodes[i].value = i;
|
||||
}
|
||||
}
|
||||
static void xx(int key, const HeapNode *heap_node) {
|
||||
static void xx(int key, const td::HeapNode *heap_node) {
|
||||
const Node *node = static_cast<const Node *>(heap_node);
|
||||
std::fprintf(stderr, "(%d;%d)", node->key, node->value);
|
||||
}
|
||||
|
@ -77,9 +74,9 @@ class CheckedHeap {
|
|||
}
|
||||
int random_id() const {
|
||||
CHECK(!empty());
|
||||
return ids[Random::fast(0, static_cast<int>(ids.size() - 1))];
|
||||
return ids[td::Random::fast(0, static_cast<int>(ids.size() - 1))];
|
||||
}
|
||||
size_t size() const {
|
||||
std::size_t size() const {
|
||||
return ids.size();
|
||||
}
|
||||
bool empty() const {
|
||||
|
@ -151,19 +148,19 @@ class CheckedHeap {
|
|||
}
|
||||
|
||||
private:
|
||||
struct Node : public HeapNode {
|
||||
struct Node : public td::HeapNode {
|
||||
Node() = default;
|
||||
Node(int key, int value) : key(key), value(value) {
|
||||
}
|
||||
int key = 0;
|
||||
int value = 0;
|
||||
};
|
||||
vector<int> ids;
|
||||
vector<int> rev_ids;
|
||||
vector<int> free_ids;
|
||||
vector<Node> nodes;
|
||||
td::vector<int> ids;
|
||||
td::vector<int> rev_ids;
|
||||
td::vector<int> free_ids;
|
||||
td::vector<Node> nodes;
|
||||
std::set<std::pair<int, int>> set_heap;
|
||||
KHeap<int> kheap;
|
||||
td::KHeap<int> kheap;
|
||||
};
|
||||
|
||||
TEST(Heap, random_events) {
|
||||
|
@ -174,11 +171,11 @@ TEST(Heap, random_events) {
|
|||
heap.top_key();
|
||||
}
|
||||
|
||||
int x = Random::fast(0, 4);
|
||||
int x = td::Random::fast(0, 4);
|
||||
if (heap.empty() || (x < 2 && heap.size() < 1000)) {
|
||||
heap.insert(Random::fast(0, 99));
|
||||
heap.insert(td::Random::fast(0, 99));
|
||||
} else if (x < 3) {
|
||||
heap.fix_key(Random::fast(0, 99), heap.random_id());
|
||||
heap.fix_key(td::Random::fast(0, 99), heap.random_id());
|
||||
} else if (x < 4) {
|
||||
heap.erase(heap.random_id());
|
||||
} else if (x < 5) {
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/StringBuilder.h"
|
||||
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
REGISTER_TESTS(json)
|
||||
|
@ -60,8 +59,8 @@ TEST(JSON, object) {
|
|||
StringBuilder sb(MutableSlice{tmp, sizeof(tmp)});
|
||||
JsonBuilder jb(std::move(sb));
|
||||
auto c = jb.enter_object();
|
||||
c << std::tie("key", "value");
|
||||
c << std::make_pair("1", 2);
|
||||
c("key", "value");
|
||||
c("1", 2);
|
||||
c.leave();
|
||||
ASSERT_EQ(jb.string_builder().is_error(), false);
|
||||
auto encoded = jb.string_builder().as_cslice().str();
|
||||
|
|
|
@ -16,25 +16,27 @@
|
|||
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "td/utils/tests.h"
|
||||
|
||||
#include "td/utils/benchmark.h"
|
||||
#include "td/utils/FileLog.h"
|
||||
#include "td/utils/TsFileLog.h"
|
||||
#include "td/utils/format.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/port/path.h"
|
||||
#include "td/utils/benchmark.h"
|
||||
#include "td/utils/port/thread.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/tests.h"
|
||||
#include "td/utils/TsFileLog.h"
|
||||
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
|
||||
// Thread safe logging with tests
|
||||
//
|
||||
// LOG uses thread local LogInterface
|
||||
// void append(CSlice slice, int log_level);
|
||||
//
|
||||
char disable_linker_warning_about_empty_file_tdutils_test_log_cpp TD_UNUSED;
|
||||
|
||||
#if !TD_THREAD_UNSUPPORTED
|
||||
template <class Log>
|
||||
class LogBenchmark : public td::Benchmark {
|
||||
public:
|
||||
explicit LogBenchmark(std::string name, int threads_n, std::function<td::unique_ptr<Log>()> creator)
|
||||
LogBenchmark(std::string name, int threads_n, std::function<td::unique_ptr<Log>()> creator)
|
||||
: name_(std::move(name)), threads_n_(threads_n), creator_(std::move(creator)) {
|
||||
}
|
||||
std::string get_description() const override {
|
||||
|
@ -78,7 +80,7 @@ class LogBenchmark : public td::Benchmark {
|
|||
};
|
||||
|
||||
template <class F>
|
||||
void bench_log(std::string name, int threads_n, F &&f) {
|
||||
static void bench_log(std::string name, int threads_n, F &&f) {
|
||||
bench(LogBenchmark<typename decltype(f())::element_type>(std::move(name), threads_n, std::move(f)));
|
||||
};
|
||||
|
||||
|
@ -89,7 +91,7 @@ TEST(Log, TsLogger) {
|
|||
class FileLog : public td::LogInterface {
|
||||
public:
|
||||
FileLog() {
|
||||
file_log_.init("tmplog", std::numeric_limits<td::int64>::max(), false);
|
||||
file_log_.init("tmplog", std::numeric_limits<td::int64>::max(), false).ensure();
|
||||
ts_log_.init(&file_log_);
|
||||
}
|
||||
~FileLog() {
|
||||
|
@ -121,7 +123,7 @@ TEST(Log, TsLogger) {
|
|||
class FileLog : public td::LogInterface {
|
||||
public:
|
||||
FileLog() {
|
||||
file_log_.init("tmplog", std::numeric_limits<td::int64>::max(), false);
|
||||
file_log_.init("tmplog", std::numeric_limits<td::int64>::max(), false).ensure();
|
||||
}
|
||||
~FileLog() {
|
||||
}
|
||||
|
@ -138,3 +140,4 @@ TEST(Log, TsLogger) {
|
|||
return td::make_unique<FileLog>();
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "td/utils/port/sleep.h"
|
||||
#include "td/utils/port/Stat.h"
|
||||
#include "td/utils/port/thread.h"
|
||||
#include "td/utils/port/uname.h"
|
||||
#include "td/utils/port/wstring_convert.h"
|
||||
#include "td/utils/Random.h"
|
||||
#include "td/utils/Slice.h"
|
||||
|
@ -174,7 +175,9 @@ TEST(Misc, base64) {
|
|||
ASSERT_TRUE(is_base64("dGVzdB==") == false);
|
||||
ASSERT_TRUE(is_base64("dGVzdA=") == false);
|
||||
ASSERT_TRUE(is_base64("dGVzdA") == false);
|
||||
ASSERT_TRUE(is_base64("dGVzd") == false);
|
||||
ASSERT_TRUE(is_base64("dGVz") == true);
|
||||
ASSERT_TRUE(is_base64("dGVz====") == false);
|
||||
ASSERT_TRUE(is_base64("") == true);
|
||||
ASSERT_TRUE(is_base64("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/") == true);
|
||||
ASSERT_TRUE(is_base64("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=") == false);
|
||||
|
@ -186,7 +189,9 @@ TEST(Misc, base64) {
|
|||
ASSERT_TRUE(is_base64url("dGVzdB==") == false);
|
||||
ASSERT_TRUE(is_base64url("dGVzdA=") == false);
|
||||
ASSERT_TRUE(is_base64url("dGVzdA") == true);
|
||||
ASSERT_TRUE(is_base64url("dGVzd") == false);
|
||||
ASSERT_TRUE(is_base64url("dGVz") == true);
|
||||
ASSERT_TRUE(is_base64url("dGVz====") == false);
|
||||
ASSERT_TRUE(is_base64url("") == true);
|
||||
ASSERT_TRUE(is_base64url("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_") == true);
|
||||
ASSERT_TRUE(is_base64url("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=") == false);
|
||||
|
@ -194,6 +199,30 @@ TEST(Misc, base64) {
|
|||
ASSERT_TRUE(is_base64url("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/") == false);
|
||||
ASSERT_TRUE(is_base64url("====") == false);
|
||||
|
||||
ASSERT_TRUE(is_base64_characters("dGVzdA==") == false);
|
||||
ASSERT_TRUE(is_base64_characters("dGVzdB==") == false);
|
||||
ASSERT_TRUE(is_base64_characters("dGVzdA=") == false);
|
||||
ASSERT_TRUE(is_base64_characters("dGVzdA") == true);
|
||||
ASSERT_TRUE(is_base64_characters("dGVz") == true);
|
||||
ASSERT_TRUE(is_base64_characters("") == true);
|
||||
ASSERT_TRUE(is_base64_characters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/") == true);
|
||||
ASSERT_TRUE(is_base64_characters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=") == false);
|
||||
ASSERT_TRUE(is_base64_characters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-/") == false);
|
||||
ASSERT_TRUE(is_base64_characters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_") == false);
|
||||
ASSERT_TRUE(is_base64_characters("====") == false);
|
||||
|
||||
ASSERT_TRUE(is_base64url_characters("dGVzdA==") == false);
|
||||
ASSERT_TRUE(is_base64url_characters("dGVzdB==") == false);
|
||||
ASSERT_TRUE(is_base64url_characters("dGVzdA=") == false);
|
||||
ASSERT_TRUE(is_base64url_characters("dGVzdA") == true);
|
||||
ASSERT_TRUE(is_base64url_characters("dGVz") == true);
|
||||
ASSERT_TRUE(is_base64url_characters("") == true);
|
||||
ASSERT_TRUE(is_base64url_characters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_") == true);
|
||||
ASSERT_TRUE(is_base64url_characters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=") == false);
|
||||
ASSERT_TRUE(is_base64url_characters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-/") == false);
|
||||
ASSERT_TRUE(is_base64url_characters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/") == false);
|
||||
ASSERT_TRUE(is_base64url_characters("====") == false);
|
||||
|
||||
for (int l = 0; l < 300000; l += l / 20 + l / 1000 * 500 + 1) {
|
||||
for (int t = 0; t < 10; t++) {
|
||||
string s = rand_string(std::numeric_limits<char>::min(), std::numeric_limits<char>::max(), l);
|
||||
|
@ -206,6 +235,10 @@ TEST(Misc, base64) {
|
|||
decoded = base64_decode(encoded);
|
||||
ASSERT_TRUE(decoded.is_ok());
|
||||
ASSERT_TRUE(decoded.ok() == s);
|
||||
|
||||
auto decoded_secure = base64_decode_secure(encoded);
|
||||
ASSERT_TRUE(decoded_secure.is_ok());
|
||||
ASSERT_TRUE(decoded_secure.ok().as_slice() == s);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,6 +251,104 @@ TEST(Misc, base64) {
|
|||
ASSERT_TRUE(base64_encode(" /'.;.';≤.];,].',[.;/,.;/]/..;!@#!*(%?::;!%\";") ==
|
||||
"ICAgICAgLycuOy4nO+KJpC5dOyxdLicsWy47LywuOy9dLy4uOyFAIyEqKCU/"
|
||||
"Ojo7ISUiOw==");
|
||||
ASSERT_TRUE(base64url_encode("ab><") == "YWI-PA");
|
||||
ASSERT_TRUE(base64url_encode("ab><c") == "YWI-PGM");
|
||||
ASSERT_TRUE(base64url_encode("ab><cd") == "YWI-PGNk");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void test_remove_if(vector<int> v, const T &func, vector<int> expected) {
|
||||
td::remove_if(v, func);
|
||||
if (expected != v) {
|
||||
LOG(FATAL) << "Receive " << v << ", expected " << expected << " in remove_if";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Misc, remove_if) {
|
||||
auto odd = [](int x) { return x % 2 == 1; };
|
||||
auto even = [](int x) { return x % 2 == 0; };
|
||||
auto all = [](int x) { return true; };
|
||||
auto none = [](int x) { return false; };
|
||||
|
||||
vector<int> v{1, 2, 3, 4, 5, 6};
|
||||
test_remove_if(v, odd, {2, 4, 6});
|
||||
test_remove_if(v, even, {1, 3, 5});
|
||||
test_remove_if(v, all, {});
|
||||
test_remove_if(v, none, v);
|
||||
|
||||
v = vector<int>{1, 3, 5, 2, 4, 6};
|
||||
test_remove_if(v, odd, {2, 4, 6});
|
||||
test_remove_if(v, even, {1, 3, 5});
|
||||
test_remove_if(v, all, {});
|
||||
test_remove_if(v, none, v);
|
||||
|
||||
v.clear();
|
||||
test_remove_if(v, odd, v);
|
||||
test_remove_if(v, even, v);
|
||||
test_remove_if(v, all, v);
|
||||
test_remove_if(v, none, v);
|
||||
|
||||
v.push_back(-1);
|
||||
test_remove_if(v, odd, v);
|
||||
test_remove_if(v, even, v);
|
||||
test_remove_if(v, all, {});
|
||||
test_remove_if(v, none, v);
|
||||
|
||||
v[0] = 1;
|
||||
test_remove_if(v, odd, {});
|
||||
test_remove_if(v, even, v);
|
||||
test_remove_if(v, all, {});
|
||||
test_remove_if(v, none, v);
|
||||
|
||||
v[0] = 2;
|
||||
test_remove_if(v, odd, v);
|
||||
test_remove_if(v, even, {});
|
||||
test_remove_if(v, all, {});
|
||||
test_remove_if(v, none, v);
|
||||
}
|
||||
|
||||
static void test_remove(vector<int> v, int value, vector<int> expected) {
|
||||
bool is_found = expected != v;
|
||||
ASSERT_EQ(is_found, td::remove(v, value));
|
||||
if (expected != v) {
|
||||
LOG(FATAL) << "Receive " << v << ", expected " << expected << " in remove";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Misc, remove) {
|
||||
vector<int> v{1, 2, 3, 4, 5, 6};
|
||||
test_remove(v, 0, {1, 2, 3, 4, 5, 6});
|
||||
test_remove(v, 1, {2, 3, 4, 5, 6});
|
||||
test_remove(v, 2, {1, 3, 4, 5, 6});
|
||||
test_remove(v, 3, {1, 2, 4, 5, 6});
|
||||
test_remove(v, 4, {1, 2, 3, 5, 6});
|
||||
test_remove(v, 5, {1, 2, 3, 4, 6});
|
||||
test_remove(v, 6, {1, 2, 3, 4, 5});
|
||||
test_remove(v, 7, {1, 2, 3, 4, 5, 6});
|
||||
|
||||
v.clear();
|
||||
test_remove(v, -1, v);
|
||||
test_remove(v, 0, v);
|
||||
test_remove(v, 1, v);
|
||||
}
|
||||
|
||||
TEST(Misc, contains) {
|
||||
td::vector<int> v{1, 3, 5, 7, 4, 2};
|
||||
for (int i = -10; i < 20; i++) {
|
||||
ASSERT_EQ(td::contains(v, i), (1 <= i && i <= 5) || i == 7);
|
||||
}
|
||||
|
||||
v.clear();
|
||||
ASSERT_TRUE(!td::contains(v, 0));
|
||||
ASSERT_TRUE(!td::contains(v, 1));
|
||||
|
||||
td::string str = "abacaba";
|
||||
ASSERT_TRUE(!td::contains(str, '0'));
|
||||
ASSERT_TRUE(!td::contains(str, 0));
|
||||
ASSERT_TRUE(!td::contains(str, 'd'));
|
||||
ASSERT_TRUE(td::contains(str, 'a'));
|
||||
ASSERT_TRUE(td::contains(str, 'b'));
|
||||
ASSERT_TRUE(td::contains(str, 'c'));
|
||||
}
|
||||
|
||||
TEST(Misc, base32) {
|
||||
|
@ -486,6 +617,29 @@ TEST(BigNum, from_decimal) {
|
|||
ASSERT_TRUE(BigNum::from_decimal("999999999999999999999999999999999999999999999999").is_ok());
|
||||
}
|
||||
|
||||
TEST(BigNum, from_binary) {
|
||||
ASSERT_STREQ(BigNum::from_binary("").to_decimal(), "0");
|
||||
ASSERT_STREQ(BigNum::from_binary("a").to_decimal(), "97");
|
||||
ASSERT_STREQ(BigNum::from_binary("\x00\xff").to_decimal(), "255");
|
||||
ASSERT_STREQ(BigNum::from_binary("\x00\x01\x00\x00").to_decimal(), "65536");
|
||||
ASSERT_STREQ(BigNum::from_le_binary("").to_decimal(), "0");
|
||||
ASSERT_STREQ(BigNum::from_le_binary("a").to_decimal(), "97");
|
||||
ASSERT_STREQ(BigNum::from_le_binary("\x00\xff").to_decimal(), "65280");
|
||||
ASSERT_STREQ(BigNum::from_le_binary("\x00\x01\x00\x00").to_decimal(), "256");
|
||||
ASSERT_STREQ(BigNum::from_decimal("255").move_as_ok().to_binary(), "\xff");
|
||||
ASSERT_STREQ(BigNum::from_decimal("255").move_as_ok().to_le_binary(), "\xff");
|
||||
ASSERT_STREQ(BigNum::from_decimal("255").move_as_ok().to_binary(2), "\x00\xff");
|
||||
ASSERT_STREQ(BigNum::from_decimal("255").move_as_ok().to_le_binary(2), "\xff\x00");
|
||||
ASSERT_STREQ(BigNum::from_decimal("65280").move_as_ok().to_binary(), "\xff\x00");
|
||||
ASSERT_STREQ(BigNum::from_decimal("65280").move_as_ok().to_le_binary(), "\x00\xff");
|
||||
ASSERT_STREQ(BigNum::from_decimal("65280").move_as_ok().to_binary(2), "\xff\x00");
|
||||
ASSERT_STREQ(BigNum::from_decimal("65280").move_as_ok().to_le_binary(2), "\x00\xff");
|
||||
ASSERT_STREQ(BigNum::from_decimal("65536").move_as_ok().to_binary(), "\x01\x00\x00");
|
||||
ASSERT_STREQ(BigNum::from_decimal("65536").move_as_ok().to_le_binary(), "\x00\x00\x01");
|
||||
ASSERT_STREQ(BigNum::from_decimal("65536").move_as_ok().to_binary(4), "\x00\x01\x00\x00");
|
||||
ASSERT_STREQ(BigNum::from_decimal("65536").move_as_ok().to_le_binary(4), "\x00\x00\x01\x00");
|
||||
}
|
||||
|
||||
static void test_get_ipv4(uint32 ip) {
|
||||
td::IPAddress ip_address;
|
||||
ip_address.init_ipv4_port(td::IPAddress::ipv4_to_str(ip), 80).ensure();
|
||||
|
@ -704,6 +858,14 @@ TEST(Misc, Bits) {
|
|||
ASSERT_EQ(0x12345678u, td::bswap32(0x78563412u));
|
||||
ASSERT_EQ(0x12345678abcdef67ull, td::bswap64(0x67efcdab78563412ull));
|
||||
|
||||
uint8 buf[8] = {1, 90, 2, 18, 129, 255, 0, 2};
|
||||
uint64 num2 = bswap64(as<td::uint64>(buf));
|
||||
uint64 num = (static_cast<uint64>(buf[0]) << 56) | (static_cast<uint64>(buf[1]) << 48) |
|
||||
(static_cast<uint64>(buf[2]) << 40) | (static_cast<uint64>(buf[3]) << 32) |
|
||||
(static_cast<uint64>(buf[4]) << 24) | (static_cast<uint64>(buf[5]) << 16) |
|
||||
(static_cast<uint64>(buf[6]) << 8) | (static_cast<uint64>(buf[7]));
|
||||
ASSERT_EQ(num, num2);
|
||||
|
||||
ASSERT_EQ(0, count_bits32(0));
|
||||
ASSERT_EQ(0, count_bits64(0));
|
||||
ASSERT_EQ(4, count_bits32((1u << 31) | 7));
|
||||
|
@ -976,6 +1138,7 @@ TEST(Misc, Hasher) {
|
|||
test_hash<AbslHash>();
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Misc, CancellationToken) {
|
||||
CancellationTokenSource source;
|
||||
source.cancel();
|
||||
|
@ -1003,3 +1166,10 @@ TEST(Misc, Xorshift128plus) {
|
|||
ASSERT_EQ(5645917797309401285ull, rnd());
|
||||
ASSERT_EQ(13554822455746959330ull, rnd());
|
||||
}
|
||||
TEST(Misc, uname) {
|
||||
auto first_version = get_operating_system_version();
|
||||
auto second_version = get_operating_system_version();
|
||||
ASSERT_STREQ(first_version, second_version);
|
||||
ASSERT_EQ(first_version.begin(), second_version.begin());
|
||||
ASSERT_TRUE(!first_version.empty());
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/tests.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
using namespace td;
|
||||
|
||||
TEST(Port, files) {
|
||||
|
@ -51,44 +53,38 @@ TEST(Port, files) {
|
|||
int cnt = 0;
|
||||
const int ITER_COUNT = 1000;
|
||||
for (int i = 0; i < ITER_COUNT; i++) {
|
||||
walk_path(main_dir,
|
||||
[&](CSlice name, WalkPath::Type type) {
|
||||
if (type == WalkPath::Type::NotDir) {
|
||||
ASSERT_TRUE(name == fd_path || name == fd2_path);
|
||||
}
|
||||
cnt++;
|
||||
})
|
||||
.ensure();
|
||||
walk_path(main_dir, [&](CSlice name, WalkPath::Type type) {
|
||||
if (type == WalkPath::Type::NotDir) {
|
||||
ASSERT_TRUE(name == fd_path || name == fd2_path);
|
||||
}
|
||||
cnt++;
|
||||
}).ensure();
|
||||
}
|
||||
ASSERT_EQ((5 * 2 + 2) * ITER_COUNT, cnt);
|
||||
bool was_abort = false;
|
||||
walk_path(main_dir,
|
||||
[&](CSlice name, WalkPath::Type type) {
|
||||
CHECK(!was_abort);
|
||||
if (type == WalkPath::Type::EnterDir && ends_with(name, PSLICE() << TD_DIR_SLASH << "B")) {
|
||||
was_abort = true;
|
||||
return WalkPath::Action::Abort;
|
||||
}
|
||||
return WalkPath::Action::Continue;
|
||||
})
|
||||
.ensure();
|
||||
walk_path(main_dir, [&](CSlice name, WalkPath::Type type) {
|
||||
CHECK(!was_abort);
|
||||
if (type == WalkPath::Type::EnterDir && ends_with(name, PSLICE() << TD_DIR_SLASH << "B")) {
|
||||
was_abort = true;
|
||||
return WalkPath::Action::Abort;
|
||||
}
|
||||
return WalkPath::Action::Continue;
|
||||
}).ensure();
|
||||
CHECK(was_abort);
|
||||
|
||||
cnt = 0;
|
||||
bool is_first_dir = true;
|
||||
walk_path(main_dir,
|
||||
[&](CSlice name, WalkPath::Type type) {
|
||||
cnt++;
|
||||
if (type == WalkPath::Type::EnterDir) {
|
||||
if (is_first_dir) {
|
||||
is_first_dir = false;
|
||||
} else {
|
||||
return WalkPath::Action::SkipDir;
|
||||
}
|
||||
}
|
||||
return WalkPath::Action::Continue;
|
||||
})
|
||||
.ensure();
|
||||
walk_path(main_dir, [&](CSlice name, WalkPath::Type type) {
|
||||
cnt++;
|
||||
if (type == WalkPath::Type::EnterDir) {
|
||||
if (is_first_dir) {
|
||||
is_first_dir = false;
|
||||
} else {
|
||||
return WalkPath::Action::SkipDir;
|
||||
}
|
||||
}
|
||||
return WalkPath::Action::Continue;
|
||||
}).ensure();
|
||||
ASSERT_EQ(6, cnt);
|
||||
|
||||
ASSERT_EQ(0u, fd.get_size().move_as_ok());
|
||||
|
@ -111,6 +107,22 @@ TEST(Port, files) {
|
|||
ASSERT_STREQ("Habcd world?!", buf_slice.substr(0, 13));
|
||||
}
|
||||
|
||||
TEST(Port, SparseFiles) {
|
||||
CSlice path = "sparse.txt";
|
||||
unlink(path).ignore();
|
||||
auto fd = FileFd::open(path, FileFd::Write | FileFd::CreateNew).move_as_ok();
|
||||
ASSERT_EQ(0, fd.get_size().move_as_ok());
|
||||
ASSERT_EQ(0, fd.get_real_size().move_as_ok());
|
||||
int64 offset = 100000000;
|
||||
fd.pwrite("a", offset).ensure();
|
||||
ASSERT_EQ(offset + 1, fd.get_size().move_as_ok());
|
||||
auto real_size = fd.get_real_size().move_as_ok();
|
||||
if (real_size >= offset + 1) {
|
||||
LOG(ERROR) << "File system doesn't support sparse files, rewind during streaming can be slow";
|
||||
}
|
||||
unlink(path).ensure();
|
||||
}
|
||||
|
||||
TEST(Port, Writev) {
|
||||
std::vector<IoSlice> vec;
|
||||
CSlice test_file_path = "test.txt";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue