From 32af56d4e2f8f00d2effa36ef0a05c0ba553c658 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Fri, 5 May 2023 14:13:17 +0100 Subject: [PATCH] test: [#115] add E2E tests for torrent download with personal announce url --- tests/e2e/contexts/torrent/asserts.rs | 61 ++++++++++++++++++++++++-- tests/e2e/contexts/torrent/contract.rs | 41 ++++++++++++++--- 2 files changed, 94 insertions(+), 8 deletions(-) diff --git a/tests/e2e/contexts/torrent/asserts.rs b/tests/e2e/contexts/torrent/asserts.rs index a7561a97..b6e8ae76 100644 --- a/tests/e2e/contexts/torrent/asserts.rs +++ b/tests/e2e/contexts/torrent/asserts.rs @@ -1,20 +1,75 @@ +use std::sync::Arc; + +use torrust_index_backend::databases::database::connect_database; use torrust_index_backend::models::torrent_file::Torrent; +use torrust_index_backend::models::tracker_key::TrackerKey; + +use crate::common::contexts::user::responses::LoggedInUserData; +use crate::e2e::environment::TestEnv; /// The backend does not generate exactly the same torrent that was uploaded. /// So we need to update the expected torrent to match the one generated by /// the backend. -pub fn expected_torrent(mut uploaded_torrent: Torrent) -> Torrent { +pub async fn expected_torrent(mut uploaded_torrent: Torrent, env: &TestEnv, downloader: &Option) -> Torrent { // code-review: The backend does not generate exactly the same torrent // that was uploaded and created by the `imdl` command-line tool. // So we need to update the expected torrent to match the one generated // by the backend. For some of them it makes sense (`announce` and `announce_list`), // for others it does not. + + let tracker_url = format!("{}", env.server_settings().unwrap().tracker.url); + + let tracker_key = match downloader { + Some(logged_in_user) => get_user_tracker_key(logged_in_user, env).await, + None => None, + }; + uploaded_torrent.info.private = Some(0); - uploaded_torrent.announce = Some("udp://tracker:6969".to_string()); + uploaded_torrent.announce = Some(build_announce_url(&tracker_url, &tracker_key)); uploaded_torrent.encoding = None; - uploaded_torrent.announce_list = Some(vec![vec!["udp://tracker:6969".to_string()]]); + uploaded_torrent.announce_list = Some(build_announce_list(&tracker_url, &tracker_key)); uploaded_torrent.creation_date = None; uploaded_torrent.created_by = None; uploaded_torrent } + +async fn get_user_tracker_key(logged_in_user: &LoggedInUserData, env: &TestEnv) -> Option { + // code-review: could we add a new endpoint to get the user's tracker key? + // `/user/keys/recent` or `/user/keys/latest + // We could use that endpoint to get the user's tracker key instead of + // querying the database. + + let database = Arc::new( + connect_database(&env.database_connect_url().unwrap()) + .await + .expect("Database error."), + ); + + // Get the logged-in user id + let user_profile = database + .get_user_profile_from_username(&logged_in_user.username) + .await + .unwrap(); + + // Get the user's tracker key + let tracker_key = database.get_user_tracker_key(user_profile.user_id).await.unwrap(); + + Some(tracker_key) +} + +fn build_announce_url(tracker_url: &str, tracker_key: &Option) -> String { + if let Some(key) = &tracker_key { + format!("{tracker_url}/{}", key.key) + } else { + format!("{tracker_url}") + } +} + +fn build_announce_list(tracker_url: &str, tracker_key: &Option) -> Vec> { + if let Some(key) = &tracker_key { + vec![vec![format!("{tracker_url}/{}", key.key)], vec![format!("{tracker_url}")]] + } else { + vec![vec![format!("{tracker_url}")]] + } +} diff --git a/tests/e2e/contexts/torrent/contract.rs b/tests/e2e/contexts/torrent/contract.rs index 3e102f4e..4d477cc5 100644 --- a/tests/e2e/contexts/torrent/contract.rs +++ b/tests/e2e/contexts/torrent/contract.rs @@ -3,10 +3,6 @@ /* todo: -Download torrent file: - -- It should allow authenticated users to download a torrent with a personal tracker url - Delete torrent: - After deleting a torrent, it should be removed from the tracker whitelist @@ -132,7 +128,7 @@ mod for_guests { let torrent = decode_torrent(&response.bytes).unwrap(); let uploaded_torrent = decode_torrent(&test_torrent.index_info.torrent_file.contents).unwrap(); - let expected_torrent = expected_torrent(uploaded_torrent); + let expected_torrent = expected_torrent(uploaded_torrent, &env, &None).await; assert_eq!(torrent, expected_torrent); assert!(response.is_bittorrent_and_ok()); } @@ -160,10 +156,14 @@ mod for_guests { mod for_authenticated_users { + use torrust_index_backend::utils::parse_torrent::decode_torrent; + use crate::common::client::Client; use crate::common::contexts::torrent::fixtures::random_torrent; use crate::common::contexts::torrent::forms::UploadTorrentMultipartForm; use crate::common::contexts::torrent::responses::UploadedTorrentResponse; + use crate::e2e::contexts::torrent::asserts::expected_torrent; + use crate::e2e::contexts::torrent::steps::upload_random_torrent_to_index; use crate::e2e::contexts::user::steps::new_logged_in_user; use crate::e2e::environment::TestEnv; @@ -275,6 +275,37 @@ mod for_authenticated_users { assert_eq!(response.status, 400); } + #[tokio::test] + async fn it_should_allow_authenticated_users_to_download_a_torrent_with_a_personal_announce_url() { + let mut env = TestEnv::new(); + env.start().await; + + if !env.provides_a_tracker() { + println!("test skipped. It requires a tracker to be running."); + return; + } + + // Given a previously uploaded torrent + let uploader = new_logged_in_user(&env).await; + let (test_torrent, torrent_listed_in_index) = upload_random_torrent_to_index(&uploader, &env).await; + let torrent_id = torrent_listed_in_index.torrent_id; + let uploaded_torrent = decode_torrent(&test_torrent.index_info.torrent_file.contents).unwrap(); + + // And a logged in user who is going to download the torrent + let downloader = new_logged_in_user(&env).await; + let client = Client::authenticated(&env.server_socket_addr().unwrap(), &downloader.token); + + // When the user downloads the torrent + let response = client.download_torrent(torrent_id).await; + let torrent = decode_torrent(&response.bytes).unwrap(); + + // Then the torrent should have the personal announce URL + let expected_torrent = expected_torrent(uploaded_torrent, &env, &Some(downloader)).await; + + assert_eq!(torrent, expected_torrent); + assert!(response.is_bittorrent_and_ok()); + } + mod and_non_admins { use crate::common::client::Client; use crate::e2e::contexts::torrent::steps::upload_random_torrent_to_index;