Skip to content

Commit a1046a2

Browse files
committed
Merge #1248: Overhaul core Tracker: add tests for announce_handler mod
5fdee78 refactor: rename enum variant (Jose Celano) b2fc663 test: [#1247] add tests for bittorrent_tracker_core::announce_handler (Jose Celano) Pull request description: Overhaul core Tracker: add tests for `announce_handler` mod. ACKs for top commit: josecelano: ACK 5fdee78 Tree-SHA512: f78d014823f6b20aafa6d9632a3ef62e0055966455120a01ae6985f067ae21380b6db662643b6429f5118a94f5a70f2a3fb343d0dac474feecf8ecd0b9b2707a
2 parents 4043962 + 5fdee78 commit a1046a2

File tree

5 files changed

+194
-37
lines changed

5 files changed

+194
-37
lines changed

packages/tracker-core/src/announce_handler.rs

Lines changed: 183 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -111,39 +111,50 @@ impl AnnounceHandler {
111111
pub enum PeersWanted {
112112
/// The peer wants as many peers as possible in the announce response.
113113
#[default]
114-
All,
114+
AsManyAsPossible,
115115
/// The peer only wants a certain amount of peers in the announce response.
116116
Only { amount: usize },
117117
}
118118

119119
impl PeersWanted {
120120
#[must_use]
121121
pub fn only(limit: u32) -> Self {
122-
let amount: usize = match limit.try_into() {
123-
Ok(amount) => amount,
124-
Err(_) => TORRENT_PEERS_LIMIT,
125-
};
126-
127-
Self::Only { amount }
122+
limit.into()
128123
}
129124

130125
fn limit(&self) -> usize {
131126
match self {
132-
PeersWanted::All => TORRENT_PEERS_LIMIT,
127+
PeersWanted::AsManyAsPossible => TORRENT_PEERS_LIMIT,
133128
PeersWanted::Only { amount } => *amount,
134129
}
135130
}
136131
}
137132

138133
impl From<i32> for PeersWanted {
139134
fn from(value: i32) -> Self {
140-
if value > 0 {
141-
match value.try_into() {
142-
Ok(peers_wanted) => Self::Only { amount: peers_wanted },
143-
Err(_) => Self::All,
144-
}
145-
} else {
146-
Self::All
135+
if value <= 0 {
136+
return PeersWanted::AsManyAsPossible;
137+
}
138+
139+
// This conversion is safe because `value > 0`
140+
let amount = usize::try_from(value).unwrap();
141+
142+
PeersWanted::Only {
143+
amount: amount.min(TORRENT_PEERS_LIMIT),
144+
}
145+
}
146+
}
147+
148+
impl From<u32> for PeersWanted {
149+
fn from(value: u32) -> Self {
150+
if value == 0 {
151+
return PeersWanted::AsManyAsPossible;
152+
}
153+
154+
let amount = value as usize;
155+
156+
PeersWanted::Only {
157+
amount: amount.min(TORRENT_PEERS_LIMIT),
147158
}
148159
}
149160
}
@@ -210,14 +221,27 @@ mod tests {
210221
}
211222
}
212223

224+
/// Sample peer when for tests that need more than two peer
225+
fn sample_peer_3() -> Peer {
226+
Peer {
227+
peer_id: PeerId(*b"-qB00000000000000003"),
228+
peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 3)), 8082),
229+
updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0),
230+
uploaded: NumberOfBytes::new(0),
231+
downloaded: NumberOfBytes::new(0),
232+
left: NumberOfBytes::new(0),
233+
event: AnnounceEvent::Completed,
234+
}
235+
}
236+
213237
mod for_all_tracker_config_modes {
214238

215239
mod handling_an_announce_request {
216240

217241
use std::sync::Arc;
218242

219243
use crate::announce_handler::tests::the_announce_handler::{
220-
peer_ip, public_tracker, sample_peer_1, sample_peer_2,
244+
peer_ip, public_tracker, sample_peer_1, sample_peer_2, sample_peer_3,
221245
};
222246
use crate::announce_handler::PeersWanted;
223247
use crate::core_tests::{sample_info_hash, sample_peer};
@@ -326,7 +350,8 @@ mod tests {
326350

327351
let mut peer = sample_peer();
328352

329-
let announce_data = announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All);
353+
let announce_data =
354+
announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::AsManyAsPossible);
330355

331356
assert_eq!(announce_data.peers, vec![]);
332357
}
@@ -340,15 +365,48 @@ mod tests {
340365
&sample_info_hash(),
341366
&mut previously_announced_peer,
342367
&peer_ip(),
343-
&PeersWanted::All,
368+
&PeersWanted::AsManyAsPossible,
344369
);
345370

