Skip to content

Commit f11f70f

Browse files
committed
dev: torrent_entry tests
1 parent daebca9 commit f11f70f

File tree

11 files changed

+897
-343
lines changed

11 files changed

+897
-343
lines changed

Cargo.lock

+413-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/primitives/src/peer.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ impl<P: Encoding> FromIterator<Peer> for Vec<P> {
332332
}
333333

334334
pub mod fixture {
335-
use std::net::SocketAddr;
335+
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
336336

337337
use super::{Id, Peer};
338338
use crate::announce_event::AnnounceEvent;
@@ -396,8 +396,8 @@ pub mod fixture {
396396
impl Default for Peer {
397397
fn default() -> Self {
398398
Self {
399-
peer_id: Id(*b"-qB00000000000000000"),
400-
peer_addr: std::net::SocketAddr::new(std::net::IpAddr::V4(std::net::Ipv4Addr::new(126, 0, 0, 1)), 8080),
399+
peer_id: Id::default(),
400+
peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080),
401401
updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0),
402402
uploaded: NumberOfBytes(0),
403403
downloaded: NumberOfBytes(0),
@@ -406,6 +406,12 @@ pub mod fixture {
406406
}
407407
}
408408
}
409+
410+
impl Default for Id {
411+
fn default() -> Self {
412+
Self(*b"-qB00000000000000000")
413+
}
414+
}
409415
}
410416

411417
#[cfg(test)]

packages/torrent-repository/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ tdyne-peer-id-registry = "0"
2727
[dev-dependencies]
2828
criterion = { version = "0", features = ["async_tokio"] }
2929
rstest = "0"
30+
async-std = {version = "1", features = ["attributes", "tokio1"] }
3031

3132
[[bench]]
3233
harness = false

packages/torrent-repository/src/entry/single.rs

