forked from premiere/premiere-libtorrent
clean up setup-swarm simulation utility to be more flexible to make it easier to add new tests. remove swarm_suite layer as it's not necessary anymore
This commit is contained in:
parent
5187b4279d
commit
1f453bf159
|
@ -12,7 +12,6 @@ project
|
|||
<simulator>on
|
||||
<library>/torrent//torrent/<export-extra>on
|
||||
<library>/libtorrent_test//libtorrent_test
|
||||
<source>swarm_suite.cpp
|
||||
<source>setup_swarm.cpp
|
||||
<source>setup_dht.cpp
|
||||
<source>create_torrent.cpp
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit a4b10668ea22e9328a2668baf8990b3685fe7578
|
||||
Subproject commit 8417cbee7f1a813f032c5c1ed81e1f2881af7580
|
|
@ -41,174 +41,291 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/ip_filter.hpp"
|
||||
#include "libtorrent/alert_types.hpp"
|
||||
#include <boost/bind.hpp>
|
||||
#include <fstream>
|
||||
|
||||
#include "settings.hpp"
|
||||
#include "setup_swarm.hpp"
|
||||
#include "setup_transfer.hpp" // for create_torrent
|
||||
|
||||
namespace lt = libtorrent;
|
||||
using namespace sim;
|
||||
|
||||
namespace {
|
||||
|
||||
struct swarm
|
||||
{
|
||||
swarm(int num_nodes, sim::simulation& sim, swarm_setup_provider& config)
|
||||
: m_sim(sim)
|
||||
, m_config(config)
|
||||
, m_ios(m_sim, asio::ip::address_v4::from_string("0.0.0.0"))
|
||||
, m_start_time(lt::clock_type::now())
|
||||
, m_timer(m_ios)
|
||||
, m_shutting_down(false)
|
||||
, m_tick(0)
|
||||
std::string save_path(int swarm_id, int idx)
|
||||
{
|
||||
|
||||
for (int i = 0; i < num_nodes; ++i)
|
||||
{
|
||||
// create a new io_service
|
||||
char ep[30];
|
||||
snprintf(ep, sizeof(ep), "50.0.%d.%d", (i + 1) >> 8, (i + 1) & 0xff);
|
||||
m_io_service.push_back(boost::make_shared<sim::asio::io_service>(
|
||||
boost::ref(m_sim), asio::ip::address_v4::from_string(ep)));
|
||||
|
||||
lt::settings_pack pack = m_config.add_session(i);
|
||||
|
||||
boost::shared_ptr<lt::session> ses =
|
||||
boost::make_shared<lt::session>(pack
|
||||
, boost::ref(*m_io_service.back()));
|
||||
m_nodes.push_back(ses);
|
||||
m_config.on_session_added(i, *ses);
|
||||
|
||||
// reserve a slot in here for when the torrent gets added (notified by
|
||||
// an alert)
|
||||
m_torrents.push_back(lt::torrent_handle());
|
||||
|
||||
lt::add_torrent_params params = m_config.add_torrent(i);
|
||||
if (!params.save_path.empty())
|
||||
ses->async_add_torrent(params);
|
||||
|
||||
ses->set_alert_notify([i,this] {
|
||||
// this function is called inside libtorrent and we cannot perform work
|
||||
// immediately in it. We have to notify the outside to pull all the alerts
|
||||
m_io_service[i]->post(boost::bind(&swarm::on_alerts, this, i));
|
||||
});
|
||||
}
|
||||
|
||||
m_timer.expires_from_now(lt::seconds(1));
|
||||
m_timer.async_wait(boost::bind(&swarm::on_tick, this, _1));
|
||||
char path[200];
|
||||
snprintf(path, sizeof(path), "swarm-%04d-peer-%02d"
|
||||
, swarm_id, idx);
|
||||
return path;
|
||||
}
|
||||
|
||||
void on_tick(lt::error_code const& ec)
|
||||
int transfer_rate(lt::address ip)
|
||||
{
|
||||
if (ec || m_shutting_down) return;
|
||||
|
||||
++m_tick;
|
||||
|
||||
if (m_config.tick(m_tick))
|
||||
{
|
||||
terminate();
|
||||
return;
|
||||
}
|
||||
|
||||
m_timer.expires_from_now(lt::seconds(1));
|
||||
m_timer.async_wait(boost::bind(&swarm::on_tick, this, _1));
|
||||
// in order to get a heterogeneous network, the last digit in the IP
|
||||
// address determines the latency to that node as well as upload and
|
||||
// download rates.
|
||||
int last_digit;
|
||||
if (ip.is_v4())
|
||||
last_digit = ip.to_v4().to_bytes()[3];
|
||||
else
|
||||
last_digit = ip.to_v6().to_bytes()[15];
|
||||
return (last_digit + 4) * 5;
|
||||
}
|
||||
|
||||
void on_alerts(int session_index)
|
||||
{
|
||||
std::vector<lt::alert*> alerts;
|
||||
|
||||
lt::session* ses = m_nodes[session_index].get();
|
||||
|
||||
// when shutting down, we may have destructed the session
|
||||
if (ses == NULL) return;
|
||||
|
||||
bool term = false;
|
||||
ses->pop_alerts(&alerts);
|
||||
|
||||
for (lt::alert* a : alerts)
|
||||
{
|
||||
lt::time_duration d = a->timestamp() - m_start_time;
|
||||
boost::uint32_t millis = lt::duration_cast<lt::milliseconds>(d).count();
|
||||
printf("%4d.%03d: [%02d] %s\n", millis / 1000, millis % 1000,
|
||||
session_index, a->message().c_str());
|
||||
|
||||
// if a torrent was added save the torrent handle
|
||||
if (lt::add_torrent_alert* at = lt::alert_cast<lt::add_torrent_alert>(a))
|
||||
{
|
||||
lt::torrent_handle h = at->handle;
|
||||
m_torrents[session_index] = h;
|
||||
|
||||
// let the config object have a chance to set up the torrent
|
||||
m_config.on_torrent_added(session_index, h);
|
||||
|
||||
// now, connect this torrent to all the others in the swarm
|
||||
for (int k = 0; k < session_index; ++k)
|
||||
{
|
||||
char ep[30];
|
||||
snprintf(ep, sizeof(ep), "50.0.%d.%d", (k + 1) >> 8, (k + 1) & 0xff);
|
||||
h.connect_peer(lt::tcp::endpoint(
|
||||
lt::address_v4::from_string(ep), 6881));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_config.on_alert(a, session_index, m_torrents
|
||||
, *m_nodes[session_index]))
|
||||
term = true;
|
||||
}
|
||||
|
||||
if (term) terminate();
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
m_sim.run();
|
||||
printf("simulation::run() returned\n");
|
||||
}
|
||||
|
||||
void terminate()
|
||||
{
|
||||
printf("TERMINATING\n");
|
||||
|
||||
m_config.on_exit(m_torrents);
|
||||
|
||||
// terminate simulation
|
||||
for (int i = 0; i < int(m_nodes.size()); ++i)
|
||||
{
|
||||
m_zombies.push_back(m_nodes[i]->abort());
|
||||
m_nodes[i].reset();
|
||||
}
|
||||
|
||||
m_shutting_down = true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
sim::simulation& m_sim;
|
||||
swarm_setup_provider& m_config;
|
||||
|
||||
asio::io_service m_ios;
|
||||
lt::time_point m_start_time;
|
||||
|
||||
std::vector<boost::shared_ptr<lt::session> > m_nodes;
|
||||
std::vector<boost::shared_ptr<sim::asio::io_service> > m_io_service;
|
||||
std::vector<lt::torrent_handle> m_torrents;
|
||||
std::vector<lt::session_proxy> m_zombies;
|
||||
lt::deadline_timer m_timer;
|
||||
bool m_shutting_down;
|
||||
int m_tick;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void setup_swarm(int num_nodes, swarm_setup_provider& cfg)
|
||||
typedef sim::chrono::high_resolution_clock::duration duration;
|
||||
using sim::chrono::milliseconds;
|
||||
|
||||
sim::route dsl_config::incoming_route(asio::ip::address ip)
|
||||
{
|
||||
sim::default_config network_cfg;
|
||||
int rate = transfer_rate(ip);
|
||||
|
||||
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())
|
||||
, rate * 1000
|
||||
, lt::duration_cast<duration>(milliseconds(rate / 2))
|
||||
, 200 * 1000, "DSL modem in")));
|
||||
return sim::route().append(it->second);
|
||||
}
|
||||
|
||||
sim::route dsl_config::outgoing_route(asio::ip::address ip)
|
||||
{
|
||||
int rate = transfer_rate(ip);
|
||||
|
||||
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()), rate * 1000
|
||||
, lt::duration_cast<duration>(milliseconds(rate / 2)), 200 * 1000, "DSL modem out")));
|
||||
return sim::route().append(it->second);
|
||||
}
|
||||
|
||||
void add_extra_peers(lt::session* ses)
|
||||
{
|
||||
auto handles = ses->get_torrents();
|
||||
TEST_EQUAL(handles.size(), 1);
|
||||
auto h = handles[0];
|
||||
|
||||
for (int i = 0; i < 30; ++i)
|
||||
{
|
||||
char ep[30];
|
||||
snprintf(ep, sizeof(ep), "60.0.0.%d", i + 1);
|
||||
h.connect_peer(lt::tcp::endpoint(
|
||||
lt::address_v4::from_string(ep), 6881));
|
||||
}
|
||||
}
|
||||
|
||||
lt::torrent_status get_status(lt::session* ses)
|
||||
{
|
||||
auto handles = ses->get_torrents();
|
||||
TEST_EQUAL(handles.size(), 1);
|
||||
auto h = handles[0];
|
||||
return h.status();
|
||||
}
|
||||
|
||||
bool is_seed(lt::session* ses)
|
||||
{
|
||||
auto handles = ses->get_torrents();
|
||||
TEST_EQUAL(handles.size(), 1);
|
||||
auto h = handles[0];
|
||||
return h.status().is_seeding;
|
||||
}
|
||||
|
||||
int completed_pieces(lt::session* ses)
|
||||
{
|
||||
auto handles = ses->get_torrents();
|
||||
TEST_EQUAL(handles.size(), 1);
|
||||
auto h = handles[0];
|
||||
return h.status().num_pieces;
|
||||
}
|
||||
|
||||
void setup_swarm(int num_nodes
|
||||
, swarm_test type
|
||||
, std::function<void(lt::settings_pack&)> new_session
|
||||
, std::function<void(lt::add_torrent_params&)> add_torrent
|
||||
, std::function<void(lt::alert const*, lt::session*)> on_alert
|
||||
, std::function<int(int, lt::session*)> terminate)
|
||||
{
|
||||
dsl_config network_cfg;
|
||||
sim::simulation sim{network_cfg};
|
||||
setup_swarm(num_nodes, sim, cfg);
|
||||
setup_swarm(num_nodes, type, sim, new_session, add_torrent, on_alert, terminate);
|
||||
}
|
||||
|
||||
void setup_swarm(int num_nodes, sim::simulation& sim, swarm_setup_provider& cfg)
|
||||
void setup_swarm(int num_nodes
|
||||
, swarm_test type
|
||||
, sim::simulation& sim
|
||||
, std::function<void(lt::settings_pack&)> new_session
|
||||
, std::function<void(lt::add_torrent_params&)> add_torrent
|
||||
, std::function<void(lt::alert const*, lt::session*)> on_alert
|
||||
, std::function<int(int, lt::session*)> terminate)
|
||||
{
|
||||
swarm s(num_nodes, sim, cfg);
|
||||
s.run();
|
||||
asio::io_service ios(sim, asio::ip::address_v4::from_string("0.0.0.0"));
|
||||
lt::time_point start_time(lt::clock_type::now());
|
||||
|
||||
std::vector<boost::shared_ptr<lt::session> > nodes;
|
||||
std::vector<boost::shared_ptr<sim::asio::io_service> > io_service;
|
||||
std::vector<lt::session_proxy> zombies;
|
||||
lt::deadline_timer timer(ios);
|
||||
|
||||
lt::error_code ec;
|
||||
int swarm_id = test_counter();
|
||||
std::string path = save_path(swarm_id, 0);
|
||||
lt::create_directory(path, ec);
|
||||
if (ec) fprintf(stderr, "failed to create directory: \"%s\": %s\n"
|
||||
, path.c_str(), ec.message().c_str());
|
||||
std::ofstream file(lt::combine_path(path, "temporary").c_str());
|
||||
auto ti = ::create_torrent(&file, "temporary", 0x4000, 9, false);
|
||||
file.close();
|
||||
|
||||
// session 0 is the one we're testing. The others provide the scaffolding
|
||||
// it's either a downloader or a seed
|
||||
for (int i = 0; i < num_nodes; ++i)
|
||||
{
|
||||
// create a new io_service
|
||||
char ep[30];
|
||||
snprintf(ep, sizeof(ep), "50.0.%d.%d", (i + 1) >> 8, (i + 1) & 0xff);
|
||||
io_service.push_back(boost::make_shared<sim::asio::io_service>(
|
||||
boost::ref(sim), asio::ip::address_v4::from_string(ep)));
|
||||
|
||||
lt::settings_pack pack = settings();
|
||||
|
||||
// make sure the sessions have different peer ids
|
||||
lt::peer_id pid;
|
||||
std::generate(&pid[0], &pid[0] + 20, &random_byte);
|
||||
pack.set_str(lt::settings_pack::peer_fingerprint, pid.to_string());
|
||||
if (i == 0) new_session(pack);
|
||||
|
||||
boost::shared_ptr<lt::session> ses =
|
||||
boost::make_shared<lt::session>(pack
|
||||
, boost::ref(*io_service.back()));
|
||||
nodes.push_back(ses);
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
// the other sessions should not talk to each other
|
||||
lt::ip_filter filter;
|
||||
filter.add_rule(lt::address::from_string("0.0.0.0")
|
||||
, lt::address::from_string("255.255.255.255"), lt::ip_filter::blocked);
|
||||
|
||||
filter.add_rule(lt::address::from_string("50.0.0.1")
|
||||
, lt::address::from_string("50.0.0.1"), 0);
|
||||
|
||||
ses->set_ip_filter(filter);
|
||||
}
|
||||
|
||||
lt::add_torrent_params p;
|
||||
p.flags &= ~lt::add_torrent_params::flag_paused;
|
||||
p.flags &= ~lt::add_torrent_params::flag_auto_managed;
|
||||
|
||||
if (type == swarm_test::download)
|
||||
{
|
||||
// in download tests, session 0 is a downloader and every other session
|
||||
// is a seed. save path 0 is where the files are, so that's for seeds
|
||||
p.save_path = save_path(swarm_id, i > 0 ? 0 : 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// in seed tests, session 0 is a seed and every other session
|
||||
// a downloader. save path 0 is where the files are, so that's for seeds
|
||||
p.save_path = save_path(swarm_id, i);
|
||||
}
|
||||
p.ti = ti;
|
||||
if (i == 0) add_torrent(p);
|
||||
ses->async_add_torrent(p);
|
||||
|
||||
ses->set_alert_notify([&, i]() {
|
||||
// this function is called inside libtorrent and we cannot perform work
|
||||
// immediately in it. We have to notify the outside to pull all the alerts
|
||||
io_service[i]->post([&,i]()
|
||||
{
|
||||
lt::session* ses = nodes[i].get();
|
||||
|
||||
// when shutting down, we may have destructed the session
|
||||
if (ses == nullptr) return;
|
||||
|
||||
std::vector<lt::alert*> alerts;
|
||||
ses->pop_alerts(&alerts);
|
||||
|
||||
// to debug the sessions not under test, comment out the following
|
||||
// line
|
||||
if (i != 0) return;
|
||||
|
||||
for (lt::alert* a : alerts)
|
||||
{
|
||||
|
||||
// only print alerts from the session under test
|
||||
lt::time_duration d = a->timestamp() - start_time;
|
||||
boost::uint32_t millis = lt::duration_cast<lt::milliseconds>(d).count();
|
||||
printf("%4d.%03d: %s\n", millis / 1000, millis % 1000
|
||||
, a->message().c_str());
|
||||
|
||||
// if a torrent was added save the torrent handle
|
||||
if (lt::add_torrent_alert* at = lt::alert_cast<lt::add_torrent_alert>(a))
|
||||
{
|
||||
lt::torrent_handle h = at->handle;
|
||||
|
||||
// now, connect this torrent to all the others in the swarm
|
||||
for (int k = 0; k < num_nodes; ++k)
|
||||
{
|
||||
char ep[30];
|
||||
snprintf(ep, sizeof(ep), "50.0.%d.%d", (k + 1) >> 8, (k + 1) & 0xff);
|
||||
h.connect_peer(lt::tcp::endpoint(
|
||||
lt::address_v4::from_string(ep), 6881));
|
||||
}
|
||||
}
|
||||
|
||||
on_alert(a, ses);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
int tick = 0;
|
||||
std::function<void(lt::error_code const&)> on_tick
|
||||
= [&](lt::error_code const& ec)
|
||||
{
|
||||
if (ec) return;
|
||||
|
||||
bool shut_down = terminate(tick, nodes[0].get());
|
||||
|
||||
if (type == swarm_test::upload)
|
||||
{
|
||||
shut_down |= std::all_of(nodes.begin() + 1, nodes.end()
|
||||
, [](boost::shared_ptr<lt::session> const& s)
|
||||
{ return is_seed(s.get()); });
|
||||
|
||||
if (tick > 70 * (num_nodes - 1) && !shut_down)
|
||||
{
|
||||
TEST_ERROR("seeding failed!");
|
||||
}
|
||||
}
|
||||
|
||||
if (shut_down)
|
||||
{
|
||||
printf("TERMINATING\n");
|
||||
|
||||
// terminate simulation
|
||||
for (int i = 0; i < int(nodes.size()); ++i)
|
||||
{
|
||||
zombies.push_back(nodes[i]->abort());
|
||||
nodes[i].reset();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
++tick;
|
||||
|
||||
timer.expires_from_now(lt::seconds(1));
|
||||
timer.async_wait(on_tick);
|
||||
};
|
||||
|
||||
timer.expires_from_now(lt::seconds(1));
|
||||
timer.async_wait(on_tick);
|
||||
|
||||
sim.run();
|
||||
}
|
||||
|
||||
|
|
|
@ -30,54 +30,52 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
*/
|
||||
|
||||
#include "libtorrent/io_service.hpp"
|
||||
#include "libtorrent/settings_pack.hpp"
|
||||
#include "libtorrent/add_torrent_params.hpp"
|
||||
#include "libtorrent/torrent_handle.hpp"
|
||||
#include "simulator/simulator.hpp"
|
||||
#include "libtorrent/address.hpp"
|
||||
#include <functional>
|
||||
|
||||
#ifndef TORRENT_SWARM_SETUP_PROVIDER_HPP_INCLUDED
|
||||
#define TORRENT_SWARM_SETUP_PROVIDER_HPP_INCLUDED
|
||||
#ifndef TORRENT_SETUP_SWARM_HPP_INCLUDED
|
||||
#define TORRENT_SETUP_SWARM_HPP_INCLUDED
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
class alert;
|
||||
class session;
|
||||
struct add_torrent_params;
|
||||
struct settings_pack;
|
||||
struct torrent_handle;
|
||||
struct torrent_status;
|
||||
}
|
||||
|
||||
struct swarm_setup_provider
|
||||
namespace lt = libtorrent;
|
||||
|
||||
enum class swarm_test { download, upload };
|
||||
|
||||
void setup_swarm(int num_nodes
|
||||
, swarm_test type
|
||||
, std::function<void(lt::settings_pack&)> new_session
|
||||
, std::function<void(lt::add_torrent_params&)> add_torrent
|
||||
, std::function<void(lt::alert const*, lt::session*)> on_alert
|
||||
, std::function<int(int, lt::session*)> terminate);
|
||||
|
||||
void setup_swarm(int num_nodes
|
||||
, swarm_test type
|
||||
, sim::simulation& sim
|
||||
, std::function<void(lt::settings_pack&)> new_session
|
||||
, std::function<void(lt::add_torrent_params&)> add_torrent
|
||||
, std::function<void(lt::alert const*, lt::session*)> on_alert
|
||||
, std::function<int(int, lt::session*)> terminate);
|
||||
|
||||
bool is_seed(lt::session* ses);
|
||||
int completed_pieces(lt::session* ses);
|
||||
void add_extra_peers(lt::session* ses);
|
||||
lt::torrent_status get_status(lt::session* ses);
|
||||
|
||||
struct dsl_config : sim::default_config
|
||||
{
|
||||
// can be used to check expected end conditions
|
||||
virtual void on_exit(std::vector<libtorrent::torrent_handle> const& torrents) {}
|
||||
|
||||
// called for every alert. if the simulation is done, return true
|
||||
virtual bool on_alert(libtorrent::alert const* alert
|
||||
, int session_idx
|
||||
, std::vector<libtorrent::torrent_handle> const& handles
|
||||
, libtorrent::session& ses) { return false; }
|
||||
|
||||
// called for every torrent that's added (and every session that's started).
|
||||
// this is useful to give every session a unique save path and to make some
|
||||
// sessions seeds and others downloaders
|
||||
virtual libtorrent::add_torrent_params add_torrent(int idx) = 0;
|
||||
|
||||
// called for every torrent that's added once the torrent_handle comes back.
|
||||
// can be used to set options on the torrent
|
||||
virtual void on_torrent_added(int idx, libtorrent::torrent_handle h) {}
|
||||
|
||||
// called for every session that's created. Leaves an opportunity for the
|
||||
// configuration object to add extensions etc.
|
||||
virtual void on_session_added(int idx, libtorrent::session& ses) {}
|
||||
|
||||
// called for every session that's added
|
||||
virtual libtorrent::settings_pack add_session(int idx) = 0;
|
||||
|
||||
// called once a second. if it returns true, the simulation is terminated
|
||||
// by default, simulations end after 200 seconds
|
||||
virtual bool tick(int t) { return t > 200; }
|
||||
virtual sim::route incoming_route(lt::address ip) override;
|
||||
virtual sim::route outgoing_route(lt::address ip) override;
|
||||
};
|
||||
|
||||
void setup_swarm(int num_nodes, swarm_setup_provider& config);
|
||||
void setup_swarm(int num_nodes, sim::simulation& sim, swarm_setup_provider& config);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2015, 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.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TORRENT_SWARM_CONFIG_HPP_INCLUDED
|
||||
#define TORRENT_SWARM_CONFIG_HPP_INCLUDED
|
||||
|
||||
#include "libtorrent/torrent_handle.hpp"
|
||||
#include "libtorrent/add_torrent_params.hpp"
|
||||
#include "libtorrent/time.hpp"
|
||||
#include "libtorrent/torrent_status.hpp"
|
||||
#include "setup_swarm.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "setup_transfer.hpp" // for create_torrent
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
using namespace libtorrent;
|
||||
namespace lt = libtorrent;
|
||||
|
||||
struct swarm_config : swarm_setup_provider
|
||||
{
|
||||
swarm_config()
|
||||
: m_start_time(lt::clock_type::now())
|
||||
{
|
||||
m_swarm_id = test_counter();
|
||||
|
||||
error_code ec;
|
||||
std::string path = save_path(0);
|
||||
create_directory(path, ec);
|
||||
if (ec) fprintf(stderr, "failed to create directory: \"%s\": %s\n"
|
||||
, path.c_str(), ec.message().c_str());
|
||||
std::ofstream file(combine_path(path, "temporary").c_str());
|
||||
m_ti = ::create_torrent(&file, "temporary", 0x4000, 9, false);
|
||||
file.close();
|
||||
}
|
||||
|
||||
virtual void on_exit(std::vector<torrent_handle> const& torrents) override
|
||||
{
|
||||
TEST_CHECK(torrents.size() > 0);
|
||||
for (int i = 0; i < int(torrents.size()); ++i)
|
||||
{
|
||||
torrent_status st = torrents[i].status();
|
||||
TEST_CHECK(st.is_seeding);
|
||||
TEST_CHECK(st.total_upload > 0 || st.total_download > 0);
|
||||
}
|
||||
}
|
||||
|
||||
// called for every alert. if the simulation is done, return true
|
||||
virtual bool on_alert(libtorrent::alert const* alert
|
||||
, int session_idx
|
||||
, std::vector<libtorrent::torrent_handle> const& torrents
|
||||
, libtorrent::session& ses) override
|
||||
{
|
||||
if (torrents.empty()) return false;
|
||||
|
||||
bool all_are_seeding = true;
|
||||
for (int i = 0; i < int(torrents.size()); ++i)
|
||||
{
|
||||
if (torrents[i].status().is_seeding)
|
||||
continue;
|
||||
|
||||
all_are_seeding = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// if all torrents are seeds, terminate the simulation, we're done
|
||||
return all_are_seeding;
|
||||
}
|
||||
|
||||
// called for every torrent that's added (and every session that's started).
|
||||
// this is useful to give every session a unique save path and to make some
|
||||
// sessions seeds and others downloaders
|
||||
virtual libtorrent::add_torrent_params add_torrent(int idx) override
|
||||
{
|
||||
add_torrent_params p;
|
||||
p.flags &= ~add_torrent_params::flag_paused;
|
||||
p.flags &= ~add_torrent_params::flag_auto_managed;
|
||||
|
||||
p.ti = m_ti;
|
||||
|
||||
p.save_path = save_path(idx);
|
||||
return p;
|
||||
}
|
||||
|
||||
virtual std::string save_path(int idx) const
|
||||
{
|
||||
char path[200];
|
||||
snprintf(path, sizeof(path), "swarm-%04d-peer-%02d"
|
||||
, m_swarm_id, idx);
|
||||
return path;
|
||||
}
|
||||
|
||||
// called for every session that's added
|
||||
virtual libtorrent::settings_pack add_session(int idx) override
|
||||
{
|
||||
settings_pack pack = settings();
|
||||
|
||||
// make sure the sessions have different peer ids
|
||||
lt::peer_id pid;
|
||||
std::generate(&pid[0], &pid[0] + 20, &random_byte);
|
||||
pack.set_str(lt::settings_pack::peer_fingerprint, pid.to_string());
|
||||
|
||||
return pack;
|
||||
}
|
||||
|
||||
protected:
|
||||
int m_swarm_id;
|
||||
lt::time_point m_start_time;
|
||||
boost::shared_ptr<libtorrent::torrent_info> m_ti;
|
||||
};
|
||||
|
||||
#endif // TORRENT_SWARM_CONFIG_HPP_INCLUDED
|
||||
|
|
@ -1,238 +0,0 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2015, 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.
|
||||
|
||||
*/
|
||||
|
||||
#include "libtorrent/session.hpp"
|
||||
#include "libtorrent/settings_pack.hpp"
|
||||
#include "libtorrent/alert_types.hpp"
|
||||
#include "libtorrent/random.hpp"
|
||||
#include "libtorrent/time.hpp" // for clock_type
|
||||
|
||||
#include "test.hpp"
|
||||
#include "setup_swarm.hpp"
|
||||
#include "swarm_suite.hpp"
|
||||
#include "swarm_config.hpp"
|
||||
|
||||
using namespace libtorrent;
|
||||
namespace lt = libtorrent;
|
||||
|
||||
struct test_swarm_config : swarm_config
|
||||
{
|
||||
test_swarm_config(int flags)
|
||||
: swarm_config()
|
||||
, m_flags(flags)
|
||||
, m_paused_once(false)
|
||||
, m_resumed_once(false)
|
||||
{}
|
||||
|
||||
virtual bool tick(int t) override
|
||||
{
|
||||
return (m_flags & early_shutdown) ? t >= 1 : t > 200;
|
||||
}
|
||||
|
||||
virtual void on_exit(std::vector<torrent_handle> const& torrents) override
|
||||
{
|
||||
if ((m_flags & early_shutdown) == 0)
|
||||
{
|
||||
swarm_config::on_exit(torrents);
|
||||
}
|
||||
|
||||
// if we stopped and started again, we loose some time and need a bit
|
||||
// more slack for completion
|
||||
if (m_flags & stop_start_seed)
|
||||
{
|
||||
TEST_CHECK(lt::clock_type::now() < m_start_time + lt::milliseconds(4700));
|
||||
}
|
||||
else if (m_flags & stop_start_download)
|
||||
{
|
||||
TEST_CHECK(lt::clock_type::now() < m_start_time + lt::milliseconds(2800));
|
||||
}
|
||||
else
|
||||
{
|
||||
TEST_CHECK(lt::clock_type::now() < m_start_time + lt::milliseconds(2100));
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool on_alert(libtorrent::alert const* alert
|
||||
, int session_idx
|
||||
, std::vector<libtorrent::torrent_handle> const& torrents
|
||||
, libtorrent::session& ses) override
|
||||
{
|
||||
if (((m_flags & stop_start_download)
|
||||
|| (m_flags & stop_start_seed))
|
||||
&& m_paused_once == false)
|
||||
{
|
||||
torrent_status st_seed = torrents[0].status();
|
||||
torrent_status st_dl = torrents[1].status();
|
||||
|
||||
int flags = 0;
|
||||
if (m_flags & graceful_pause)
|
||||
flags = torrent_handle::graceful_pause;
|
||||
|
||||
if (m_flags & stop_start_download)
|
||||
{
|
||||
if (st_dl.total_wanted_done > st_dl.total_wanted / 2
|
||||
&& st_dl.paused == false)
|
||||
{
|
||||
m_paused_once = true;
|
||||
torrents[1].auto_managed(false);
|
||||
torrents[1].pause(flags);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_flags & stop_start_seed)
|
||||
{
|
||||
if (st_dl.total_wanted_done > st_dl.total_wanted / 2
|
||||
&& st_seed.paused == false)
|
||||
{
|
||||
m_paused_once = true;
|
||||
torrents[0].auto_managed(false);
|
||||
torrents[0].pause(flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (alert_cast<torrent_paused_alert>(alert))
|
||||
{
|
||||
TEST_EQUAL(m_resumed_once, false);
|
||||
|
||||
if (m_flags & stop_start_download)
|
||||
{
|
||||
torrents[1].resume();
|
||||
m_resumed_once = true;
|
||||
}
|
||||
|
||||
if (m_flags & stop_start_seed)
|
||||
{
|
||||
torrents[0].resume();
|
||||
m_resumed_once = true;
|
||||
}
|
||||
}
|
||||
|
||||
return swarm_config::on_alert(alert, session_idx, torrents, ses);
|
||||
}
|
||||
|
||||
virtual void on_torrent_added(int session_index, torrent_handle h) override
|
||||
{
|
||||
if (m_flags & add_extra_peers)
|
||||
{
|
||||
for (int i = 0; i < 30; ++i)
|
||||
{
|
||||
char ep[30];
|
||||
snprintf(ep, sizeof(ep), "60.0.0.%d", i + 1);
|
||||
h.connect_peer(lt::tcp::endpoint(
|
||||
lt::address_v4::from_string(ep), 6881));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// called for every torrent that's added (and every session that's started).
|
||||
// this is useful to give every session a unique save path and to make some
|
||||
// sessions seeds and others downloaders
|
||||
virtual libtorrent::add_torrent_params add_torrent(int idx) override
|
||||
{
|
||||
add_torrent_params p = swarm_config::add_torrent(idx);
|
||||
|
||||
// only the first session is set to seed mode
|
||||
if (idx == 0)
|
||||
{
|
||||
if (m_flags & seed_mode) p.flags |= add_torrent_params::flag_seed_mode;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
// called for every session that's added
|
||||
virtual libtorrent::settings_pack add_session(int idx) override
|
||||
{
|
||||
settings_pack pack = swarm_config::add_session(idx);
|
||||
|
||||
pack.set_bool(settings_pack::strict_super_seeding, m_flags & strict_super_seeding);
|
||||
|
||||
if (m_flags & suggest_read_cache)
|
||||
pack.set_int(settings_pack::suggest_mode, settings_pack::suggest_read_cache);
|
||||
else
|
||||
pack.set_int(settings_pack::suggest_mode, 0);
|
||||
|
||||
if (m_flags & explicit_cache)
|
||||
{
|
||||
pack.set_bool(settings_pack::explicit_read_cache, true);
|
||||
pack.set_int(settings_pack::explicit_cache_interval, 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
pack.set_bool(settings_pack::explicit_read_cache, false);
|
||||
}
|
||||
|
||||
if (m_flags & utp_only)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
pack.set_bool(settings_pack::enable_incoming_utp, false);
|
||||
pack.set_bool(settings_pack::enable_outgoing_utp, false);
|
||||
pack.set_bool(settings_pack::enable_incoming_tcp, true);
|
||||
pack.set_bool(settings_pack::enable_outgoing_tcp, true);
|
||||
}
|
||||
|
||||
pack.set_int(settings_pack::alert_mask, alert::all_categories);
|
||||
return pack;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_flags;
|
||||
bool m_paused_once;
|
||||
bool m_resumed_once;
|
||||
};
|
||||
|
||||
void simulate_swarm(int flags)
|
||||
{
|
||||
fprintf(stderr, "\n\n ==== TEST SWARM === %s%s%s%s%s%s%s%s%s%s===\n\n\n"
|
||||
, (flags & super_seeding) ? "super-seeding ": ""
|
||||
, (flags & strict_super_seeding) ? "strict-super-seeding ": ""
|
||||
, (flags & seed_mode) ? "seed-mode ": ""
|
||||
, (flags & time_critical) ? "time-critical ": ""
|
||||
, (flags & suggest_read_cache) ? "suggest-read-cache ": ""
|
||||
, (flags & explicit_cache) ? "explicit-cache ": ""
|
||||
, (flags & utp_only) ? "utp-only": ""
|
||||
, (flags & stop_start_download) ? "stop-start-download ": ""
|
||||
, (flags & stop_start_seed) ? "stop-start-seed ": ""
|
||||
, (flags & stop_start_seed) ? "graceful-pause ": ""
|
||||
);
|
||||
|
||||
test_swarm_config cfg(flags);
|
||||
setup_swarm(2, cfg);
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2014, 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.
|
||||
|
||||
*/
|
||||
|
||||
#include "test.hpp"
|
||||
|
||||
enum test_flags_t
|
||||
{
|
||||
super_seeding = 1,
|
||||
strict_super_seeding = 2,
|
||||
seed_mode = 4,
|
||||
time_critical = 8,
|
||||
suggest_read_cache = 16,
|
||||
explicit_cache = 32,
|
||||
utp_only = 64,
|
||||
stop_start_download = 128,
|
||||
stop_start_seed = 256,
|
||||
graceful_pause = 1024,
|
||||
add_extra_peers = 2048,
|
||||
early_shutdown = 4096
|
||||
};
|
||||
|
||||
void EXPORT simulate_swarm(int flags = 0);
|
||||
|
|
@ -30,18 +30,44 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
*/
|
||||
|
||||
#include "swarm_suite.hpp"
|
||||
#include "setup_swarm.hpp"
|
||||
#include "libtorrent/add_torrent_params.hpp"
|
||||
#include "libtorrent/settings_pack.hpp"
|
||||
#include "test.hpp"
|
||||
|
||||
TORRENT_TEST(plain)
|
||||
using namespace libtorrent;
|
||||
|
||||
TORRENT_TEST(super_seeding)
|
||||
{
|
||||
// with super seeding
|
||||
simulate_swarm(super_seeding);
|
||||
setup_swarm(5, swarm_test::upload
|
||||
// add session
|
||||
, [](lt::settings_pack& pack) {}
|
||||
// add torrent
|
||||
, [](lt::add_torrent_params& params) {
|
||||
params.flags |= add_torrent_params::flag_super_seeding;
|
||||
}
|
||||
// on alert
|
||||
, [](lt::alert const* a, lt::session* ses) {}
|
||||
// terminate
|
||||
, [](int ticks, lt::session* ses) -> bool
|
||||
{ return true; });
|
||||
}
|
||||
|
||||
TORRENT_TEST(strict)
|
||||
TORRENT_TEST(strict_super_seeding)
|
||||
{
|
||||
// with strict super seeding
|
||||
simulate_swarm(super_seeding | strict_super_seeding);
|
||||
setup_swarm(5, swarm_test::upload
|
||||
// add session
|
||||
, [](lt::settings_pack& pack) {
|
||||
pack.set_bool(settings_pack::strict_super_seeding, true);
|
||||
}
|
||||
// add torrent
|
||||
, [](lt::add_torrent_params& params) {
|
||||
params.flags |= add_torrent_params::flag_super_seeding;
|
||||
}
|
||||
// on alert
|
||||
, [](lt::alert const* a, lt::session* ses) {}
|
||||
// terminate
|
||||
, [](int ticks, lt::session* ses) -> bool
|
||||
{ return true; });
|
||||
}
|
||||
|
||||
|
|
|
@ -30,68 +30,230 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
*/
|
||||
|
||||
#include "swarm_suite.hpp"
|
||||
#include "setup_swarm.hpp"
|
||||
#include "test.hpp"
|
||||
#include "libtorrent/alert.hpp"
|
||||
#include "libtorrent/alert_types.hpp"
|
||||
#include "libtorrent/session.hpp"
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
TORRENT_TEST(seed_mode)
|
||||
{
|
||||
// with seed mode
|
||||
simulate_swarm(seed_mode);
|
||||
setup_swarm(2, swarm_test::upload
|
||||
// add session
|
||||
, [](lt::settings_pack& pack) {}
|
||||
// add torrent
|
||||
, [](lt::add_torrent_params& params) {
|
||||
params.flags |= add_torrent_params::flag_seed_mode;
|
||||
}
|
||||
// on alert
|
||||
, [](lt::alert const* a, lt::session* ses) {}
|
||||
// terminate
|
||||
, [](int ticks, lt::session* ses) -> bool
|
||||
{ return true; });
|
||||
}
|
||||
|
||||
TORRENT_TEST(plain)
|
||||
{
|
||||
simulate_swarm();
|
||||
setup_swarm(2, swarm_test::download
|
||||
// add session
|
||||
, [](lt::settings_pack& pack) {}
|
||||
// add torrent
|
||||
, [](lt::add_torrent_params& params) {}
|
||||
// on alert
|
||||
, [](lt::alert const* a, lt::session* ses) {}
|
||||
// terminate
|
||||
, [](int ticks, lt::session* ses) -> bool
|
||||
{
|
||||
if (ticks > 75)
|
||||
{
|
||||
TEST_ERROR("timeout");
|
||||
return true;
|
||||
}
|
||||
if (!is_seed(ses)) return false;
|
||||
printf("completed in %d ticks\n", ticks);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
TORRENT_TEST(suggest)
|
||||
{
|
||||
// with suggest pieces
|
||||
simulate_swarm(suggest_read_cache);
|
||||
setup_swarm(2, swarm_test::download
|
||||
// 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) {}
|
||||
// on alert
|
||||
, [](lt::alert const* a, lt::session* ses) {}
|
||||
// terminate
|
||||
, [](int ticks, lt::session* ses) -> bool
|
||||
{
|
||||
if (ticks > 75)
|
||||
{
|
||||
TEST_ERROR("timeout");
|
||||
return true;
|
||||
}
|
||||
if (!is_seed(ses)) return false;
|
||||
printf("completed in %d ticks\n", ticks);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
TORRENT_TEST(utp)
|
||||
TORRENT_TEST(utp_only)
|
||||
{
|
||||
simulate_swarm(utp_only);
|
||||
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
|
||||
, [](lt::add_torrent_params& params) {}
|
||||
// on alert
|
||||
, [](lt::alert const* a, lt::session* ses) {}
|
||||
// terminate
|
||||
, [](int ticks, lt::session* ses) -> bool
|
||||
{
|
||||
if (ticks > 75)
|
||||
{
|
||||
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
|
||||
, [](lt::settings_pack& pack) {}
|
||||
// add torrent
|
||||
, [](lt::add_torrent_params& params) {}
|
||||
// on alert
|
||||
, [&](lt::alert const* a, lt::session* ses) {
|
||||
|
||||
if (lt::alert_cast<lt::torrent_added_alert>(a))
|
||||
add_extra_peers(ses);
|
||||
|
||||
if (auto tp = lt::alert_cast<lt::torrent_paused_alert>(a))
|
||||
{
|
||||
TEST_EQUAL(resumed, false);
|
||||
tp->handle.resume();
|
||||
resumed = true;
|
||||
}
|
||||
}
|
||||
// terminate
|
||||
, [&](int ticks, lt::session* ses) -> bool
|
||||
{
|
||||
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)
|
||||
{
|
||||
auto h = ses->get_torrents()[0];
|
||||
h.pause(graceful ? torrent_handle::graceful_pause : 0);
|
||||
paused_once = true;
|
||||
}
|
||||
}
|
||||
|
||||
const int timeout = (type == swarm_test::upload) ? 64 : 20;
|
||||
|
||||
if (ticks > timeout)
|
||||
{
|
||||
TEST_ERROR("timeout");
|
||||
return true;
|
||||
}
|
||||
if (type == swarm_test::upload) return false;
|
||||
if (!is_seed(ses)) return false;
|
||||
printf("completed in %d ticks\n", ticks);
|
||||
return true;
|
||||
});
|
||||
|
||||
TEST_EQUAL(paused_once, true);
|
||||
TEST_EQUAL(resumed, true);
|
||||
}
|
||||
|
||||
TORRENT_TEST(stop_start_download)
|
||||
{
|
||||
simulate_swarm(stop_start_download | add_extra_peers);
|
||||
test_stop_start_download(swarm_test::download, false);
|
||||
}
|
||||
|
||||
TORRENT_TEST(stop_start_download_graceful)
|
||||
{
|
||||
simulate_swarm(stop_start_download | graceful_pause | add_extra_peers);
|
||||
test_stop_start_download(swarm_test::download, true);
|
||||
}
|
||||
|
||||
TORRENT_TEST(stop_start_seed)
|
||||
{
|
||||
simulate_swarm(stop_start_seed | add_extra_peers);
|
||||
test_stop_start_download(swarm_test::upload, false);
|
||||
}
|
||||
|
||||
TORRENT_TEST(stop_start_seed_graceful)
|
||||
{
|
||||
simulate_swarm(stop_start_seed | graceful_pause | add_extra_peers);
|
||||
test_stop_start_download(swarm_test::upload, true);
|
||||
}
|
||||
|
||||
TORRENT_TEST(explicit_cache)
|
||||
{
|
||||
// test explicit cache
|
||||
simulate_swarm(suggest_read_cache | explicit_cache);
|
||||
setup_swarm(2, swarm_test::download
|
||||
// add session
|
||||
, [](lt::settings_pack& pack) {
|
||||
pack.set_int(settings_pack::suggest_mode, settings_pack::suggest_read_cache);
|
||||
pack.set_bool(settings_pack::explicit_read_cache, true);
|
||||
pack.set_int(settings_pack::explicit_cache_interval, 5);
|
||||
}
|
||||
// add torrent
|
||||
, [](lt::add_torrent_params& params) {}
|
||||
// on alert
|
||||
, [](lt::alert const* a, lt::session* ses) {}
|
||||
// terminate
|
||||
, [](int ticks, lt::session* ses) -> bool
|
||||
{
|
||||
if (ticks > 75)
|
||||
{
|
||||
TEST_ERROR("timeout");
|
||||
return true;
|
||||
}
|
||||
if (!is_seed(ses)) return false;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
TORRENT_TEST(shutdown)
|
||||
{
|
||||
simulate_swarm(early_shutdown);
|
||||
setup_swarm(2, swarm_test::download
|
||||
// add session
|
||||
, [](lt::settings_pack& pack) {}
|
||||
// add torrent
|
||||
, [](lt::add_torrent_params& params) {}
|
||||
// on alert
|
||||
, [](lt::alert const* a, lt::session* ses) {}
|
||||
// terminate
|
||||
, [](int ticks, lt::session* ses) -> bool
|
||||
{
|
||||
if (completed_pieces(ses) == 0) return false;
|
||||
TEST_EQUAL(is_seed(ses), false);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: the swarm_suite is probably not a very good abstraction, it's not
|
||||
// configurable enough.
|
||||
|
||||
// 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
|
||||
// TODO: add test that makes sure a torrent in graceful pause mode only posts
|
||||
// the torrent_paused_alert once, and exactly once
|
||||
|
||||
|
|
Loading…
Reference in New Issue