/* Copyright (c) 2010, 2014-2020, 2022, Arvid Norberg Copyright (c) 2016-2017, Alden Torres All rights reserved. You may use, distribute and modify this code under the terms of the BSD license, see LICENSE file. */ #include "test.hpp" #include "libtorrent/settings_pack.hpp" #include "libtorrent/aux_/session_settings.hpp" #include "libtorrent/entry.hpp" #include "libtorrent/bencode.hpp" #include "libtorrent/bdecode.hpp" #include using namespace lt; using namespace lt::aux; TORRENT_TEST(default_settings) { aux::session_settings sett; entry e; save_settings_to_dict(non_default_settings(sett), e.dict()); // all default values are supposed to be skipped // by save_settings TEST_EQUAL(e.dict().size(), 0); #if TORRENT_USE_IOSTREAM if (e.dict().size() > 0) std::cout << e << std::endl; #endif } TORRENT_TEST(default_settings2) { aux::session_settings sett; settings_pack def = default_settings(); for (int i = 0; i < settings_pack::num_string_settings; ++i) { TEST_EQUAL(sett.get_str(settings_pack::string_type_base + i) , def.get_str(settings_pack::string_type_base + i)); } for (int i = 0; i < settings_pack::num_int_settings; ++i) { TEST_EQUAL(sett.get_int(settings_pack::int_type_base + i) , def.get_int(settings_pack::int_type_base + i)); } for (int i = 0; i < settings_pack::num_bool_settings; ++i) { TEST_EQUAL(sett.get_bool(settings_pack::bool_type_base + i) , def.get_bool(settings_pack::bool_type_base + i)); } } TORRENT_TEST(apply_pack) { aux::session_settings sett; settings_pack sp; sp.set_int(settings_pack::max_out_request_queue, 1337); TEST_CHECK(sett.get_int(settings_pack::max_out_request_queue) != 1337); apply_pack(&sp, sett); TEST_EQUAL(sett.get_int(settings_pack::max_out_request_queue), 1337); entry e; save_settings_to_dict(non_default_settings(sett), e.dict()); TEST_EQUAL(e.dict().size(), 1); std::string out; bencode(std::back_inserter(out), e); TEST_EQUAL(out, "d21:max_out_request_queuei1337ee"); } TORRENT_TEST(sparse_pack) { settings_pack pack; TEST_EQUAL(pack.has_val(settings_pack::send_redundant_have), false); pack.set_bool(settings_pack::send_redundant_have, true); TEST_EQUAL(pack.has_val(settings_pack::send_redundant_have), true); TEST_EQUAL(pack.has_val(settings_pack::user_agent), false); TEST_EQUAL(pack.get_bool(settings_pack::send_redundant_have), true); } TORRENT_TEST(test_name) { #define TEST_NAME(n) \ TEST_EQUAL(setting_by_name(#n), settings_pack:: n); \ TEST_EQUAL(name_for_setting(settings_pack:: n), std::string(#n)) #if TORRENT_ABI_VERSION == 1 TEST_NAME(contiguous_recv_buffer); #endif TEST_NAME(choking_algorithm); TEST_NAME(seeding_piece_quota); #if TORRENT_ABI_VERSION == 1 TEST_NAME(half_open_limit); TEST_NAME(mmap_cache); #endif TEST_NAME(peer_turnover_interval); TEST_NAME(peer_fingerprint); TEST_NAME(proxy_tracker_connections); TEST_NAME(predictive_piece_announce); TEST_NAME(max_metadata_size); TEST_NAME(num_optimistic_unchoke_slots); TEST_EQUAL(name_for_setting(settings_pack::peer_tos), std::string("peer_dscp")); TEST_EQUAL(setting_by_name("peer_tos"), settings_pack::peer_dscp); \ } TORRENT_TEST(clear) { settings_pack pack; TEST_EQUAL(pack.has_val(settings_pack::send_redundant_have), false); pack.set_bool(settings_pack::send_redundant_have, true); TEST_EQUAL(pack.has_val(settings_pack::send_redundant_have), true); TEST_EQUAL(pack.has_val(settings_pack::user_agent), false); TEST_EQUAL(pack.get_bool(settings_pack::send_redundant_have), true); pack.clear(); TEST_EQUAL(pack.has_val(settings_pack::send_redundant_have), false); TEST_EQUAL(pack.has_val(settings_pack::user_agent), false); } TORRENT_TEST(clear_single_int) { settings_pack sp; sp.set_int(settings_pack::max_out_request_queue, 1337); TEST_EQUAL(sp.get_int(settings_pack::max_out_request_queue), 1337); sp.clear(settings_pack::max_out_request_queue); // when cleared, we'll get the default value TEST_EQUAL(sp.get_int(settings_pack::max_out_request_queue), 500); } TORRENT_TEST(clear_single_bool) { settings_pack sp; sp.set_bool(settings_pack::send_redundant_have, false); TEST_EQUAL(sp.get_bool(settings_pack::send_redundant_have), false); sp.clear(settings_pack::send_redundant_have); // when cleared, we'll get the default value TEST_EQUAL(sp.get_bool(settings_pack::send_redundant_have), true); } TORRENT_TEST(clear_single_string) { settings_pack sp; sp.set_str(settings_pack::user_agent, "foobar"); TEST_EQUAL(sp.get_str(settings_pack::user_agent), "foobar"); sp.clear(settings_pack::user_agent); // when cleared, we'll get the default value TEST_EQUAL(sp.get_str(settings_pack::user_agent), "libtorrent/2.1.0.0"); } TORRENT_TEST(duplicates) { settings_pack p; p.set_str(settings_pack::peer_fingerprint, "abc"); p.set_str(settings_pack::peer_fingerprint, "cde"); p.set_str(settings_pack::peer_fingerprint, "efg"); p.set_str(settings_pack::peer_fingerprint, "hij"); TEST_EQUAL(p.get_str(settings_pack::peer_fingerprint), "hij"); } TORRENT_TEST(load_pack_from_dict) { aux::session_settings p1; p1.set_str(settings_pack::peer_fingerprint, "abc"); p1.set_int(settings_pack::max_out_request_queue, 1337); p1.set_bool(settings_pack::send_redundant_have, false); entry e; save_settings_to_dict(non_default_settings(p1), e.dict()); std::string s; bencode(std::back_inserter(s), e); bdecode_node n; error_code ec; int ret = bdecode(s.data(), s.data() + int(s.size()), n, ec); TEST_EQUAL(ret, 0); TEST_CHECK(!ec); settings_pack p2 = load_pack_from_dict(n); TEST_EQUAL(p2.get_str(settings_pack::peer_fingerprint), "abc"); TEST_EQUAL(p2.get_int(settings_pack::max_out_request_queue), 1337); TEST_EQUAL(p2.get_bool(settings_pack::send_redundant_have), false); } TORRENT_TEST(settings_pack_abi) { // make sure enum values are preserved across libtorrent versions // for ABI compatibility // These values are only allowed to change across major versions TEST_EQUAL(settings_pack::string_type_base, 0x0000); TEST_EQUAL(settings_pack::int_type_base, 0x4000); TEST_EQUAL(settings_pack::bool_type_base, 0x8000); TEST_EQUAL(settings_pack::type_mask, 0xc000); // strings TEST_EQUAL(settings_pack::outgoing_interfaces, settings_pack::string_type_base + 4); TEST_EQUAL(settings_pack::dht_bootstrap_nodes, settings_pack::string_type_base + 11); // bool TEST_EQUAL(settings_pack::use_dht_as_fallback, settings_pack::bool_type_base + 4); TEST_EQUAL(settings_pack::auto_manage_prefer_seeds, settings_pack::bool_type_base + 12); TEST_EQUAL(settings_pack::proxy_tracker_connections, settings_pack::bool_type_base + 67); // ints TEST_EQUAL(settings_pack::tracker_completion_timeout, settings_pack::int_type_base + 0); TEST_EQUAL(settings_pack::tracker_receive_timeout, settings_pack::int_type_base + 1); TEST_EQUAL(settings_pack::stop_tracker_timeout, settings_pack::int_type_base + 2); TEST_EQUAL(settings_pack::max_suggest_pieces, settings_pack::int_type_base + 66); TEST_EQUAL(settings_pack::connections_slack, settings_pack::int_type_base + 86); TEST_EQUAL(settings_pack::aio_threads, settings_pack::int_type_base + 104); TEST_EQUAL(settings_pack::max_http_recv_buffer_size, settings_pack::int_type_base + 115); TEST_EQUAL(settings_pack::web_seed_name_lookup_retry, settings_pack::int_type_base + 128); TEST_EQUAL(settings_pack::close_file_interval, settings_pack::int_type_base + 129); TEST_EQUAL(settings_pack::max_web_seed_connections, settings_pack::int_type_base + 131); TEST_EQUAL(settings_pack::resolver_cache_timeout, settings_pack::int_type_base + 132); } namespace { bool empty_pack(settings_pack const& sp) { for (std::uint16_t i = 0; i < settings_pack::num_string_settings; ++i) if (sp.has_val(i | settings_pack::string_type_base)) return false; for (std::uint16_t i = 0; i < settings_pack::num_int_settings; ++i) if (sp.has_val(i | settings_pack::int_type_base)) return false; for (std::uint16_t i = 0; i < settings_pack::num_bool_settings; ++i) if (sp.has_val(i | settings_pack::bool_type_base)) return false; return true; } } TORRENT_TEST(non_default_settings) { aux::session_settings def; settings_pack const p = non_default_settings(def); TEST_CHECK(empty_pack(p)); } TORRENT_TEST(non_default_settings2) { aux::session_settings def; def.set_int(settings_pack::max_out_request_queue, 1337); settings_pack const p = non_default_settings(def); TEST_EQUAL(p.get_int(settings_pack::max_out_request_queue), 1337); } TORRENT_TEST(save_settings_to_dict) { settings_pack p; p.set_str(settings_pack::peer_fingerprint, "abc"); p.set_int(settings_pack::max_out_request_queue, 1337); p.set_bool(settings_pack::send_redundant_have, false); entry e; save_settings_to_dict(p, e.dict()); std::string buf; bencode(std::back_inserter(buf), e); TEST_EQUAL(buf, "d21:max_out_request_queuei1337e16:peer_fingerprint3:abc19:send_redundant_havei0ee"); } // MSVC doesn't support making these arrays constexpr yet (which is required to // initialize them before global constructors) #if !defined _MSC_VER namespace { // make sure a global constructor has access to the default values, to // initialize itself with lt::aux::session_settings g_sett; } TORRENT_TEST(global_constructors) { TEST_CHECK(g_sett.get_int(lt::settings_pack::aio_threads) > 0); } #endif TORRENT_TEST(i2p_tunnel_variance_settings) { #if TORRENT_USE_I2P lt::settings_pack pack; // Default values should be 0 TEST_EQUAL(pack.get_int(lt::settings_pack::i2p_inbound_length_variance), 0); TEST_EQUAL(pack.get_int(lt::settings_pack::i2p_outbound_length_variance), 0); pack.set_int(lt::settings_pack::i2p_inbound_length_variance, 2); pack.set_int(lt::settings_pack::i2p_outbound_length_variance, -3); TEST_EQUAL(pack.get_int(lt::settings_pack::i2p_inbound_length_variance), 2); TEST_EQUAL(pack.get_int(lt::settings_pack::i2p_outbound_length_variance), -3); // After clearing, it should go back to defaults pack.clear(lt::settings_pack::i2p_inbound_length_variance); pack.clear(lt::settings_pack::i2p_outbound_length_variance); TEST_EQUAL(pack.get_int(lt::settings_pack::i2p_inbound_length_variance), 0); TEST_EQUAL(pack.get_int(lt::settings_pack::i2p_outbound_length_variance), 0); #endif }