now that force-started torrents aren't affected by the auto-manager, they need to be explicitly kicked when entering checking state (it would be nice if all this could be done through set_state())
This commit is contained in:
parent
dab0f8b8d0
commit
5da511f140
@ -23,6 +23,7 @@ project
|
||||
;
|
||||
|
||||
alias libtorrent-sims :
|
||||
[ run test_auto_manage.cpp ]
|
||||
[ run test_torrent_status.cpp ]
|
||||
[ run test_swarm.cpp ]
|
||||
[ run test_super_seeding.cpp ]
|
||||
|
@ -82,7 +82,8 @@ struct swarm
|
||||
m_torrents.push_back(lt::torrent_handle());
|
||||
|
||||
lt::add_torrent_params params = m_config.add_torrent(i);
|
||||
ses->async_add_torrent(params);
|
||||
if (!params.save_path.empty())
|
||||
ses->async_add_torrent(params);
|
||||
|
||||
ses->set_alert_notify(boost::bind(&swarm::on_alert_notify, this, i));
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ struct swarm_config : swarm_setup_provider
|
||||
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, 0x4000, 9, false);
|
||||
m_ti = ::create_torrent(&file, "temporary", 0x4000, 9, false);
|
||||
file.close();
|
||||
}
|
||||
|
||||
|
626
simulation/test_auto_manage.cpp
Normal file
626
simulation/test_auto_manage.cpp
Normal file
@ -0,0 +1,626 @@
|
||||
/*
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#include "libtorrent/session.hpp"
|
||||
#include "libtorrent/torrent_handle.hpp"
|
||||
#include "libtorrent/settings_pack.hpp"
|
||||
#include "libtorrent/alert_types.hpp"
|
||||
#include "libtorrent/deadline_timer.hpp"
|
||||
#include "test.hpp"
|
||||
#include "swarm_config.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "simulator/simulator.hpp"
|
||||
#include <iostream>
|
||||
|
||||
using namespace sim;
|
||||
|
||||
const int num_torrents = 10;
|
||||
|
||||
lt::add_torrent_params create_torrent(int idx, bool seed)
|
||||
{
|
||||
// TODO: if we want non-seeding torrents, that could be a bit cheaper to
|
||||
// create
|
||||
lt::add_torrent_params params;
|
||||
int swarm_id = test_counter();
|
||||
char name[200];
|
||||
snprintf(name, sizeof(name), "temp-%02d", idx);
|
||||
char path[200];
|
||||
snprintf(path, sizeof(path), "swarm-%04d-peer-%02d"
|
||||
, swarm_id, idx);
|
||||
error_code ec;
|
||||
create_directory(path, ec);
|
||||
if (ec) fprintf(stderr, "failed to create directory: \"%s\": %s\n"
|
||||
, path, ec.message().c_str());
|
||||
std::ofstream file(combine_path(path, name).c_str());
|
||||
params.ti = ::create_torrent(&file, name
|
||||
, 0x4000, 9 + idx, false);
|
||||
file.close();
|
||||
|
||||
// by setting the save path to a dummy path, it won't be seeding
|
||||
params.save_path = seed ? path : "dummy";
|
||||
return params;
|
||||
}
|
||||
|
||||
using sim::asio::ip::address_v4;
|
||||
|
||||
std::unique_ptr<sim::asio::io_service> make_io_service(sim::simulation& sim, int i)
|
||||
{
|
||||
char ep[30];
|
||||
snprintf(ep, sizeof(ep), "50.0.%d.%d", (i + 1) >> 8, (i + 1) & 0xff);
|
||||
return std::unique_ptr<sim::asio::io_service>(new sim::asio::io_service(
|
||||
sim, asio::ip::address_v4::from_string(ep)));
|
||||
}
|
||||
|
||||
// this is the general template for these tests. create the session with custom
|
||||
// settings (Settings), set up the test, by adding torrents with certain
|
||||
// arguments (Setup), run the test and verify the end state (Test)
|
||||
template <typename Settings, typename Setup, typename Test>
|
||||
void run_test(Settings const& sett, Setup const& setup, Test const& test)
|
||||
{
|
||||
// setup the simulation
|
||||
sim::default_config network_cfg;
|
||||
sim::simulation sim{network_cfg};
|
||||
std::unique_ptr<sim::asio::io_service> ios = make_io_service(sim, 0);
|
||||
lt::session_proxy zombie;
|
||||
|
||||
// setup settings pack to use for the session (customization point)
|
||||
lt::settings_pack pack = settings();
|
||||
sett(pack);
|
||||
|
||||
// create session
|
||||
std::shared_ptr<lt::session> ses = std::make_shared<lt::session>(pack, *ios);
|
||||
|
||||
// set up test, like adding torrents (customization point)
|
||||
setup(*ses);
|
||||
|
||||
// set up a timer to fire later, to verify everything we expected to happen
|
||||
// happened
|
||||
lt::deadline_timer timer(*ios);
|
||||
timer.expires_from_now(lt::seconds((num_torrents + 1) * 60));
|
||||
timer.async_wait([&](boost::system::error_code const& ec)
|
||||
{
|
||||
test(*ses);
|
||||
|
||||
// shut down
|
||||
zombie = ses->abort();
|
||||
ses.reset();
|
||||
});
|
||||
|
||||
sim.run();
|
||||
}
|
||||
|
||||
TORRENT_TEST(dont_count_slow_torrents)
|
||||
{
|
||||
run_test(
|
||||
[](settings_pack& sett) {
|
||||
// session settings
|
||||
sett.set_bool(settings_pack::dont_count_slow_torrents, true);
|
||||
sett.set_int(settings_pack::active_downloads, 1);
|
||||
sett.set_int(settings_pack::active_seeds, 1);
|
||||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// add torrents
|
||||
for (int i = 0; i < num_torrents; ++i)
|
||||
{
|
||||
lt::add_torrent_params params = create_torrent(i, false);
|
||||
params.flags |= add_torrent_params::flag_auto_managed;
|
||||
params.flags |= add_torrent_params::flag_paused;
|
||||
ses.async_add_torrent(params);
|
||||
}
|
||||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// verify result
|
||||
|
||||
std::vector<lt::alert*> alerts;
|
||||
ses.pop_alerts(&alerts);
|
||||
|
||||
lt::time_point last = lt::time_point::min();
|
||||
lt::time_point start_time = alerts[0]->timestamp();
|
||||
|
||||
int num_started = 0;
|
||||
for (alert* a : alerts)
|
||||
{
|
||||
printf("%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
|
||||
- start_time).count()), a->message().c_str());
|
||||
if (alert_cast<torrent_resumed_alert>(a) == nullptr) continue;
|
||||
|
||||
lt::time_point t = a->timestamp();
|
||||
if (last != lt::time_point::min())
|
||||
{
|
||||
// expect starting of new torrents to be spaced by 60 seconds
|
||||
// the division by 2 is to allow some slack (it's integer
|
||||
// division)
|
||||
TEST_EQUAL(duration_cast<lt::seconds>(t - last).count() / 2, 60 / 2);
|
||||
}
|
||||
last = t;
|
||||
++num_started;
|
||||
}
|
||||
|
||||
TEST_EQUAL(num_started, num_torrents);
|
||||
|
||||
for (torrent_handle const& h : ses.get_torrents())
|
||||
{
|
||||
TEST_CHECK(h.status().auto_managed);
|
||||
TEST_EQUAL(h.status().paused, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TORRENT_TEST(count_slow_torrents)
|
||||
{
|
||||
run_test(
|
||||
[](settings_pack& sett) {
|
||||
// session settings
|
||||
sett.set_bool(settings_pack::dont_count_slow_torrents, false);
|
||||
sett.set_int(settings_pack::active_downloads, 1);
|
||||
sett.set_int(settings_pack::active_seeds, 1);
|
||||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// add torrents
|
||||
for (int i = 0; i < num_torrents; ++i)
|
||||
{
|
||||
lt::add_torrent_params params = create_torrent(i, false);
|
||||
params.flags |= add_torrent_params::flag_auto_managed;
|
||||
params.flags |= add_torrent_params::flag_paused;
|
||||
ses.async_add_torrent(params);
|
||||
}
|
||||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// verify result (only one should have been started, even though
|
||||
// they're all idle)
|
||||
|
||||
std::vector<lt::alert*> alerts;
|
||||
ses.pop_alerts(&alerts);
|
||||
|
||||
lt::time_point start_time = alerts[0]->timestamp();
|
||||
|
||||
int num_started = 0;
|
||||
for (alert* a : alerts)
|
||||
{
|
||||
printf("%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
|
||||
- start_time).count()), a->message().c_str());
|
||||
if (alert_cast<torrent_resumed_alert>(a) == nullptr) continue;
|
||||
++num_started;
|
||||
}
|
||||
|
||||
TEST_EQUAL(num_started, 1);
|
||||
|
||||
num_started = 0;
|
||||
for (torrent_handle const& h : ses.get_torrents())
|
||||
{
|
||||
TEST_CHECK(h.status().auto_managed);
|
||||
num_started += !h.status().paused;
|
||||
}
|
||||
TEST_EQUAL(num_started, 1);
|
||||
});
|
||||
}
|
||||
|
||||
TORRENT_TEST(force_stopped_download)
|
||||
{
|
||||
run_test(
|
||||
[](settings_pack& sett) {
|
||||
// session settings
|
||||
sett.set_bool(settings_pack::dont_count_slow_torrents, true);
|
||||
sett.set_int(settings_pack::active_downloads, 10);
|
||||
sett.set_int(settings_pack::active_seeds, 10);
|
||||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// add torrents
|
||||
for (int i = 0; i < num_torrents; ++i)
|
||||
{
|
||||
lt::add_torrent_params params = create_torrent(i, false);
|
||||
// torrents are paused and not auto-managed
|
||||
params.flags &= ~add_torrent_params::flag_auto_managed;
|
||||
params.flags |= add_torrent_params::flag_paused;
|
||||
ses.async_add_torrent(params);
|
||||
}
|
||||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// verify result (none should have been started)
|
||||
|
||||
std::vector<lt::alert*> alerts;
|
||||
ses.pop_alerts(&alerts);
|
||||
|
||||
lt::time_point start_time = alerts[0]->timestamp();
|
||||
|
||||
for (alert* a : alerts)
|
||||
{
|
||||
printf("%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
|
||||
- start_time).count()), a->message().c_str());
|
||||
// we don't expect any torrents being started or stopped, since
|
||||
// they're all force stopped
|
||||
TEST_CHECK(alert_cast<torrent_resumed_alert>(a) == nullptr);
|
||||
TEST_CHECK(alert_cast<torrent_paused_alert>(a) == nullptr);
|
||||
}
|
||||
|
||||
for (torrent_handle const& h : ses.get_torrents())
|
||||
{
|
||||
TEST_CHECK(!h.status().auto_managed);
|
||||
TEST_CHECK(h.status().paused);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TORRENT_TEST(force_started)
|
||||
{
|
||||
run_test(
|
||||
[](settings_pack& sett) {
|
||||
// session settings
|
||||
sett.set_bool(settings_pack::dont_count_slow_torrents, false);
|
||||
sett.set_int(settings_pack::active_downloads, 1);
|
||||
sett.set_int(settings_pack::active_seeds, 1);
|
||||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// add torrents
|
||||
for (int i = 0; i < num_torrents; ++i)
|
||||
{
|
||||
lt::add_torrent_params params = create_torrent(i, false);
|
||||
// torrents are started and not auto-managed
|
||||
params.flags &= ~add_torrent_params::flag_auto_managed;
|
||||
params.flags &= ~add_torrent_params::flag_paused;
|
||||
ses.async_add_torrent(params);
|
||||
}
|
||||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// verify result (none should have been started)
|
||||
|
||||
std::vector<lt::alert*> alerts;
|
||||
ses.pop_alerts(&alerts);
|
||||
|
||||
lt::time_point start_time = alerts[0]->timestamp();
|
||||
|
||||
for (alert* a : alerts)
|
||||
{
|
||||
printf("%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
|
||||
- start_time).count()), a->message().c_str());
|
||||
// we don't expect any torrents being started or stopped, since
|
||||
// they're all force started
|
||||
TEST_CHECK(alert_cast<torrent_resumed_alert>(a) == nullptr);
|
||||
TEST_CHECK(alert_cast<torrent_paused_alert>(a) == nullptr);
|
||||
}
|
||||
|
||||
for (torrent_handle const& h : ses.get_torrents())
|
||||
{
|
||||
TEST_CHECK(!h.status().auto_managed);
|
||||
TEST_CHECK(!h.status().paused);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TORRENT_TEST(seed_limit)
|
||||
{
|
||||
run_test(
|
||||
[](settings_pack& sett) {
|
||||
// session settings
|
||||
// set the seed limit to 3
|
||||
sett.set_bool(settings_pack::dont_count_slow_torrents, false);
|
||||
sett.set_int(settings_pack::active_checking, 1);
|
||||
sett.set_int(settings_pack::active_seeds, 3);
|
||||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// add torrents
|
||||
// add 5 seeds
|
||||
for (int i = 0; i < num_torrents; ++i)
|
||||
{
|
||||
lt::add_torrent_params params = create_torrent(i, true);
|
||||
// torrents are paused and auto-managed
|
||||
params.flags |= add_torrent_params::flag_auto_managed;
|
||||
params.flags |= add_torrent_params::flag_paused;
|
||||
ses.async_add_torrent(params);
|
||||
}
|
||||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// verify result (none should have been started)
|
||||
// make sure only 3 got started
|
||||
std::vector<lt::alert*> alerts;
|
||||
ses.pop_alerts(&alerts);
|
||||
|
||||
lt::time_point start_time = alerts[0]->timestamp();
|
||||
|
||||
int num_started = 0;
|
||||
int num_checking = 0;
|
||||
int num_seeding = 0;
|
||||
for (alert* a : alerts)
|
||||
{
|
||||
fprintf(stderr, "%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
|
||||
- start_time).count()), a->message().c_str());
|
||||
if (alert_cast<torrent_resumed_alert>(a))
|
||||
{
|
||||
++num_started;
|
||||
|
||||
fprintf(stderr, "started: %d checking: %d seeding: %d\n"
|
||||
, num_started, num_checking, num_seeding);
|
||||
}
|
||||
else if (alert_cast<torrent_paused_alert>(a))
|
||||
{
|
||||
TEST_CHECK(num_started > 0);
|
||||
--num_started;
|
||||
|
||||
fprintf(stderr, "started: %d checking: %d seeding: %d\n"
|
||||
, num_started, num_checking, num_seeding);
|
||||
}
|
||||
else if (state_changed_alert* sc = alert_cast<state_changed_alert>(a))
|
||||
{
|
||||
if (sc->prev_state == torrent_status::checking_files)
|
||||
--num_checking;
|
||||
else if (sc->prev_state == torrent_status::seeding)
|
||||
--num_seeding;
|
||||
|
||||
if (sc->state == torrent_status::checking_files)
|
||||
++num_checking;
|
||||
else if (sc->state == torrent_status::seeding)
|
||||
++num_seeding;
|
||||
|
||||
fprintf(stderr, "started: %d checking: %d seeding: %d\n"
|
||||
, num_started, num_checking, num_seeding);
|
||||
|
||||
// while at least one torrent is checking, there may be another
|
||||
// started torrent (the checking one), other than that, only 3
|
||||
// torrents are allowed to be started and seeding
|
||||
TEST_CHECK(num_started <= 3 + 1);
|
||||
TEST_CHECK(num_started <= 1 || num_seeding > 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_EQUAL(num_started, 3);
|
||||
|
||||
num_started = 0;
|
||||
for (torrent_handle const& h : ses.get_torrents())
|
||||
{
|
||||
TEST_CHECK(h.status().auto_managed);
|
||||
TEST_CHECK(h.status().is_seeding);
|
||||
num_started += !h.status().paused;
|
||||
}
|
||||
TEST_EQUAL(num_started, 3);
|
||||
});
|
||||
}
|
||||
|
||||
TORRENT_TEST(download_limit)
|
||||
{
|
||||
run_test(
|
||||
[](settings_pack& sett) {
|
||||
// session settings
|
||||
// set the seed limit to 3
|
||||
sett.set_bool(settings_pack::dont_count_slow_torrents, false);
|
||||
sett.set_int(settings_pack::active_checking, 1);
|
||||
sett.set_int(settings_pack::active_downloads, 3);
|
||||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// add torrents
|
||||
// add 5 seeds
|
||||
for (int i = 0; i < num_torrents; ++i)
|
||||
{
|
||||
lt::add_torrent_params params = create_torrent(i, false);
|
||||
// torrents are paused and auto-managed
|
||||
params.flags |= add_torrent_params::flag_auto_managed;
|
||||
params.flags |= add_torrent_params::flag_paused;
|
||||
ses.async_add_torrent(params);
|
||||
}
|
||||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// verify result (none should have been started)
|
||||
// make sure only 3 got started
|
||||
std::vector<lt::alert*> alerts;
|
||||
ses.pop_alerts(&alerts);
|
||||
|
||||
lt::time_point start_time = alerts[0]->timestamp();
|
||||
|
||||
int num_started = 0;
|
||||
int num_checking = 0;
|
||||
int num_downloading = 0;
|
||||
for (alert* a : alerts)
|
||||
{
|
||||
fprintf(stderr, "%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
|
||||
- start_time).count()), a->message().c_str());
|
||||
if (alert_cast<torrent_resumed_alert>(a))
|
||||
{
|
||||
++num_started;
|
||||
|
||||
fprintf(stderr, "started: %d checking: %d downloading: %d\n"
|
||||
, num_started, num_checking, num_downloading);
|
||||
}
|
||||
else if (alert_cast<torrent_paused_alert>(a))
|
||||
{
|
||||
TEST_CHECK(num_started > 0);
|
||||
--num_started;
|
||||
|
||||
fprintf(stderr, "started: %d checking: %d downloading: %d\n"
|
||||
, num_started, num_checking, num_downloading);
|
||||
}
|
||||
else if (state_changed_alert* sc = alert_cast<state_changed_alert>(a))
|
||||
{
|
||||
if (sc->prev_state == torrent_status::checking_files)
|
||||
--num_checking;
|
||||
else if (sc->prev_state == torrent_status::downloading)
|
||||
--num_downloading;
|
||||
|
||||
if (sc->state == torrent_status::checking_files)
|
||||
++num_checking;
|
||||
else if (sc->state == torrent_status::downloading)
|
||||
++num_downloading;
|
||||
|
||||
fprintf(stderr, "started: %d checking: %d downloading: %d\n"
|
||||
, num_started, num_checking, num_downloading);
|
||||
|
||||
// while at least one torrent is checking, there may be another
|
||||
// started torrent (the checking one), other than that, only 3
|
||||
// torrents are allowed to be started and seeding
|
||||
TEST_CHECK(num_started <= 3 + 1);
|
||||
TEST_CHECK(num_started <= 1 || num_downloading > 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_EQUAL(num_started, 3);
|
||||
|
||||
num_started = 0;
|
||||
for (torrent_handle const& h : ses.get_torrents())
|
||||
{
|
||||
TEST_CHECK(h.status().auto_managed);
|
||||
TEST_CHECK(!h.status().is_finished);
|
||||
num_started += !h.status().paused;
|
||||
}
|
||||
TEST_EQUAL(num_started, 3);
|
||||
});
|
||||
}
|
||||
// make sure torrents don't announce to the tracker when transitioning from
|
||||
// checking to paused downloading
|
||||
TORRENT_TEST(checking_announce)
|
||||
{
|
||||
run_test(
|
||||
[](settings_pack& sett) {
|
||||
// session settings
|
||||
// set the seed limit to 3
|
||||
sett.set_bool(settings_pack::dont_count_slow_torrents, false);
|
||||
sett.set_int(settings_pack::active_checking, 1);
|
||||
|
||||
// just set the tracker retry intervals really long, to make sure we
|
||||
// don't keep retrying the tracker (since there's nothing running
|
||||
// there, it will fail)
|
||||
sett.set_int(settings_pack::tracker_backoff, 100000);
|
||||
// only the first torrent added should ever announce
|
||||
sett.set_int(settings_pack::active_seeds, 1);
|
||||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// add torrents
|
||||
// add 5 seeds
|
||||
for (int i = 0; i < num_torrents; ++i)
|
||||
{
|
||||
lt::add_torrent_params params = create_torrent(i, true);
|
||||
// torrents are paused and auto-managed
|
||||
params.flags |= add_torrent_params::flag_auto_managed;
|
||||
params.flags |= add_torrent_params::flag_paused;
|
||||
// we need this to get the tracker_announce_alert
|
||||
params.trackers.push_back("http://10.10.0.2/announce");
|
||||
ses.async_add_torrent(params);
|
||||
}
|
||||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// verify result (none should have been started)
|
||||
// make sure only 3 got started
|
||||
std::vector<lt::alert*> alerts;
|
||||
ses.pop_alerts(&alerts);
|
||||
|
||||
lt::time_point start_time = alerts[0]->timestamp();
|
||||
|
||||
int num_announce = 0;
|
||||
for (alert* a : alerts)
|
||||
{
|
||||
fprintf(stderr, "%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
|
||||
- start_time).count()), a->message().c_str());
|
||||
if (alert_cast<tracker_announce_alert>(a))
|
||||
++num_announce;
|
||||
}
|
||||
|
||||
TEST_EQUAL(num_announce, 1);
|
||||
|
||||
int num_started = 0;
|
||||
for (torrent_handle const& h : ses.get_torrents())
|
||||
{
|
||||
TEST_CHECK(h.status().auto_managed);
|
||||
num_started += !h.status().paused;
|
||||
}
|
||||
TEST_EQUAL(num_started, 1);
|
||||
});
|
||||
}
|
||||
|
||||
TORRENT_TEST(paused_checking)
|
||||
{
|
||||
run_test(
|
||||
[](settings_pack& sett) {
|
||||
// session settings
|
||||
// set the seed limit to 3
|
||||
sett.set_bool(settings_pack::dont_count_slow_torrents, true);
|
||||
sett.set_int(settings_pack::active_checking, 1);
|
||||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// add torrents
|
||||
// add 5 seeds
|
||||
for (int i = 0; i < num_torrents; ++i)
|
||||
{
|
||||
lt::add_torrent_params params = create_torrent(i, true);
|
||||
// torrents are paused and auto-managed
|
||||
params.flags &= ~add_torrent_params::flag_auto_managed;
|
||||
params.flags |= add_torrent_params::flag_paused;
|
||||
ses.async_add_torrent(params);
|
||||
}
|
||||
},
|
||||
|
||||
[](lt::session& ses) {
|
||||
// verify result (none should have been started)
|
||||
// make sure only 3 got started
|
||||
std::vector<lt::alert*> alerts;
|
||||
ses.pop_alerts(&alerts);
|
||||
|
||||
lt::time_point start_time = alerts[0]->timestamp();
|
||||
|
||||
for (alert* a : alerts)
|
||||
{
|
||||
fprintf(stderr, "%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
|
||||
- start_time).count()), a->message().c_str());
|
||||
if (state_changed_alert* sc = alert_cast<state_changed_alert>(a))
|
||||
{
|
||||
TEST_CHECK(sc->state == torrent_status::checking_files
|
||||
|| sc->state == torrent_status::checking_resume_data);
|
||||
}
|
||||
}
|
||||
|
||||
for (torrent_handle const& h : ses.get_torrents())
|
||||
{
|
||||
// even though all torrents are seeding, libtorrent shouldn't know
|
||||
// that, because they should never have been checked (because they
|
||||
// were force stopped)
|
||||
TEST_CHECK(!h.status().is_seeding);
|
||||
TEST_CHECK(!h.status().auto_managed);
|
||||
TEST_CHECK(h.status().paused);
|
||||
}
|
||||
});
|
||||
}
|
||||
// TODO: assert that the torrent_paused_alert is posted when pausing
|
||||
// downloading, seeding, checking torrents as well as the graceful pause
|
||||
// TODO: test limits of tracker, DHT and LSD announces
|
||||
|
||||
|
@ -39,6 +39,7 @@ using namespace libtorrent;
|
||||
using namespace sim;
|
||||
namespace lt = libtorrent;
|
||||
|
||||
// this is a test for torrent_status time counters are correct
|
||||
struct test_swarm_config : swarm_config
|
||||
{
|
||||
test_swarm_config()
|
||||
|
@ -63,7 +63,7 @@ struct swarm_config : swarm_setup_provider
|
||||
|
||||
create_directory(save_path, ec);
|
||||
std::ofstream file(combine_path(save_path, "temporary").c_str());
|
||||
m_ti = ::create_torrent(&file, 0x4000, 90, false);
|
||||
m_ti = ::create_torrent(&file, "temporary", 0x4000, 90, false);
|
||||
file.close();
|
||||
}
|
||||
|
||||
|
@ -3800,6 +3800,15 @@ namespace libtorrent
|
||||
peer_log(peer_log_alert::info, "GRACEFUL_PAUSE", "NO MORE DOWNLOAD");
|
||||
#endif
|
||||
disconnect(errors::torrent_paused, op_bittorrent);
|
||||
|
||||
// if this was the last connection, post the alert
|
||||
// TODO: it would be nice if none of this logic would leak outside of
|
||||
// the torrent object)
|
||||
if (t->num_peers() == 0)
|
||||
{
|
||||
if (t->alerts().should_post<torrent_paused_alert>())
|
||||
t->alerts().emplace_alert<torrent_paused_alert>(t->get_handle());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3581,6 +3581,23 @@ retry:
|
||||
|
||||
TORRENT_ASSERT(t->state() != torrent_status::checking_files);
|
||||
|
||||
// inactive torrents don't count (and if you configured them to do so,
|
||||
// the torrent won't say it's inactive)
|
||||
if (hard_limit > 0 && t->is_inactive())
|
||||
{
|
||||
t->set_announce_to_dht(--dht_limit >= 0);
|
||||
t->set_announce_to_trackers(--tracker_limit >= 0);
|
||||
t->set_announce_to_lsd(--lsd_limit >= 0);
|
||||
|
||||
--hard_limit;
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
if (!t->allows_peers())
|
||||
t->log_to_all_peers("auto manager starting (inactive) torrent");
|
||||
#endif
|
||||
t->set_allow_peers(true);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type_limit > 0 && hard_limit > 0)
|
||||
{
|
||||
t->set_announce_to_dht(--dht_limit >= 0);
|
||||
@ -3594,19 +3611,18 @@ retry:
|
||||
t->log_to_all_peers("auto manager starting torrent");
|
||||
#endif
|
||||
t->set_allow_peers(true);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
if (t->allows_peers())
|
||||
t->log_to_all_peers("auto manager pausing torrent");
|
||||
if (t->allows_peers())
|
||||
t->log_to_all_peers("auto manager pausing torrent");
|
||||
#endif
|
||||
// use graceful pause for auto-managed torrents
|
||||
t->set_allow_peers(false, true);
|
||||
t->set_announce_to_dht(false);
|
||||
t->set_announce_to_trackers(false);
|
||||
t->set_announce_to_lsd(false);
|
||||
}
|
||||
// use graceful pause for auto-managed torrents
|
||||
t->set_allow_peers(false, true);
|
||||
t->set_announce_to_dht(false);
|
||||
t->set_announce_to_trackers(false);
|
||||
t->set_announce_to_lsd(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2553,6 +2553,7 @@ namespace libtorrent
|
||||
// either the fastresume data was rejected or there are
|
||||
// some files
|
||||
set_state(torrent_status::checking_files);
|
||||
if (should_check_files()) start_checking();
|
||||
|
||||
// start the checking right away (potentially)
|
||||
m_ses.trigger_auto_manage();
|
||||
@ -2814,20 +2815,19 @@ namespace libtorrent
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_graceful_pause_mode && !m_allow_peers && m_checking_piece == m_num_checked_pieces)
|
||||
{
|
||||
// we are in graceful pause mode, and we just completed the last outstanding job.
|
||||
// now we can be considered paused
|
||||
if (alerts().should_post<torrent_paused_alert>())
|
||||
alerts().emplace_alert<torrent_paused_alert>(get_handle());
|
||||
}
|
||||
|
||||
// we paused the checking
|
||||
if (!should_check_files())
|
||||
{
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
debug_log("on_piece_hashed, checking paused");
|
||||
#endif
|
||||
if (m_checking_piece == m_num_checked_pieces)
|
||||
{
|
||||
// we are paused, and we just completed the last outstanding job.
|
||||
// now we can be considered paused
|
||||
if (alerts().should_post<torrent_paused_alert>())
|
||||
alerts().emplace_alert<torrent_paused_alert>(get_handle());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2853,12 +2853,15 @@ namespace libtorrent
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
debug_log("on_piece_hashed, completed");
|
||||
#endif
|
||||
// we're done checking!
|
||||
files_checked();
|
||||
if (m_auto_managed)
|
||||
{
|
||||
// if we're auto managed. assume we need to be paused until the auto
|
||||
// managed logic runs again (which is triggered further down)
|
||||
pause();
|
||||
}
|
||||
|
||||
// recalculate auto-managed torrents sooner
|
||||
// in order to start checking the next torrent
|
||||
m_ses.trigger_auto_manage();
|
||||
// we're done checking! (this should cause a call to trigger_auto_manage)
|
||||
files_checked();
|
||||
|
||||
// reset the checking state
|
||||
m_checking_piece = 0;
|
||||
@ -8554,10 +8557,6 @@ namespace libtorrent
|
||||
m_need_save_resume_data = true;
|
||||
}
|
||||
|
||||
// if we just finished checking and we're not a seed, we are
|
||||
// likely to be unpaused
|
||||
m_ses.trigger_auto_manage();
|
||||
|
||||
if (is_finished() && m_state != torrent_status::finished)
|
||||
finished();
|
||||
}
|
||||
@ -9564,17 +9563,8 @@ namespace libtorrent
|
||||
m_need_save_resume_data = true;
|
||||
state_updated();
|
||||
|
||||
bool prev_graceful = m_graceful_pause_mode;
|
||||
m_graceful_pause_mode = graceful;
|
||||
update_gauge();
|
||||
|
||||
if (!m_ses.is_paused() || (prev_graceful && !m_graceful_pause_mode))
|
||||
{
|
||||
do_pause();
|
||||
// if this torrent was just paused
|
||||
// we might have to resume some other auto-managed torrent
|
||||
m_ses.trigger_auto_manage();
|
||||
}
|
||||
}
|
||||
|
||||
void torrent::do_pause()
|
||||
@ -9683,6 +9673,11 @@ namespace libtorrent
|
||||
p->disconnect(errors::torrent_paused, op_bittorrent);
|
||||
i = j;
|
||||
}
|
||||
if (m_connections.empty())
|
||||
{
|
||||
if (alerts().should_post<torrent_paused_alert>())
|
||||
alerts().emplace_alert<torrent_paused_alert>(get_handle());
|
||||
}
|
||||
if (update_ticks)
|
||||
{
|
||||
update_want_peers();
|
||||
@ -9738,8 +9733,20 @@ namespace libtorrent
|
||||
{
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
|
||||
if (m_allow_peers == b
|
||||
&& m_graceful_pause_mode == graceful) return;
|
||||
if (m_allow_peers == b)
|
||||
{
|
||||
// there is one special case here. If we are
|
||||
// currently in graceful pause mode, and we just turned into regular
|
||||
// paused mode, we need to actually pause the torrent properly
|
||||
if (m_allow_peers == false
|
||||
&& m_graceful_pause_mode == true
|
||||
&& graceful == false)
|
||||
{
|
||||
m_graceful_pause_mode = graceful;
|
||||
do_pause();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
m_allow_peers = b;
|
||||
if (!m_ses.is_paused())
|
||||
|
@ -68,6 +68,7 @@ using namespace libtorrent;
|
||||
int old_stdout = -1;
|
||||
int old_stderr = -1;
|
||||
bool redirect_output = true;
|
||||
bool keep_files = false;
|
||||
|
||||
extern int _g_test_idx;
|
||||
|
||||
@ -143,6 +144,8 @@ void print_usage(char const* executable)
|
||||
"OPTIONS:\n"
|
||||
"-h,--help show this help\n"
|
||||
"-l,--list list the tests available to run\n"
|
||||
"-k,--keep keep files created by the test\n"
|
||||
" regardless of whether it passed or not\n"
|
||||
"-n,--no-redirect don't redirect test output to\n"
|
||||
" temporary file, but let it go straight\n"
|
||||
" to stdout\n"
|
||||
@ -181,6 +184,11 @@ EXPORT int main(int argc, char const* argv[])
|
||||
{
|
||||
redirect_output = false;
|
||||
}
|
||||
|
||||
if (strcmp(argv[0], "-k") == 0 || strcmp(argv[0], "--keep") == 0)
|
||||
{
|
||||
keep_files = true;
|
||||
}
|
||||
++argv;
|
||||
--argc;
|
||||
}
|
||||
@ -365,7 +373,7 @@ EXPORT int main(int argc, char const* argv[])
|
||||
|
||||
int ret = print_failures();
|
||||
#if !defined TORRENT_LOGGING
|
||||
if (ret == 0)
|
||||
if (ret == 0 && !keep_files)
|
||||
{
|
||||
remove_all(test_dir, ec);
|
||||
if (ec)
|
||||
|
@ -615,7 +615,8 @@ void create_random_files(std::string const& path, const int file_sizes[], int nu
|
||||
free(random_data);
|
||||
}
|
||||
|
||||
boost::shared_ptr<torrent_info> create_torrent(std::ostream* file, int piece_size
|
||||
boost::shared_ptr<torrent_info> create_torrent(std::ostream* file
|
||||
, char const* name, int piece_size
|
||||
, int num_pieces, bool add_tracker, std::string ssl_certificate)
|
||||
{
|
||||
// excercise the path when encountering invalid urls
|
||||
@ -624,7 +625,7 @@ boost::shared_ptr<torrent_info> create_torrent(std::ostream* file, int piece_siz
|
||||
|
||||
file_storage fs;
|
||||
int total_size = piece_size * num_pieces;
|
||||
fs.add_file("temporary", total_size);
|
||||
fs.add_file(name, total_size);
|
||||
libtorrent::create_torrent t(fs, piece_size);
|
||||
if (add_tracker)
|
||||
{
|
||||
@ -744,7 +745,7 @@ setup_transfer(lt::session* ses1, lt::session* ses2, lt::session* ses3
|
||||
error_code ec;
|
||||
create_directory("tmp1" + suffix, ec);
|
||||
std::ofstream file(combine_path("tmp1" + suffix, "temporary").c_str());
|
||||
t = ::create_torrent(&file, piece_size, 9, false);
|
||||
t = ::create_torrent(&file, "temporary", piece_size, 9, false);
|
||||
file.close();
|
||||
if (clear_files)
|
||||
{
|
||||
|
@ -83,8 +83,8 @@ EXPORT void test_sleep(int millisec);
|
||||
EXPORT void create_random_files(std::string const& path, const int file_sizes[], int num_files);
|
||||
|
||||
EXPORT boost::shared_ptr<libtorrent::torrent_info> create_torrent(std::ostream* file = 0
|
||||
, int piece_size = 16 * 1024, int num_pieces = 13, bool add_tracker = true
|
||||
, std::string ssl_certificate = "");
|
||||
, char const* name = "temporary", int piece_size = 16 * 1024, int num_pieces = 13
|
||||
, bool add_tracker = true, std::string ssl_certificate = "");
|
||||
|
||||
EXPORT boost::tuple<libtorrent::torrent_handle
|
||||
, libtorrent::torrent_handle
|
||||
|
@ -119,7 +119,7 @@ void test_transfer(settings_pack const& sett)
|
||||
error_code ec;
|
||||
create_directory("tmp1_priority", ec);
|
||||
std::ofstream file("tmp1_priority/temporary");
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 16 * 1024, 13, false);
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 16 * 1024, 13, false);
|
||||
file.close();
|
||||
|
||||
add_torrent_params addp;
|
||||
|
@ -139,7 +139,7 @@ session_proxy test_proxy(settings_pack::proxy_type_t proxy_type, int flags)
|
||||
remove_all("tmp1_privacy", ec);
|
||||
create_directory("tmp1_privacy", ec);
|
||||
std::ofstream file(combine_path("tmp1_privacy", "temporary").c_str());
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 16 * 1024, 13, false);
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 16 * 1024, 13, false);
|
||||
file.close();
|
||||
|
||||
char http_tracker_url[200];
|
||||
|
@ -80,7 +80,7 @@ TORRENT_TEST(recheck)
|
||||
create_directory("tmp1_recheck", ec);
|
||||
if (ec) fprintf(stderr, "create_directory: %s\n", ec.message().c_str());
|
||||
std::ofstream file("tmp1_recheck/temporary");
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 4 * 1024 * 1024
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 4 * 1024 * 1024
|
||||
, 7, false);
|
||||
file.close();
|
||||
|
||||
|
@ -256,7 +256,7 @@ void test_remap_files_scatter(storage_mode_t storage_mode = storage_mode_sparse)
|
||||
|
||||
create_directory("tmp1_remap2", ec);
|
||||
std::ofstream file("tmp1_remap2/temporary");
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 32 * 1024, 7);
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 32 * 1024, 7);
|
||||
file.close();
|
||||
|
||||
file_storage fs;
|
||||
|
@ -160,7 +160,7 @@ void test_ssl(int test_idx, bool use_utp)
|
||||
|
||||
create_directory("tmp1_ssl", ec);
|
||||
std::ofstream file("tmp1_ssl/temporary");
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary"
|
||||
, 16 * 1024, 13, false, combine_path("..", combine_path("ssl", "root_ca_cert.pem")));
|
||||
file.close();
|
||||
|
||||
@ -549,7 +549,7 @@ void test_malicious_peer()
|
||||
// create torrent
|
||||
create_directory("tmp3_ssl", ec);
|
||||
std::ofstream file("tmp3_ssl/temporary");
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary"
|
||||
, 16 * 1024, 13, false, combine_path("..", combine_path("ssl", "root_ca_cert.pem")));
|
||||
file.close();
|
||||
|
||||
|
@ -330,7 +330,7 @@ TORRENT_TEST(udp_tracker)
|
||||
remove_all("tmp1_tracker", ec);
|
||||
create_directory("tmp1_tracker", ec);
|
||||
std::ofstream file(combine_path("tmp1_tracker", "temporary").c_str());
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 16 * 1024, 13, false);
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 16 * 1024, 13, false);
|
||||
file.close();
|
||||
|
||||
char tracker_url[200];
|
||||
@ -411,7 +411,7 @@ TORRENT_TEST(try_next)
|
||||
remove_all("tmp2_tracker", ec);
|
||||
create_directory("tmp2_tracker", ec);
|
||||
std::ofstream file(combine_path("tmp2_tracker", "temporary").c_str());
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 16 * 1024, 13, false);
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 16 * 1024, 13, false);
|
||||
file.close();
|
||||
|
||||
// this should fail
|
||||
@ -519,7 +519,7 @@ TORRENT_TEST(http_peers)
|
||||
remove_all("tmp2_tracker", ec);
|
||||
create_directory("tmp2_tracker", ec);
|
||||
std::ofstream file(combine_path("tmp2_tracker", "temporary").c_str());
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 16 * 1024, 13, false);
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 16 * 1024, 13, false);
|
||||
file.close();
|
||||
|
||||
char tracker_url[200];
|
||||
@ -593,7 +593,7 @@ void test_proxy(bool proxy_trackers)
|
||||
remove_all("tmp2_tracker", ec);
|
||||
create_directory("tmp2_tracker", ec);
|
||||
std::ofstream file(combine_path("tmp2_tracker", "temporary").c_str());
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 16 * 1024, 13, false);
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 16 * 1024, 13, false);
|
||||
file.close();
|
||||
|
||||
char tracker_url[200];
|
||||
|
@ -235,7 +235,7 @@ void test_transfer(int proxy_type, settings_pack const& sett
|
||||
|
||||
create_directory("tmp1_transfer", ec);
|
||||
std::ofstream file("tmp1_transfer/temporary");
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 16 * 1024, 13, false);
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 16 * 1024, 13, false);
|
||||
file.close();
|
||||
|
||||
TEST_CHECK(exists(combine_path("tmp1_transfer", "temporary")));
|
||||
|
@ -93,7 +93,7 @@ void test_transfer()
|
||||
|
||||
create_directory("./tmp1_utp", ec);
|
||||
std::ofstream file("./tmp1_utp/temporary");
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 128 * 1024, 6, false);
|
||||
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 128 * 1024, 6, false);
|
||||
file.close();
|
||||
|
||||
// for performance testing
|
||||
|
Loading…
x
Reference in New Issue
Block a user