add tests for edge cases of session settings, and fix a few integer overflows

This commit is contained in:
arvidn 2017-02-02 09:19:17 -05:00 committed by Arvid Norberg
parent 2b53eb28a9
commit c9a2fed2c9
4 changed files with 139 additions and 32 deletions

View File

@ -451,6 +451,107 @@ TORRENT_TEST(torrent_completed_alert)
TEST_EQUAL(num_file_completed, 1);
}
// 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
, [](lt::add_torrent_params& params) {}
// on alert
, [](lt::alert const* a, lt::session& ses) {}
// 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); }
);
}
TORRENT_TEST(redundant_have)
{
test_settings([](lt::settings_pack& pack) {
pack.set_bool(settings_pack::send_redundant_have, false); }
);
}
TORRENT_TEST(lazy_bitfields)
{
test_settings([](lt::settings_pack& pack) {
pack.set_bool(settings_pack::lazy_bitfields, true); }
);
}
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()); }
);
}
TORRENT_TEST(active_limit)
{
test_settings([](lt::settings_pack& pack) {
pack.set_int(settings_pack::active_limit, std::numeric_limits<int>::max()); }
);
}
TORRENT_TEST(upload_rate_limit)
{
test_settings([](lt::settings_pack& pack) {
pack.set_int(settings_pack::upload_rate_limit, std::numeric_limits<int>::max()); }
);
}
TORRENT_TEST(download_rate_limit)
{
test_settings([](lt::settings_pack& pack) {
pack.set_int(settings_pack::download_rate_limit, std::numeric_limits<int>::max()); }
);
}
TORRENT_TEST(unchoke_slots_limit)
{
test_settings([](lt::settings_pack& pack) {
pack.set_int(settings_pack::unchoke_slots_limit, std::numeric_limits<int>::max()); }
);
}
// 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

View File

@ -50,7 +50,7 @@ namespace libtorrent
TORRENT_ASSERT(limit < INT_MAX);
m_limit = limit;
}
int bandwidth_channel::quota_left() const
{
if (m_limit == 0) return inf;
@ -60,12 +60,18 @@ namespace libtorrent
void bandwidth_channel::update_quota(int dt_milliseconds)
{
if (m_limit == 0) return;
m_quota_left += (m_limit * dt_milliseconds + 500) / 1000;
if (m_quota_left > m_limit * 3) m_quota_left = m_limit * 3;
// avoid integer overflow
if (m_limit >= std::numeric_limits<int>::max() / dt_milliseconds)
{
m_quota_left = std::numeric_limits<int>::max();
}
else
{
m_quota_left += (m_limit * dt_milliseconds + 500) / 1000;
if (m_quota_left / 3 > m_limit) m_quota_left = m_limit * 3;
}
distribute_quota = int((std::max)(m_quota_left, boost::int64_t(0)));
// fprintf(stderr, "%p: [%d]: + %"PRId64" limit: %"PRId64" quota_left: %"PRId64"\n", this
// , dt_milliseconds, (m_limit * dt_milliseconds + 500) / 1000, m_limit
// , m_quota_left);
}
// this is used when connections disconnect with
@ -85,8 +91,6 @@ namespace libtorrent
TORRENT_ASSERT(m_limit >= 0);
if (m_limit == 0) return;
// fprintf(stderr, "%p: - %"PRId64" limit: %"PRId64" quota_left: %"PRId64"\n", this
// , amount, m_limit, m_quota_left);
m_quota_left -= amount;
}

View File

@ -3024,6 +3024,7 @@ retry:
peer_class* pc = m_classes.at(c);
if (pc == 0) return;
if (limit <= 0) limit = 0;
else limit = std::min(limit, std::numeric_limits<int>::max() - 1);
pc->channel[channel].throttle(limit);
}
@ -4148,8 +4149,9 @@ retry:
// TODO: use a lower limit than m_settings.connections_limit
// to allocate the to 10% or so of connection slots for incoming
// connections
int limit = m_settings.get_int(settings_pack::connections_limit)
- num_connections();
// cap this at max - 1, since we may add one below
int const limit = std::min(m_settings.get_int(settings_pack::connections_limit)
- num_connections(), std::numeric_limits<int>::max() - 1);
// this logic is here to smooth out the number of new connection
// attempts over time, to prevent connecting a large number of

View File

@ -87,7 +87,7 @@ struct peer_connection: bandwidth_socket, boost::enable_shared_from_this<peer_co
int m_priority;
bool m_ignore_limits;
std::string m_name;
int m_quota;
boost::int64_t m_quota;
};
void peer_connection::assign_bandwidth(int channel, int amount)
@ -459,36 +459,36 @@ void test_no_starvation(int limit)
TORRENT_TEST(equal_connection)
{
test_equal_connections(2, 20);
test_equal_connections(2, 2000);
test_equal_connections(2, 20000);
test_equal_connections(3, 20000);
test_equal_connections(5, 20000);
test_equal_connections(7, 20000);
test_equal_connections(33, 60000);
test_equal_connections(33, 500000);
test_equal_connections(1, 100000000);
test_equal_connections( 2, 20);
test_equal_connections( 2, 2000);
test_equal_connections( 2, 20000);
test_equal_connections( 3, 20000);
test_equal_connections( 5, 20000);
test_equal_connections( 7, 20000);
test_equal_connections(33, 60000);
test_equal_connections(33, 500000);
test_equal_connections( 1, 1000000);
}
TORRENT_TEST(conn_var_rate)
{
test_connections_variable_rate(2, 20, 0);
test_connections_variable_rate(5, 20000, 0);
test_connections_variable_rate(3, 2000, 6000);
test_connections_variable_rate(5, 2000, 30000);
test_connections_variable_rate( 2, 20, 0);
test_connections_variable_rate( 5, 20000, 0);
test_connections_variable_rate( 3, 2000, 6000);
test_connections_variable_rate( 5, 2000, 30000);
test_connections_variable_rate(33, 500000, 0);
}
TORRENT_TEST(torrents)
{
test_torrents(2, 400, 400, 0);
test_torrents(2, 100, 500, 0);
test_torrents(2, 3000, 3000, 6000);
test_torrents(1, 40000, 40000, 0);
test_torrents(24, 50000, 50000, 0);
test_torrents(5, 6000, 6000, 3000);
test_torrents(5, 6000, 5000, 4000);
test_torrents(5, 20000, 20000, 30000);
test_torrents( 2, 400, 400, 0);
test_torrents( 2, 100, 500, 0);
test_torrents( 2, 3000, 3000, 6000);
test_torrents( 1, 40000, 40000, 0);
test_torrents(24, 50000, 50000, 0);
test_torrents( 5, 6000, 6000, 3000);
test_torrents( 5, 6000, 5000, 4000);
test_torrents( 5, 20000, 20000, 30000);
}
TORRENT_TEST(torrent_var_rate)