346371
let mut peer = sample_peer_2();
347-
let announce_data = announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All);
372+
let announce_data =
373+
announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::AsManyAsPossible);
348374

349375
assert_eq!(announce_data.peers, vec![Arc::new(previously_announced_peer)]);
350376
}
351377

378+
#[tokio::test]
379+
async fn it_should_allow_peers_to_get_only_a_subset_of_the_peers_in_the_swarm() {
380+
let (announce_handler, _scrape_handler) = public_tracker();
381+
382+
let mut previously_announced_peer_1 = sample_peer_1();
383+
announce_handler.announce(
384+
&sample_info_hash(),
385+
&mut previously_announced_peer_1,
386+
&peer_ip(),
387+
&PeersWanted::AsManyAsPossible,
388+
);
389+
390+
let mut previously_announced_peer_2 = sample_peer_2();
391+
announce_handler.announce(
392+
&sample_info_hash(),
393+
&mut previously_announced_peer_2,
394+
&peer_ip(),
395+
&PeersWanted::AsManyAsPossible,
396+
);
397+
398+
let mut peer = sample_peer_3();
399+
let announce_data =
400+
announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::only(1));
401+
402+
// It should return only one peer. There is no guarantee on
403+
// which peer will be returned.
404+
assert!(
405+
announce_data.peers == vec![Arc::new(previously_announced_peer_1)]
406+
|| announce_data.peers == vec![Arc::new(previously_announced_peer_2)]
407+
);
408+
}
409+
352410
mod it_should_update_the_swarm_stats_for_the_torrent {
353411

354412
use crate::announce_handler::tests::the_announce_handler::{peer_ip, public_tracker};
@@ -362,7 +420,7 @@ mod tests {
362420
let mut peer = seeder();
363421

364422
let announce_data =
365-
announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All);
423+
announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::AsManyAsPossible);
366424

367425
assert_eq!(announce_data.stats.complete, 1);
368426
}
@@ -374,7 +432,7 @@ mod tests {
374432
let mut peer = leecher();
375433

376434
let announce_data =
377-
announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All);
435+
announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::AsManyAsPossible);
378436

379437
assert_eq!(announce_data.stats.incomplete, 1);
380438
}
@@ -385,11 +443,20 @@ mod tests {
385443

386444
// We have to announce with "started" event because peer does not count if peer was not previously known
387445
let mut started_peer = started_peer();
388-
announce_handler.announce(&sample_info_hash(), &mut started_peer, &peer_ip(), &PeersWanted::All);
446+
announce_handler.announce(
447+
&sample_info_hash(),
448+
&mut started_peer,
449+
&peer_ip(),
450+
&PeersWanted::AsManyAsPossible,
451+
);
389452

390453
let mut completed_peer = completed_peer();
391-
let announce_data =
392-
announce_handler.announce(&sample_info_hash(), &mut completed_peer, &peer_ip(), &PeersWanted::All);
454+
let announce_data = announce_handler.announce(
455+
&sample_info_hash(),
456+
&mut completed_peer,
457+
&peer_ip(),
458+
&PeersWanted::AsManyAsPossible,
459+
);
393460

394461
assert_eq!(announce_data.stats.downloaded, 1);
395462
}
@@ -438,11 +505,11 @@ mod tests {
438505
let mut peer = sample_peer();
439506

440507
peer.event = AnnounceEvent::Started;
441-
let announce_data = announce_handler.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::All);
508+
let announce_data = announce_handler.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::AsManyAsPossible);
442509
assert_eq!(announce_data.stats.downloaded, 0);
443510

