1 /*
2
3 Copyright (c) 2013, Arvid Norberg
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
9
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the distribution.
15 * Neither the name of the author nor the names of its
16 contributors may be used to endorse or promote products derived
17 from this software without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 POSSIBILITY OF SUCH DAMAGE.
30
31 */
32
33 #include "libtorrent/session.hpp"
34 #include <functional>
35 #include <thread>
36
37 #include "test.hpp"
38 #include "setup_transfer.hpp"
39 #include "libtorrent/alert_types.hpp"
40 #include "libtorrent/session_stats.hpp"
41 #include "libtorrent/performance_counters.hpp"
42 #include "libtorrent/bdecode.hpp"
43 #include "libtorrent/bencode.hpp"
44 #include "libtorrent/torrent_info.hpp"
45 #include "libtorrent/session_stats.hpp"
46 #include "settings.hpp"
47
48 #include <fstream>
49
50 using namespace std::placeholders;
51 using namespace lt;
52
TORRENT_TEST(session)53 TORRENT_TEST(session)
54 {
55 settings_pack p = settings();
56 p.set_int(settings_pack::alert_mask, ~0);
57 lt::session ses(p);
58
59 settings_pack sett = settings();
60 sett.set_int(settings_pack::num_optimistic_unchoke_slots, 10);
61 sett.set_int(settings_pack::unchoke_slots_limit, 10);
62 sett.set_int(settings_pack::resolver_cache_timeout, 1000);
63
64 ses.apply_settings(sett);
65
66 // verify that we get the appropriate performance warning
67
68 alert const* a;
69 for (;;)
70 {
71 a = wait_for_alert(ses, performance_alert::alert_type, "ses1");
72
73 if (a == nullptr) break;
74 TEST_EQUAL(a->type(), performance_alert::alert_type);
75
76 if (alert_cast<performance_alert>(a)->warning_code
77 == performance_alert::too_many_optimistic_unchoke_slots)
78 break;
79 }
80
81 TEST_CHECK(a);
82
83 sett.set_int(settings_pack::unchoke_slots_limit, 0);
84 ses.apply_settings(sett);
85 TEST_CHECK(ses.get_settings().get_int(settings_pack::unchoke_slots_limit) == 0);
86
87 sett.set_int(settings_pack::unchoke_slots_limit, -1);
88 ses.apply_settings(sett);
89 TEST_CHECK(ses.get_settings().get_int(settings_pack::unchoke_slots_limit) == -1);
90
91 sett.set_int(settings_pack::unchoke_slots_limit, 8);
92 ses.apply_settings(sett);
93 TEST_CHECK(ses.get_settings().get_int(settings_pack::unchoke_slots_limit) == 8);
94
95 TEST_EQUAL(ses.get_settings().get_int(settings_pack::resolver_cache_timeout), 1000);
96 sett.set_int(settings_pack::resolver_cache_timeout, 1001);
97 ses.apply_settings(sett);
98 TEST_EQUAL(ses.get_settings().get_int(settings_pack::resolver_cache_timeout), 1001);
99
100 // make sure the destructor waits properly
101 // for the asynchronous call to set the alert
102 // mask completes, before it goes on to destruct
103 // the session object
104 }
105
TORRENT_TEST(async_add_torrent_duplicate_error)106 TORRENT_TEST(async_add_torrent_duplicate_error)
107 {
108 settings_pack p = settings();
109 p.set_int(settings_pack::alert_mask, ~0);
110 lt::session ses(p);
111
112 add_torrent_params atp;
113 atp.info_hash.assign("abababababababababab");
114 atp.save_path = ".";
115 ses.async_add_torrent(atp);
116
117 auto* a = alert_cast<add_torrent_alert>(wait_for_alert(ses, add_torrent_alert::alert_type, "ses"));
118 TEST_CHECK(a);
119 if (a == nullptr) return;
120
121 atp.flags |= torrent_flags::duplicate_is_error;
122 ses.async_add_torrent(atp);
123 a = alert_cast<add_torrent_alert>(wait_for_alert(ses, add_torrent_alert::alert_type, "ses"));
124 TEST_CHECK(a);
125 if (a == nullptr) return;
126 TEST_CHECK(!a->handle.is_valid());
127 TEST_CHECK(a->error);
128 }
129
TORRENT_TEST(async_add_torrent_duplicate)130 TORRENT_TEST(async_add_torrent_duplicate)
131 {
132 settings_pack p = settings();
133 p.set_int(settings_pack::alert_mask, ~0);
134 lt::session ses(p);
135
136 add_torrent_params atp;
137 atp.info_hash.assign("abababababababababab");
138 atp.save_path = ".";
139 ses.async_add_torrent(atp);
140
141 auto* a = alert_cast<add_torrent_alert>(wait_for_alert(ses, add_torrent_alert::alert_type, "ses"));
142 TEST_CHECK(a);
143 if (a == nullptr) return;
144 torrent_handle h = a->handle;
145 TEST_CHECK(!a->error);
146
147 atp.flags &= ~torrent_flags::duplicate_is_error;
148 ses.async_add_torrent(atp);
149 a = alert_cast<add_torrent_alert>(wait_for_alert(ses, add_torrent_alert::alert_type, "ses"));
150 TEST_CHECK(a);
151 if (a == nullptr) return;
152 TEST_CHECK(a->handle == h);
153 TEST_CHECK(!a->error);
154 }
155
TORRENT_TEST(async_add_torrent_duplicate_back_to_back)156 TORRENT_TEST(async_add_torrent_duplicate_back_to_back)
157 {
158 settings_pack p = settings();
159 p.set_int(settings_pack::alert_mask, ~0);
160 lt::session ses(p);
161
162 add_torrent_params atp;
163 atp.info_hash.assign("abababababababababab");
164 atp.save_path = ".";
165 atp.flags |= torrent_flags::paused;
166 atp.flags &= ~torrent_flags::apply_ip_filter;
167 atp.flags &= ~torrent_flags::auto_managed;
168 ses.async_add_torrent(atp);
169
170 atp.flags &= ~torrent_flags::duplicate_is_error;
171 ses.async_add_torrent(atp);
172
173 auto* a = alert_cast<add_torrent_alert>(wait_for_alert(ses
174 , add_torrent_alert::alert_type, "ses", pop_alerts::cache_alerts));
175 TEST_CHECK(a);
176 if (a == nullptr) return;
177 torrent_handle h = a->handle;
178 TEST_CHECK(!a->error);
179
180 a = alert_cast<add_torrent_alert>(wait_for_alert(ses
181 , add_torrent_alert::alert_type, "ses", pop_alerts::cache_alerts));
182 TEST_CHECK(a);
183 if (a == nullptr) return;
184 TEST_CHECK(a->handle == h);
185 TEST_CHECK(!a->error);
186
187 torrent_status st = h.status();
188 TEST_CHECK(st.flags & torrent_flags::paused);
189 TEST_CHECK(!(st.flags & torrent_flags::apply_ip_filter));
190 TEST_CHECK(!(st.flags & torrent_flags::auto_managed));
191 }
192
TORRENT_TEST(load_empty_file)193 TORRENT_TEST(load_empty_file)
194 {
195 settings_pack p = settings();
196 p.set_int(settings_pack::alert_mask, ~0);
197 lt::session ses(p);
198
199 add_torrent_params atp;
200 error_code ignore_errors;
201 atp.ti = std::make_shared<torrent_info>("", std::ref(ignore_errors), from_span);
202 atp.save_path = ".";
203 error_code ec;
204 torrent_handle h = ses.add_torrent(std::move(atp), ec);
205
206 TEST_CHECK(!h.is_valid());
207 TEST_CHECK(ec == error_code(errors::no_metadata));
208 }
209
TORRENT_TEST(session_stats)210 TORRENT_TEST(session_stats)
211 {
212 std::vector<stats_metric> stats = session_stats_metrics();
213 std::sort(stats.begin(), stats.end()
214 , [](stats_metric const& lhs, stats_metric const& rhs)
215 { return lhs.value_index < rhs.value_index; });
216
217 TEST_EQUAL(stats.size(), lt::counters::num_counters);
218 // make sure every stat index is represented in the stats_metric vector
219 for (int i = 0; i < int(stats.size()); ++i)
220 {
221 TEST_EQUAL(stats[std::size_t(i)].value_index, i);
222 }
223
224 TEST_EQUAL(lt::find_metric_idx("peer.incoming_connections")
225 , lt::counters::incoming_connections);
226 }
227
TORRENT_TEST(paused_session)228 TORRENT_TEST(paused_session)
229 {
230 lt::session s(settings());
231 s.pause();
232
233 lt::add_torrent_params ps;
234 std::ofstream file("temporary");
235 ps.ti = ::create_torrent(&file, "temporary", 16 * 1024, 13, false);
236 ps.flags = lt::torrent_flags::paused;
237 ps.save_path = ".";
238
239 torrent_handle h = s.add_torrent(std::move(ps));
240
241 std::this_thread::sleep_for(lt::milliseconds(2000));
242 h.resume();
243 std::this_thread::sleep_for(lt::milliseconds(1000));
244
245 TEST_CHECK(!(h.flags() & torrent_flags::paused));
246 }
247
TORRENT_TEST(get_cache_info)248 TORRENT_TEST(get_cache_info)
249 {
250 lt::session s(settings());
251 lt::cache_status ret;
252 s.get_cache_info(&ret);
253
254 TEST_CHECK(ret.pieces.empty());
255 #if TORRENT_ABI_VERSION == 1
256 TEST_EQUAL(ret.blocks_written, 0);
257 TEST_EQUAL(ret.writes, 0);
258 TEST_EQUAL(ret.blocks_read, 0);
259 TEST_EQUAL(ret.blocks_read_hit, 0);
260 TEST_EQUAL(ret.reads, 0);
261 TEST_EQUAL(ret.queued_bytes, 0);
262 TEST_EQUAL(ret.cache_size, 0);
263 TEST_EQUAL(ret.write_cache_size, 0);
264 TEST_EQUAL(ret.read_cache_size, 0);
265 TEST_EQUAL(ret.pinned_blocks, 0);
266 TEST_EQUAL(ret.total_used_buffers, 0);
267 TEST_EQUAL(ret.average_read_time, 0);
268 TEST_EQUAL(ret.average_write_time, 0);
269 TEST_EQUAL(ret.average_hash_time, 0);
270 TEST_EQUAL(ret.average_job_time, 0);
271 TEST_EQUAL(ret.cumulative_job_time, 0);
272 TEST_EQUAL(ret.cumulative_read_time, 0);
273 TEST_EQUAL(ret.cumulative_write_time, 0);
274 TEST_EQUAL(ret.cumulative_hash_time, 0);
275 TEST_EQUAL(ret.total_read_back, 0);
276 TEST_EQUAL(ret.read_queue_size, 0);
277 TEST_EQUAL(ret.blocked_jobs, 0);
278 TEST_EQUAL(ret.queued_jobs, 0);
279 TEST_EQUAL(ret.peak_queued, 0);
280 TEST_EQUAL(ret.pending_jobs, 0);
281 TEST_EQUAL(ret.num_jobs, 0);
282 TEST_EQUAL(ret.num_read_jobs, 0);
283 TEST_EQUAL(ret.num_write_jobs, 0);
284 TEST_EQUAL(ret.arc_mru_size, 0);
285 TEST_EQUAL(ret.arc_mru_ghost_size, 0);
286 TEST_EQUAL(ret.arc_mfu_size, 0);
287 TEST_EQUAL(ret.arc_mfu_ghost_size, 0);
288 TEST_EQUAL(ret.arc_write_size, 0);
289 TEST_EQUAL(ret.arc_volatile_size, 0);
290 TEST_EQUAL(ret.num_writing_threads, 0);
291 #endif
292 }
293
294 template <typename Set, typename Save, typename Default, typename Load>
test_save_restore(Set setup,Save s,Default d,Load l)295 void test_save_restore(Set setup, Save s, Default d, Load l)
296 {
297 entry st;
298 {
299 settings_pack p = settings();
300 setup(p);
301 lt::session ses(p);
302 s(ses, st);
303 }
304
305 {
306 settings_pack p = settings();
307 d(p);
308 lt::session ses(p);
309 // the loading function takes a bdecode_node, so we have to transform the
310 // entry
311 std::printf("%s\n", st.to_string().c_str());
312 std::vector<char> buf;
313 bencode(std::back_inserter(buf), st);
314 bdecode_node state;
315 error_code ec;
316 int ret = bdecode(buf.data(), buf.data() + buf.size()
317 , state, ec, nullptr, 100, 1000);
318 TEST_EQUAL(ret, 0);
319 if (ec)
320 {
321 std::printf("bdecode: %s\n", ec.message().c_str());
322 std::printf("%s\n", std::string(buf.data(), buf.size()).c_str());
323 }
324 TEST_CHECK(!ec);
325 l(ses, state);
326 }
327 }
328
TORRENT_TEST(save_restore_state)329 TORRENT_TEST(save_restore_state)
330 {
331 test_save_restore(
332 [](settings_pack& p) {
333 // set the cache size
334 p.set_int(settings_pack::request_queue_time, 1337);
335 },
336 [](lt::session& ses, entry& st) {
337 ses.save_state(st);
338 },
339 [](settings_pack& p) {
340 p.set_int(settings_pack::request_queue_time, 90);
341 },
342 [](lt::session& ses, bdecode_node& st) {
343 ses.load_state(st);
344 // make sure we loaded the cache size correctly
345 settings_pack sett = ses.get_settings();
346 TEST_EQUAL(sett.get_int(settings_pack::request_queue_time), 1337);
347 });
348 }
349
TORRENT_TEST(save_restore_state_save_filter)350 TORRENT_TEST(save_restore_state_save_filter)
351 {
352 test_save_restore(
353 [](settings_pack& p) {
354 // set the cache size
355 p.set_int(settings_pack::request_queue_time, 1337);
356 },
357 [](lt::session& ses, entry& st) {
358 // save everything _but_ the settings
359 ses.save_state(st, ~session::save_settings);
360 },
361 [](settings_pack& p) {
362 p.set_int(settings_pack::request_queue_time, 90);
363 },
364 [](lt::session& ses, bdecode_node& st) {
365 ses.load_state(st);
366 // make sure whatever we loaded did not include the cache size
367 settings_pack sett = ses.get_settings();
368 TEST_EQUAL(sett.get_int(settings_pack::request_queue_time), 90);
369 });
370 }
371
TORRENT_TEST(save_restore_state_load_filter)372 TORRENT_TEST(save_restore_state_load_filter)
373 {
374 test_save_restore(
375 [](settings_pack& p) {
376 // set the cache size
377 p.set_int(settings_pack::request_queue_time, 1337);
378 },
379 [](lt::session& ses, entry& st) {
380 // save everything
381 ses.save_state(st);
382 },
383 [](settings_pack& p) {
384 p.set_int(settings_pack::request_queue_time, 90);
385 },
386 [](lt::session& ses, bdecode_node& st) {
387 // load everything _but_ the settings
388 ses.load_state(st, ~session::save_settings);
389 settings_pack sett = ses.get_settings();
390 TEST_EQUAL(sett.get_int(settings_pack::request_queue_time), 90);
391 });
392 }
393
TORRENT_TEST(session_shutdown)394 TORRENT_TEST(session_shutdown)
395 {
396 lt::settings_pack pack;
397 lt::session ses(pack);
398 }
399
400 // make sure we don't restore peer_id from session state
TORRENT_TEST(save_state_peer_id)401 TORRENT_TEST(save_state_peer_id)
402 {
403 lt::settings_pack pack;
404 pack.set_str(settings_pack::peer_fingerprint, "AAA");
405 lt::session ses(pack);
406 TEST_EQUAL(ses.get_settings().get_str(settings_pack::peer_fingerprint), "AAA");
407
408 lt::entry st;
409 ses.save_state(st);
410
411 pack.set_str(settings_pack::peer_fingerprint, "foobar");
412 ses.apply_settings(pack);
413
414 TEST_EQUAL(ses.get_settings().get_str(settings_pack::peer_fingerprint), "foobar");
415
416 std::vector<char> buf;
417 bencode(std::back_inserter(buf), st);
418 bdecode_node state;
419 error_code ec;
420 int ret = bdecode(buf.data(), buf.data() + buf.size()
421 , state, ec, nullptr, 100, 1000);
422 TEST_EQUAL(ret, 0);
423 ses.load_state(state);
424
425 TEST_EQUAL(ses.get_settings().get_str(settings_pack::peer_fingerprint), "foobar");
426 }
427
TORRENT_TEST(pop_alert_clear)428 TORRENT_TEST(pop_alert_clear)
429 {
430 session s;
431
432 // make sure the vector is cleared if there are no alerts to be popped
433 std::vector<alert*> alerts(100);
434
435 for (int i = 0; i < 10; ++i)
436 {
437 alerts.resize(100);
438 s.pop_alerts(&alerts);
439 if (alerts.empty()) break;
440 }
441 TEST_CHECK(alerts.empty());
442 }
443
444 namespace {
445
test_move_session(lt::session ses)446 lt::session_proxy test_move_session(lt::session ses)
447 {
448 std::this_thread::sleep_for(lt::milliseconds(100));
449 auto t = ses.get_torrents();
450 return ses.abort();
451 }
452 }
453
TORRENT_TEST(move_session)454 TORRENT_TEST(move_session)
455 {
456 lt::settings_pack pack;
457 lt::session ses(pack);
458 lt::session_proxy p = test_move_session(std::move(ses));
459 }
460
461 #if !defined TORRENT_DISABLE_LOGGING
462 #if !defined TORRENT_DISABLE_ALERT_MSG
463
464 #if !defined TORRENT_DISABLE_DHT
465
466 auto const count_dht_inits = [](session& ses)
__anon94d223830f02(session& ses) 467 {
468 int count = 0;
469 int num = 200; // this number is adjusted per version, an estimate
470 time_point const end_time = clock_type::now() + seconds(15);
471 while (true)
472 {
473 time_point const now = clock_type::now();
474 if (now > end_time) return count;
475
476 ses.wait_for_alert(end_time - now);
477 std::vector<alert*> alerts;
478 ses.pop_alerts(&alerts);
479 for (auto a : alerts)
480 {
481 std::printf("%d: [%s] %s\n", num, a->what(), a->message().c_str());
482 if (a->type() == log_alert::alert_type)
483 {
484 std::string const msg = a->message();
485 if (msg.find("starting DHT, running: ") != std::string::npos)
486 count++;
487 }
488 num--;
489 }
490 if (num <= 0) return count;
491 }
492 };
493
TORRENT_TEST(init_dht_default_bootstrap)494 TORRENT_TEST(init_dht_default_bootstrap)
495 {
496 settings_pack p = settings();
497 p.set_bool(settings_pack::enable_dht, true);
498 p.set_int(settings_pack::alert_mask, alert_category::all);
499 // default value
500 p.set_str(settings_pack::dht_bootstrap_nodes, "dht.libtorrent.org:25401");
501
502 lt::session s(p);
503
504 int const count = count_dht_inits(s);
505 TEST_EQUAL(count, 1);
506 }
507
TORRENT_TEST(init_dht_invalid_bootstrap)508 TORRENT_TEST(init_dht_invalid_bootstrap)
509 {
510 settings_pack p = settings();
511 p.set_bool(settings_pack::enable_dht, true);
512 p.set_int(settings_pack::alert_mask, alert_category::all);
513 // no default value
514 p.set_str(settings_pack::dht_bootstrap_nodes, "test.libtorrent.org:25401:8888");
515
516 lt::session s(p);
517
518 int const count = count_dht_inits(s);
519 TEST_EQUAL(count, 1);
520 }
521
TORRENT_TEST(init_dht_empty_bootstrap)522 TORRENT_TEST(init_dht_empty_bootstrap)
523 {
524 settings_pack p = settings();
525 p.set_bool(settings_pack::enable_dht, true);
526 p.set_int(settings_pack::alert_mask, alert_category::all);
527 // empty value
528 p.set_str(settings_pack::dht_bootstrap_nodes, "");
529
530 lt::session s(p);
531
532 int const count = count_dht_inits(s);
533 TEST_EQUAL(count, 1);
534 }
535
TORRENT_TEST(dht_upload_rate_overflow_pack)536 TORRENT_TEST(dht_upload_rate_overflow_pack)
537 {
538 settings_pack p = settings();
539 // make sure this doesn't cause an overflow
540 p.set_int(settings_pack::dht_upload_rate_limit, std::numeric_limits<int>::max());
541 p.set_int(settings_pack::alert_mask, alert_category_t(std::uint32_t(p.get_int(settings_pack::alert_mask)))
542 | alert_category::dht_log);
543 p.set_bool(settings_pack::enable_dht, true);
544 lt::session s(p);
545
546 p = s.get_settings();
547 TEST_EQUAL(p.get_int(settings_pack::dht_upload_rate_limit), std::numeric_limits<int>::max() / 3);
548
549 int const count = count_dht_inits(s);
550 TEST_EQUAL(count, 1);
551 }
552
TORRENT_TEST(dht_upload_rate_overflow)553 TORRENT_TEST(dht_upload_rate_overflow)
554 {
555 settings_pack p = settings();
556 p.set_bool(settings_pack::enable_dht, true);
557 p.set_int(settings_pack::alert_mask, alert_category_t(std::uint32_t(p.get_int(settings_pack::alert_mask)))
558 | alert_category::dht_log);
559 lt::session s(p);
560
561 // make sure this doesn't cause an overflow
562 dht::dht_settings sett;
563 sett.upload_rate_limit = std::numeric_limits<int>::max();
564 s.set_dht_settings(sett);
565
566 p = s.get_settings();
567 TEST_EQUAL(p.get_int(settings_pack::dht_upload_rate_limit), std::numeric_limits<int>::max() / 3);
568
569 int const count = count_dht_inits(s);
570 TEST_EQUAL(count, 1);
571 }
572
573 #endif // TORRENT_DISABLE_DHT
574
TORRENT_TEST(reopen_network_sockets)575 TORRENT_TEST(reopen_network_sockets)
576 {
577 auto count_alerts = [](session& ses, int const listen, int const portmap)
578 {
579 int count_listen = 0;
580 int count_portmap = 0;
581 int num = 50; // this number is adjusted per version, an estimate
582 time_point const end_time = clock_type::now() + seconds(1);
583 while (true)
584 {
585 time_point const now = clock_type::now();
586 if (now > end_time)
587 break;
588
589 ses.wait_for_alert(end_time - now);
590 std::vector<alert*> alerts;
591 ses.pop_alerts(&alerts);
592 for (auto a : alerts)
593 {
594 std::printf("%d: [%s] %s\n", num, a->what(), a->message().c_str());
595 std::string const msg = a->message();
596 if (msg.find("successfully listening on") != std::string::npos)
597 count_listen++;
598 // upnp
599 if (msg.find("adding port map:") != std::string::npos)
600 count_portmap++;
601 // natpmp
602 if (msg.find("add-mapping: proto:") != std::string::npos)
603 count_portmap++;
604 num--;
605 }
606 if (num <= 0)
607 break;
608 }
609
610 std::printf("count_listen: %d, count_portmap: %d\n", count_listen, count_portmap);
611 return count_listen == listen && count_portmap == portmap;
612 };
613
614 settings_pack p = settings();
615 p.set_int(settings_pack::alert_mask, alert_category::all);
616 p.set_str(settings_pack::listen_interfaces, "127.0.0.1:6881l");
617
618 p.set_bool(settings_pack::enable_upnp, true);
619 p.set_bool(settings_pack::enable_natpmp, true);
620
621 lt::session s(p);
622
623 // NAT-PMP nad UPnP will be disabled when we only listen on loopback
624 TEST_CHECK(count_alerts(s, 2, 0));
625
626 // this is a bit of a pointless test now, since neither UPnP nor NAT-PMP are
627 // enabled for loopback
628 s.reopen_network_sockets(session_handle::reopen_map_ports);
629
630 TEST_CHECK(count_alerts(s, 0, 0));
631
632 s.reopen_network_sockets({});
633
634 TEST_CHECK(count_alerts(s, 0, 0));
635
636 p.set_bool(settings_pack::enable_upnp, false);
637 p.set_bool(settings_pack::enable_natpmp, false);
638 s.apply_settings(p);
639
640 s.reopen_network_sockets(session_handle::reopen_map_ports);
641
642 TEST_CHECK(count_alerts(s, 0, 0));
643 }
644 #endif // TORRENT_DISABLE_ALERT_MSG
645 #endif
646
647