diff --git a/packages/primitives/src/core.rs b/packages/primitives/src/core.rs index 0c0f68b8b..aa2fe6926 100644 --- a/packages/primitives/src/core.rs +++ b/packages/primitives/src/core.rs @@ -56,3 +56,33 @@ impl ScrapeData { self.files.insert(*info_hash, SwarmMetadata::zeroed()); } } + +#[cfg(test)] +mod tests { + + use bittorrent_primitives::info_hash::InfoHash; + + use crate::core::ScrapeData; + + /// # Panics + /// + /// Will panic if the string representation of the info hash is not a valid info hash. + #[must_use] + pub fn sample_info_hash() -> InfoHash { + "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0" // DevSkim: ignore DS173237 + .parse::() + .expect("String should be a valid info hash") + } + + #[test] + fn it_should_be_able_to_build_a_zeroed_scrape_data_for_a_list_of_info_hashes() { + // Zeroed scrape data is used when the authentication for the scrape request fails. + + let sample_info_hash = sample_info_hash(); + + let mut expected_scrape_data = ScrapeData::empty(); + expected_scrape_data.add_file_with_zeroed_metadata(&sample_info_hash); + + assert_eq!(ScrapeData::zeroed(&vec![sample_info_hash]), expected_scrape_data); + } +} diff --git a/src/app_test.rs b/src/app_test.rs index 5f189f391..fb1dd01c8 100644 --- a/src/app_test.rs +++ b/src/app_test.rs @@ -23,7 +23,7 @@ pub fn initialize_tracker_dependencies( ) -> ( Arc>, Arc, - Arc, + Arc, Arc, Arc, Arc, @@ -31,7 +31,7 @@ pub fn initialize_tracker_dependencies( ) { let database = initialize_database(config); let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); - let whitelist_authorization = Arc::new(whitelist::authorization::Authorization::new( + let whitelist_authorization = Arc::new(whitelist::authorization::WhitelistAuthorization::new( &config.core, &in_memory_whitelist.clone(), )); diff --git a/src/bootstrap/app.rs b/src/bootstrap/app.rs index da63048e0..c69162322 100644 --- a/src/bootstrap/app.rs +++ b/src/bootstrap/app.rs @@ -93,7 +93,7 @@ pub fn initialize_app_container(configuration: &Configuration) -> AppContainer { let ban_service = Arc::new(RwLock::new(BanService::new(MAX_CONNECTION_ID_ERRORS_PER_IP))); let database = initialize_database(configuration); let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); - let whitelist_authorization = Arc::new(whitelist::authorization::Authorization::new( + let whitelist_authorization = Arc::new(whitelist::authorization::WhitelistAuthorization::new( &configuration.core, &in_memory_whitelist.clone(), )); diff --git a/src/bootstrap/jobs/http_tracker.rs b/src/bootstrap/jobs/http_tracker.rs index 4a3aa7a9f..dc6ed6b60 100644 --- a/src/bootstrap/jobs/http_tracker.rs +++ b/src/bootstrap/jobs/http_tracker.rs @@ -52,7 +52,7 @@ pub async fn start_job( announce_handler: Arc, scrape_handler: Arc, authentication_service: Arc, - whitelist_authorization: Arc, + whitelist_authorization: Arc, stats_event_sender: Arc>>, form: ServiceRegistrationForm, version: Version, @@ -99,7 +99,7 @@ async fn start_v1( announce_handler: Arc, scrape_handler: Arc, authentication_service: Arc, - whitelist_authorization: Arc, + whitelist_authorization: Arc, stats_event_sender: Arc>>, form: ServiceRegistrationForm, ) -> JoinHandle<()> { diff --git a/src/bootstrap/jobs/tracker_apis.rs b/src/bootstrap/jobs/tracker_apis.rs index f735bc4d7..ce6f3912c 100644 --- a/src/bootstrap/jobs/tracker_apis.rs +++ b/src/bootstrap/jobs/tracker_apis.rs @@ -34,7 +34,7 @@ use crate::core::authentication::handler::KeysHandler; use crate::core::statistics::event::sender::Sender; use crate::core::statistics::repository::Repository; use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; -use crate::core::whitelist::manager::WhiteListManager; +use crate::core::whitelist::manager::WhitelistManager; use crate::servers::apis::server::{ApiServer, Launcher}; use crate::servers::apis::Version; use crate::servers::registar::ServiceRegistrationForm; @@ -74,7 +74,7 @@ pub async fn start_job( config: &HttpApi, in_memory_torrent_repository: Arc, keys_handler: Arc, - whitelist_manager: Arc, + whitelist_manager: Arc, ban_service: Arc>, stats_event_sender: Arc>>, stats_repository: Arc, @@ -126,7 +126,7 @@ async fn start_v1( tls: Option, in_memory_torrent_repository: Arc, keys_handler: Arc, - whitelist_manager: Arc, + whitelist_manager: Arc, ban_service: Arc>, stats_event_sender: Arc>>, stats_repository: Arc, diff --git a/src/bootstrap/jobs/udp_tracker.rs b/src/bootstrap/jobs/udp_tracker.rs index 3679c3195..4f54ecb59 100644 --- a/src/bootstrap/jobs/udp_tracker.rs +++ b/src/bootstrap/jobs/udp_tracker.rs @@ -49,7 +49,7 @@ pub async fn start_job( config: &UdpTracker, announce_handler: Arc, scrape_handler: Arc, - whitelist_authorization: Arc, + whitelist_authorization: Arc, stats_event_sender: Arc>>, ban_service: Arc>, form: ServiceRegistrationForm, diff --git a/src/container.rs b/src/container.rs index 544abd02e..192fa62f1 100644 --- a/src/container.rs +++ b/src/container.rs @@ -13,7 +13,7 @@ use crate::core::torrent::manager::TorrentsManager; use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; use crate::core::torrent::repository::persisted::DatabasePersistentTorrentRepository; use crate::core::whitelist; -use crate::core::whitelist::manager::WhiteListManager; +use crate::core::whitelist::manager::WhitelistManager; use crate::servers::udp::server::banning::BanService; pub struct AppContainer { @@ -22,11 +22,11 @@ pub struct AppContainer { pub scrape_handler: Arc, pub keys_handler: Arc, pub authentication_service: Arc, - pub whitelist_authorization: Arc, + pub whitelist_authorization: Arc, pub ban_service: Arc>, pub stats_event_sender: Arc>>, pub stats_repository: Arc, - pub whitelist_manager: Arc, + pub whitelist_manager: Arc, pub in_memory_torrent_repository: Arc, pub db_torrent_repository: Arc, pub torrents_manager: Arc, diff --git a/src/core/announce_handler.rs b/src/core/announce_handler.rs index a037d33d4..1a5f84d47 100644 --- a/src/core/announce_handler.rs +++ b/src/core/announce_handler.rs @@ -155,10 +155,317 @@ impl From for PeersWanted { } #[must_use] -pub fn assign_ip_address_to_peer(remote_client_ip: &IpAddr, tracker_external_ip: Option) -> IpAddr { +fn assign_ip_address_to_peer(remote_client_ip: &IpAddr, tracker_external_ip: Option) -> IpAddr { if let Some(host_ip) = tracker_external_ip.filter(|_| remote_client_ip.is_loopback()) { host_ip } else { *remote_client_ip } } + +#[cfg(test)] +mod tests { + mod the_announce_handler { + + use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + use std::str::FromStr; + use std::sync::Arc; + + use aquatic_udp_protocol::{AnnounceEvent, NumberOfBytes, PeerId}; + use torrust_tracker_primitives::peer::Peer; + use torrust_tracker_primitives::DurationSinceUnixEpoch; + use torrust_tracker_test_helpers::configuration; + + use crate::core::announce_handler::AnnounceHandler; + use crate::core::core_tests::initialize_handlers; + use crate::core::scrape_handler::ScrapeHandler; + + fn public_tracker() -> (Arc, Arc) { + let config = configuration::ephemeral_public(); + initialize_handlers(&config) + } + + // The client peer IP + fn peer_ip() -> IpAddr { + IpAddr::V4(Ipv4Addr::from_str("126.0.0.1").unwrap()) + } + + /// Sample peer when for tests that need more than one peer + fn sample_peer_1() -> Peer { + Peer { + peer_id: PeerId(*b"-qB00000000000000001"), + peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)), 8081), + updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0), + uploaded: NumberOfBytes::new(0), + downloaded: NumberOfBytes::new(0), + left: NumberOfBytes::new(0), + event: AnnounceEvent::Completed, + } + } + + /// Sample peer when for tests that need more than one peer + fn sample_peer_2() -> Peer { + Peer { + peer_id: PeerId(*b"-qB00000000000000002"), + peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 2)), 8082), + updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0), + uploaded: NumberOfBytes::new(0), + downloaded: NumberOfBytes::new(0), + left: NumberOfBytes::new(0), + event: AnnounceEvent::Completed, + } + } + + mod for_all_tracker_config_modes { + + mod handling_an_announce_request { + + use std::sync::Arc; + + use crate::core::announce_handler::tests::the_announce_handler::{ + peer_ip, public_tracker, sample_peer_1, sample_peer_2, + }; + use crate::core::announce_handler::PeersWanted; + use crate::core::core_tests::{sample_info_hash, sample_peer}; + + mod should_assign_the_ip_to_the_peer { + + use std::net::{IpAddr, Ipv4Addr}; + + use crate::core::announce_handler::assign_ip_address_to_peer; + + #[test] + fn using_the_source_ip_instead_of_the_ip_in_the_announce_request() { + let remote_ip = IpAddr::V4(Ipv4Addr::new(126, 0, 0, 2)); + + let peer_ip = assign_ip_address_to_peer(&remote_ip, None); + + assert_eq!(peer_ip, remote_ip); + } + + mod and_when_the_client_ip_is_a_ipv4_loopback_ip { + + use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + use std::str::FromStr; + + use crate::core::announce_handler::assign_ip_address_to_peer; + + #[test] + fn it_should_use_the_loopback_ip_if_the_tracker_does_not_have_the_external_ip_configuration() { + let remote_ip = IpAddr::V4(Ipv4Addr::LOCALHOST); + + let peer_ip = assign_ip_address_to_peer(&remote_ip, None); + + assert_eq!(peer_ip, remote_ip); + } + + #[test] + fn it_should_use_the_external_tracker_ip_in_tracker_configuration_if_it_is_defined() { + let remote_ip = IpAddr::V4(Ipv4Addr::LOCALHOST); + + let tracker_external_ip = IpAddr::V4(Ipv4Addr::from_str("126.0.0.1").unwrap()); + + let peer_ip = assign_ip_address_to_peer(&remote_ip, Some(tracker_external_ip)); + + assert_eq!(peer_ip, tracker_external_ip); + } + + #[test] + fn it_should_use_the_external_ip_in_the_tracker_configuration_if_it_is_defined_even_if_the_external_ip_is_an_ipv6_ip( + ) { + let remote_ip = IpAddr::V4(Ipv4Addr::LOCALHOST); + + let tracker_external_ip = + IpAddr::V6(Ipv6Addr::from_str("2345:0425:2CA1:0000:0000:0567:5673:23b5").unwrap()); + + let peer_ip = assign_ip_address_to_peer(&remote_ip, Some(tracker_external_ip)); + + assert_eq!(peer_ip, tracker_external_ip); + } + } + + mod and_when_client_ip_is_a_ipv6_loopback_ip { + + use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + use std::str::FromStr; + + use crate::core::announce_handler::assign_ip_address_to_peer; + + #[test] + fn it_should_use_the_loopback_ip_if_the_tracker_does_not_have_the_external_ip_configuration() { + let remote_ip = IpAddr::V6(Ipv6Addr::LOCALHOST); + + let peer_ip = assign_ip_address_to_peer(&remote_ip, None); + + assert_eq!(peer_ip, remote_ip); + } + + #[test] + fn it_should_use_the_external_ip_in_tracker_configuration_if_it_is_defined() { + let remote_ip = IpAddr::V6(Ipv6Addr::LOCALHOST); + + let tracker_external_ip = + IpAddr::V6(Ipv6Addr::from_str("2345:0425:2CA1:0000:0000:0567:5673:23b5").unwrap()); + + let peer_ip = assign_ip_address_to_peer(&remote_ip, Some(tracker_external_ip)); + + assert_eq!(peer_ip, tracker_external_ip); + } + + #[test] + fn it_should_use_the_external_ip_in_the_tracker_configuration_if_it_is_defined_even_if_the_external_ip_is_an_ipv4_ip( + ) { + let remote_ip = IpAddr::V6(Ipv6Addr::LOCALHOST); + + let tracker_external_ip = IpAddr::V4(Ipv4Addr::from_str("126.0.0.1").unwrap()); + + let peer_ip = assign_ip_address_to_peer(&remote_ip, Some(tracker_external_ip)); + + assert_eq!(peer_ip, tracker_external_ip); + } + } + } + + #[tokio::test] + async fn it_should_return_the_announce_data_with_an_empty_peer_list_when_it_is_the_first_announced_peer() { + let (announce_handler, _scrape_handler) = public_tracker(); + + let mut peer = sample_peer(); + + let announce_data = announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All); + + assert_eq!(announce_data.peers, vec![]); + } + + #[tokio::test] + async fn it_should_return_the_announce_data_with_the_previously_announced_peers() { + let (announce_handler, _scrape_handler) = public_tracker(); + + let mut previously_announced_peer = sample_peer_1(); + announce_handler.announce( + &sample_info_hash(), + &mut previously_announced_peer, + &peer_ip(), + &PeersWanted::All, + ); + + let mut peer = sample_peer_2(); + let announce_data = announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All); + + assert_eq!(announce_data.peers, vec![Arc::new(previously_announced_peer)]); + } + + mod it_should_update_the_swarm_stats_for_the_torrent { + + use crate::core::announce_handler::tests::the_announce_handler::{peer_ip, public_tracker}; + use crate::core::announce_handler::PeersWanted; + use crate::core::core_tests::{completed_peer, leecher, sample_info_hash, seeder, started_peer}; + + #[tokio::test] + async fn when_the_peer_is_a_seeder() { + let (announce_handler, _scrape_handler) = public_tracker(); + + let mut peer = seeder(); + + let announce_data = + announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All); + + assert_eq!(announce_data.stats.complete, 1); + } + + #[tokio::test] + async fn when_the_peer_is_a_leecher() { + let (announce_handler, _scrape_handler) = public_tracker(); + + let mut peer = leecher(); + + let announce_data = + announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All); + + assert_eq!(announce_data.stats.incomplete, 1); + } + + #[tokio::test] + async fn when_a_previously_announced_started_peer_has_completed_downloading() { + let (announce_handler, _scrape_handler) = public_tracker(); + + // We have to announce with "started" event because peer does not count if peer was not previously known + let mut started_peer = started_peer(); + announce_handler.announce(&sample_info_hash(), &mut started_peer, &peer_ip(), &PeersWanted::All); + + let mut completed_peer = completed_peer(); + let announce_data = + announce_handler.announce(&sample_info_hash(), &mut completed_peer, &peer_ip(), &PeersWanted::All); + + assert_eq!(announce_data.stats.downloaded, 1); + } + } + } + } + + mod handling_torrent_persistence { + + use std::sync::Arc; + + use aquatic_udp_protocol::AnnounceEvent; + use torrust_tracker_test_helpers::configuration; + use torrust_tracker_torrent_repository::entry::EntrySync; + + use crate::core::announce_handler::tests::the_announce_handler::peer_ip; + use crate::core::announce_handler::{AnnounceHandler, PeersWanted}; + use crate::core::core_tests::{sample_info_hash, sample_peer}; + use crate::core::services::initialize_database; + use crate::core::torrent::manager::TorrentsManager; + use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; + use crate::core::torrent::repository::persisted::DatabasePersistentTorrentRepository; + + #[tokio::test] + async fn it_should_persist_the_number_of_completed_peers_for_all_torrents_into_the_database() { + let mut config = configuration::ephemeral_listed(); + + config.core.tracker_policy.persistent_torrent_completed_stat = true; + + let database = initialize_database(&config); + let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); + let db_torrent_repository = Arc::new(DatabasePersistentTorrentRepository::new(&database)); + let torrents_manager = Arc::new(TorrentsManager::new( + &config.core, + &in_memory_torrent_repository, + &db_torrent_repository, + )); + let announce_handler = Arc::new(AnnounceHandler::new( + &config.core, + &in_memory_torrent_repository, + &db_torrent_repository, + )); + + let info_hash = sample_info_hash(); + + let mut peer = sample_peer(); + + peer.event = AnnounceEvent::Started; + let announce_data = announce_handler.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::All); + assert_eq!(announce_data.stats.downloaded, 0); + + peer.event = AnnounceEvent::Completed; + let announce_data = announce_handler.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::All); + assert_eq!(announce_data.stats.downloaded, 1); + + // Remove the newly updated torrent from memory + let _unused = in_memory_torrent_repository.remove(&info_hash); + + torrents_manager.load_torrents_from_database().unwrap(); + + let torrent_entry = in_memory_torrent_repository + .get(&info_hash) + .expect("it should be able to get entry"); + + // It persists the number of completed peers. + assert_eq!(torrent_entry.get_swarm_metadata().downloaded, 1); + + // It does not persist the peers + assert!(torrent_entry.peers_is_empty()); + } + } + } +} diff --git a/src/core/core_tests.rs b/src/core/core_tests.rs new file mode 100644 index 000000000..45949bae2 --- /dev/null +++ b/src/core/core_tests.rs @@ -0,0 +1,105 @@ +//! Some generic test helpers functions. +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +use std::sync::Arc; + +use aquatic_udp_protocol::{AnnounceEvent, NumberOfBytes, PeerId}; +use bittorrent_primitives::info_hash::InfoHash; +use torrust_tracker_configuration::Configuration; +use torrust_tracker_primitives::peer::Peer; +use torrust_tracker_primitives::DurationSinceUnixEpoch; + +use super::announce_handler::AnnounceHandler; +use super::scrape_handler::ScrapeHandler; +use super::services::initialize_database; +use super::torrent::repository::in_memory::InMemoryTorrentRepository; +use super::torrent::repository::persisted::DatabasePersistentTorrentRepository; +use super::whitelist::repository::in_memory::InMemoryWhitelist; +use super::whitelist::{self}; + +/// # Panics +/// +/// Will panic if the string representation of the info hash is not a valid info hash. +#[must_use] +pub fn sample_info_hash() -> InfoHash { + "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0" // DevSkim: ignore DS173237 + .parse::() + .expect("String should be a valid info hash") +} + +/// Sample peer whose state is not relevant for the tests. +#[must_use] +pub fn sample_peer() -> Peer { + complete_peer() +} + +#[must_use] +pub fn seeder() -> Peer { + complete_peer() +} + +#[must_use] +pub fn leecher() -> Peer { + incomplete_peer() +} + +#[must_use] +pub fn started_peer() -> Peer { + incomplete_peer() +} + +#[must_use] +pub fn completed_peer() -> Peer { + complete_peer() +} + +/// A peer that counts as `complete` is swarm metadata +/// IMPORTANT!: it only counts if the it has been announce at least once before +/// announcing the `AnnounceEvent::Completed` event. +#[must_use] +pub fn complete_peer() -> Peer { + Peer { + peer_id: PeerId(*b"-qB00000000000000000"), + peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)), 8080), + updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0), + uploaded: NumberOfBytes::new(0), + downloaded: NumberOfBytes::new(0), + left: NumberOfBytes::new(0), // No bytes left to download + event: AnnounceEvent::Completed, + } +} + +/// A peer that counts as `incomplete` is swarm metadata +#[must_use] +pub fn incomplete_peer() -> Peer { + Peer { + peer_id: PeerId(*b"-qB00000000000000000"), + peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)), 8080), + updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0), + uploaded: NumberOfBytes::new(0), + downloaded: NumberOfBytes::new(0), + left: NumberOfBytes::new(1000), // Still bytes to download + event: AnnounceEvent::Started, + } +} + +#[must_use] +pub fn initialize_handlers(config: &Configuration) -> (Arc, Arc) { + let database = initialize_database(config); + let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); + let whitelist_authorization = Arc::new(whitelist::authorization::WhitelistAuthorization::new( + &config.core, + &in_memory_whitelist.clone(), + )); + let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); + let db_torrent_repository = Arc::new(DatabasePersistentTorrentRepository::new(&database)); + + let announce_handler = Arc::new(AnnounceHandler::new( + &config.core, + &in_memory_torrent_repository, + &db_torrent_repository, + )); + + let scrape_handler = Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository)); + + (announce_handler, scrape_handler) +} diff --git a/src/core/mod.rs b/src/core/mod.rs index f09e7d417..77d8e1450 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -449,134 +449,30 @@ pub mod statistics; pub mod torrent; pub mod whitelist; +pub mod core_tests; pub mod peer_tests; #[cfg(test)] mod tests { - // Integration tests for the core module. - mod the_tracker { - - use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + use std::net::{IpAddr, Ipv4Addr}; use std::str::FromStr; use std::sync::Arc; - use aquatic_udp_protocol::{AnnounceEvent, NumberOfBytes, PeerId}; - use bittorrent_primitives::info_hash::fixture::gen_seeded_infohash; - use bittorrent_primitives::info_hash::InfoHash; - use torrust_tracker_configuration::TORRENT_PEERS_LIMIT; - use torrust_tracker_primitives::peer::Peer; - use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; - use torrust_tracker_primitives::DurationSinceUnixEpoch; use torrust_tracker_test_helpers::configuration; - use crate::app_test::initialize_tracker_dependencies; use crate::core::announce_handler::AnnounceHandler; + use crate::core::core_tests::initialize_handlers; use crate::core::scrape_handler::ScrapeHandler; - use crate::core::services::initialize_whitelist_manager; - use crate::core::torrent::manager::TorrentsManager; - use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; - use crate::core::whitelist; - use crate::core::whitelist::manager::WhiteListManager; - - fn public_tracker() -> (Arc, Arc, Arc) { - let config = configuration::ephemeral_public(); - - let ( - _database, - _in_memory_whitelist, - whitelist_authorization, - _authentication_service, - in_memory_torrent_repository, - db_torrent_repository, - _torrents_manager, - ) = initialize_tracker_dependencies(&config); - - let announce_handler = Arc::new(AnnounceHandler::new( - &config.core, - &in_memory_torrent_repository, - &db_torrent_repository, - )); - - let scrape_handler = Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository)); - (announce_handler, in_memory_torrent_repository, scrape_handler) - } - - fn initialize_in_memory_torrents_repository() -> Arc { + fn initialize_handlers_for_public_tracker() -> (Arc, Arc) { let config = configuration::ephemeral_public(); - - let ( - _database, - _in_memory_whitelist, - _whitelist_authorization, - _authentication_service, - in_memory_torrent_repository, - _db_torrent_repository, - _torrents_manager, - ) = initialize_tracker_dependencies(&config); - - in_memory_torrent_repository + initialize_handlers(&config) } - #[allow(clippy::type_complexity)] - fn whitelisted_tracker() -> ( - Arc, - Arc, - Arc, - Arc, - ) { + fn initialize_handlers_for_listed_tracker() -> (Arc, Arc) { let config = configuration::ephemeral_listed(); - - let ( - database, - in_memory_whitelist, - whitelist_authorization, - _authentication_service, - in_memory_torrent_repository, - db_torrent_repository, - _torrents_manager, - ) = initialize_tracker_dependencies(&config); - - let whitelist_manager = initialize_whitelist_manager(database.clone(), in_memory_whitelist.clone()); - - let announce_handler = Arc::new(AnnounceHandler::new( - &config.core, - &in_memory_torrent_repository, - &db_torrent_repository, - )); - - let scrape_handler = Arc::new(ScrapeHandler::new(&whitelist_authorization, &in_memory_torrent_repository)); - - (announce_handler, whitelist_authorization, whitelist_manager, scrape_handler) - } - - pub fn tracker_persisting_torrents_in_database( - ) -> (Arc, Arc, Arc) { - let mut config = configuration::ephemeral_listed(); - config.core.tracker_policy.persistent_torrent_completed_stat = true; - - let ( - _database, - _in_memory_whitelist, - _whitelist_authorization, - _authentication_service, - in_memory_torrent_repository, - db_torrent_repository, - torrents_manager, - ) = initialize_tracker_dependencies(&config); - - let announce_handler = Arc::new(AnnounceHandler::new( - &config.core, - &in_memory_torrent_repository, - &db_torrent_repository, - )); - - (announce_handler, torrents_manager, in_memory_torrent_repository) - } - - fn sample_info_hash() -> InfoHash { - "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::().unwrap() + initialize_handlers(&config) } // The client peer IP @@ -584,413 +480,8 @@ mod tests { IpAddr::V4(Ipv4Addr::from_str("126.0.0.1").unwrap()) } - /// Sample peer whose state is not relevant for the tests - fn sample_peer() -> Peer { - complete_peer() - } - - /// Sample peer when for tests that need more than one peer - fn sample_peer_1() -> Peer { - Peer { - peer_id: PeerId(*b"-qB00000000000000001"), - peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)), 8081), - updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0), - uploaded: NumberOfBytes::new(0), - downloaded: NumberOfBytes::new(0), - left: NumberOfBytes::new(0), - event: AnnounceEvent::Completed, - } - } - - /// Sample peer when for tests that need more than one peer - fn sample_peer_2() -> Peer { - Peer { - peer_id: PeerId(*b"-qB00000000000000002"), - peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 2)), 8082), - updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0), - uploaded: NumberOfBytes::new(0), - downloaded: NumberOfBytes::new(0), - left: NumberOfBytes::new(0), - event: AnnounceEvent::Completed, - } - } - - fn seeder() -> Peer { - complete_peer() - } - - fn leecher() -> Peer { - incomplete_peer() - } - - fn started_peer() -> Peer { - incomplete_peer() - } - - fn completed_peer() -> Peer { - complete_peer() - } - - /// A peer that counts as `complete` is swarm metadata - /// IMPORTANT!: it only counts if the it has been announce at least once before - /// announcing the `AnnounceEvent::Completed` event. - fn complete_peer() -> Peer { - Peer { - peer_id: PeerId(*b"-qB00000000000000000"), - peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)), 8080), - updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0), - uploaded: NumberOfBytes::new(0), - downloaded: NumberOfBytes::new(0), - left: NumberOfBytes::new(0), // No bytes left to download - event: AnnounceEvent::Completed, - } - } - - /// A peer that counts as `incomplete` is swarm metadata - fn incomplete_peer() -> Peer { - Peer { - peer_id: PeerId(*b"-qB00000000000000000"), - peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)), 8080), - updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0), - uploaded: NumberOfBytes::new(0), - downloaded: NumberOfBytes::new(0), - left: NumberOfBytes::new(1000), // Still bytes to download - event: AnnounceEvent::Started, - } - } - - #[tokio::test] - async fn it_should_return_the_peers_for_a_given_torrent() { - let in_memory_torrent_repository = initialize_in_memory_torrents_repository(); - - let info_hash = sample_info_hash(); - let peer = sample_peer(); - - let () = in_memory_torrent_repository.upsert_peer(&info_hash, &peer); - - let peers = in_memory_torrent_repository.get_torrent_peers(&info_hash); - - assert_eq!(peers, vec![Arc::new(peer)]); - } - - /// It generates a peer id from a number where the number is the last - /// part of the peer ID. For example, for `12` it returns - /// `-qB00000000000000012`. - fn numeric_peer_id(two_digits_value: i32) -> PeerId { - // Format idx as a string with leading zeros, ensuring it has exactly 2 digits - let idx_str = format!("{two_digits_value:02}"); - - // Create the base part of the peer ID. - let base = b"-qB00000000000000000"; - - // Concatenate the base with idx bytes, ensuring the total length is 20 bytes. - let mut peer_id_bytes = [0u8; 20]; - peer_id_bytes[..base.len()].copy_from_slice(base); - peer_id_bytes[base.len() - idx_str.len()..].copy_from_slice(idx_str.as_bytes()); - - PeerId(peer_id_bytes) - } - - #[tokio::test] - async fn it_should_return_74_peers_at_the_most_for_a_given_torrent() { - let in_memory_torrent_repository = initialize_in_memory_torrents_repository(); - - let info_hash = sample_info_hash(); - - for idx in 1..=75 { - let peer = Peer { - peer_id: numeric_peer_id(idx), - peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, idx.try_into().unwrap())), 8080), - updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0), - uploaded: NumberOfBytes::new(0), - downloaded: NumberOfBytes::new(0), - left: NumberOfBytes::new(0), // No bytes left to download - event: AnnounceEvent::Completed, - }; - - let () = in_memory_torrent_repository.upsert_peer(&info_hash, &peer); - } - - let peers = in_memory_torrent_repository.get_torrent_peers(&info_hash); - - assert_eq!(peers.len(), 74); - } - - #[tokio::test] - async fn it_should_return_the_peers_for_a_given_torrent_excluding_a_given_peer() { - let (_announce_handler, in_memory_torrent_repository, _scrape_handler) = public_tracker(); - - let info_hash = sample_info_hash(); - let peer = sample_peer(); - - let () = in_memory_torrent_repository.upsert_peer(&info_hash, &peer); - - let peers = in_memory_torrent_repository.get_peers_for(&info_hash, &peer, TORRENT_PEERS_LIMIT); - - assert_eq!(peers, vec![]); - } - - #[tokio::test] - async fn it_should_return_74_peers_at_the_most_for_a_given_torrent_when_it_filters_out_a_given_peer() { - let (_announce_handler, in_memory_torrent_repository, _scrape_handler) = public_tracker(); - - let info_hash = sample_info_hash(); - - let excluded_peer = sample_peer(); - - let () = in_memory_torrent_repository.upsert_peer(&info_hash, &excluded_peer); - - // Add 74 peers - for idx in 2..=75 { - let peer = Peer { - peer_id: numeric_peer_id(idx), - peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, idx.try_into().unwrap())), 8080), - updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0), - uploaded: NumberOfBytes::new(0), - downloaded: NumberOfBytes::new(0), - left: NumberOfBytes::new(0), // No bytes left to download - event: AnnounceEvent::Completed, - }; - - let () = in_memory_torrent_repository.upsert_peer(&info_hash, &peer); - } - - let peers = in_memory_torrent_repository.get_peers_for(&info_hash, &excluded_peer, TORRENT_PEERS_LIMIT); - - assert_eq!(peers.len(), 74); - } - - #[tokio::test] - async fn it_should_return_the_torrent_metrics() { - let in_memory_torrent_repository = initialize_in_memory_torrents_repository(); - - let () = in_memory_torrent_repository.upsert_peer(&sample_info_hash(), &leecher()); - - let torrent_metrics = in_memory_torrent_repository.get_torrents_metrics(); - - assert_eq!( - torrent_metrics, - TorrentsMetrics { - complete: 0, - downloaded: 0, - incomplete: 1, - torrents: 1, - } - ); - } - - #[tokio::test] - async fn it_should_get_many_the_torrent_metrics() { - let in_memory_torrent_repository = initialize_in_memory_torrents_repository(); - - let start_time = std::time::Instant::now(); - for i in 0..1_000_000 { - let () = in_memory_torrent_repository.upsert_peer(&gen_seeded_infohash(&i), &leecher()); - } - let result_a = start_time.elapsed(); - - let start_time = std::time::Instant::now(); - let torrent_metrics = in_memory_torrent_repository.get_torrents_metrics(); - let result_b = start_time.elapsed(); - - assert_eq!( - (torrent_metrics), - (TorrentsMetrics { - complete: 0, - downloaded: 0, - incomplete: 1_000_000, - torrents: 1_000_000, - }), - "{result_a:?} {result_b:?}" - ); - } - mod for_all_config_modes { - mod handling_an_announce_request { - - use std::sync::Arc; - - use crate::core::announce_handler::PeersWanted; - use crate::core::tests::the_tracker::{ - peer_ip, public_tracker, sample_info_hash, sample_peer, sample_peer_1, sample_peer_2, - }; - - mod should_assign_the_ip_to_the_peer { - - use std::net::{IpAddr, Ipv4Addr}; - - use crate::core::announce_handler::assign_ip_address_to_peer; - - #[test] - fn using_the_source_ip_instead_of_the_ip_in_the_announce_request() { - let remote_ip = IpAddr::V4(Ipv4Addr::new(126, 0, 0, 2)); - - let peer_ip = assign_ip_address_to_peer(&remote_ip, None); - - assert_eq!(peer_ip, remote_ip); - } - - mod and_when_the_client_ip_is_a_ipv4_loopback_ip { - - use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; - use std::str::FromStr; - - use crate::core::announce_handler::assign_ip_address_to_peer; - - #[test] - fn it_should_use_the_loopback_ip_if_the_tracker_does_not_have_the_external_ip_configuration() { - let remote_ip = IpAddr::V4(Ipv4Addr::LOCALHOST); - - let peer_ip = assign_ip_address_to_peer(&remote_ip, None); - - assert_eq!(peer_ip, remote_ip); - } - - #[test] - fn it_should_use_the_external_tracker_ip_in_tracker_configuration_if_it_is_defined() { - let remote_ip = IpAddr::V4(Ipv4Addr::LOCALHOST); - - let tracker_external_ip = IpAddr::V4(Ipv4Addr::from_str("126.0.0.1").unwrap()); - - let peer_ip = assign_ip_address_to_peer(&remote_ip, Some(tracker_external_ip)); - - assert_eq!(peer_ip, tracker_external_ip); - } - - #[test] - fn it_should_use_the_external_ip_in_the_tracker_configuration_if_it_is_defined_even_if_the_external_ip_is_an_ipv6_ip( - ) { - let remote_ip = IpAddr::V4(Ipv4Addr::LOCALHOST); - - let tracker_external_ip = - IpAddr::V6(Ipv6Addr::from_str("2345:0425:2CA1:0000:0000:0567:5673:23b5").unwrap()); - - let peer_ip = assign_ip_address_to_peer(&remote_ip, Some(tracker_external_ip)); - - assert_eq!(peer_ip, tracker_external_ip); - } - } - - mod and_when_client_ip_is_a_ipv6_loopback_ip { - - use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; - use std::str::FromStr; - - use crate::core::announce_handler::assign_ip_address_to_peer; - - #[test] - fn it_should_use_the_loopback_ip_if_the_tracker_does_not_have_the_external_ip_configuration() { - let remote_ip = IpAddr::V6(Ipv6Addr::LOCALHOST); - - let peer_ip = assign_ip_address_to_peer(&remote_ip, None); - - assert_eq!(peer_ip, remote_ip); - } - - #[test] - fn it_should_use_the_external_ip_in_tracker_configuration_if_it_is_defined() { - let remote_ip = IpAddr::V6(Ipv6Addr::LOCALHOST); - - let tracker_external_ip = - IpAddr::V6(Ipv6Addr::from_str("2345:0425:2CA1:0000:0000:0567:5673:23b5").unwrap()); - - let peer_ip = assign_ip_address_to_peer(&remote_ip, Some(tracker_external_ip)); - - assert_eq!(peer_ip, tracker_external_ip); - } - - #[test] - fn it_should_use_the_external_ip_in_the_tracker_configuration_if_it_is_defined_even_if_the_external_ip_is_an_ipv4_ip( - ) { - let remote_ip = IpAddr::V6(Ipv6Addr::LOCALHOST); - - let tracker_external_ip = IpAddr::V4(Ipv4Addr::from_str("126.0.0.1").unwrap()); - - let peer_ip = assign_ip_address_to_peer(&remote_ip, Some(tracker_external_ip)); - - assert_eq!(peer_ip, tracker_external_ip); - } - } - } - - #[tokio::test] - async fn it_should_return_the_announce_data_with_an_empty_peer_list_when_it_is_the_first_announced_peer() { - let (announce_handler, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); - - let mut peer = sample_peer(); - - let announce_data = announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All); - - assert_eq!(announce_data.peers, vec![]); - } - - #[tokio::test] - async fn it_should_return_the_announce_data_with_the_previously_announced_peers() { - let (announce_handler, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); - - let mut previously_announced_peer = sample_peer_1(); - announce_handler.announce( - &sample_info_hash(), - &mut previously_announced_peer, - &peer_ip(), - &PeersWanted::All, - ); - - let mut peer = sample_peer_2(); - let announce_data = announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All); - - assert_eq!(announce_data.peers, vec![Arc::new(previously_announced_peer)]); - } - - mod it_should_update_the_swarm_stats_for_the_torrent { - - use crate::core::announce_handler::PeersWanted; - use crate::core::tests::the_tracker::{ - completed_peer, leecher, peer_ip, public_tracker, sample_info_hash, seeder, started_peer, - }; - - #[tokio::test] - async fn when_the_peer_is_a_seeder() { - let (announce_handler, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); - - let mut peer = seeder(); - - let announce_data = - announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All); - - assert_eq!(announce_data.stats.complete, 1); - } - - #[tokio::test] - async fn when_the_peer_is_a_leecher() { - let (announce_handler, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); - - let mut peer = leecher(); - - let announce_data = - announce_handler.announce(&sample_info_hash(), &mut peer, &peer_ip(), &PeersWanted::All); - - assert_eq!(announce_data.stats.incomplete, 1); - } - - #[tokio::test] - async fn when_a_previously_announced_started_peer_has_completed_downloading() { - let (announce_handler, _in_memory_torrent_repository, _scrape_handler) = public_tracker(); - - // We have to announce with "started" event because peer does not count if peer was not previously known - let mut started_peer = started_peer(); - announce_handler.announce(&sample_info_hash(), &mut started_peer, &peer_ip(), &PeersWanted::All); - - let mut completed_peer = completed_peer(); - let announce_data = - announce_handler.announce(&sample_info_hash(), &mut completed_peer, &peer_ip(), &PeersWanted::All); - - assert_eq!(announce_data.stats.downloaded, 1); - } - } - } - mod handling_a_scrape_request { use std::net::{IpAddr, Ipv4Addr}; @@ -1000,11 +491,12 @@ mod tests { use torrust_tracker_primitives::swarm_metadata::SwarmMetadata; use crate::core::announce_handler::PeersWanted; - use crate::core::tests::the_tracker::{complete_peer, incomplete_peer, public_tracker}; + use crate::core::core_tests::{complete_peer, incomplete_peer}; + use crate::core::tests::the_tracker::initialize_handlers_for_public_tracker; #[tokio::test] async fn it_should_return_the_swarm_metadata_for_the_requested_file_if_the_tracker_has_that_torrent() { - let (announce_handler, _in_memory_torrent_repository, scrape_handler) = public_tracker(); + let (announce_handler, scrape_handler) = initialize_handlers_for_public_tracker(); let info_hash = "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::().unwrap(); // # DevSkim: ignore DS173237 @@ -1047,116 +539,19 @@ mod tests { mod configured_as_whitelisted { - mod handling_authorization { - use crate::core::tests::the_tracker::{sample_info_hash, whitelisted_tracker}; - - #[tokio::test] - async fn it_should_authorize_the_announce_and_scrape_actions_on_whitelisted_torrents() { - let (_announce_handler, whitelist_authorization, whitelist_manager, _scrape_handler) = whitelisted_tracker(); - - let info_hash = sample_info_hash(); - - let result = whitelist_manager.add_torrent_to_whitelist(&info_hash).await; - assert!(result.is_ok()); - - let result = whitelist_authorization.authorize(&info_hash).await; - assert!(result.is_ok()); - } - - #[tokio::test] - async fn it_should_not_authorize_the_announce_and_scrape_actions_on_not_whitelisted_torrents() { - let (_announce_handler, whitelist_authorization, _whitelist_manager, _scrape_handler) = whitelisted_tracker(); - - let info_hash = sample_info_hash(); - - let result = whitelist_authorization.authorize(&info_hash).await; - assert!(result.is_err()); - } - } - - mod handling_the_torrent_whitelist { - use crate::core::tests::the_tracker::{sample_info_hash, whitelisted_tracker}; - - // todo: after extracting the WhitelistManager from the Tracker, - // there is no need to use the tracker to test the whitelist. - // Test not using the `tracker` (`_tracker` variable) should be - // moved to the whitelist module. - - #[tokio::test] - async fn it_should_add_a_torrent_to_the_whitelist() { - let (_announce_handler, _whitelist_authorization, whitelist_manager, _scrape_handler) = whitelisted_tracker(); - - let info_hash = sample_info_hash(); - - whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap(); - - assert!(whitelist_manager.is_info_hash_whitelisted(&info_hash).await); - } - - #[tokio::test] - async fn it_should_remove_a_torrent_from_the_whitelist() { - let (_announce_handler, _whitelist_authorization, whitelist_manager, _scrape_handler) = whitelisted_tracker(); - - let info_hash = sample_info_hash(); - - whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap(); - - whitelist_manager.remove_torrent_from_whitelist(&info_hash).await.unwrap(); - - assert!(!whitelist_manager.is_info_hash_whitelisted(&info_hash).await); - } - - mod persistence { - use crate::core::tests::the_tracker::{sample_info_hash, whitelisted_tracker}; - - #[tokio::test] - async fn it_should_load_the_whitelist_from_the_database() { - let (_announce_handler, _whitelist_authorization, whitelist_manager, _scrape_handler) = - whitelisted_tracker(); - - let info_hash = sample_info_hash(); - - whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap(); - - whitelist_manager.remove_torrent_from_memory_whitelist(&info_hash).await; - - assert!(!whitelist_manager.is_info_hash_whitelisted(&info_hash).await); - - whitelist_manager.load_whitelist_from_database().await.unwrap(); - - assert!(whitelist_manager.is_info_hash_whitelisted(&info_hash).await); - } - } - } - - mod handling_an_announce_request {} - - mod handling_an_scrape_request { + mod handling_a_scrape_request { use bittorrent_primitives::info_hash::InfoHash; use torrust_tracker_primitives::core::ScrapeData; use torrust_tracker_primitives::swarm_metadata::SwarmMetadata; use crate::core::announce_handler::PeersWanted; - use crate::core::tests::the_tracker::{ - complete_peer, incomplete_peer, peer_ip, sample_info_hash, whitelisted_tracker, - }; - - #[test] - fn it_should_be_able_to_build_a_zeroed_scrape_data_for_a_list_of_info_hashes() { - // Zeroed scrape data is used when the authentication for the scrape request fails. - - let sample_info_hash = sample_info_hash(); - - let mut expected_scrape_data = ScrapeData::empty(); - expected_scrape_data.add_file_with_zeroed_metadata(&sample_info_hash); - - assert_eq!(ScrapeData::zeroed(&vec![sample_info_hash]), expected_scrape_data); - } + use crate::core::core_tests::{complete_peer, incomplete_peer}; + use crate::core::tests::the_tracker::{initialize_handlers_for_listed_tracker, peer_ip}; #[tokio::test] async fn it_should_return_the_zeroed_swarm_metadata_for_the_requested_file_if_it_is_not_whitelisted() { - let (announce_handler, _whitelist_authorization, _whitelist_manager, scrape_handler) = whitelisted_tracker(); + let (announce_handler, scrape_handler) = initialize_handlers_for_listed_tracker(); let info_hash = "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::().unwrap(); // # DevSkim: ignore DS173237 @@ -1177,49 +572,5 @@ mod tests { } } } - - mod handling_torrent_persistence { - - use aquatic_udp_protocol::AnnounceEvent; - use torrust_tracker_torrent_repository::entry::EntrySync; - - use crate::core::announce_handler::PeersWanted; - use crate::core::tests::the_tracker::{ - peer_ip, sample_info_hash, sample_peer, tracker_persisting_torrents_in_database, - }; - - #[tokio::test] - async fn it_should_persist_the_number_of_completed_peers_for_all_torrents_into_the_database() { - let (announce_handler, torrents_manager, in_memory_torrent_repository) = - tracker_persisting_torrents_in_database(); - - let info_hash = sample_info_hash(); - - let mut peer = sample_peer(); - - peer.event = AnnounceEvent::Started; - let announce_data = announce_handler.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::All); - assert_eq!(announce_data.stats.downloaded, 0); - - peer.event = AnnounceEvent::Completed; - let announce_data = announce_handler.announce(&info_hash, &mut peer, &peer_ip(), &PeersWanted::All); - assert_eq!(announce_data.stats.downloaded, 1); - - // Remove the newly updated torrent from memory - let _unused = in_memory_torrent_repository.remove(&info_hash); - - torrents_manager.load_torrents_from_database().unwrap(); - - let torrent_entry = in_memory_torrent_repository - .get(&info_hash) - .expect("it should be able to get entry"); - - // It persists the number of completed peers. - assert_eq!(torrent_entry.get_swarm_metadata().downloaded, 1); - - // It does not persist the peers - assert!(torrent_entry.peers_is_empty()); - } - } } } diff --git a/src/core/scrape_handler.rs b/src/core/scrape_handler.rs index 1d513a5a9..7de82aa06 100644 --- a/src/core/scrape_handler.rs +++ b/src/core/scrape_handler.rs @@ -9,7 +9,7 @@ use super::whitelist; pub struct ScrapeHandler { /// The service to check is a torrent is whitelisted. - whitelist_authorization: Arc, + whitelist_authorization: Arc, /// The in-memory torrents repository. in_memory_torrent_repository: Arc, @@ -18,7 +18,7 @@ pub struct ScrapeHandler { impl ScrapeHandler { #[must_use] pub fn new( - whitelist_authorization: &Arc, + whitelist_authorization: &Arc, in_memory_torrent_repository: &Arc, ) -> Self { Self { @@ -62,7 +62,7 @@ mod tests { let config = configuration::ephemeral_public(); let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); - let whitelist_authorization = Arc::new(whitelist::authorization::Authorization::new( + let whitelist_authorization = Arc::new(whitelist::authorization::WhitelistAuthorization::new( &config.core, &in_memory_whitelist.clone(), )); diff --git a/src/core/services/mod.rs b/src/core/services/mod.rs index 73328aaeb..f2ee79993 100644 --- a/src/core/services/mod.rs +++ b/src/core/services/mod.rs @@ -14,7 +14,7 @@ use torrust_tracker_configuration::v2_0_0::database; use torrust_tracker_configuration::Configuration; use super::databases::{self, Database}; -use super::whitelist::manager::WhiteListManager; +use super::whitelist::manager::WhitelistManager; use super::whitelist::repository::in_memory::InMemoryWhitelist; use super::whitelist::repository::persisted::DatabaseWhitelist; @@ -35,7 +35,7 @@ pub fn initialize_database(config: &Configuration) -> Arc> { pub fn initialize_whitelist_manager( database: Arc>, in_memory_whitelist: Arc, -) -> Arc { +) -> Arc { let database_whitelist = Arc::new(DatabaseWhitelist::new(database)); - Arc::new(WhiteListManager::new(database_whitelist, in_memory_whitelist)) + Arc::new(WhitelistManager::new(database_whitelist, in_memory_whitelist)) } diff --git a/src/core/torrent/repository/in_memory.rs b/src/core/torrent/repository/in_memory.rs index 7d469a0f5..2e80a2e9b 100644 --- a/src/core/torrent/repository/in_memory.rs +++ b/src/core/torrent/repository/in_memory.rs @@ -104,14 +104,39 @@ impl InMemoryTorrentRepository { #[cfg(test)] mod tests { + use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::sync::Arc; + use aquatic_udp_protocol::{AnnounceEvent, NumberOfBytes, PeerId}; + use bittorrent_primitives::info_hash::fixture::gen_seeded_infohash; + use torrust_tracker_configuration::TORRENT_PEERS_LIMIT; + use torrust_tracker_primitives::peer::Peer; use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; + use torrust_tracker_primitives::DurationSinceUnixEpoch; + use crate::core::core_tests::{leecher, sample_info_hash, sample_peer}; use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; + /// It generates a peer id from a number where the number is the last + /// part of the peer ID. For example, for `12` it returns + /// `-qB00000000000000012`. + fn numeric_peer_id(two_digits_value: i32) -> PeerId { + // Format idx as a string with leading zeros, ensuring it has exactly 2 digits + let idx_str = format!("{two_digits_value:02}"); + + // Create the base part of the peer ID. + let base = b"-qB00000000000000000"; + + // Concatenate the base with idx bytes, ensuring the total length is 20 bytes. + let mut peer_id_bytes = [0u8; 20]; + peer_id_bytes[..base.len()].copy_from_slice(base); + peer_id_bytes[base.len() - idx_str.len()..].copy_from_slice(idx_str.as_bytes()); + + PeerId(peer_id_bytes) + } + #[tokio::test] - async fn should_collect_torrent_metrics() { + async fn it_should_collect_torrent_metrics() { let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); let torrents_metrics = in_memory_torrent_repository.get_torrents_metrics(); @@ -126,4 +151,132 @@ mod tests { } ); } + + #[tokio::test] + async fn it_should_return_74_peers_at_the_most_for_a_given_torrent() { + let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); + + let info_hash = sample_info_hash(); + + for idx in 1..=75 { + let peer = Peer { + peer_id: numeric_peer_id(idx), + peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, idx.try_into().unwrap())), 8080), + updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0), + uploaded: NumberOfBytes::new(0), + downloaded: NumberOfBytes::new(0), + left: NumberOfBytes::new(0), // No bytes left to download + event: AnnounceEvent::Completed, + }; + + let () = in_memory_torrent_repository.upsert_peer(&info_hash, &peer); + } + + let peers = in_memory_torrent_repository.get_torrent_peers(&info_hash); + + assert_eq!(peers.len(), 74); + } + + #[tokio::test] + async fn it_should_return_the_peers_for_a_given_torrent_excluding_a_given_peer() { + let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); + + let info_hash = sample_info_hash(); + let peer = sample_peer(); + + let () = in_memory_torrent_repository.upsert_peer(&info_hash, &peer); + + let peers = in_memory_torrent_repository.get_peers_for(&info_hash, &peer, TORRENT_PEERS_LIMIT); + + assert_eq!(peers, vec![]); + } + + #[tokio::test] + async fn it_should_return_74_peers_at_the_most_for_a_given_torrent_when_it_filters_out_a_given_peer() { + let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); + + let info_hash = sample_info_hash(); + + let excluded_peer = sample_peer(); + + let () = in_memory_torrent_repository.upsert_peer(&info_hash, &excluded_peer); + + // Add 74 peers + for idx in 2..=75 { + let peer = Peer { + peer_id: numeric_peer_id(idx), + peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, idx.try_into().unwrap())), 8080), + updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0), + uploaded: NumberOfBytes::new(0), + downloaded: NumberOfBytes::new(0), + left: NumberOfBytes::new(0), // No bytes left to download + event: AnnounceEvent::Completed, + }; + + let () = in_memory_torrent_repository.upsert_peer(&info_hash, &peer); + } + + let peers = in_memory_torrent_repository.get_peers_for(&info_hash, &excluded_peer, TORRENT_PEERS_LIMIT); + + assert_eq!(peers.len(), 74); + } + + #[tokio::test] + async fn it_should_return_the_torrent_metrics() { + let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); + + let () = in_memory_torrent_repository.upsert_peer(&sample_info_hash(), &leecher()); + + let torrent_metrics = in_memory_torrent_repository.get_torrents_metrics(); + + assert_eq!( + torrent_metrics, + TorrentsMetrics { + complete: 0, + downloaded: 0, + incomplete: 1, + torrents: 1, + } + ); + } + + #[tokio::test] + async fn it_should_get_many_the_torrent_metrics() { + let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); + + let start_time = std::time::Instant::now(); + for i in 0..1_000_000 { + let () = in_memory_torrent_repository.upsert_peer(&gen_seeded_infohash(&i), &leecher()); + } + let result_a = start_time.elapsed(); + + let start_time = std::time::Instant::now(); + let torrent_metrics = in_memory_torrent_repository.get_torrents_metrics(); + let result_b = start_time.elapsed(); + + assert_eq!( + (torrent_metrics), + (TorrentsMetrics { + complete: 0, + downloaded: 0, + incomplete: 1_000_000, + torrents: 1_000_000, + }), + "{result_a:?} {result_b:?}" + ); + } + + #[tokio::test] + async fn it_should_return_the_peers_for_a_given_torrent() { + let in_memory_torrent_repository = Arc::new(InMemoryTorrentRepository::default()); + + let info_hash = sample_info_hash(); + let peer = sample_peer(); + + let () = in_memory_torrent_repository.upsert_peer(&info_hash, &peer); + + let peers = in_memory_torrent_repository.get_torrent_peers(&info_hash); + + assert_eq!(peers, vec![Arc::new(peer)]); + } } diff --git a/src/core/whitelist/authorization.rs b/src/core/whitelist/authorization.rs index 74029495f..1a6d8b758 100644 --- a/src/core/whitelist/authorization.rs +++ b/src/core/whitelist/authorization.rs @@ -8,7 +8,7 @@ use tracing::instrument; use super::repository::in_memory::InMemoryWhitelist; use crate::core::error::Error; -pub struct Authorization { +pub struct WhitelistAuthorization { /// Core tracker configuration. config: Core, @@ -16,7 +16,7 @@ pub struct Authorization { in_memory_whitelist: Arc, } -impl Authorization { +impl WhitelistAuthorization { /// Creates a new authorization instance. pub fn new(config: &Core, in_memory_whitelist: &Arc) -> Self { Self { @@ -57,3 +57,38 @@ impl Authorization { self.in_memory_whitelist.contains(info_hash).await } } + +#[cfg(test)] +mod tests { + + mod configured_as_whitelisted { + + mod handling_authorization { + use crate::core::core_tests::sample_info_hash; + use crate::core::whitelist::whitelist_tests::initialize_whitelist_services_for_listed_tracker; + + #[tokio::test] + async fn it_should_authorize_the_announce_and_scrape_actions_on_whitelisted_torrents() { + let (whitelist_authorization, whitelist_manager) = initialize_whitelist_services_for_listed_tracker(); + + let info_hash = sample_info_hash(); + + let result = whitelist_manager.add_torrent_to_whitelist(&info_hash).await; + assert!(result.is_ok()); + + let result = whitelist_authorization.authorize(&info_hash).await; + assert!(result.is_ok()); + } + + #[tokio::test] + async fn it_should_not_authorize_the_announce_and_scrape_actions_on_not_whitelisted_torrents() { + let (whitelist_authorization, _whitelist_manager) = initialize_whitelist_services_for_listed_tracker(); + + let info_hash = sample_info_hash(); + + let result = whitelist_authorization.authorize(&info_hash).await; + assert!(result.is_err()); + } + } + } +} diff --git a/src/core/whitelist/manager.rs b/src/core/whitelist/manager.rs index 757053f71..0d9751994 100644 --- a/src/core/whitelist/manager.rs +++ b/src/core/whitelist/manager.rs @@ -7,7 +7,7 @@ use super::repository::persisted::DatabaseWhitelist; use crate::core::databases; /// It handles the list of allowed torrents. Only for listed trackers. -pub struct WhiteListManager { +pub struct WhitelistManager { /// The in-memory list of allowed torrents. in_memory_whitelist: Arc, @@ -15,7 +15,7 @@ pub struct WhiteListManager { database_whitelist: Arc, } -impl WhiteListManager { +impl WhitelistManager { #[must_use] pub fn new(database_whitelist: Arc, in_memory_whitelist: Arc) -> Self { Self { @@ -89,3 +89,76 @@ impl WhiteListManager { Ok(()) } } + +#[cfg(test)] +mod tests { + + use std::sync::Arc; + + use torrust_tracker_test_helpers::configuration; + + use crate::core::whitelist::manager::WhitelistManager; + use crate::core::whitelist::whitelist_tests::initialize_whitelist_services; + + fn initialize_whitelist_manager_for_whitelisted_tracker() -> Arc { + let config = configuration::ephemeral_listed(); + + let (_whitelist_authorization, whitelist_manager) = initialize_whitelist_services(&config); + + whitelist_manager + } + + mod configured_as_whitelisted { + + mod handling_the_torrent_whitelist { + use crate::core::core_tests::sample_info_hash; + use crate::core::whitelist::manager::tests::initialize_whitelist_manager_for_whitelisted_tracker; + + #[tokio::test] + async fn it_should_add_a_torrent_to_the_whitelist() { + let whitelist_manager = initialize_whitelist_manager_for_whitelisted_tracker(); + + let info_hash = sample_info_hash(); + + whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap(); + + assert!(whitelist_manager.is_info_hash_whitelisted(&info_hash).await); + } + + #[tokio::test] + async fn it_should_remove_a_torrent_from_the_whitelist() { + let whitelist_manager = initialize_whitelist_manager_for_whitelisted_tracker(); + + let info_hash = sample_info_hash(); + + whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap(); + + whitelist_manager.remove_torrent_from_whitelist(&info_hash).await.unwrap(); + + assert!(!whitelist_manager.is_info_hash_whitelisted(&info_hash).await); + } + + mod persistence { + use crate::core::core_tests::sample_info_hash; + use crate::core::whitelist::manager::tests::initialize_whitelist_manager_for_whitelisted_tracker; + + #[tokio::test] + async fn it_should_load_the_whitelist_from_the_database() { + let whitelist_manager = initialize_whitelist_manager_for_whitelisted_tracker(); + + let info_hash = sample_info_hash(); + + whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap(); + + whitelist_manager.remove_torrent_from_memory_whitelist(&info_hash).await; + + assert!(!whitelist_manager.is_info_hash_whitelisted(&info_hash).await); + + whitelist_manager.load_whitelist_from_database().await.unwrap(); + + assert!(whitelist_manager.is_info_hash_whitelisted(&info_hash).await); + } + } + } + } +} diff --git a/src/core/whitelist/mod.rs b/src/core/whitelist/mod.rs index 89c69b761..c23740111 100644 --- a/src/core/whitelist/mod.rs +++ b/src/core/whitelist/mod.rs @@ -1,3 +1,39 @@ pub mod authorization; pub mod manager; pub mod repository; +pub mod whitelist_tests; + +#[cfg(test)] +mod tests { + + mod configured_as_whitelisted { + + mod handling_authorization { + use crate::core::core_tests::sample_info_hash; + use crate::core::whitelist::whitelist_tests::initialize_whitelist_services_for_listed_tracker; + + #[tokio::test] + async fn it_should_authorize_the_announce_and_scrape_actions_on_whitelisted_torrents() { + let (whitelist_authorization, whitelist_manager) = initialize_whitelist_services_for_listed_tracker(); + + let info_hash = sample_info_hash(); + + let result = whitelist_manager.add_torrent_to_whitelist(&info_hash).await; + assert!(result.is_ok()); + + let result = whitelist_authorization.authorize(&info_hash).await; + assert!(result.is_ok()); + } + + #[tokio::test] + async fn it_should_not_authorize_the_announce_and_scrape_actions_on_not_whitelisted_torrents() { + let (whitelist_authorization, _whitelist_manager) = initialize_whitelist_services_for_listed_tracker(); + + let info_hash = sample_info_hash(); + + let result = whitelist_authorization.authorize(&info_hash).await; + assert!(result.is_err()); + } + } + } +} diff --git a/src/core/whitelist/repository/in_memory.rs b/src/core/whitelist/repository/in_memory.rs index 8d919f1e4..f023c1610 100644 --- a/src/core/whitelist/repository/in_memory.rs +++ b/src/core/whitelist/repository/in_memory.rs @@ -32,14 +32,10 @@ impl InMemoryWhitelist { #[cfg(test)] mod tests { - use bittorrent_primitives::info_hash::InfoHash; + use crate::core::core_tests::sample_info_hash; use crate::core::whitelist::repository::in_memory::InMemoryWhitelist; - fn sample_info_hash() -> InfoHash { - "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::().unwrap() // # DevSkim: ignore DS173237 - } - #[tokio::test] async fn should_allow_adding_a_new_torrent_to_the_whitelist() { let info_hash = sample_info_hash(); diff --git a/src/core/whitelist/whitelist_tests.rs b/src/core/whitelist/whitelist_tests.rs new file mode 100644 index 000000000..aa9c5ca14 --- /dev/null +++ b/src/core/whitelist/whitelist_tests.rs @@ -0,0 +1,26 @@ +use std::sync::Arc; + +use torrust_tracker_configuration::Configuration; + +use super::authorization::WhitelistAuthorization; +use super::manager::WhitelistManager; +use super::repository::in_memory::InMemoryWhitelist; +use crate::core::services::{initialize_database, initialize_whitelist_manager}; + +#[must_use] +pub fn initialize_whitelist_services(config: &Configuration) -> (Arc, Arc) { + let database = initialize_database(config); + let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); + let whitelist_authorization = Arc::new(WhitelistAuthorization::new(&config.core, &in_memory_whitelist.clone())); + let whitelist_manager = initialize_whitelist_manager(database.clone(), in_memory_whitelist.clone()); + + (whitelist_authorization, whitelist_manager) +} + +#[cfg(test)] +#[must_use] +pub fn initialize_whitelist_services_for_listed_tracker() -> (Arc, Arc) { + use torrust_tracker_test_helpers::configuration; + + initialize_whitelist_services(&configuration::ephemeral_listed()) +} diff --git a/src/servers/apis/routes.rs b/src/servers/apis/routes.rs index c27b5f906..92ecb067d 100644 --- a/src/servers/apis/routes.rs +++ b/src/servers/apis/routes.rs @@ -34,7 +34,7 @@ use crate::core::authentication::handler::KeysHandler; use crate::core::statistics::event::sender::Sender; use crate::core::statistics::repository::Repository; use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; -use crate::core::whitelist::manager::WhiteListManager; +use crate::core::whitelist::manager::WhitelistManager; use crate::servers::apis::API_LOG_TARGET; use crate::servers::logging::Latency; use crate::servers::udp::server::banning::BanService; @@ -53,7 +53,7 @@ use crate::servers::udp::server::banning::BanService; pub fn router( in_memory_torrent_repository: Arc, keys_handler: Arc, - whitelist_manager: Arc, + whitelist_manager: Arc, ban_service: Arc>, stats_event_sender: Arc>>, stats_repository: Arc, diff --git a/src/servers/apis/server.rs b/src/servers/apis/server.rs index b37f71d5b..b3621de0e 100644 --- a/src/servers/apis/server.rs +++ b/src/servers/apis/server.rs @@ -43,7 +43,7 @@ use crate::core::authentication::handler::KeysHandler; use crate::core::statistics; use crate::core::statistics::repository::Repository; use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; -use crate::core::whitelist::manager::WhiteListManager; +use crate::core::whitelist::manager::WhitelistManager; use crate::servers::apis::API_LOG_TARGET; use crate::servers::custom_axum_server::{self, TimeoutAcceptor}; use crate::servers::logging::STARTED_ON; @@ -134,7 +134,7 @@ impl ApiServer { self, in_memory_torrent_repository: Arc, keys_handler: Arc, - whitelist_manager: Arc, + whitelist_manager: Arc, stats_event_sender: Arc>>, stats_repository: Arc, ban_service: Arc>, @@ -275,7 +275,7 @@ impl Launcher { &self, in_memory_torrent_repository: Arc, keys_handler: Arc, - whitelist_manager: Arc, + whitelist_manager: Arc, ban_service: Arc>, stats_event_sender: Arc>>, stats_repository: Arc, diff --git a/src/servers/apis/v1/context/whitelist/handlers.rs b/src/servers/apis/v1/context/whitelist/handlers.rs index 473ed56c5..ebe0bb15c 100644 --- a/src/servers/apis/v1/context/whitelist/handlers.rs +++ b/src/servers/apis/v1/context/whitelist/handlers.rs @@ -10,7 +10,7 @@ use bittorrent_primitives::info_hash::InfoHash; use super::responses::{ failed_to_reload_whitelist_response, failed_to_remove_torrent_from_whitelist_response, failed_to_whitelist_torrent_response, }; -use crate::core::whitelist::manager::WhiteListManager; +use crate::core::whitelist::manager::WhitelistManager; use crate::servers::apis::v1::responses::{invalid_info_hash_param_response, ok_response}; use crate::servers::apis::InfoHashParam; @@ -24,7 +24,7 @@ use crate::servers::apis::InfoHashParam; /// Refer to the [API endpoint documentation](crate::servers::apis::v1::context::whitelist#add-a-torrent-to-the-whitelist) /// for more information about this endpoint. pub async fn add_torrent_to_whitelist_handler( - State(whitelist_manager): State>, + State(whitelist_manager): State>, Path(info_hash): Path, ) -> Response { match InfoHash::from_str(&info_hash.0) { @@ -47,7 +47,7 @@ pub async fn add_torrent_to_whitelist_handler( /// Refer to the [API endpoint documentation](crate::servers::apis::v1::context::whitelist#remove-a-torrent-from-the-whitelist) /// for more information about this endpoint. pub async fn remove_torrent_from_whitelist_handler( - State(whitelist_manager): State>, + State(whitelist_manager): State>, Path(info_hash): Path, ) -> Response { match InfoHash::from_str(&info_hash.0) { @@ -69,7 +69,7 @@ pub async fn remove_torrent_from_whitelist_handler( /// /// Refer to the [API endpoint documentation](crate::servers::apis::v1::context::whitelist#reload-the-whitelist) /// for more information about this endpoint. -pub async fn reload_whitelist_handler(State(whitelist_manager): State>) -> Response { +pub async fn reload_whitelist_handler(State(whitelist_manager): State>) -> Response { match whitelist_manager.load_whitelist_from_database().await { Ok(()) => ok_response(), Err(e) => failed_to_reload_whitelist_response(e), diff --git a/src/servers/apis/v1/context/whitelist/routes.rs b/src/servers/apis/v1/context/whitelist/routes.rs index 34f1393b8..5069332af 100644 --- a/src/servers/apis/v1/context/whitelist/routes.rs +++ b/src/servers/apis/v1/context/whitelist/routes.rs @@ -11,10 +11,10 @@ use axum::routing::{delete, get, post}; use axum::Router; use super::handlers::{add_torrent_to_whitelist_handler, reload_whitelist_handler, remove_torrent_from_whitelist_handler}; -use crate::core::whitelist::manager::WhiteListManager; +use crate::core::whitelist::manager::WhitelistManager; /// It adds the routes to the router for the [`whitelist`](crate::servers::apis::v1::context::whitelist) API context. -pub fn add(prefix: &str, router: Router, whitelist_manager: &Arc) -> Router { +pub fn add(prefix: &str, router: Router, whitelist_manager: &Arc) -> Router { let prefix = format!("{prefix}/whitelist"); router diff --git a/src/servers/apis/v1/routes.rs b/src/servers/apis/v1/routes.rs index 8fac453b8..87c28de08 100644 --- a/src/servers/apis/v1/routes.rs +++ b/src/servers/apis/v1/routes.rs @@ -9,7 +9,7 @@ use crate::core::authentication::handler::KeysHandler; use crate::core::statistics::event::sender::Sender; use crate::core::statistics::repository::Repository; use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; -use crate::core::whitelist::manager::WhiteListManager; +use crate::core::whitelist::manager::WhitelistManager; use crate::servers::udp::server::banning::BanService; /// Add the routes for the v1 API. @@ -19,7 +19,7 @@ pub fn add( router: Router, in_memory_torrent_repository: &Arc, keys_handler: &Arc, - whitelist_manager: &Arc, + whitelist_manager: &Arc, ban_service: Arc>, stats_event_sender: Arc>>, stats_repository: Arc, diff --git a/src/servers/http/server.rs b/src/servers/http/server.rs index 28f407ad3..2792697b3 100644 --- a/src/servers/http/server.rs +++ b/src/servers/http/server.rs @@ -63,7 +63,7 @@ impl Launcher { announce_handler: Arc, scrape_handler: Arc, authentication_service: Arc, - whitelist_authorization: Arc, + whitelist_authorization: Arc, stats_event_sender: Arc>>, tx_start: Sender, rx_halt: Receiver, @@ -192,7 +192,7 @@ impl HttpServer { announce_handler: Arc, scrape_handler: Arc, authentication_service: Arc, - whitelist_authorization: Arc, + whitelist_authorization: Arc, stats_event_sender: Arc>>, form: ServiceRegistrationForm, ) -> Result, Error> { diff --git a/src/servers/http/v1/handlers/announce.rs b/src/servers/http/v1/handlers/announce.rs index 632688763..247c6b8c6 100644 --- a/src/servers/http/v1/handlers/announce.rs +++ b/src/servers/http/v1/handlers/announce.rs @@ -43,7 +43,7 @@ pub async fn handle_without_key( Arc, Arc, Arc, - Arc, + Arc, Arc>>, )>, ExtractRequest(announce_request): ExtractRequest, @@ -73,7 +73,7 @@ pub async fn handle_with_key( Arc, Arc, Arc, - Arc, + Arc, Arc>>, )>, ExtractRequest(announce_request): ExtractRequest, @@ -104,7 +104,7 @@ async fn handle( config: &Arc, announce_handler: &Arc, authentication_service: &Arc, - whitelist_authorization: &Arc, + whitelist_authorization: &Arc, opt_stats_event_sender: &Arc>>, announce_request: &Announce, client_ip_sources: &ClientIpSources, @@ -139,7 +139,7 @@ async fn handle_announce( core_config: &Arc, announce_handler: &Arc, authentication_service: &Arc, - whitelist_authorization: &Arc, + whitelist_authorization: &Arc, opt_stats_event_sender: &Arc>>, announce_request: &Announce, client_ip_sources: &ClientIpSources, @@ -265,7 +265,7 @@ mod tests { Arc, Arc, Arc>>, - Arc, + Arc, Arc, ); diff --git a/src/servers/http/v1/routes.rs b/src/servers/http/v1/routes.rs index 757a7d1bd..f80760955 100644 --- a/src/servers/http/v1/routes.rs +++ b/src/servers/http/v1/routes.rs @@ -49,7 +49,7 @@ pub fn router( announce_handler: Arc, scrape_handler: Arc, authentication_service: Arc, - whitelist_authorization: Arc, + whitelist_authorization: Arc, stats_event_sender: Arc>>, server_socket_addr: SocketAddr, ) -> Router { diff --git a/src/servers/http/v1/services/announce.rs b/src/servers/http/v1/services/announce.rs index e70377fd6..c8c2980c3 100644 --- a/src/servers/http/v1/services/announce.rs +++ b/src/servers/http/v1/services/announce.rs @@ -60,7 +60,6 @@ mod tests { use std::sync::Arc; use aquatic_udp_protocol::{AnnounceEvent, NumberOfBytes, PeerId}; - use bittorrent_primitives::info_hash::InfoHash; use torrust_tracker_configuration::Core; use torrust_tracker_primitives::{peer, DurationSinceUnixEpoch}; use torrust_tracker_test_helpers::configuration; @@ -97,10 +96,6 @@ mod tests { (core_config, announce_handler, stats_event_sender) } - fn sample_info_hash() -> InfoHash { - "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::().unwrap() - } - fn sample_peer_using_ipv4() -> peer::Peer { sample_peer() } @@ -140,9 +135,10 @@ mod tests { use super::{sample_peer_using_ipv4, sample_peer_using_ipv6}; use crate::app_test::initialize_tracker_dependencies; use crate::core::announce_handler::{AnnounceHandler, PeersWanted}; + use crate::core::core_tests::sample_info_hash; use crate::core::statistics; use crate::servers::http::v1::services::announce::invoke; - use crate::servers::http::v1::services::announce::tests::{public_tracker, sample_info_hash, sample_peer}; + use crate::servers::http::v1::services::announce::tests::{public_tracker, sample_peer}; fn initialize_announce_handler() -> Arc { let config = configuration::ephemeral(); diff --git a/src/servers/http/v1/services/scrape.rs b/src/servers/http/v1/services/scrape.rs index 06c21d945..6cd7213be 100644 --- a/src/servers/http/v1/services/scrape.rs +++ b/src/servers/http/v1/services/scrape.rs @@ -82,6 +82,7 @@ mod tests { use crate::app_test::initialize_tracker_dependencies; use crate::core::announce_handler::AnnounceHandler; + use crate::core::core_tests::sample_info_hash; use crate::core::scrape_handler::ScrapeHandler; fn public_tracker_and_announce_and_scrape_handlers() -> (Arc, Arc) { @@ -112,10 +113,6 @@ mod tests { vec![sample_info_hash()] } - fn sample_info_hash() -> InfoHash { - "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::().unwrap() // # DevSkim: ignore DS173237 - } - fn sample_peer() -> peer::Peer { peer::Peer { peer_id: PeerId(*b"-qB00000000000000000"), diff --git a/src/servers/udp/handlers.rs b/src/servers/udp/handlers.rs index 5589331a7..2e753404d 100644 --- a/src/servers/udp/handlers.rs +++ b/src/servers/udp/handlers.rs @@ -64,7 +64,7 @@ pub(crate) async fn handle_packet( core_config: &Arc, announce_handler: &Arc, scrape_handler: &Arc, - whitelist_authorization: &Arc, + whitelist_authorization: &Arc, opt_stats_event_sender: &Arc>>, local_addr: SocketAddr, cookie_time_values: CookieTimeValues, @@ -157,7 +157,7 @@ pub async fn handle_request( core_config: &Arc, announce_handler: &Arc, scrape_handler: &Arc, - whitelist_authorization: &Arc, + whitelist_authorization: &Arc, opt_stats_event_sender: &Arc>>, cookie_time_values: CookieTimeValues, ) -> Result { @@ -247,7 +247,7 @@ pub async fn handle_announce( request: &AnnounceRequest, core_config: &Arc, announce_handler: &Arc, - whitelist_authorization: &Arc, + whitelist_authorization: &Arc, opt_stats_event_sender: &Arc>>, cookie_valid_range: Range, ) -> Result { @@ -505,7 +505,7 @@ mod tests { use crate::core::statistics::event::sender::Sender; use crate::core::torrent::repository::in_memory::InMemoryTorrentRepository; use crate::core::whitelist; - use crate::core::whitelist::manager::WhiteListManager; + use crate::core::whitelist::manager::WhitelistManager; use crate::core::whitelist::repository::in_memory::InMemoryWhitelist; use crate::CurrentClock; @@ -516,8 +516,8 @@ mod tests { Arc, Arc>>, Arc, - Arc, - Arc, + Arc, + Arc, ); fn tracker_configuration() -> Configuration { @@ -672,7 +672,7 @@ mod tests { Arc, Arc, Arc, - Arc, + Arc, ) { let config = tracker_configuration(); @@ -1088,7 +1088,7 @@ mod tests { async fn announce_a_new_peer_using_ipv4( core_config: Arc, announce_handler: Arc, - whitelist_authorization: Arc, + whitelist_authorization: Arc, ) -> Response { let (stats_event_sender, _stats_repository) = crate::core::services::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); @@ -1426,7 +1426,7 @@ mod tests { async fn announce_a_new_peer_using_ipv6( core_config: Arc, announce_handler: Arc, - whitelist_authorization: Arc, + whitelist_authorization: Arc, ) -> Response { let (stats_event_sender, _stats_repository) = crate::core::services::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); diff --git a/src/servers/udp/server/launcher.rs b/src/servers/udp/server/launcher.rs index f1b14860d..4aaf87ae2 100644 --- a/src/servers/udp/server/launcher.rs +++ b/src/servers/udp/server/launcher.rs @@ -58,7 +58,7 @@ impl Launcher { core_config: Arc, announce_handler: Arc, scrape_handler: Arc, - whitelist_authorization: Arc, + whitelist_authorization: Arc, opt_stats_event_sender: Arc>>, ban_service: Arc>, bind_to: SocketAddr, @@ -159,7 +159,7 @@ impl Launcher { core_config: Arc, announce_handler: Arc, scrape_handler: Arc, - whitelist_authorization: Arc, + whitelist_authorization: Arc, opt_stats_event_sender: Arc>>, ban_service: Arc>, cookie_lifetime: Duration, diff --git a/src/servers/udp/server/processor.rs b/src/servers/udp/server/processor.rs index 475a36b74..24a34f98d 100644 --- a/src/servers/udp/server/processor.rs +++ b/src/servers/udp/server/processor.rs @@ -24,7 +24,7 @@ pub struct Processor { core_config: Arc, announce_handler: Arc, scrape_handler: Arc, - whitelist_authorization: Arc, + whitelist_authorization: Arc, opt_stats_event_sender: Arc>>, cookie_lifetime: f64, } @@ -36,7 +36,7 @@ impl Processor { core_config: Arc, announce_handler: Arc, scrape_handler: Arc, - whitelist_authorization: Arc, + whitelist_authorization: Arc, opt_stats_event_sender: Arc>>, cookie_lifetime: f64, ) -> Self { diff --git a/src/servers/udp/server/spawner.rs b/src/servers/udp/server/spawner.rs index 2415b2631..d5fd5d58e 100644 --- a/src/servers/udp/server/spawner.rs +++ b/src/servers/udp/server/spawner.rs @@ -36,7 +36,7 @@ impl Spawner { core_config: Arc, announce_handler: Arc, scrape_handler: Arc, - whitelist_authorization: Arc, + whitelist_authorization: Arc, opt_stats_event_sender: Arc>>, ban_service: Arc>, cookie_lifetime: Duration, diff --git a/src/servers/udp/server/states.rs b/src/servers/udp/server/states.rs index 4d18593fe..9bcde9003 100644 --- a/src/servers/udp/server/states.rs +++ b/src/servers/udp/server/states.rs @@ -74,7 +74,7 @@ impl Server { core_config: Arc, announce_handler: Arc, scrape_handler: Arc, - whitelist_authorization: Arc, + whitelist_authorization: Arc, opt_stats_event_sender: Arc>>, ban_service: Arc>, form: ServiceRegistrationForm, diff --git a/tests/servers/api/environment.rs b/tests/servers/api/environment.rs index 3488456e7..66018032e 100644 --- a/tests/servers/api/environment.rs +++ b/tests/servers/api/environment.rs @@ -14,7 +14,7 @@ use torrust_tracker_lib::core::databases::Database; use torrust_tracker_lib::core::statistics::event::sender::Sender; use torrust_tracker_lib::core::statistics::repository::Repository; use torrust_tracker_lib::core::torrent::repository::in_memory::InMemoryTorrentRepository; -use torrust_tracker_lib::core::whitelist::manager::WhiteListManager; +use torrust_tracker_lib::core::whitelist::manager::WhitelistManager; use torrust_tracker_lib::servers::apis::server::{ApiServer, Launcher, Running, Stopped}; use torrust_tracker_lib::servers::registar::Registar; use torrust_tracker_lib::servers::udp::server::banning::BanService; @@ -31,7 +31,7 @@ where pub authentication_service: Arc, pub stats_event_sender: Arc>>, pub stats_repository: Arc, - pub whitelist_manager: Arc, + pub whitelist_manager: Arc, pub ban_service: Arc>, pub registar: Registar, pub server: ApiServer, diff --git a/tests/servers/http/environment.rs b/tests/servers/http/environment.rs index 589430848..5bf1d1c65 100644 --- a/tests/servers/http/environment.rs +++ b/tests/servers/http/environment.rs @@ -14,7 +14,7 @@ use torrust_tracker_lib::core::statistics::event::sender::Sender; use torrust_tracker_lib::core::statistics::repository::Repository; use torrust_tracker_lib::core::torrent::repository::in_memory::InMemoryTorrentRepository; use torrust_tracker_lib::core::whitelist; -use torrust_tracker_lib::core::whitelist::manager::WhiteListManager; +use torrust_tracker_lib::core::whitelist::manager::WhitelistManager; use torrust_tracker_lib::servers::http::server::{HttpServer, Launcher, Running, Stopped}; use torrust_tracker_lib::servers::registar::Registar; use torrust_tracker_primitives::peer; @@ -30,8 +30,8 @@ pub struct Environment { pub authentication_service: Arc, pub stats_event_sender: Arc>>, pub stats_repository: Arc, - pub whitelist_authorization: Arc, - pub whitelist_manager: Arc, + pub whitelist_authorization: Arc, + pub whitelist_manager: Arc, pub registar: Registar, pub server: HttpServer, } diff --git a/tests/servers/udp/environment.rs b/tests/servers/udp/environment.rs index a6ddd7a83..b3a2670e8 100644 --- a/tests/servers/udp/environment.rs +++ b/tests/servers/udp/environment.rs @@ -29,7 +29,7 @@ where pub in_memory_torrent_repository: Arc, pub announce_handler: Arc, pub scrape_handler: Arc, - pub whitelist_authorization: Arc, + pub whitelist_authorization: Arc, pub stats_event_sender: Arc>>, pub stats_repository: Arc, pub ban_service: Arc>,