444511
peer.event = AnnounceEvent::Completed;
445-
let announce_data = announce_handler.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::All);
512+
let announce_data = announce_handler.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::AsManyAsPossible);
446513
assert_eq!(announce_data.stats.downloaded, 1);
447514

448515
// Remove the newly updated torrent from memory
@@ -461,5 +528,95 @@ mod tests {
461528
assert!(torrent_entry.peers_is_empty());
462529
}
463530
}
531+
532+
mod should_allow_the_client_peers_to_specified_the_number_of_peers_wanted {
533+
534+
use torrust_tracker_configuration::TORRENT_PEERS_LIMIT;
535+
536+
use crate::announce_handler::PeersWanted;
537+
538+
#[test]
539+
fn it_should_return_the_maximin_number_of_peers_by_default() {
540+
let peers_wanted = PeersWanted::default();
541+
542+
assert_eq!(peers_wanted.limit(), TORRENT_PEERS_LIMIT);
543+
}
544+
545+
#[test]
546+
fn it_should_return_74_at_the_most_if_the_client_wants_them_all() {
547+
let peers_wanted = PeersWanted::AsManyAsPossible;
548+
549+
assert_eq!(peers_wanted.limit(), TORRENT_PEERS_LIMIT);
550+
}
551+
552+
#[test]
553+
fn it_should_allow_limiting_the_peer_list() {
554+
let peers_wanted = PeersWanted::only(10);
555+
556+
assert_eq!(peers_wanted.limit(), 10);
557+
}
558+
559+
fn maximum_as_u32() -> u32 {
560+
u32::try_from(TORRENT_PEERS_LIMIT).unwrap()
561+
}
562+
563+
fn maximum_as_i32() -> i32 {
564+
i32::try_from(TORRENT_PEERS_LIMIT).unwrap()
565+
}
566+
567+
#[test]
568+
fn it_should_return_the_maximum_when_wanting_more_than_the_maximum() {
569+
let peers_wanted = PeersWanted::only(maximum_as_u32() + 1);
570+
assert_eq!(peers_wanted.limit(), TORRENT_PEERS_LIMIT);
571+
}
572+
573+
#[test]
574+
fn it_should_return_the_maximum_when_wanting_only_zero() {
575+
let peers_wanted = PeersWanted::only(0);
576+
assert_eq!(peers_wanted.limit(), TORRENT_PEERS_LIMIT);
577+
}
578+
579+
#[test]
580+
fn it_should_convert_the_peers_wanted_number_from_i32() {
581+
// Negative. It should return the maximum
582+
let peers_wanted: PeersWanted = (-1i32).into();
583+
assert_eq!(peers_wanted.limit(), TORRENT_PEERS_LIMIT);
584+
585+
// Zero. It should return the maximum
586+
let peers_wanted: PeersWanted = 0i32.into();
587+
assert_eq!(peers_wanted.limit(), TORRENT_PEERS_LIMIT);
588+
589+
// Greater than the maximum. It should return the maximum
590+
let peers_wanted: PeersWanted = (maximum_as_i32() + 1).into();
591+
assert_eq!(peers_wanted.limit(), TORRENT_PEERS_LIMIT);
592+
593+
// The maximum
594+
let peers_wanted: PeersWanted = (maximum_as_i32()).into();
595+
assert_eq!(peers_wanted.limit(), TORRENT_PEERS_LIMIT);
596+
597+
// Smaller than the maximum
598+
let peers_wanted: PeersWanted = (maximum_as_i32() - 1).into();
599+
assert_eq!(i32::try_from(peers_wanted.limit()).unwrap(), maximum_as_i32() - 1);
600+
}
601+
602+
#[test]
603+
fn it_should_convert_the_peers_wanted_number_from_u32() {
604+
// Zero. It should return the maximum
605+
let peers_wanted: PeersWanted = 0u32.into();
606+
assert_eq!(peers_wanted.limit(), TORRENT_PEERS_LIMIT);
607+
608+
// Greater than the maximum. It should return the maximum
609+
let peers_wanted: PeersWanted = (maximum_as_u32() + 1).into();
610+
assert_eq!(peers_wanted.limit(), TORRENT_PEERS_LIMIT);
611+
612+
// The maximum
613+
let peers_wanted: PeersWanted = (maximum_as_u32()).into();
614+
assert_eq!(peers_wanted.limit(), TORRENT_PEERS_LIMIT);
615+
616+
// Smaller than the maximum
617+
let peers_wanted: PeersWanted = (maximum_as_u32() - 1).into();
618+
assert_eq!(i32::try_from(peers_wanted.limit()).unwrap(), maximum_as_i32() - 1);
619+
}
620+
}
464621
}
465622
}

