1
0
Fork 0
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:
ton 2020-07-06 17:07:20 +03:00
parent dbde9c1c40
commit f064b1047a
257 changed files with 6665 additions and 2608 deletions

View file

@ -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
View 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); });
}
}

View 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, {}, {});
}

View file

@ -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

View file

@ -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"

View file

@ -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));

View file

@ -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");
}

View file

@ -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;

View file

@ -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) {

View file

@ -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();

View file

@ -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

View file

@ -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());
}

View file

@ -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";