use crate::testing_prelude::*;
const MODIFICATION_TIME_WAIT: Duration = Duration::from_millis(50);
#[tokio::test]
async fn transcode_creates_only_indexed_torrent() {
init_logger();
let test_dir = TestDirectory::new();
let album = AlbumProvider::get(SampleFormat::default()).await;
let host = HostBuilder::new()
.with_mock_api(album)
.with_test_options(&test_dir)
.await
.with_options(TargetOptions {
target: vec![TargetFormat::_320],
..TargetOptions::default()
})
.expect_build();
let provider = host.services.get_required::<SourceProvider>();
let transcoder = host.services.get_required::<TranscodeCommand>();
let paths = host.services.get_required::<PathManager>();
let source = provider
.get(AlbumConfig::TORRENT_ID)
.await
.expect("should not fail")
.expect("should find source");
let result = transcoder.execute(&source).await;
assert!(result.is_ok(), "transcode should succeed");
let indexed_torrent = paths.get_torrent_path(&source, TargetFormat::_320);
assert!(
indexed_torrent.exists(),
"Indexed torrent should exist: {}",
indexed_torrent.display()
);
let filename = indexed_torrent
.file_name()
.expect("should have filename")
.to_string_lossy();
assert!(
filename.ends_with(".red.torrent"),
"Torrent should have indexer suffix: {filename}"
);
}
#[tokio::test]
async fn get_or_duplicate_returns_path_when_exists() -> Result<(), TestError> {
init_logger();
let test_dir = TestDirectory::new();
let album = AlbumProvider::get(SampleFormat::default()).await;
let host = HostBuilder::new()
.with_mock_api(album)
.with_test_options(&test_dir)
.await
.with_options(TargetOptions {
target: vec![TargetFormat::_320],
..TargetOptions::default()
})
.expect_build();
let provider = host.services.get_required::<SourceProvider>();
let transcoder = host.services.get_required::<TranscodeCommand>();
let paths = host.services.get_required::<PathManager>();
let source = provider
.get(AlbumConfig::TORRENT_ID)
.await
.expect("should not fail")
.expect("should find source");
transcoder
.execute(&source)
.await
.expect("transcode should succeed");
let result = paths
.get_or_duplicate_existing_torrent_path(&source, TargetFormat::_320)
.await?;
assert!(result.is_some(), "Should find indexed torrent");
let path = result.expect("checked above");
let filename = path
.file_name()
.expect("should have name")
.to_string_lossy();
assert!(
filename.ends_with(".red.torrent"),
"Should return indexed path: {filename}"
);
Ok(())
}
#[tokio::test]
async fn get_or_duplicate_creates_from_other_tracker() -> Result<(), TestError> {
init_logger();
let test_dir = TestDirectory::new();
let album = AlbumProvider::get(SampleFormat::default()).await;
let host_red = HostBuilder::new()
.with_mock_api(album.clone())
.with_test_options(&test_dir)
.await
.with_options(TargetOptions {
target: vec![TargetFormat::_320],
..TargetOptions::default()
})
.expect_build();
let provider = host_red.services.get_required::<SourceProvider>();
let transcoder = host_red.services.get_required::<TranscodeCommand>();
let source = provider
.get(AlbumConfig::TORRENT_ID)
.await
.expect("should not fail")
.expect("should find source");
transcoder
.execute(&source)
.await
.expect("transcode should succeed");
let host_ops = HostBuilder::new()
.with_mock_api(album)
.with_test_options(&test_dir)
.await
.with_options(SharedOptions {
content: vec![SAMPLE_SOURCES_DIR.clone()],
output: test_dir.output(),
indexer: "ops".to_owned(),
..SharedOptions::mock()
})
.with_options(TargetOptions {
target: vec![TargetFormat::_320],
..TargetOptions::default()
})
.expect_build();
let paths_ops = host_ops.services.get_required::<PathManager>();
let result = paths_ops
.get_or_duplicate_existing_torrent_path(&source, TargetFormat::_320)
.await?;
assert!(result.is_some(), "Should create from RED torrent");
let path = result.expect("checked above");
let filename = path
.file_name()
.expect("should have name")
.to_string_lossy();
assert!(
filename.ends_with(".ops.torrent"),
"Should create OPS torrent: {filename}"
);
assert!(path.exists(), "OPS torrent file should exist");
Ok(())
}
#[tokio::test]
async fn get_or_duplicate_returns_none_when_missing() -> Result<(), TestError> {
init_logger();
let test_dir = TestDirectory::new();
let album = AlbumProvider::get(SampleFormat::default()).await;
let host = HostBuilder::new()
.with_mock_api(album)
.with_test_options(&test_dir)
.await
.expect_build();
let provider = host.services.get_required::<SourceProvider>();
let paths = host.services.get_required::<PathManager>();
let source = provider
.get(AlbumConfig::TORRENT_ID)
.await
.expect("should not fail")
.expect("should find source");
let result = paths
.get_or_duplicate_existing_torrent_path(&source, TargetFormat::_320)
.await?;
assert!(
result.is_none(),
"Should return None when no torrent exists"
);
Ok(())
}
#[tokio::test]
async fn torrent_filename_includes_format_and_indexer() {
init_logger();
let test_dir = TestDirectory::new();
let album = AlbumProvider::get(SampleFormat::default()).await;
let host = HostBuilder::new()
.with_mock_api(album)
.with_test_options(&test_dir)
.await
.with_options(TargetOptions {
target: vec![TargetFormat::_320],
..TargetOptions::default()
})
.expect_build();
let provider = host.services.get_required::<SourceProvider>();
let transcoder = host.services.get_required::<TranscodeCommand>();
let paths = host.services.get_required::<PathManager>();
let source = provider
.get(AlbumConfig::TORRENT_ID)
.await
.expect("should not fail")
.expect("should find source");
transcoder
.execute(&source)
.await
.expect("transcode should succeed");
let torrent_path = paths.get_torrent_path(&source, TargetFormat::_320);
let filename = torrent_path
.file_name()
.expect("should have filename")
.to_string_lossy();
assert!(
filename.contains("[WEB 320]"),
"Filename should contain format: {filename}"
);
assert!(
filename.ends_with(".red.torrent"),
"Filename should end with indexer: {filename}"
);
assert!(
filename.contains("Test Artist"),
"Filename should contain artist: {filename}"
);
}
#[tokio::test]
async fn transcode_creates_torrents_for_each_format() {
init_logger();
let test_dir = TestDirectory::new();
let album = AlbumProvider::get(SampleFormat::default()).await;
let host = HostBuilder::new()
.with_mock_api(album)
.with_test_options(&test_dir)
.await
.with_options(TargetOptions {
target: vec![TargetFormat::_320, TargetFormat::V0],
..TargetOptions::default()
})
.expect_build();
let provider = host.services.get_required::<SourceProvider>();
let transcoder = host.services.get_required::<TranscodeCommand>();
let paths = host.services.get_required::<PathManager>();
let source = provider
.get(AlbumConfig::TORRENT_ID)
.await
.expect("should not fail")
.expect("should find source");
let result = transcoder.execute(&source).await;
assert!(result.is_ok(), "transcode should succeed");
for target in [TargetFormat::_320, TargetFormat::V0] {
let torrent_path = paths.get_torrent_path(&source, target);
assert!(
torrent_path.exists(),
"{target} torrent should exist: {}",
torrent_path.display()
);
}
}
#[tokio::test]
async fn transcode_skips_when_other_tracker_torrent_exists() {
init_logger();
let test_dir = TestDirectory::new();
let album = AlbumProvider::get(SampleFormat::default()).await;
let host_red = HostBuilder::new()
.with_mock_api(album.clone())
.with_test_options(&test_dir)
.await
.with_options(TargetOptions {
target: vec![TargetFormat::_320],
..TargetOptions::default()
})
.expect_build();
let provider = host_red.services.get_required::<SourceProvider>();
let transcoder_red = host_red.services.get_required::<TranscodeCommand>();
let paths_red = host_red.services.get_required::<PathManager>();
let source = provider
.get(AlbumConfig::TORRENT_ID)
.await
.expect("should not fail")
.expect("should find source");
transcoder_red
.execute(&source)
.await
.expect("transcode should succeed");
let red_torrent = paths_red.get_torrent_path(&source, TargetFormat::_320);
assert!(red_torrent.exists(), "RED torrent should exist");
let transcode_dir = paths_red.get_transcode_target_dir(&source, TargetFormat::_320);
let mp3_file = read_dir(&transcode_dir)
.expect("should read transcode dir")
.filter_map(Result::ok)
.find(|e| e.path().extension().is_some_and(|ext| ext == "mp3"))
.expect("should have mp3 file");
let mp3_modified_before = metadata(mp3_file.path())
.expect("should get metadata")
.modified()
.expect("should get mtime");
sleep(MODIFICATION_TIME_WAIT).await;
let host_ops = HostBuilder::new()
.with_mock_api(album)
.with_test_options(&test_dir)
.await
.with_options(SharedOptions {
content: vec![SAMPLE_SOURCES_DIR.clone()],
output: test_dir.output(),
indexer: "ops".to_owned(),
..SharedOptions::mock()
})
.with_options(TargetOptions {
target: vec![TargetFormat::_320],
..TargetOptions::default()
})
.expect_build();
let transcoder_ops = host_ops.services.get_required::<TranscodeCommand>();
let paths_ops = host_ops.services.get_required::<PathManager>();
transcoder_ops
.execute(&source)
.await
.expect("transcode should succeed");
let ops_torrent = paths_ops.get_torrent_path(&source, TargetFormat::_320);
assert!(
ops_torrent.exists(),
"OPS torrent should be created from RED: {}",
ops_torrent.display()
);
assert!(red_torrent.exists(), "RED torrent should still exist");
let mp3_modified_after = metadata(mp3_file.path())
.expect("should get metadata")
.modified()
.expect("should get mtime");
assert_eq!(
mp3_modified_before, mp3_modified_after,
"MP3 file should not be recreated - transcoding should be skipped"
);
}
#[tokio::test]
async fn transcode_skips_when_torrent_exists() {
init_logger();
let test_dir = TestDirectory::new();
let album = AlbumProvider::get(SampleFormat::default()).await;
let host = HostBuilder::new()
.with_mock_api(album)
.with_test_options(&test_dir)
.await
.with_options(TargetOptions {
target: vec![TargetFormat::_320],
..TargetOptions::default()
})
.expect_build();
let provider = host.services.get_required::<SourceProvider>();
let transcoder = host.services.get_required::<TranscodeCommand>();
let paths = host.services.get_required::<PathManager>();
let source = provider
.get(AlbumConfig::TORRENT_ID)
.await
.expect("should not fail")
.expect("should find source");
transcoder
.execute(&source)
.await
.expect("transcode should succeed");
let torrent_path = paths.get_torrent_path(&source, TargetFormat::_320);
let modified_before = metadata(&torrent_path)
.expect("torrent should exist")
.modified()
.expect("should get modified time");
sleep(MODIFICATION_TIME_WAIT).await;
transcoder
.execute(&source)
.await
.expect("transcode should succeed");
let modified_after = metadata(&torrent_path)
.expect("torrent should exist")
.modified()
.expect("should get modified time");
assert_eq!(
modified_before, modified_after,
"Torrent file should not be recreated"
);
}