From d3df16cd12f6f4f73496db850bddb17d0b8992e8 Mon Sep 17 00:00:00 2001 From: arvidn Date: Fri, 18 Mar 2016 14:38:45 -0400 Subject: [PATCH] convert tracker try-next test to be a simulation (and deterministic) --- simulation/test_tracker.cpp | 97 ++++++++++++++++++++++++++++-- test/test_tracker.cpp | 115 ------------------------------------ 2 files changed, 92 insertions(+), 120 deletions(-) diff --git a/simulation/test_tracker.cpp b/simulation/test_tracker.cpp index e33659c45..7e7789c00 100644 --- a/simulation/test_tracker.cpp +++ b/simulation/test_tracker.cpp @@ -363,8 +363,17 @@ TORRENT_TEST(ipv6_support) TEST_EQUAL(v6_announces, 2); } -template -void tracker_test(Announce a, Test1 test1, Test2 test2, char const* url_path = "/announce") +// this runs a simulation of a torrent with tracker(s), making sure the request +// received by the tracker matches the expectation. +// The Setup function is run first, giving the test an opportunity to add +// trackers to the torrent. It's expected to return the number of seconds to +// wait until test2 is called. +// The Announce function is called on http requests. Test1 is run on the session +// 5 seconds after startup. The tracker is running at 10.0.0.2 (or tracker.com) +// port 8080. +template +void tracker_test(Setup setup, Announce a, Test1 test1, Test2 test2 + , char const* url_path = "/announce") { using sim::asio::ip::address_v4; sim_config network_cfg; @@ -390,7 +399,7 @@ void tracker_test(Announce a, Test1 test1, Test2 test2, char const* url_path = " p.name = "test-torrent"; p.save_path = "."; p.info_hash.assign("abababababababababab"); - p.trackers.push_back("http://tracker.com:8080/announce"); + int const delay = setup(p); ses->async_add_torrent(p); // run the test 5 seconds in @@ -405,7 +414,7 @@ void tracker_test(Announce a, Test1 test1, Test2 test2, char const* url_path = " }); asio::high_resolution_timer t2(ios); - t2.expires_from_now(chrono::seconds(9)); + t2.expires_from_now(chrono::seconds(5 + delay)); t2.async_wait([&ses,&test2](boost::system::error_code const& ec) { std::vector torrents = ses->get_torrents(); @@ -416,7 +425,7 @@ void tracker_test(Announce a, Test1 test1, Test2 test2, char const* url_path = " // then shut down 10 seconds in asio::high_resolution_timer t3(ios); - t3.expires_from_now(chrono::seconds(10)); + t3.expires_from_now(chrono::seconds(10 + delay)); t3.async_wait([&ses,&zombie](boost::system::error_code const& ec) { zombie = ses->abort(); @@ -427,6 +436,16 @@ void tracker_test(Announce a, Test1 test1, Test2 test2, char const* url_path = " sim.run(); } +template +void tracker_test(Announce a, Test1 test1, Test2 test2, char const* url_path = "/announce") +{ + tracker_test([](lt::add_torrent_params& p) { + p.trackers.push_back("http://tracker.com:8080/announce"); + return 5; + }, + a, test1, test2, url_path); +} + template void announce_entry_test(Announce a, Test t, char const* url_path = "/announce") { @@ -609,6 +628,74 @@ TORRENT_TEST(test_invalid_bencoding) }); } +TORRENT_TEST(try_next) +{ +// test that we move on to try the next tier if the first one fails + + bool got_announce = false; + tracker_test( + [](lt::add_torrent_params& p) + { + // TODO: 3 use tracker_tiers here to put the trackers in different tiers + p.trackers.push_back("udp://failing-tracker.com/announce"); + p.trackers.push_back("http://failing-tracker.com/announce"); + + // this is the working tracker + p.trackers.push_back("http://tracker.com:8080/announce"); + return 60; + }, + [&](std::string method, std::string req + , std::map& headers) + { + got_announce = true; + TEST_EQUAL(method, "GET"); + + char response[500]; + // respond with an empty peer list + int size = snprintf(response, sizeof(response), "d5:peers0:e"); + return sim::send_response(200, "OK", size) + response; + } + , [](torrent_handle h) {} + , [](torrent_handle h) + { + torrent_status st = h.status(); + TEST_EQUAL(st.current_tracker, "http://tracker.com:8080/announce"); + + std::vector tr = h.trackers(); + + TEST_EQUAL(tr.size(), 3); + + for (int i = 0; i < tr.size(); ++i) + { + fprintf(stderr, "tracker \"%s\"\n", tr[i].url.c_str()); + if (tr[i].url == "http://tracker.com:8080/announce") + { + TEST_EQUAL(tr[i].fails, 0); + TEST_EQUAL(tr[i].verified, true); + } + else if (tr[i].url == "http://failing-tracker.com/announce") + { + TEST_CHECK(tr[i].fails >= 1); + TEST_EQUAL(tr[i].verified, false); + TEST_EQUAL(tr[i].last_error + , error_code(boost::asio::error::host_not_found)); + } + else if (tr[i].url == "udp://failing-tracker.com/announce") + { + TEST_CHECK(tr[i].fails >= 1); + TEST_EQUAL(tr[i].verified, false); + TEST_EQUAL(tr[i].last_error + , error_code(boost::asio::error::host_not_found)); + } + else + { + TEST_ERROR(("unexpected tracker URL: " + tr[i].url).c_str()); + } + } + }); + TEST_EQUAL(got_announce, true); +} + // TODO: test external IP // TODO: test with different queuing settings // TODO: test when a torrent transitions from downloading to finished and diff --git a/test/test_tracker.cpp b/test/test_tracker.cpp index 8c7d8adc3..eead9c622 100644 --- a/test/test_tracker.cpp +++ b/test/test_tracker.cpp @@ -387,121 +387,6 @@ TORRENT_TEST(udp_tracker) TEST_EQUAL(num_udp_announces(), prev_udp_announces + 2); } -TORRENT_TEST(try_next) -{ -// ======================================== -// test that we move on to try the next tier if the first one fails -// ======================================== - - int http_port = start_web_server(); - int udp_port = start_udp_tracker(); - - int prev_udp_announces = num_udp_announces(); - - settings_pack pack = settings(); - pack.set_bool(settings_pack::announce_to_all_trackers, true); - pack.set_bool(settings_pack::announce_to_all_tiers, false); - pack.set_int(settings_pack::tracker_completion_timeout, 2); - pack.set_int(settings_pack::tracker_receive_timeout, 1); - pack.set_str(settings_pack::listen_interfaces, "0.0.0.0:39775"); - - boost::scoped_ptr s(new lt::session(pack)); - - error_code ec; - remove_all("tmp2_tracker", ec); - create_directory("tmp2_tracker", ec); - std::ofstream file(combine_path("tmp2_tracker", "temporary").c_str()); - boost::shared_ptr t = ::create_torrent(&file, "temporary", 16 * 1024, 13, false); - file.close(); - - // this should fail - char tracker_url[200]; - snprintf(tracker_url, sizeof(tracker_url), "udp://www1.non-existent.com:80/announce"); - t->add_tracker(tracker_url, 0); - - // and this should fail - snprintf(tracker_url, sizeof(tracker_url), "http://127.0.0.2:3/announce"); - t->add_tracker(tracker_url, 1); - - // this should be announced to - // udp trackers are prioritized if they're on the same host as an http one - // so this must be before the http one on 127.0.0.1 - snprintf(tracker_url, sizeof(tracker_url), "udp://127.0.0.1:%d/announce", udp_port); - t->add_tracker(tracker_url, 2); - - // and this should not be announced to (since the one before it succeeded) - snprintf(tracker_url, sizeof(tracker_url), "http://127.0.0.1:%d/announce", http_port); - t->add_tracker(tracker_url, 3); - - prev_udp_announces = num_udp_announces(); - - add_torrent_params addp; - addp.flags &= ~add_torrent_params::flag_paused; - addp.flags &= ~add_torrent_params::flag_auto_managed; - addp.flags |= add_torrent_params::flag_seed_mode; - addp.ti = t; - addp.save_path = "tmp2_tracker"; - torrent_handle h = s->add_torrent(addp); - - for (int i = 0; i < 50; ++i) - { - print_alerts(*s, "s"); - if (num_udp_announces() == prev_udp_announces + 1) break; - - fprintf(stderr, "UDP: %d / %d\n", int(num_udp_announces()) - , int(prev_udp_announces) + 1); - test_sleep(100); - } - - // we expect the first two trackers to have failed (because the hostname - // doesn't exist and the port isn't open), - // the second tracker to have succeeded and the third to not have been used - std::vector tr = h.trackers(); - - TEST_EQUAL(tr.size(), 4); - - if (tr.size() == 4) - { - // this tracker may not have failed yet, but just timed out (if the - // hostname lookup is slow) - if (tr[0].fails == 1) - { - TEST_EQUAL(tr[0].verified, false); - TEST_EQUAL(tr[0].last_error - , error_code(boost::asio::error::host_not_found)); - } - - TEST_EQUAL(tr[1].fails, 1); - TEST_EQUAL(tr[1].verified, false); - const bool tracker_error = tr[1].last_error == boost::asio::error::timed_out - || tr[1].last_error == boost::system::error_condition(boost::system::errc::connection_refused) -#ifdef TORRENT_WINDOWS - || tr[1].last_error == boost::system::error_code(ERROR_CONNECTION_REFUSED, boost::system::system_category()) -#endif - ; - TEST_EQUAL(tracker_error, true); - - TEST_EQUAL(tr[2].fails, 0); - TEST_EQUAL(tr[2].verified, true); - - TEST_EQUAL(tr[3].fails, 0); - TEST_EQUAL(tr[3].verified, false); - } - test_sleep(1000); - - TEST_EQUAL(num_udp_announces(), prev_udp_announces + 1); - - fprintf(stderr, "destructing session\n"); - s.reset(); - fprintf(stderr, "done\n"); - - fprintf(stderr, "stop_tracker\n"); - stop_udp_tracker(); - fprintf(stderr, "stop_web_server\n"); - stop_web_server(); - fprintf(stderr, "done\n"); -} - TORRENT_TEST(http_peers) { int http_port = start_web_server();