Files
libtorrent/simulation/test_dht_storage.cpp
2022-06-23 08:07:28 +02:00

198 lines
5.6 KiB
C++

/*
Copyright (c) 2015-2017, Alden Torres
Copyright (c) 2015-2019, 2021, Arvid Norberg
All rights reserved.
You may use, distribute and modify this code under the terms of the BSD license,
see LICENSE file.
*/
#include "test.hpp"
#ifndef TORRENT_DISABLE_DHT
#include "settings.hpp"
#include "setup_transfer.hpp" // for ep()
#include "libtorrent/config.hpp"
#include "libtorrent/kademlia/dht_storage.hpp"
#include "libtorrent/kademlia/dht_settings.hpp"
#include "libtorrent/io_context.hpp"
#include "libtorrent/aux_/session_settings.hpp"
#include "libtorrent/address.hpp"
#include "libtorrent/aux_/time.hpp"
#include "simulator/simulator.hpp"
#include <functional>
#include <sstream>
using namespace lt;
using namespace lt::dht;
using namespace sim;
using sim::chrono::high_resolution_clock;
using namespace sim::asio;
using sim::simulation;
using sim::default_config;
using namespace std::placeholders;
namespace
{
lt::aux::session_settings test_settings()
{
lt::aux::session_settings sett;
sett.set_int(settings_pack::dht_max_torrents, 2);
sett.set_int(settings_pack::dht_max_dht_items, 2);
sett.set_int(settings_pack::dht_item_lifetime, 120 * 60);
return sett;
}
std::unique_ptr<dht_storage_interface> create_default_dht_storage(
settings_interface const& sett)
{
std::unique_ptr<dht_storage_interface> s(dht_default_storage_constructor(sett));
TEST_CHECK(s.get() != nullptr);
s->update_node_ids({to_hash("0000000000000000000000000000000000000200")});
return s;
}
}
void timer_tick(dht_storage_interface* s
, dht_storage_counters const& c
, boost::system::error_code const&)
{
s->tick();
TEST_EQUAL(s->counters().peers, c.peers);
TEST_EQUAL(s->counters().torrents, c.torrents);
TEST_EQUAL(s->counters().immutable_data, c.immutable_data);
TEST_EQUAL(s->counters().mutable_data, c.mutable_data);
}
void test_expiration(simulation& sim
, high_resolution_clock::duration const& expiry_time
, std::unique_ptr<dht_storage_interface>& s
, dht_storage_counters const& c)
{
sim::asio::io_context ios(sim, addr("10.0.0.1"));
sim::asio::high_resolution_timer timer(ios);
timer.expires_after(expiry_time);
timer.async_wait(std::bind(&timer_tick, s.get(), c, _1));
sim.run();
}
TORRENT_TEST(dht_storage_counters)
{
auto sett = test_settings();
std::unique_ptr<dht_storage_interface> s(create_default_dht_storage(sett));
TEST_CHECK(s.get() != nullptr);
sha1_hash const n1 = to_hash("5fbfbff10c5d6a4ec8a88e4c6ab4c28b95eee401");
sha1_hash const n2 = to_hash("5fbfbff10c5d6a4ec8a88e4c6ab4c28b95eee402");
sha1_hash const n3 = to_hash("5fbfbff10c5d6a4ec8a88e4c6ab4c28b95eee403");
sha1_hash const n4 = to_hash("5fbfbff10c5d6a4ec8a88e4c6ab4c28b95eee404");
tcp::endpoint const p1 = ep("124.31.75.21", 1);
tcp::endpoint const p2 = ep("124.31.75.22", 1);
tcp::endpoint const p3 = ep("124.31.75.23", 1);
tcp::endpoint const p4 = ep("124.31.75.24", 1);
s->announce_peer(n1, p1, "torrent_name", false);
s->announce_peer(n2, p2, "torrent_name1", false);
s->announce_peer(n2, p3, "torrent_name1", false);
s->announce_peer(n3, p4, "torrent_name2", false);
s->put_immutable_item(n4, {"123", 3}, addr("124.31.75.21"));
s->put_immutable_item(n1, {"123", 3}, addr("124.31.75.21"));
s->put_immutable_item(n2, {"123", 3}, addr("124.31.75.21"));
s->put_immutable_item(n3, {"123", 3}, addr("124.31.75.21"));
dht::public_key pk;
dht::signature sig;
s->put_mutable_item(n4, {"123", 3}, sig, sequence_number(1), pk, {"salt", 4}
, addr("124.31.75.21"));
dht_storage_counters c;
// note that we are using the aux global timer
default_config cfg;
simulation sim(cfg);
c.peers = 3;
c.torrents = 2;
c.immutable_data = 2;
c.mutable_data = 1;
test_expiration(sim, minutes(30), s, c); // test expiration of torrents and peers
c.peers = 0;
c.torrents = 0;
c.immutable_data = 2;
c.mutable_data = 1;
test_expiration(sim, minutes(80), s, c); // test expiration of items before 2 hours
c.peers = 0;
c.torrents = 0;
c.immutable_data = 0;
c.mutable_data = 0;
test_expiration(sim, hours(1), s, c); // test expiration of everything after 3 hours
}
TORRENT_TEST(dht_storage_infohashes_sample)
{
default_config cfg;
simulation sim(cfg);
sim::asio::io_context ios(sim, addr("10.0.0.1"));
auto sett = test_settings();
sett.set_int(settings_pack::dht_max_torrents, 5);
sett.set_int(settings_pack::dht_sample_infohashes_interval, 30);
sett.set_int(settings_pack::dht_max_infohashes_sample_count, 2);
std::unique_ptr<dht_storage_interface> s(create_default_dht_storage(sett));
TEST_CHECK(s.get() != nullptr);
sha1_hash const n1 = to_hash("5fbfbff10c5d6a4ec8a88e4c6ab4c28b95eee401");
sha1_hash const n2 = to_hash("5fbfbff10c5d6a4ec8a88e4c6ab4c28b95eee402");
sha1_hash const n3 = to_hash("5fbfbff10c5d6a4ec8a88e4c6ab4c28b95eee403");
sha1_hash const n4 = to_hash("5fbfbff10c5d6a4ec8a88e4c6ab4c28b95eee404");
tcp::endpoint const p1 = ep("124.31.75.21", 1);
tcp::endpoint const p2 = ep("124.31.75.22", 1);
tcp::endpoint const p3 = ep("124.31.75.23", 1);
tcp::endpoint const p4 = ep("124.31.75.24", 1);
s->announce_peer(n1, p1, "torrent_name1", false);
s->announce_peer(n2, p2, "torrent_name2", false);
s->announce_peer(n3, p3, "torrent_name3", false);
s->announce_peer(n4, p4, "torrent_name4", false);
entry item;
int r = s->get_infohashes_sample(item);
TEST_EQUAL(r, 2);
sim::asio::high_resolution_timer timer(ios);
timer.expires_after(hours(1)); // expiration of torrents
timer.async_wait([&s](boost::system::error_code const&)
{
// tick here to trigger the torrents expiration
s->tick();
entry item;
int r = s->get_infohashes_sample(item);
TEST_EQUAL(r, 0);
});
sim.run();
}
#else
TORRENT_TEST(disabled) {}
#endif // TORRENT_DISABLE_DHT