fix backwards compatibility issue when loading the torrent info dict from resume data

This commit is contained in:
arvidn 2017-06-29 17:24:24 +03:00 committed by Arvid Norberg
parent b13ac50f4e
commit 3c8450d47c
4 changed files with 198 additions and 127 deletions

View File

@ -49,6 +49,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <map>
#include <cstring>
#include <deque>
#include <mutex>
#ifdef __MACH__
#include <mach/task_info.h>

View File

@ -59,7 +59,8 @@ namespace {
current_flags |= flag;
}
}
}
} // anonyous namespace
add_torrent_params read_resume_data(bdecode_node const& rd, error_code& ec)
{
@ -89,7 +90,6 @@ namespace {
ret.info_hash.assign(info_hash.data());
// TODO: 4 add unit test for this, and all other fields of the resume data
bdecode_node const info = rd.dict_find_dict("info");
if (info)
{

View File

@ -219,7 +219,12 @@ namespace {
if (atp.flags & add_torrent_params::flag_use_resume_save_path
&& !resume_data.save_path.empty())
{
atp.save_path = resume_data.save_path;
atp.save_path = std::move(resume_data.save_path);
}
if (!atp.ti)
{
atp.ti = std::move(resume_data.ti);
}
if (!resume_data.trackers.empty())
@ -285,9 +290,9 @@ namespace {
atp.verified_pieces.swap(resume_data.verified_pieces);
atp.piece_priorities.swap(resume_data.piece_priorities);
atp.merkle_tree.swap(resume_data.merkle_tree);
atp.merkle_tree = std::move(resume_data.merkle_tree);
atp.renamed_files.swap(resume_data.renamed_files);
atp.renamed_files = std::move(resume_data.renamed_files);
if ((atp.flags & add_torrent_params::flag_override_resume_data) == 0)
{
@ -315,7 +320,9 @@ namespace {
atp.file_priorities = resume_data.file_priorities;
}
}
}
} // anonymous namespace
#endif
#ifndef BOOST_NO_EXCEPTIONS

View File

@ -751,19 +751,80 @@ TORRENT_TEST(zero_file_prio_deprecated)
{
test_zero_file_prio(true);
}
TORRENT_TEST(backwards_compatible_resume_info_dict)
{
// make sure the "info" dictionary is picked up correctly from the
// resume data in backwards compatible mode
std::shared_ptr<torrent_info> ti = generate_torrent();
entry rd;
rd["file-format"] = "libtorrent resume file";
rd["name"] = ti->name();
rd["info-hash"] = ti->info_hash();
auto metainfo = ti->metadata();
rd["info"] = bdecode(metainfo.get(), metainfo.get() + ti->metadata_size());
std::vector<char> resume_data;
bencode(back_inserter(resume_data), rd);
add_torrent_params atp;
atp.resume_data = std::move(resume_data);
atp.save_path = ".";
session ses;
torrent_handle h = ses.add_torrent(atp);
auto torrent = h.torrent_file();
TEST_CHECK(torrent->info_hash() == ti->info_hash());
torrent_status s = h.status();
}
#endif
TORRENT_TEST(resume_info_dict)
{
// make sure the "info" dictionary is picked up correctly from the
// resume data
std::shared_ptr<torrent_info> ti = generate_torrent();
entry rd;
rd["file-format"] = "libtorrent resume file";
rd["name"] = ti->name();
rd["info-hash"] = ti->info_hash();
auto metainfo = ti->metadata();
rd["info"] = bdecode(metainfo.get(), metainfo.get() + ti->metadata_size());
std::vector<char> resume_data;
bencode(back_inserter(resume_data), rd);
error_code ec;
add_torrent_params atp = read_resume_data(resume_data, ec);
TEST_CHECK(atp.ti->info_hash() == ti->info_hash());
}
TORRENT_TEST(zero_file_prio)
{
test_zero_file_prio();
}
void test_seed_mode(bool const file_prio, bool const pieces_have, bool const piece_prio
, bool const all_files_zero = false, bool const test_deprecated = false)
enum class test_mode_t
{
std::printf("test_seed_mode file_prio: %d pieces_have: %d piece_prio: %d\n"
, file_prio, pieces_have, piece_prio);
none = 0,
file_prio = 1,
pieces_have = 2,
piece_prio = 4,
all_files_zero = 8,
deprecated = 16
};
namespace libtorrent {
namespace flags {
template <>
struct enable_flag_operators<test_mode_t> : std::true_type {};
}
}
void test_seed_mode(test_mode_t const flags)
{
lt::session ses(settings());
std::shared_ptr<torrent_info> ti = generate_torrent();
add_torrent_params p;
@ -777,12 +838,12 @@ void test_seed_mode(bool const file_prio, bool const pieces_have, bool const pie
rd["info-hash"] = ti->info_hash().to_string();
rd["blocks per piece"] = (std::max)(1, ti->piece_length() / 0x4000);
if (file_prio)
if (test(flags & test_mode_t::file_prio))
{
// this should take it out of seed_mode
entry::list_type& file_prio = rd["file_priority"].list();
file_prio.push_back(entry(0));
if (all_files_zero)
if (test(flags & test_mode_t::all_files_zero))
{
for (int i = 0; i < 100; ++i)
{
@ -792,14 +853,14 @@ void test_seed_mode(bool const file_prio, bool const pieces_have, bool const pie
}
std::string pieces(ti->num_pieces(), '\x01');
if (pieces_have)
if (test(flags & test_mode_t::pieces_have))
{
pieces[0] = '\0';
}
rd["pieces"] = pieces;
std::string pieces_prio(ti->num_pieces(), '\x01');
if (piece_prio)
if (test(flags & test_mode_t::piece_prio))
{
pieces_prio[0] = '\0';
}
@ -811,7 +872,7 @@ void test_seed_mode(bool const file_prio, bool const pieces_have, bool const pie
bencode(back_inserter(resume_data), rd);
#ifndef TORRENT_NO_DEPRECATE
if (test_deprecated)
if (test(flags & test_mode_t::deprecated))
{
p.resume_data = resume_data;
}
@ -828,7 +889,9 @@ void test_seed_mode(bool const file_prio, bool const pieces_have, bool const pie
torrent_handle h = ses.add_torrent(p);
torrent_status s = h.status();
if (file_prio || piece_prio || pieces_have)
if (test(flags & (test_mode_t::file_prio
| test_mode_t::piece_prio
| test_mode_t::pieces_have)))
{
TEST_EQUAL(s.seed_mode, false);
}
@ -840,43 +903,43 @@ void test_seed_mode(bool const file_prio, bool const pieces_have, bool const pie
#ifndef TORRENT_NO_DEPRECATE
TORRENT_TEST(seed_mode_file_prio_deprecated)
{
test_seed_mode(true, false, false, true);
test_seed_mode(test_mode_t::file_prio | test_mode_t::deprecated);
}
TORRENT_TEST(seed_mode_piece_prio_deprecated)
{
test_seed_mode(false, true, false, true);
test_seed_mode(test_mode_t::pieces_have | test_mode_t::deprecated);
}
TORRENT_TEST(seed_mode_piece_have_deprecated)
{
test_seed_mode(false, false, true, true);
test_seed_mode(test_mode_t::piece_prio | test_mode_t::deprecated);
}
TORRENT_TEST(seed_mode_preserve_deprecated)
{
test_seed_mode(false, false, false, true);
test_seed_mode(test_mode_t::deprecated);
}
#endif
TORRENT_TEST(seed_mode_file_prio)
{
test_seed_mode(true, false, false);
test_seed_mode(test_mode_t::file_prio);
}
TORRENT_TEST(seed_mode_piece_prio)
{
test_seed_mode(false, true, false);
test_seed_mode(test_mode_t::pieces_have);
}
TORRENT_TEST(seed_mode_piece_have)
{
test_seed_mode(false, false, true);
test_seed_mode(test_mode_t::piece_prio);
}
TORRENT_TEST(seed_mode_preserve)
{
test_seed_mode(false, false, false);
test_seed_mode(test_mode_t::none);
}
TORRENT_TEST(resume_save_load)