2015-08-08 03:28:51 +02:00
|
|
|
/*
|
|
|
|
|
|
|
|
Copyright (c) 2008, Arvid Norberg
|
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions
|
|
|
|
are met:
|
|
|
|
|
|
|
|
* Redistributions of source code must retain the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in
|
|
|
|
the documentation and/or other materials provided with the distribution.
|
|
|
|
* Neither the name of the author nor the names of its
|
|
|
|
contributors may be used to endorse or promote products derived
|
|
|
|
from this software without specific prior written permission.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
|
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2015-12-06 06:14:30 +01:00
|
|
|
#include "setup_swarm.hpp"
|
2015-08-08 03:28:51 +02:00
|
|
|
#include "test.hpp"
|
2016-03-27 03:02:49 +02:00
|
|
|
#include "utils.hpp"
|
2015-12-06 06:14:30 +01:00
|
|
|
#include "libtorrent/alert.hpp"
|
|
|
|
#include "libtorrent/alert_types.hpp"
|
|
|
|
#include "libtorrent/session.hpp"
|
2016-01-11 08:10:42 +01:00
|
|
|
#include "libtorrent/session_stats.hpp"
|
2017-04-11 06:52:46 +02:00
|
|
|
#include "libtorrent/aux_/path.hpp"
|
2016-07-02 22:20:12 +02:00
|
|
|
#include "libtorrent/torrent_info.hpp"
|
2017-06-13 10:41:26 +02:00
|
|
|
#include "libtorrent/time.hpp"
|
2016-07-02 22:20:12 +02:00
|
|
|
#include "settings.hpp"
|
2017-06-13 10:41:26 +02:00
|
|
|
#include "setup_transfer.hpp" // for ep()
|
|
|
|
#include "fake_peer.hpp"
|
|
|
|
|
2018-08-18 10:36:38 +02:00
|
|
|
#include "simulator/nat.hpp"
|
2017-06-13 10:41:26 +02:00
|
|
|
#include "simulator/queue.hpp"
|
|
|
|
#include "utils.hpp"
|
2015-12-06 06:14:30 +01:00
|
|
|
|
2017-04-12 20:05:53 +02:00
|
|
|
using namespace lt;
|
2015-08-08 03:28:51 +02:00
|
|
|
|
|
|
|
TORRENT_TEST(seed_mode)
|
|
|
|
{
|
|
|
|
// with seed mode
|
2016-07-02 22:20:12 +02:00
|
|
|
setup_swarm(3, swarm_test::upload
|
2015-12-06 06:14:30 +01:00
|
|
|
// add session
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::settings_pack&) {}
|
2015-12-06 06:14:30 +01:00
|
|
|
// add torrent
|
|
|
|
, [](lt::add_torrent_params& params) {
|
2017-07-26 23:56:17 +02:00
|
|
|
params.flags |= torrent_flags::seed_mode;
|
2015-12-06 06:14:30 +01:00
|
|
|
}
|
|
|
|
// on alert
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::alert const*, lt::session&) {}
|
2015-12-06 06:14:30 +01:00
|
|
|
// terminate
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](int, lt::session&) -> bool
|
2016-07-02 22:20:12 +02:00
|
|
|
{ return false; });
|
|
|
|
}
|
|
|
|
|
|
|
|
TORRENT_TEST(seed_mode_disable_hash_checks)
|
|
|
|
{
|
|
|
|
// all nodes need to disable hash checking, otherwise the downloader would
|
|
|
|
// just fail
|
|
|
|
settings_pack swarm_settings = settings();
|
|
|
|
swarm_settings.set_bool(settings_pack::disable_hash_checks, true);
|
|
|
|
|
|
|
|
dsl_config network_cfg;
|
|
|
|
sim::simulation sim{network_cfg};
|
|
|
|
|
|
|
|
// with seed mode
|
|
|
|
setup_swarm(2, swarm_test::upload, sim, swarm_settings, add_torrent_params()
|
|
|
|
// add session
|
|
|
|
, [](lt::settings_pack& pack) {
|
|
|
|
pack.set_int(settings_pack::suggest_mode, settings_pack::suggest_read_cache);
|
|
|
|
}
|
|
|
|
// add torrent
|
|
|
|
, [](lt::add_torrent_params& params) {
|
2017-07-26 23:56:17 +02:00
|
|
|
params.flags |= torrent_flags::seed_mode;
|
2016-07-02 22:20:12 +02:00
|
|
|
// just to make sure the disable_hash_checks really work, we
|
|
|
|
// shouldn't be verifying anything from the storage
|
|
|
|
params.storage = disabled_storage_constructor;
|
|
|
|
}
|
|
|
|
// on alert
|
|
|
|
, [](lt::alert const*, lt::session&) {}
|
|
|
|
// terminate
|
|
|
|
, [](int, lt::session&) -> bool
|
|
|
|
{ return false; });
|
2015-08-08 03:28:51 +02:00
|
|
|
}
|
|
|
|
|
2018-05-10 12:13:59 +02:00
|
|
|
TORRENT_TEST(seed_mode_suggest)
|
|
|
|
{
|
|
|
|
setup_swarm(2, swarm_test::upload
|
|
|
|
// add session
|
|
|
|
, [](lt::settings_pack& pack) {
|
|
|
|
pack.set_int(settings_pack::suggest_mode, settings_pack::suggest_read_cache);
|
|
|
|
pack.set_int(settings_pack::cache_size, 2);
|
|
|
|
}
|
|
|
|
// add torrent
|
|
|
|
, [](lt::add_torrent_params& params) {
|
2018-05-10 19:16:33 +02:00
|
|
|
params.flags |= torrent_flags::seed_mode;
|
2018-05-10 12:13:59 +02:00
|
|
|
}
|
|
|
|
// on alert
|
2018-11-16 16:19:12 +01:00
|
|
|
, [](lt::alert const*, lt::session&) {}
|
2018-05-10 12:13:59 +02:00
|
|
|
// terminate
|
2018-11-16 16:19:12 +01:00
|
|
|
, [](int, lt::session&) -> bool
|
2018-05-10 12:13:59 +02:00
|
|
|
{ return true; });
|
|
|
|
}
|
|
|
|
|
2015-08-08 03:28:51 +02:00
|
|
|
TORRENT_TEST(plain)
|
|
|
|
{
|
2015-12-06 06:14:30 +01:00
|
|
|
setup_swarm(2, swarm_test::download
|
|
|
|
// add session
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::settings_pack&) {}
|
2015-12-06 06:14:30 +01:00
|
|
|
// add torrent
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::add_torrent_params&) {}
|
2015-12-06 06:14:30 +01:00
|
|
|
// on alert
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::alert const*, lt::session&) {}
|
2015-12-06 06:14:30 +01:00
|
|
|
// terminate
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](int const ticks, lt::session& ses) -> bool
|
2015-12-06 06:14:30 +01:00
|
|
|
{
|
2016-03-14 04:13:12 +01:00
|
|
|
if (ticks > 80)
|
2015-12-06 06:14:30 +01:00
|
|
|
{
|
|
|
|
TEST_ERROR("timeout");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (!is_seed(ses)) return false;
|
2016-05-17 15:24:06 +02:00
|
|
|
std::printf("completed in %d ticks\n", ticks);
|
2015-12-06 06:14:30 +01:00
|
|
|
return true;
|
|
|
|
});
|
2015-08-08 03:28:51 +02:00
|
|
|
}
|
|
|
|
|
2016-01-11 08:10:42 +01:00
|
|
|
TORRENT_TEST(session_stats)
|
|
|
|
{
|
|
|
|
std::vector<stats_metric> stats = session_stats_metrics();
|
|
|
|
int const downloading_idx = find_metric_idx("ses.num_downloading_torrents");
|
|
|
|
TEST_CHECK(downloading_idx >= 0);
|
|
|
|
int const incoming_extended_idx = find_metric_idx("ses.num_incoming_extended");
|
|
|
|
TEST_CHECK(incoming_extended_idx >= 0);
|
|
|
|
|
|
|
|
setup_swarm(2, swarm_test::download
|
|
|
|
// add session
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::settings_pack&) {}
|
2016-01-11 08:10:42 +01:00
|
|
|
// add torrent
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::add_torrent_params&) {}
|
2016-01-11 08:10:42 +01:00
|
|
|
// on alert
|
2016-06-19 01:24:27 +02:00
|
|
|
, [=](lt::alert const* a, lt::session&)
|
2016-01-11 08:10:42 +01:00
|
|
|
{
|
2016-03-05 17:02:41 +01:00
|
|
|
auto const* ss = lt::alert_cast<session_stats_alert>(a);
|
2016-01-11 08:10:42 +01:00
|
|
|
if (!ss) return;
|
|
|
|
|
|
|
|
// there's one downloading torrent
|
2017-06-09 21:30:36 +02:00
|
|
|
TEST_EQUAL(ss->counters()[downloading_idx], 1);
|
|
|
|
TEST_EQUAL(ss->counters()[incoming_extended_idx], 1);
|
2016-01-11 08:10:42 +01:00
|
|
|
}
|
|
|
|
// terminate
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](int const ticks, lt::session& ses) -> bool
|
2016-01-11 08:10:42 +01:00
|
|
|
{
|
|
|
|
ses.post_session_stats();
|
2016-03-14 01:47:50 +01:00
|
|
|
if (ticks > 80)
|
2016-01-11 08:10:42 +01:00
|
|
|
{
|
|
|
|
TEST_ERROR("timeout");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (!is_seed(ses)) return false;
|
2016-05-17 15:24:06 +02:00
|
|
|
std::printf("completed in %d ticks\n", ticks);
|
2016-01-11 08:10:42 +01:00
|
|
|
return true;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-11-24 00:45:54 +01:00
|
|
|
// this test relies on picking up log alerts
|
|
|
|
#ifndef TORRENT_DISABLE_LOGGING
|
2015-08-08 03:28:51 +02:00
|
|
|
TORRENT_TEST(suggest)
|
|
|
|
{
|
2016-06-15 19:29:54 +02:00
|
|
|
int num_suggests = 0;
|
|
|
|
setup_swarm(10, swarm_test::upload
|
2015-12-06 06:14:30 +01:00
|
|
|
// add session
|
|
|
|
, [](lt::settings_pack& pack) {
|
|
|
|
pack.set_int(settings_pack::suggest_mode, settings_pack::suggest_read_cache);
|
2016-06-15 19:29:54 +02:00
|
|
|
pack.set_int(settings_pack::max_suggest_pieces, 10);
|
2018-05-10 12:13:59 +02:00
|
|
|
pack.set_int(settings_pack::cache_size, 2);
|
2015-12-06 06:14:30 +01:00
|
|
|
}
|
|
|
|
// add torrent
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::add_torrent_params&) {}
|
2015-12-06 06:14:30 +01:00
|
|
|
// on alert
|
2016-06-19 01:24:27 +02:00
|
|
|
, [&num_suggests](lt::alert const* a, lt::session&) {
|
2016-06-15 19:29:54 +02:00
|
|
|
if (auto pl = alert_cast<peer_log_alert>(a))
|
|
|
|
{
|
|
|
|
if (pl->direction == peer_log_alert::outgoing_message
|
|
|
|
&& pl->event_type == std::string("SUGGEST"))
|
|
|
|
{
|
|
|
|
++num_suggests;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-12-06 06:14:30 +01:00
|
|
|
// terminate
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](int const ticks, lt::session&) -> bool
|
2015-12-06 06:14:30 +01:00
|
|
|
{
|
2016-06-15 19:29:54 +02:00
|
|
|
if (ticks > 500)
|
2015-12-06 06:14:30 +01:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
2016-06-15 19:29:54 +02:00
|
|
|
return false;
|
2015-12-06 06:14:30 +01:00
|
|
|
});
|
2016-06-15 19:29:54 +02:00
|
|
|
|
|
|
|
// for now, just make sure we send any suggests at all. This feature is
|
|
|
|
// experimental and it's not entirely clear it's correct or how to verify
|
|
|
|
// that it does what it's supposed to do.
|
|
|
|
// perhaps a better way would be to look at piece upload distribution over
|
|
|
|
// time
|
|
|
|
TEST_CHECK(num_suggests > 0);
|
2015-08-08 03:28:51 +02:00
|
|
|
}
|
2017-11-24 00:45:54 +01:00
|
|
|
#endif
|
2015-08-08 03:28:51 +02:00
|
|
|
|
2015-12-06 06:14:30 +01:00
|
|
|
TORRENT_TEST(utp_only)
|
2015-08-08 03:28:51 +02:00
|
|
|
{
|
2015-12-06 06:14:30 +01:00
|
|
|
setup_swarm(2, swarm_test::download
|
|
|
|
// add session
|
|
|
|
, [](lt::settings_pack& pack) {
|
|
|
|
pack.set_bool(settings_pack::enable_incoming_utp, true);
|
|
|
|
pack.set_bool(settings_pack::enable_outgoing_utp, true);
|
|
|
|
pack.set_bool(settings_pack::enable_incoming_tcp, false);
|
|
|
|
pack.set_bool(settings_pack::enable_outgoing_tcp, false);
|
|
|
|
}
|
|
|
|
// add torrent
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::add_torrent_params&) {}
|
2015-12-06 06:14:30 +01:00
|
|
|
// on alert
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::alert const*, lt::session&) {}
|
2015-12-06 06:14:30 +01:00
|
|
|
// terminate
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](int const ticks, lt::session& ses) -> bool
|
2015-12-06 06:14:30 +01:00
|
|
|
{
|
2016-03-14 04:13:12 +01:00
|
|
|
if (ticks > 80)
|
2015-12-06 06:14:30 +01:00
|
|
|
{
|
|
|
|
TEST_ERROR("timeout");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (!is_seed(ses)) return false;
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_stop_start_download(swarm_test type, bool graceful)
|
|
|
|
{
|
|
|
|
bool paused_once = false;
|
|
|
|
bool resumed = false;
|
|
|
|
|
|
|
|
setup_swarm(3, type
|
|
|
|
// add session
|
2015-12-10 07:56:33 +01:00
|
|
|
, [](lt::settings_pack& pack) {
|
|
|
|
// this test will pause and resume the torrent immediately, we expect
|
|
|
|
// to reconnect immediately too, so disable the min reconnect time
|
|
|
|
// limit.
|
|
|
|
pack.set_int(settings_pack::min_reconnect_time, 0);
|
|
|
|
}
|
2015-12-06 06:14:30 +01:00
|
|
|
// add torrent
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::add_torrent_params&) {
|
2015-12-10 07:56:33 +01:00
|
|
|
|
|
|
|
}
|
2015-12-06 06:14:30 +01:00
|
|
|
// on alert
|
2015-12-10 07:56:33 +01:00
|
|
|
, [&](lt::alert const* a, lt::session& ses) {
|
2015-12-06 06:14:30 +01:00
|
|
|
|
2017-03-27 01:19:20 +02:00
|
|
|
if (lt::alert_cast<lt::add_torrent_alert>(a))
|
2015-12-06 06:14:30 +01:00
|
|
|
add_extra_peers(ses);
|
|
|
|
|
|
|
|
if (auto tp = lt::alert_cast<lt::torrent_paused_alert>(a))
|
|
|
|
{
|
|
|
|
TEST_EQUAL(resumed, false);
|
2016-05-17 15:24:06 +02:00
|
|
|
std::printf("\nSTART\n\n");
|
2015-12-06 06:14:30 +01:00
|
|
|
tp->handle.resume();
|
|
|
|
resumed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// terminate
|
2016-06-19 01:24:27 +02:00
|
|
|
, [&](int const ticks, lt::session& ses) -> bool
|
2015-12-06 06:14:30 +01:00
|
|
|
{
|
|
|
|
if (paused_once == false)
|
|
|
|
{
|
|
|
|
auto st = get_status(ses);
|
|
|
|
const bool limit_reached = (type == swarm_test::download)
|
|
|
|
? st.total_wanted_done > st.total_wanted / 2
|
|
|
|
: st.total_payload_upload >= 3 * 16 * 1024;
|
|
|
|
|
|
|
|
if (limit_reached)
|
|
|
|
{
|
2016-05-17 15:24:06 +02:00
|
|
|
std::printf("\nSTOP\n\n");
|
2015-12-10 07:56:33 +01:00
|
|
|
auto h = ses.get_torrents()[0];
|
2017-07-27 10:37:32 +02:00
|
|
|
h.pause(graceful ? torrent_handle::graceful_pause : pause_flags_t{});
|
2015-12-06 06:14:30 +01:00
|
|
|
paused_once = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-17 15:24:06 +02:00
|
|
|
std::printf("tick: %d\n", ticks);
|
2015-12-06 06:14:30 +01:00
|
|
|
|
2018-08-12 22:58:31 +02:00
|
|
|
const int timeout = type == swarm_test::download ? 21 : 100;
|
2015-12-06 06:14:30 +01:00
|
|
|
if (ticks > timeout)
|
|
|
|
{
|
|
|
|
TEST_ERROR("timeout");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (type == swarm_test::upload) return false;
|
|
|
|
if (!is_seed(ses)) return false;
|
2016-05-17 15:24:06 +02:00
|
|
|
std::printf("completed in %d ticks\n", ticks);
|
2015-12-06 06:14:30 +01:00
|
|
|
return true;
|
|
|
|
});
|
|
|
|
|
|
|
|
TEST_EQUAL(paused_once, true);
|
|
|
|
TEST_EQUAL(resumed, true);
|
2015-08-08 03:28:51 +02:00
|
|
|
}
|
2015-11-20 06:51:58 +01:00
|
|
|
|
|
|
|
TORRENT_TEST(stop_start_download)
|
|
|
|
{
|
2015-12-06 06:14:30 +01:00
|
|
|
test_stop_start_download(swarm_test::download, false);
|
2015-11-20 06:51:58 +01:00
|
|
|
}
|
2015-12-06 06:14:30 +01:00
|
|
|
|
2015-11-20 06:51:58 +01:00
|
|
|
TORRENT_TEST(stop_start_download_graceful)
|
|
|
|
{
|
2015-12-06 06:14:30 +01:00
|
|
|
test_stop_start_download(swarm_test::download, true);
|
2015-11-20 06:51:58 +01:00
|
|
|
}
|
|
|
|
|
2015-12-10 07:56:33 +01:00
|
|
|
TORRENT_TEST(stop_start_download_graceful_no_peers)
|
|
|
|
{
|
|
|
|
bool paused_once = false;
|
|
|
|
bool resumed = false;
|
|
|
|
|
|
|
|
setup_swarm(1, swarm_test::download
|
|
|
|
// add session
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::settings_pack&) {}
|
2015-12-10 07:56:33 +01:00
|
|
|
// add torrent
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::add_torrent_params&) {}
|
2015-12-10 07:56:33 +01:00
|
|
|
// on alert
|
2016-06-19 01:24:27 +02:00
|
|
|
, [&](lt::alert const* a, lt::session&) {
|
2015-12-10 07:56:33 +01:00
|
|
|
if (auto tp = lt::alert_cast<lt::torrent_paused_alert>(a))
|
|
|
|
{
|
|
|
|
TEST_EQUAL(resumed, false);
|
2016-05-17 15:24:06 +02:00
|
|
|
std::printf("\nSTART\n\n");
|
2015-12-10 07:56:33 +01:00
|
|
|
tp->handle.resume();
|
|
|
|
resumed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// terminate
|
2016-06-19 01:24:27 +02:00
|
|
|
, [&](int const ticks, lt::session& ses) -> bool
|
2015-12-10 07:56:33 +01:00
|
|
|
{
|
|
|
|
if (paused_once == false
|
|
|
|
&& ticks == 6)
|
|
|
|
{
|
2016-05-17 15:24:06 +02:00
|
|
|
std::printf("\nSTOP\n\n");
|
2015-12-10 07:56:33 +01:00
|
|
|
auto h = ses.get_torrents()[0];
|
|
|
|
h.pause(torrent_handle::graceful_pause);
|
|
|
|
paused_once = true;
|
|
|
|
}
|
|
|
|
|
2016-05-17 15:24:06 +02:00
|
|
|
std::printf("tick: %d\n", ticks);
|
2015-12-10 07:56:33 +01:00
|
|
|
|
|
|
|
// when there's only one node (i.e. no peers) we won't ever download
|
|
|
|
// the torrent. It's just a test to make sure we still get the
|
|
|
|
// torrent_paused_alert
|
|
|
|
return ticks > 60;
|
|
|
|
});
|
|
|
|
|
|
|
|
TEST_EQUAL(paused_once, true);
|
|
|
|
TEST_EQUAL(resumed, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-20 06:51:58 +01:00
|
|
|
TORRENT_TEST(stop_start_seed)
|
|
|
|
{
|
2015-12-06 06:14:30 +01:00
|
|
|
test_stop_start_download(swarm_test::upload, false);
|
2015-11-21 04:22:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
TORRENT_TEST(stop_start_seed_graceful)
|
|
|
|
{
|
2015-12-06 06:14:30 +01:00
|
|
|
test_stop_start_download(swarm_test::upload, true);
|
2015-11-20 06:51:58 +01:00
|
|
|
}
|
|
|
|
|
2015-11-28 20:06:40 +01:00
|
|
|
TORRENT_TEST(shutdown)
|
|
|
|
{
|
2018-05-10 12:13:59 +02:00
|
|
|
setup_swarm(4, swarm_test::download
|
2015-12-06 06:14:30 +01:00
|
|
|
// add session
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::settings_pack&) {}
|
2015-12-06 06:14:30 +01:00
|
|
|
// add torrent
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::add_torrent_params&) {}
|
2015-12-06 06:14:30 +01:00
|
|
|
// on alert
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::alert const*, lt::session&) {}
|
2015-12-06 06:14:30 +01:00
|
|
|
// terminate
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](int, lt::session& ses) -> bool
|
2015-12-06 06:14:30 +01:00
|
|
|
{
|
|
|
|
if (completed_pieces(ses) == 0) return false;
|
|
|
|
TEST_EQUAL(is_seed(ses), false);
|
|
|
|
return true;
|
|
|
|
});
|
2015-11-28 20:06:40 +01:00
|
|
|
}
|
|
|
|
|
2017-06-13 10:41:26 +02:00
|
|
|
// make the delays on the connections unreasonable long, so libtorrent times-out
|
|
|
|
// the connection attempts
|
|
|
|
struct timeout_config : sim::default_config
|
|
|
|
{
|
|
|
|
virtual sim::route incoming_route(lt::address ip) override
|
|
|
|
{
|
|
|
|
auto it = m_incoming.find(ip);
|
|
|
|
if (it != m_incoming.end()) return sim::route().append(it->second);
|
|
|
|
it = m_incoming.insert(it, std::make_pair(ip, std::make_shared<queue>(
|
|
|
|
std::ref(m_sim->get_io_service())
|
|
|
|
, 1000
|
|
|
|
, lt::duration_cast<lt::time_duration>(seconds(10))
|
|
|
|
, 1000, "packet-loss modem in")));
|
|
|
|
return sim::route().append(it->second);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual sim::route outgoing_route(lt::address ip) override
|
|
|
|
{
|
|
|
|
auto it = m_outgoing.find(ip);
|
|
|
|
if (it != m_outgoing.end()) return sim::route().append(it->second);
|
|
|
|
it = m_outgoing.insert(it, std::make_pair(ip, std::make_shared<queue>(
|
|
|
|
std::ref(m_sim->get_io_service()), 1000
|
|
|
|
, lt::duration_cast<lt::time_duration>(seconds(5)), 200 * 1000, "packet-loss out")));
|
|
|
|
return sim::route().append(it->second);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// make sure peers that are no longer alive are handled correctly.
|
|
|
|
TORRENT_TEST(dead_peers)
|
|
|
|
{
|
|
|
|
int num_connect_timeout = 0;
|
|
|
|
|
|
|
|
timeout_config network_cfg;
|
|
|
|
sim::simulation sim{network_cfg};
|
|
|
|
setup_swarm(1, swarm_test::download, sim
|
|
|
|
// add session
|
|
|
|
, [](lt::settings_pack& p) {
|
|
|
|
p.set_int(settings_pack::peer_connect_timeout, 1);
|
|
|
|
}
|
|
|
|
// add torrent
|
|
|
|
, [](lt::add_torrent_params& params) {
|
|
|
|
params.peers.assign({
|
|
|
|
ep("66.66.66.60", 9999)
|
|
|
|
, ep("66.66.66.61", 9999)
|
|
|
|
, ep("66.66.66.62", 9999)
|
|
|
|
});
|
|
|
|
}
|
|
|
|
// on alert
|
|
|
|
, [&](lt::alert const* a, lt::session&) {
|
|
|
|
auto* e = alert_cast<peer_disconnected_alert>(a);
|
|
|
|
if (e
|
2017-06-18 00:18:19 +02:00
|
|
|
&& e->op == operation_t::connect
|
2017-06-13 10:41:26 +02:00
|
|
|
&& e->error == error_code(errors::timed_out))
|
|
|
|
{
|
|
|
|
++num_connect_timeout;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// terminate
|
|
|
|
, [](int t, lt::session&) -> bool
|
|
|
|
{ return t > 100; });
|
|
|
|
|
|
|
|
TEST_EQUAL(num_connect_timeout, 3);
|
|
|
|
}
|
|
|
|
|
2018-08-18 10:36:38 +02:00
|
|
|
// the address 50.0.0.1 sits behind a NAT. All of its outgoing connections have
|
|
|
|
// their source address rewritten to 51.51.51.51
|
|
|
|
struct nat_config : sim::default_config
|
|
|
|
{
|
|
|
|
nat_config() : m_nat_hop(std::make_shared<nat>(addr("51.51.51.51"))) {}
|
|
|
|
|
|
|
|
sim::route outgoing_route(lt::address ip) override
|
|
|
|
{
|
|
|
|
// This is extremely simplistic. It will simply alter the percieved source
|
|
|
|
// IP of the connecting client.
|
|
|
|
sim::route r;
|
|
|
|
if (ip == addr("50.0.0.1")) r.append(m_nat_hop);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
std::shared_ptr<nat> m_nat_hop;
|
|
|
|
};
|
|
|
|
|
|
|
|
TORRENT_TEST(self_connect)
|
|
|
|
{
|
|
|
|
int num_self_connection_disconnects = 0;
|
|
|
|
|
|
|
|
nat_config network_cfg;
|
|
|
|
sim::simulation sim{network_cfg};
|
|
|
|
|
|
|
|
setup_swarm(1, swarm_test::download, sim
|
|
|
|
// add session
|
|
|
|
, [](lt::settings_pack& p) {
|
|
|
|
p.set_bool(settings_pack::enable_incoming_utp, false);
|
|
|
|
p.set_bool(settings_pack::enable_outgoing_utp, false);
|
|
|
|
}
|
|
|
|
// add torrent
|
|
|
|
, [](lt::add_torrent_params& params) {
|
|
|
|
// this is our own address and listen port, just to make sure we get
|
|
|
|
// ourself as a peer (which normally happens one way or another in the
|
|
|
|
// wild)
|
|
|
|
params.peers.assign({ep("50.0.0.1", 6881)});
|
|
|
|
}
|
|
|
|
// on alert
|
|
|
|
, [&](lt::alert const* a, lt::session&) {
|
|
|
|
auto* e = alert_cast<peer_disconnected_alert>(a);
|
|
|
|
if (e
|
|
|
|
&& e->op == operation_t::bittorrent
|
|
|
|
&& e->error == error_code(errors::self_connection))
|
|
|
|
{
|
|
|
|
++num_self_connection_disconnects;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// terminate
|
|
|
|
, [](int t, lt::session&) -> bool
|
|
|
|
{ return t > 100; });
|
|
|
|
|
|
|
|
TEST_EQUAL(num_self_connection_disconnects, 1);
|
|
|
|
}
|
|
|
|
|
2016-03-13 08:50:37 +01:00
|
|
|
TORRENT_TEST(delete_files)
|
|
|
|
{
|
|
|
|
std::string save_path;
|
|
|
|
|
|
|
|
setup_swarm(2, swarm_test::download
|
|
|
|
// add session
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::settings_pack&) {}
|
2016-03-13 08:50:37 +01:00
|
|
|
// add torrent
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::add_torrent_params&) {}
|
2016-03-13 08:50:37 +01:00
|
|
|
// on alert
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::alert const*, lt::session&) {}
|
2016-03-13 08:50:37 +01:00
|
|
|
// terminate
|
2016-06-19 01:24:27 +02:00
|
|
|
, [&save_path](int, lt::session& ses) -> bool
|
2016-03-13 08:50:37 +01:00
|
|
|
{
|
|
|
|
if (completed_pieces(ses) == 0) return false;
|
|
|
|
|
|
|
|
auto h = ses.get_torrents()[0];
|
|
|
|
save_path = h.status().save_path;
|
|
|
|
ses.remove_torrent(h, session::delete_files);
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
|
|
|
|
// assert the file is no longer there
|
|
|
|
file_status st;
|
|
|
|
error_code ec;
|
|
|
|
stat_file(combine_path(save_path, "temporary"), &st, ec);
|
2016-05-17 15:24:06 +02:00
|
|
|
std::printf("expecting \"%s/temporary\" to NOT exist [%s | %s]\n"
|
2016-03-13 08:50:37 +01:00
|
|
|
, save_path.c_str()
|
|
|
|
, ec.category().name()
|
|
|
|
, ec.message().c_str());
|
|
|
|
TEST_EQUAL(ec, error_code(boost::system::errc::no_such_file_or_directory, system_category()));
|
|
|
|
}
|
|
|
|
|
|
|
|
TORRENT_TEST(delete_partfile)
|
|
|
|
{
|
|
|
|
std::string save_path;
|
|
|
|
setup_swarm(2, swarm_test::download
|
|
|
|
// add session
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::settings_pack&) {}
|
2016-03-13 08:50:37 +01:00
|
|
|
// add torrent
|
2016-06-19 01:24:27 +02:00
|
|
|
, [](lt::add_torrent_params&) {}
|
2016-03-13 08:50:37 +01:00
|
|
|
// on alert
|
2018-11-16 16:19:12 +01:00
|
|
|
, [](lt::alert const*, lt::session&) {}
|
2016-03-13 08:50:37 +01:00
|
|
|
// terminate
|
2016-06-19 01:24:27 +02:00
|
|
|
, [&save_path](int, lt::session& ses) -> bool
|
2016-03-13 08:50:37 +01:00
|
|
|
{
|
|
|
|
if (completed_pieces(ses) == 0) return false;
|
|
|
|
|
|
|
|
auto h = ses.get_torrents()[0];
|
|
|
|
save_path = h.status().save_path;
|
|
|
|
ses.remove_torrent(h, session::delete_partfile);
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
// assert the file *is* still there
|
|
|
|
file_status st;
|
|
|
|
error_code ec;
|
|
|
|
stat_file(combine_path(save_path, "temporary"), &st, ec);
|
2016-05-17 15:24:06 +02:00
|
|
|
std::printf("expecting \"%s/temporary\" to exist [%s]\n", save_path.c_str()
|
2016-03-13 08:50:37 +01:00
|
|
|
, ec.message().c_str());
|
|
|
|
TEST_CHECK(!ec);
|
|
|
|
}
|
|
|
|
|
2016-07-03 20:48:18 +02:00
|
|
|
TORRENT_TEST(torrent_completed_alert)
|
|
|
|
{
|
|
|
|
int num_file_completed = false;
|
|
|
|
|
|
|
|
setup_swarm(2, swarm_test::download
|
|
|
|
// add session
|
|
|
|
, [](lt::settings_pack& pack)
|
|
|
|
{
|
2020-03-31 21:48:29 +02:00
|
|
|
pack.set_int(lt::settings_pack::alert_mask, alert_category::file_progress);
|
2016-07-03 20:48:18 +02:00
|
|
|
}
|
|
|
|
// add torrent
|
|
|
|
, [](lt::add_torrent_params&) {}
|
|
|
|
// on alert
|
|
|
|
, [&](lt::alert const* a, lt::session&)
|
|
|
|
{
|
|
|
|
auto tc = alert_cast<lt::file_completed_alert>(a);
|
|
|
|
if (tc == nullptr) return;
|
|
|
|
++num_file_completed;
|
|
|
|
}
|
|
|
|
// terminate
|
|
|
|
, [](int ticks, lt::session& ses) -> bool
|
|
|
|
{
|
|
|
|
if (ticks > 80)
|
|
|
|
{
|
|
|
|
TEST_ERROR("timeout");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (!is_seed(ses)) return false;
|
|
|
|
printf("completed in %d ticks\n", ticks);
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
|
|
|
|
TEST_EQUAL(num_file_completed, 1);
|
|
|
|
}
|
|
|
|
|
2017-07-02 19:41:38 +02:00
|
|
|
TORRENT_TEST(block_uploaded_alert)
|
|
|
|
{
|
|
|
|
// blocks[piece count][number of blocks per piece] (each block's element will
|
|
|
|
// be set to true when a block_uploaded_alert alert is received for that block)
|
|
|
|
std::vector<std::vector<bool>> blocks;
|
|
|
|
|
|
|
|
setup_swarm(2, swarm_test::upload
|
|
|
|
// add session
|
|
|
|
, [](lt::settings_pack& pack)
|
|
|
|
{
|
|
|
|
pack.set_int(lt::settings_pack::alert_mask,
|
2020-03-31 21:48:29 +02:00
|
|
|
alert_category::upload | alert_category::status);
|
2017-07-02 19:41:38 +02:00
|
|
|
}
|
|
|
|
// add torrent
|
|
|
|
, [](lt::add_torrent_params&) {}
|
|
|
|
// on alert
|
|
|
|
, [&](lt::alert const* a, lt::session&) {
|
|
|
|
if (auto at = lt::alert_cast<lt::add_torrent_alert>(a))
|
|
|
|
{
|
|
|
|
// init blocks vector, MUST happen before any block_uploaded_alert alerts
|
|
|
|
int blocks_per_piece = at->handle.torrent_file()->piece_length() / 0x4000;
|
|
|
|
blocks.resize(at->handle.torrent_file()->num_pieces(), std::vector<bool>(blocks_per_piece, false));
|
|
|
|
}
|
2018-11-16 16:19:12 +01:00
|
|
|
else if (auto ua = lt::alert_cast<lt::block_uploaded_alert>(a))
|
2017-07-02 19:41:38 +02:00
|
|
|
{
|
2018-11-16 16:19:12 +01:00
|
|
|
TEST_EQUAL(blocks[static_cast<int>(ua->piece_index)][ua->block_index], false);
|
|
|
|
blocks[static_cast<int>(ua->piece_index)][ua->block_index] = true;
|
2017-07-02 19:41:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// terminate
|
|
|
|
, [](int, lt::session&) -> bool
|
|
|
|
{ return false; });
|
|
|
|
|
|
|
|
// ensure a block_uploaded_alert was received for each block in the torrent
|
|
|
|
TEST_CHECK(std::all_of(blocks.begin(), blocks.end(),
|
|
|
|
[](std::vector<bool> const& piece_row) {
|
|
|
|
return std::all_of(piece_row.begin(), piece_row.end(),
|
|
|
|
[](bool upload_alert_received) {
|
|
|
|
return upload_alert_received;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2017-02-02 15:19:17 +01:00
|
|
|
// template for testing running swarms with edge case settings
|
|
|
|
template <typename SettingsFun>
|
|
|
|
void test_settings(SettingsFun fun)
|
|
|
|
{
|
|
|
|
setup_swarm(2, swarm_test::download
|
|
|
|
// add session
|
|
|
|
, fun
|
|
|
|
// add torrent
|
2018-11-16 16:19:12 +01:00
|
|
|
, [](lt::add_torrent_params&) {}
|
2017-02-02 15:19:17 +01:00
|
|
|
// on alert
|
2018-11-16 16:19:12 +01:00
|
|
|
, [](lt::alert const*, lt::session&) {}
|
2017-02-02 15:19:17 +01:00
|
|
|
// terminate
|
|
|
|
, [](int ticks, lt::session& ses) -> bool
|
|
|
|
{
|
|
|
|
if (ticks > 80)
|
|
|
|
{
|
|
|
|
TEST_ERROR("timeout");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (!is_seed(ses)) return false;
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
TORRENT_TEST(unlimited_connections)
|
|
|
|
{
|
|
|
|
test_settings([](lt::settings_pack& pack) {
|
|
|
|
pack.set_int(settings_pack::connections_limit, std::numeric_limits<int>::max()); }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
TORRENT_TEST(default_connections_limit)
|
|
|
|
{
|
|
|
|
test_settings([](lt::settings_pack& pack) {
|
|
|
|
pack.set_int(settings_pack::connections_limit, 0); }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-02-17 02:21:29 +01:00
|
|
|
TORRENT_TEST(default_connections_limit_negative)
|
|
|
|
{
|
|
|
|
test_settings([](lt::settings_pack& pack) {
|
|
|
|
pack.set_int(settings_pack::connections_limit, -1); }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-02 15:19:17 +01:00
|
|
|
TORRENT_TEST(redundant_have)
|
|
|
|
{
|
|
|
|
test_settings([](lt::settings_pack& pack) {
|
|
|
|
pack.set_bool(settings_pack::send_redundant_have, false); }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-04-26 09:01:14 +02:00
|
|
|
#if TORRENT_ABI_VERSION == 1
|
2017-02-02 15:19:17 +01:00
|
|
|
TORRENT_TEST(lazy_bitfields)
|
|
|
|
{
|
|
|
|
test_settings([](lt::settings_pack& pack) {
|
|
|
|
pack.set_bool(settings_pack::lazy_bitfields, true); }
|
|
|
|
);
|
|
|
|
}
|
2017-03-09 00:32:58 +01:00
|
|
|
#endif
|
2017-02-02 15:19:17 +01:00
|
|
|
|
|
|
|
TORRENT_TEST(prioritize_partial_pieces)
|
|
|
|
{
|
|
|
|
test_settings([](lt::settings_pack& pack) {
|
|
|
|
pack.set_bool(settings_pack::prioritize_partial_pieces, true); }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
TORRENT_TEST(active_downloads)
|
|
|
|
{
|
|
|
|
test_settings([](lt::settings_pack& pack) {
|
|
|
|
pack.set_int(settings_pack::active_downloads, std::numeric_limits<int>::max()); }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
TORRENT_TEST(active_seeds)
|
|
|
|
{
|
|
|
|
test_settings([](lt::settings_pack& pack) {
|
|
|
|
pack.set_int(settings_pack::active_seeds, std::numeric_limits<int>::max()); }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-02-17 02:21:29 +01:00
|
|
|
TORRENT_TEST(active_seeds_negative)
|
|
|
|
{
|
|
|
|
test_settings([](lt::settings_pack& pack) {
|
|
|
|
pack.set_int(settings_pack::active_seeds, -1); }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-02-02 15:19:17 +01:00
|
|
|
TORRENT_TEST(active_limit)
|
|
|
|
{
|
|
|
|
test_settings([](lt::settings_pack& pack) {
|
|
|
|
pack.set_int(settings_pack::active_limit, std::numeric_limits<int>::max()); }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-02-17 02:21:29 +01:00
|
|
|
TORRENT_TEST(active_limit_negative)
|
|
|
|
{
|
|
|
|
test_settings([](lt::settings_pack& pack) {
|
|
|
|
pack.set_int(settings_pack::active_limit, -1); }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-02-02 15:19:17 +01:00
|
|
|
TORRENT_TEST(upload_rate_limit)
|
|
|
|
{
|
|
|
|
test_settings([](lt::settings_pack& pack) {
|
|
|
|
pack.set_int(settings_pack::upload_rate_limit, std::numeric_limits<int>::max()); }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-02-17 02:21:29 +01:00
|
|
|
TORRENT_TEST(upload_rate_limit_negative)
|
|
|
|
{
|
|
|
|
test_settings([](lt::settings_pack& pack) {
|
|
|
|
pack.set_int(settings_pack::upload_rate_limit, -1); }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-02-02 15:19:17 +01:00
|
|
|
TORRENT_TEST(download_rate_limit)
|
|
|
|
{
|
|
|
|
test_settings([](lt::settings_pack& pack) {
|
|
|
|
pack.set_int(settings_pack::download_rate_limit, std::numeric_limits<int>::max()); }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-02-17 02:21:29 +01:00
|
|
|
TORRENT_TEST(download_rate_limit_negative)
|
|
|
|
{
|
|
|
|
test_settings([](lt::settings_pack& pack) {
|
|
|
|
pack.set_int(settings_pack::download_rate_limit, -1); }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-02 15:19:17 +01:00
|
|
|
TORRENT_TEST(unchoke_slots_limit)
|
|
|
|
{
|
|
|
|
test_settings([](lt::settings_pack& pack) {
|
|
|
|
pack.set_int(settings_pack::unchoke_slots_limit, std::numeric_limits<int>::max()); }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-02-17 02:21:29 +01:00
|
|
|
TORRENT_TEST(unchoke_slots_limit_negative)
|
|
|
|
{
|
|
|
|
test_settings([](lt::settings_pack& pack) {
|
|
|
|
pack.set_int(settings_pack::unchoke_slots_limit, -1);
|
|
|
|
pack.set_int(settings_pack::choking_algorithm, settings_pack::fixed_slots_choker);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-12-05 05:39:37 +01:00
|
|
|
// TODO: add test that makes sure a torrent in graceful pause mode won't make
|
|
|
|
// outgoing connections
|
|
|
|
// TODO: add test that makes sure a torrent in graceful pause mode won't accept
|
|
|
|
// incoming connections
|
2015-12-10 07:56:33 +01:00
|
|
|
// TODO: test the different storage allocation modes
|
|
|
|
// TODO: test contiguous buffers
|
|
|
|
|
2015-12-05 05:39:37 +01:00
|
|
|
|