Skip to content

Commit

Permalink
test: [torrust#278] use non canonical info-hash to get torrent details
Browse files Browse the repository at this point in the history
  • Loading branch information
josecelano committed Sep 13, 2023
1 parent 83d31f2 commit 05b67c7
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 16 deletions.
2 changes: 1 addition & 1 deletion tests/common/contexts/torrent/fixtures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ impl TestTorrent {
}
}

pub fn info_hash_as_hex_string(&self) -> InfoHash {
pub fn file_info_hash(&self) -> InfoHash {
self.file_info.info_hash.clone()
}
}
Expand Down
75 changes: 60 additions & 15 deletions tests/e2e/web/api/v1/contexts/torrent/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,19 @@ Get torrent info:
mod for_guests {

use torrust_index_backend::web::api;
use uuid::Uuid;

use crate::common::client::Client;
use crate::common::contexts::category::fixtures::software_predefined_category_id;
use crate::common::contexts::torrent::asserts::assert_expected_torrent_details;
use crate::common::contexts::torrent::fixtures::TestTorrent;
use crate::common::contexts::torrent::requests::InfoHash;
use crate::common::contexts::torrent::responses::{
Category, File, TorrentDetails, TorrentDetailsResponse, TorrentListResponse,
};
use crate::common::http::{Query, QueryParam};
use crate::e2e::environment::TestEnv;
use crate::e2e::web::api::v1::contexts::torrent::steps::upload_random_torrent_to_index;
use crate::e2e::web::api::v1::contexts::torrent::steps::{upload_random_torrent_to_index, upload_test_torrent};
use crate::e2e::web::api::v1::contexts::user::steps::new_logged_in_user;

#[tokio::test]
Expand Down Expand Up @@ -164,7 +166,7 @@ mod for_guests {
let uploader = new_logged_in_user(&env).await;
let (test_torrent, uploaded_torrent) = upload_random_torrent_to_index(&uploader, &env).await;

let response = client.get_torrent(&test_torrent.info_hash_as_hex_string()).await;
let response = client.get_torrent(&test_torrent.file_info_hash()).await;

let torrent_details_response: TorrentDetailsResponse = serde_json::from_str(&response.body).unwrap();

Expand Down Expand Up @@ -213,7 +215,50 @@ mod for_guests {
assert!(response.is_json_and_ok());
}

mod it_should_allow_guests_download_a_torrent_file_searching_by_info_hash {
#[tokio::test]
async fn it_should_allow_guests_to_find_torrent_details_using_a_non_canonical_info_hash() {
let mut env = TestEnv::new();
env.start(api::Version::V1).await;

if !env.provides_a_tracker() {
println!("test skipped. It requires a tracker to be running.");
return;
}

let uploader = new_logged_in_user(&env).await;
let client = Client::authenticated(&env.server_socket_addr().unwrap(), &uploader.token);

// Sample data needed to build two torrents with the same canonical info-hash.
// Those torrents belong to the same Canonical Infohash Group.
let id = Uuid::new_v4();
let title = format!("title-{id}");
let file_contents = "data".to_string();

let mut first_torrent = TestTorrent::with_custom_info_dict_field(id, &file_contents, "custom 01");
first_torrent.index_info.title = title.clone();

let first_torrent_canonical_info_hash = upload_test_torrent(&client, &first_torrent)
.await
.expect("first torrent should be uploaded");

let mut second_torrent = TestTorrent::with_custom_info_dict_field(id, &file_contents, "custom 02");
second_torrent.index_info.title = format!("{title}-clone");

let _result = upload_test_torrent(&client, &second_torrent).await;

// Get torrent details using the non-canonical info-hash (second torrent info-hash)
let response = client.get_torrent(&second_torrent.file_info_hash()).await;
let torrent_details_response: TorrentDetailsResponse = serde_json::from_str(&response.body).unwrap();

// The returned torrent info should be the same as the first torrent
assert_eq!(response.status, 200);
assert_eq!(
torrent_details_response.data.info_hash,
first_torrent_canonical_info_hash.to_hex_string()
);
}

mod it_should_allow_guests_to_download_a_torrent_file_searching_by_info_hash {

use torrust_index_backend::utils::parse_torrent::{calculate_info_hash, decode_torrent};
use torrust_index_backend::web::api;
Expand Down Expand Up @@ -241,7 +286,7 @@ mod for_guests {
let (test_torrent, _torrent_listed_in_index) = upload_random_torrent_to_index(&uploader, &env).await;

// Download
let response = client.download_torrent(&test_torrent.info_hash_as_hex_string()).await;
let response = client.download_torrent(&test_torrent.file_info_hash()).await;

assert!(response.is_a_bit_torrent_file());
}
Expand All @@ -264,13 +309,13 @@ mod for_guests {
let (test_torrent, _torrent_listed_in_index) = upload_random_torrent_to_index(&uploader, &env).await;

// Download
let response = client.download_torrent(&test_torrent.info_hash_as_hex_string()).await;
let response = client.download_torrent(&test_torrent.file_info_hash()).await;

let downloaded_torrent_info_hash = calculate_info_hash(&response.bytes);

assert_eq!(
downloaded_torrent_info_hash.to_hex_string(),
test_torrent.info_hash_as_hex_string(),
test_torrent.file_info_hash(),
"downloaded torrent info-hash does not match uploaded torrent info-hash"
);
}
Expand All @@ -295,7 +340,7 @@ mod for_guests {
decode_torrent(&test_torrent.index_info.torrent_file.contents).expect("could not decode uploaded torrent");

// Download
let response = client.download_torrent(&test_torrent.info_hash_as_hex_string()).await;
let response = client.download_torrent(&test_torrent.file_info_hash()).await;

let downloaded_torrent = decode_torrent(&response.bytes).expect("could not decode downloaded torrent");

Expand Down Expand Up @@ -348,7 +393,7 @@ mod for_guests {
let uploader = new_logged_in_user(&env).await;
let (test_torrent, _uploaded_torrent) = upload_random_torrent_to_index(&uploader, &env).await;

let response = client.delete_torrent(&test_torrent.info_hash_as_hex_string()).await;
let response = client.delete_torrent(&test_torrent.file_info_hash()).await;

assert_eq!(response.status, 401);
}
Expand Down Expand Up @@ -384,7 +429,7 @@ mod for_authenticated_users {
let client = Client::authenticated(&env.server_socket_addr().unwrap(), &uploader.token);

let test_torrent = random_torrent();
let info_hash = test_torrent.info_hash_as_hex_string().clone();
let info_hash = test_torrent.file_info_hash().clone();

let form: UploadTorrentMultipartForm = test_torrent.index_info.into();

Expand Down Expand Up @@ -527,7 +572,7 @@ mod for_authenticated_users {
let client = Client::authenticated(&env.server_socket_addr().unwrap(), &downloader.token);

// When the user downloads the torrent
let response = client.download_torrent(&test_torrent.info_hash_as_hex_string()).await;
let response = client.download_torrent(&test_torrent.file_info_hash()).await;

let torrent = decode_torrent(&response.bytes).expect("could not decode downloaded torrent");

Expand Down Expand Up @@ -569,7 +614,7 @@ mod for_authenticated_users {

let client = Client::authenticated(&env.server_socket_addr().unwrap(), &uploader.token);

let response = client.delete_torrent(&test_torrent.info_hash_as_hex_string()).await;
let response = client.delete_torrent(&test_torrent.file_info_hash()).await;

assert_eq!(response.status, 403);
}
Expand Down Expand Up @@ -597,7 +642,7 @@ mod for_authenticated_users {

let response = client
.update_torrent(
&test_torrent.info_hash_as_hex_string(),
&test_torrent.file_info_hash(),
UpdateTorrentFrom {
title: Some(new_title.clone()),
description: Some(new_description.clone()),
Expand Down Expand Up @@ -642,7 +687,7 @@ mod for_authenticated_users {

let response = client
.update_torrent(
&test_torrent.info_hash_as_hex_string(),
&test_torrent.file_info_hash(),
UpdateTorrentFrom {
title: Some(new_title.clone()),
description: Some(new_description.clone()),
Expand Down Expand Up @@ -689,7 +734,7 @@ mod for_authenticated_users {
let admin = new_logged_in_admin(&env).await;
let client = Client::authenticated(&env.server_socket_addr().unwrap(), &admin.token);

let response = client.delete_torrent(&test_torrent.info_hash_as_hex_string()).await;
let response = client.delete_torrent(&test_torrent.file_info_hash()).await;

let deleted_torrent_response: DeletedTorrentResponse = serde_json::from_str(&response.body).unwrap();

Expand Down Expand Up @@ -718,7 +763,7 @@ mod for_authenticated_users {

let response = client
.update_torrent(
&test_torrent.info_hash_as_hex_string(),
&test_torrent.file_info_hash(),
UpdateTorrentFrom {
title: Some(new_title.clone()),
description: Some(new_description.clone()),
Expand Down
29 changes: 29 additions & 0 deletions tests/e2e/web/api/v1/contexts/torrent/steps.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
use std::str::FromStr;

use torrust_index_backend::models::info_hash::InfoHash;
use torrust_index_backend::web::api::v1::responses::ErrorResponseData;

use crate::common::client::Client;
use crate::common::contexts::torrent::fixtures::{random_torrent, TestTorrent, TorrentIndexInfo, TorrentListedInIndex};
use crate::common::contexts::torrent::forms::UploadTorrentMultipartForm;
Expand Down Expand Up @@ -28,3 +33,27 @@ pub async fn upload_torrent(uploader: &LoggedInUserData, torrent: &TorrentIndexI

TorrentListedInIndex::from(torrent.clone(), res.unwrap().data.torrent_id)
}

/// Upload a torrent to the index.
///
/// # Errors
///
/// Returns an `ErrorResponseData` if the response is not a 200.
pub async fn upload_test_torrent(client: &Client, test_torrent: &TestTorrent) -> Result<InfoHash, ErrorResponseData> {
let form: UploadTorrentMultipartForm = test_torrent.clone().index_info.into();
let response = client.upload_torrent(form.into()).await;

if response.status != 200 {
let error: ErrorResponseData = serde_json::from_str(&response.body)
.unwrap_or_else(|_| panic!("response {:#?} should be a ErrorResponseData", response.body));
return Err(error);
}

let uploaded_torrent_response: UploadedTorrentResponse = serde_json::from_str(&response.body).unwrap();
let canonical_info_hash_hex = uploaded_torrent_response.data.info_hash.to_lowercase();

let canonical_info_hash = InfoHash::from_str(&canonical_info_hash_hex)
.unwrap_or_else(|_| panic!("Invalid info-hash in database: {canonical_info_hash_hex}"));

Ok(canonical_info_hash)
}

0 comments on commit 05b67c7

Please sign in to comment.