-299
Original file line numberDiff line numberDiff line change
@@ -103,302 +103,3 @@ impl Entry for EntrySingle {
103103
.retain(|_, peer| peer::ReadInfo::get_updated(peer) > current_cutoff);
104104
}
105105
}
106-
107-
#[cfg(test)]
108-
mod tests {
109-
mod torrent_entry {
110-
111-
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
112-
use std::ops::Sub;
113-
use std::sync::Arc;
114-
use std::time::Duration;
115-
116-
use torrust_tracker_clock::clock::stopped::Stopped as _;
117-
use torrust_tracker_clock::clock::{self, Time};
118-
use torrust_tracker_configuration::TORRENT_PEERS_LIMIT;
119-
use torrust_tracker_primitives::announce_event::AnnounceEvent;
120-
use torrust_tracker_primitives::{peer, DurationSinceUnixEpoch, NumberOfBytes};
121-
122-
use crate::entry::Entry;
123-
use crate::{CurrentClock, EntrySingle};
124-
125-
struct TorrentPeerBuilder {
126-
peer: peer::Peer,
127-
}
128-
129-
impl TorrentPeerBuilder {
130-
pub fn default() -> TorrentPeerBuilder {
131-
let default_peer = peer::Peer {
132-
peer_id: peer::Id([0u8; 20]),
133-
peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080),
134-
updated: CurrentClock::now(),
135-
uploaded: NumberOfBytes(0),
136-
downloaded: NumberOfBytes(0),
137-
left: NumberOfBytes(0),
138-
event: AnnounceEvent::Started,
139-
};
140-
TorrentPeerBuilder { peer: default_peer }
141-
}
142-
143-
pub fn with_event_completed(mut self) -> Self {
144-
self.peer.event = AnnounceEvent::Completed;
145-
self
146-
}
147-
148-
pub fn with_peer_address(mut self, peer_addr: SocketAddr) -> Self {
149-
self.peer.peer_addr = peer_addr;
150-
self
151-
}
152-
153-
pub fn with_peer_id(mut self, peer_id: peer::Id) -> Self {
154-
self.peer.peer_id = peer_id;
155-
self
156-
}
157-
158-
pub fn with_number_of_bytes_left(mut self, left: i64) -> Self {
159-
self.peer.left = NumberOfBytes(left);
160-
self
161-
}
162-
163-
pub fn updated_at(mut self, updated: DurationSinceUnixEpoch) -> Self {
164-
self.peer.updated = updated;
165-
self
166-
}
167-
168-
pub fn into(self) -> peer::Peer {
169-
self.peer
170-
}
171-
}
172-
173-
/// A torrent seeder is a peer with 0 bytes left to download which
174-
/// has not announced it has stopped
175-
fn a_torrent_seeder() -> peer::Peer {
176-
TorrentPeerBuilder::default()
177-
.with_number_of_bytes_left(0)
178-
.with_event_completed()
179-
.into()
180-
}
181-
182-
/// A torrent leecher is a peer that is not a seeder.
183-
/// Leecher: left > 0 OR event = Stopped
184-
fn a_torrent_leecher() -> peer::Peer {
185-
TorrentPeerBuilder::default()
186-
.with_number_of_bytes_left(1)
187-
.with_event_completed()
188-
.into()
189-
}
190-
191-
#[test]
192-
fn the_default_torrent_entry_should_contain_an_empty_list_of_peers() {
193-
let torrent_entry = EntrySingle::default();
194-
195-
assert_eq!(torrent_entry.get_peers(None).len(), 0);
196-
}
197-
198-
#[test]
199-
fn a_new_peer_can_be_added_to_a_torrent_entry() {
200-
let mut torrent_entry = EntrySingle::default();
201-
let torrent_peer = TorrentPeerBuilder::default().into();
202-
203-
torrent_entry.insert_or_update_peer(&torrent_peer); // Add the peer
204-
205-
assert_eq!(*torrent_entry.get_peers(None)[0], torrent_peer);
206-
assert_eq!(torrent_entry.get_peers(None).len(), 1);
207-
}
208-
209-
#[test]
210-
fn a_torrent_entry_should_contain_the_list_of_peers_that_were_added_to_the_torrent() {
211-
let mut torrent_entry = EntrySingle::default();
212-
let torrent_peer = TorrentPeerBuilder::default().into();
213-
214-
torrent_entry.insert_or_update_peer(&torrent_peer); // Add the peer
215-
216-
assert_eq!(torrent_entry.get_peers(None), vec![Arc::new(torrent_peer)]);
217-
}
218-
219-
#[test]
220-
fn a_peer_can_be_updated_in_a_torrent_entry() {
221-
let mut torrent_entry = EntrySingle::default();
222-
let mut torrent_peer = TorrentPeerBuilder::default().into();
223-
torrent_entry.insert_or_update_peer(&torrent_peer); // Add the peer
224-
225-
torrent_peer.event = AnnounceEvent::Completed; // Update the peer
226-
torrent_entry.insert_or_update_peer(&torrent_peer); // Update the peer in the torrent entry
227-
228-
assert_eq!(torrent_entry.get_peers(None)[0].event, AnnounceEvent::Completed);
229-
}
230-
231-
#[test]
232-
fn a_peer_should_be_removed_from_a_torrent_entry_when_the_peer_announces_it_has_stopped() {
233-
let mut torrent_entry = EntrySingle::default();
234-
let mut torrent_peer = TorrentPeerBuilder::default().into();
235-
torrent_entry.insert_or_update_peer(&torrent_peer); // Add the peer
236-
237-
torrent_peer.event = AnnounceEvent::Stopped; // Update the peer
238-
torrent_entry.insert_or_update_peer(&torrent_peer); // Update the peer in the torrent entry
239-
240-
assert_eq!(torrent_entry.get_peers(None).len(), 0);
241-
}
242-
243-
#[test]
244-
fn torrent_stats_change_when_a_previously_known_peer_announces_it_has_completed_the_torrent() {
245-
let mut torrent_entry = EntrySingle::default();
246-
let mut torrent_peer = TorrentPeerBuilder::default().into();
247-
248-
torrent_entry.insert_or_update_peer(&torrent_peer); // Add the peer
249-
250-
torrent_peer.event = AnnounceEvent::Completed; // Update the peer
251-
let stats_have_changed = torrent_entry.insert_or_update_peer(&torrent_peer); // Update the peer in the torrent entry
252-
253-
assert!(stats_have_changed);
254-
}
255-
256-
#[test]
257-
fn torrent_stats_should_not_change_when_a_peer_announces_it_has_completed_the_torrent_if_it_is_the_first_announce_from_the_peer(
258-
) {
259-
let mut torrent_entry = EntrySingle::default();
260-
let torrent_peer_announcing_complete_event = TorrentPeerBuilder::default().with_event_completed().into();
261-
262-
// Add a peer that did not exist before in the entry
263-
let torrent_stats_have_not_changed = !torrent_entry.insert_or_update_peer(&torrent_peer_announcing_complete_event);
264-
265-
assert!(torrent_stats_have_not_changed);
266-
}
267-
268-
#[test]
269-
fn a_torrent_entry_should_return_the_list_of_peers_for_a_given_peer_filtering_out_the_client_that_is_making_the_request()
270-
{
271-
let mut torrent_entry = EntrySingle::default();
272-
let peer_socket_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
273-
let torrent_peer = TorrentPeerBuilder::default().with_peer_address(peer_socket_address).into();
274-
torrent_entry.insert_or_update_peer(&torrent_peer); // Add peer
275-
276-
// Get peers excluding the one we have just added
277-
let peers = torrent_entry.get_peers_for_peer(&torrent_peer, None);
278-
279-
assert_eq!(peers.len(), 0);
280-
}
281-
282-
#[test]
283-
fn two_peers_with_the_same_ip_but_different_port_should_be_considered_different_peers() {
284-
let mut torrent_entry = EntrySingle::default();
285-
286-
let peer_ip = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
287-
288-
// Add peer 1
289-
let torrent_peer_1 = TorrentPeerBuilder::default()
290-
.with_peer_address(SocketAddr::new(peer_ip, 8080))
291-
.into();
292-
torrent_entry.insert_or_update_peer(&torrent_peer_1);
293-
294-
// Add peer 2
295-
let torrent_peer_2 = TorrentPeerBuilder::default()
296-
.with_peer_address(SocketAddr::new(peer_ip, 8081))
297-
.into();
298-
torrent_entry.insert_or_update_peer(&torrent_peer_2);
299-
300-
// Get peers for peer 1
301-
let peers = torrent_entry.get_peers_for_peer(&torrent_peer_1, None);
302-
303-
// The peer 2 using the same IP but different port should be included
304-
assert_eq!(peers[0].peer_addr.ip(), Ipv4Addr::new(127, 0, 0, 1));
305-
assert_eq!(peers[0].peer_addr.port(), 8081);
306-
}
307-
308-
fn peer_id_from_i32(number: i32) -> peer::Id {
309-
let peer_id = number.to_le_bytes();
310-
peer::Id([
311-
0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, peer_id[0], peer_id[1],
312-
peer_id[2], peer_id[3],
313-
])
314-
}
315-
316-
#[test]
317-
fn the_tracker_should_limit_the_list_of_peers_to_74_when_clients_scrape_torrents() {
318-
let mut torrent_entry = EntrySingle::default();
319-
320-
// We add one more peer than the scrape limit
321-
for peer_number in 1..=74 + 1 {
322-
let torrent_peer = TorrentPeerBuilder::default()
323-
.with_peer_id(peer_id_from_i32(peer_number))
324-
.into();
325-
torrent_entry.insert_or_update_peer(&torrent_peer);
326-
}
327-
328-
let peers = torrent_entry.get_peers(Some(TORRENT_PEERS_LIMIT));
329-
330-
assert_eq!(peers.len(), 74);
331-
}
332-
333-
#[test]
334-
fn torrent_stats_should_have_the_number_of_seeders_for_a_torrent() {
335-
let mut torrent_entry = EntrySingle::default();
336-
let torrent_seeder = a_torrent_seeder();
337-
338-
torrent_entry.insert_or_update_peer(&torrent_seeder); // Add seeder
339-
340-
assert_eq!(torrent_entry.get_stats().complete, 1);
341-
}
342-
343-
#[test]
344-
fn torrent_stats_should_have_the_number_of_leechers_for_a_torrent() {
345-
let mut torrent_entry = EntrySingle::default();
346-
let torrent_leecher = a_torrent_leecher();
347-
348-
torrent_entry.insert_or_update_peer(&torrent_leecher); // Add leecher
349-
350-
assert_eq!(torrent_entry.get_stats().incomplete, 1);
351-
}
352-
353-
#[test]
354-
fn torrent_stats_should_have_the_number_of_peers_that_having_announced_at_least_two_events_the_latest_one_is_the_completed_event(
355-
) {
356-
let mut torrent_entry = EntrySingle::default();
357-
let mut torrent_peer = TorrentPeerBuilder::default().into();
358-
torrent_entry.insert_or_update_peer(&torrent_peer); // Add the peer
359-
360-
// Announce "Completed" torrent download event.
361-
torrent_peer.event = AnnounceEvent::Completed;
362-
torrent_entry.insert_or_update_peer(&torrent_peer); // Update the peer
363-
364-
let number_of_previously_known_peers_with_completed_torrent = torrent_entry.get_stats().complete;
365-
366-
assert_eq!(number_of_previously_known_peers_with_completed_torrent, 1);
367-
}
368-
369-
#[test]
370-
fn torrent_stats_should_not_include_a_peer_in_the_completed_counter_if_the_peer_has_announced_only_one_event() {
371-
let mut torrent_entry = EntrySingle::default();
372-
let torrent_peer_announcing_complete_event = TorrentPeerBuilder::default().with_event_completed().into();
373-
374-
// Announce "Completed" torrent download event.
375-
// It's the first event announced from this peer.
376-
torrent_entry.insert_or_update_peer(&torrent_peer_announcing_complete_event); // Add the peer
377-
378-
let number_of_peers_with_completed_torrent = torrent_entry.get_stats().downloaded;
379-
380-
assert_eq!(number_of_peers_with_completed_torrent, 0);
381-
}
382-
383-
#[test]
384-
fn a_torrent_entry_should_remove_a_peer_not_updated_after_a_timeout_in_seconds() {
385-
let mut torrent_entry = EntrySingle::default();
386-
387-
let timeout = 120u32;
388-
389-
let now = clock::Working::now();
390-
clock::Stopped::local_set(&now);
391-
392-
let timeout_seconds_before_now = now.sub(Duration::from_secs(u64::from(timeout)));
393-
let inactive_peer = TorrentPeerBuilder::default()
394-
.updated_at(timeout_seconds_before_now.sub(Duration::from_secs(1)))
395-
.into();
396-
torrent_entry.insert_or_update_peer(&inactive_peer); // Add the peer
397-
398-
let current_cutoff = CurrentClock::now_sub(&Duration::from_secs(u64::from(timeout))).unwrap_or_default();
399-
torrent_entry.remove_inactive_peers(current_cutoff);
400-
401-
assert_eq!(torrent_entry.get_peers_len(), 0);
402-
}
403-
}
404-
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod torrent_peer_builder;

0 commit comments

Comments
 (0)