packages/tracker-core/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ mod tests {
460460
&info_hash,
461461
&mut complete_peer,
462462
&IpAddr::V4(Ipv4Addr::new(126, 0, 0, 10)),
463-
&PeersWanted::All,
463+
&PeersWanted::AsManyAsPossible,
464464
);
465465

466466
// Announce an "incomplete" peer for the torrent
@@ -469,7 +469,7 @@ mod tests {
469469
&info_hash,
470470
&mut incomplete_peer,
471471
&IpAddr::V4(Ipv4Addr::new(126, 0, 0, 11)),
472-
&PeersWanted::All,
472+
&PeersWanted::AsManyAsPossible,
473473
);
474474

475475
// Scrape
@@ -510,11 +510,11 @@ mod tests {
510510
let info_hash = "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::<InfoHash>().unwrap(); // DevSkim: ignore DS173237
511511

512512
let mut peer = incomplete_peer();
513-
announce_handler.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::All);
513+
announce_handler.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::AsManyAsPossible);
514514

515515
// Announce twice to force non zeroed swarm metadata
516516
let mut peer = complete_peer();
517-
announce_handler.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::All);
517+
announce_handler.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::AsManyAsPossible);
518518

519519
let scrape_data = scrape_handler.scrape(&vec![info_hash]).await;
520520

src/servers/http/v1/handlers/announce.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ async fn handle_announce(
175175
let mut peer = peer_from_request(announce_request, &peer_ip);
176176
let peers_wanted = match announce_request.numwant {
177177
Some(numwant) => PeersWanted::only(numwant),
178-
None => PeersWanted::All,
178+
None => PeersWanted::AsManyAsPossible,
179179
};
180180

181181
let announce_data = services::announce::invoke(

src/servers/http/v1/services/announce.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ mod tests {
195195
core_http_tracker_services.http_stats_event_sender.clone(),
196196
sample_info_hash(),
197197
&mut peer,
198-
&PeersWanted::All,
198+
&PeersWanted::AsManyAsPossible,
199199
)
200200
.await;
201201

@@ -232,7 +232,7 @@ mod tests {
232232
http_stats_event_sender,
233233
sample_info_hash(),
234234
&mut peer,
235-
&PeersWanted::All,
235+
&PeersWanted::AsManyAsPossible,
236236
)
237237
.await;
238238
}
@@ -277,7 +277,7 @@ mod tests {
277277
http_stats_event_sender,
278278
sample_info_hash(),
279279
&mut peer,
280-
&PeersWanted::All,
280+
&PeersWanted::AsManyAsPossible,
281281
)
282282
.await;
283283
}
@@ -303,7 +303,7 @@ mod tests {
303303
http_stats_event_sender,
304304
sample_info_hash(),
305305
&mut peer,
306-
&PeersWanted::All,
306+
&PeersWanted::AsManyAsPossible,
307307
)
308308
.await;
309309
}

0 commit comments

Comments
 (0)