diff --git a/include/libtorrent/storage.hpp b/include/libtorrent/storage.hpp index a8763ee10..1d9ab0331 100755 --- a/include/libtorrent/storage.hpp +++ b/include/libtorrent/storage.hpp @@ -213,7 +213,12 @@ namespace libtorrent { m_storage->write_resume_data(rd); } bool verify_resume_data(entry const& rd, std::string& error) - { return m_storage->verify_resume_data(rd, error); } + { +#ifndef NDEBUG + m_resume_data_verified = true; +#endif + return m_storage->verify_resume_data(rd, error); + } bool is_allocating() const { return m_state == state_expand_pieces; } @@ -398,6 +403,9 @@ namespace libtorrent // the piece_manager destructs. This is because // the torrent_info object is owned by the torrent. boost::shared_ptr m_torrent; +#ifndef NDEBUG + bool m_resume_data_verified; +#endif }; } diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 667456f3a..3d3392b6a 100755 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -1826,7 +1826,6 @@ namespace detail { tracker_request req = t.generate_tracker_request(); TORRENT_ASSERT(req.event == tracker_request::stopped); - TORRENT_ASSERT(!m_listen_sockets.empty()); req.listen_port = 0; if (!m_listen_sockets.empty()) req.listen_port = m_listen_sockets.front().external_port; diff --git a/src/storage.cpp b/src/storage.cpp index 528fa6785..020a061bc 100755 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -635,8 +635,9 @@ namespace libtorrent // the resume data says we have the entire torrent // make sure the file sizes are the right ones for (torrent_info::file_iterator i = m_info->begin_files(true) - , end(m_info->end_files(true)); i != end; ++i, ++fs) + , end(m_info->end_files(true)); i != end; ++i, ++fs) { + std::cerr << "filesize: " << i->size << std::endl; if (i->size != fs->first) { error = "file size for '" + i->path.native_file_string() @@ -645,7 +646,6 @@ namespace libtorrent return false; } } - return true; } return match_filesizes(*m_info, m_save_path, file_sizes @@ -1108,6 +1108,9 @@ namespace libtorrent , m_io_thread(io) , m_torrent(torrent) { +#ifndef NDEBUG + m_resume_data_verified = false; +#endif } piece_manager::~piece_manager() @@ -1578,6 +1581,7 @@ namespace libtorrent if (!data.piece_map.empty() && int(data.piece_map.size()) <= m_info->num_pieces()) { + TORRENT_ASSERT(m_resume_data_verified); for (int i = 0; i < (int)data.piece_map.size(); ++i) { m_slot_to_piece[i] = data.piece_map[i]; diff --git a/test/test_storage.cpp b/test/test_storage.cpp index 9901d1be1..b437a56af 100644 --- a/test/test_storage.cpp +++ b/test/test_storage.cpp @@ -2,6 +2,7 @@ #include "libtorrent/file_pool.hpp" #include "libtorrent/hasher.hpp" #include "libtorrent/session.hpp" +#include "libtorrent/alert_types.hpp" #include "libtorrent/aux_/session_impl.hpp" #include @@ -96,6 +97,8 @@ void run_storage_tests(boost::intrusive_ptr info std::vector pieces; num_pieces = 0; std::string error_msg; + entry frd; + pm->verify_resume_data(frd, error_msg); TEST_CHECK(pm->check_fastresume(d, pieces, num_pieces , storage_mode, error_msg) == false); bool finished = false; @@ -253,6 +256,63 @@ void run_test(path const& test_path) } +void test_fastresume() +{ + std::cout << "=== test fastresume ===" << std::endl; + create_directory("tmp1"); + std::ofstream file("tmp1/temporary"); + boost::intrusive_ptr t = create_torrent(&file); + file.close(); + TEST_CHECK(exists("tmp1/temporary")); + + entry resume; + { + session ses; + + torrent_handle h = ses.add_torrent(boost::intrusive_ptr(new torrent_info(*t)) + , "tmp1", entry() + , storage_mode_compact); + + for (int i = 0; i < 10; ++i) + { + test_sleep(1000); + torrent_status s = h.status(); + if (s.progress == 1.0f) + { + std::cout << "progress: 1.0f" << std::endl; + break; + } + } + resume = h.write_resume_data(); + ses.remove_torrent(h, session::delete_files); + } + TEST_CHECK(!exists("tmp1/temporary")); + resume.print(std::cout); + + { + session ses; + ses.set_severity_level(alert::debug); + torrent_handle h = ses.add_torrent(t, "tmp1", resume + , storage_mode_compact); + + + std::auto_ptr a = ses.pop_alert(); + ptime end = time_now() + seconds(20); + while (a.get() == 0 || dynamic_cast(a.get()) == 0) + { + if (ses.wait_for_alert(end - time_now()) == 0) + { + std::cerr << "wait_for_alert() expired" << std::endl; + break; + } + a = ses.pop_alert(); + assert(a.get()); + std::cerr << a->msg() << std::endl; + } + TEST_CHECK(dynamic_cast(a.get()) != 0); + } +} + int test_main() { std::vector test_paths; @@ -273,6 +333,8 @@ int test_main() std::for_each(test_paths.begin(), test_paths.end(), bind(&run_test, _1)); + test_fastresume(); + return 0; }