use std::time::Duration;
use qubit_command::CommandRunner;
#[cfg(unix)]
use qubit_mime::MediaStreamClassifier;
use qubit_mime::{
FfprobeCommandMediaStreamClassifier,
MediaStreamType,
};
#[cfg(unix)]
use tempfile::TempDir;
#[cfg(unix)]
use crate::support::PathEnvGuard;
#[test]
fn test_classify_stream_listing_maps_ffprobe_output() {
assert_eq!(
MediaStreamType::VideoWithAudio,
FfprobeCommandMediaStreamClassifier::classify_stream_listing("video\naudio\n")
);
assert_eq!(
MediaStreamType::VideoOnly,
FfprobeCommandMediaStreamClassifier::classify_stream_listing("video\n")
);
assert_eq!(
MediaStreamType::AudioOnly,
FfprobeCommandMediaStreamClassifier::classify_stream_listing("audio\n")
);
assert_eq!(
MediaStreamType::None,
FfprobeCommandMediaStreamClassifier::classify_stream_listing("data\n")
);
}
#[test]
fn test_with_command_runner_uses_runner_configuration() {
let runner = CommandRunner::new()
.timeout(Duration::from_secs(2))
.disable_logging(true);
let mut classifier = FfprobeCommandMediaStreamClassifier::new().with_command_runner(runner);
assert_eq!(
Some(Duration::from_secs(2)),
classifier.command_runner().configured_timeout()
);
assert!(classifier.command_runner().is_logging_disabled());
classifier.set_command_runner(classifier.command_runner().clone().working_directory("."));
assert_eq!(
Some(std::path::Path::new(".")),
classifier.command_runner().configured_working_directory()
);
}
#[test]
fn test_default_uses_disabled_logging_runner() {
let classifier = FfprobeCommandMediaStreamClassifier::default();
assert!(classifier.command_runner().is_logging_disabled());
}
#[test]
#[cfg(unix)]
fn test_classify_file_uses_ffprobe_stdout_and_working_directory() {
let temp_dir = TempDir::new().expect("temporary command directory should be created");
let script_path = temp_dir
.path()
.join(FfprobeCommandMediaStreamClassifier::COMMAND);
std::fs::write(&script_path, "#!/bin/sh\nprintf 'video\\naudio\\n'\n")
.expect("fake ffprobe should be written");
let mut permissions = std::fs::metadata(&script_path)
.expect("fake ffprobe metadata should be readable")
.permissions();
use std::os::unix::fs::PermissionsExt;
permissions.set_mode(0o755);
std::fs::set_permissions(&script_path, permissions).expect("fake ffprobe should be executable");
let _path_guard = PathEnvGuard::prepend(temp_dir.path());
let classifier = FfprobeCommandMediaStreamClassifier::new()
.with_command_runner(CommandRunner::new().disable_logging(true));
let mut working_classifier = classifier.clone();
working_classifier.set_working_directory(Some(".".to_owned()));
assert_eq!(Some("."), working_classifier.working_directory());
assert!(FfprobeCommandMediaStreamClassifier::is_available());
assert_eq!(
MediaStreamType::VideoWithAudio,
working_classifier
.classify_file(std::path::Path::new("Cargo.toml"))
.expect("fake ffprobe should classify staged file")
);
assert_eq!(
MediaStreamType::VideoWithAudio,
working_classifier
.classify_content(b"media")
.expect("fake ffprobe should classify staged content")
);
let trait_classifier: &dyn MediaStreamClassifier = &working_classifier;
assert_eq!(
MediaStreamType::VideoWithAudio,
trait_classifier
.classify_file(std::path::Path::new("Cargo.toml"))
.expect("trait object should delegate to ffprobe classifier")
);
}
#[test]
#[cfg(unix)]
fn test_classify_file_maps_unexpected_ffprobe_exit_to_none() {
let temp_dir = TempDir::new().expect("temporary command directory should be created");
let script_path = temp_dir
.path()
.join(FfprobeCommandMediaStreamClassifier::COMMAND);
std::fs::write(&script_path, "#!/bin/sh\nexit 7\n").expect("fake ffprobe should be written");
let mut permissions = std::fs::metadata(&script_path)
.expect("fake ffprobe metadata should be readable")
.permissions();
use std::os::unix::fs::PermissionsExt;
permissions.set_mode(0o755);
std::fs::set_permissions(&script_path, permissions).expect("fake ffprobe should be executable");
let _path_guard = PathEnvGuard::prepend(temp_dir.path());
let classifier = FfprobeCommandMediaStreamClassifier::new()
.with_command_runner(CommandRunner::new().disable_logging(true));
assert_eq!(
MediaStreamType::None,
classifier
.classify_file(std::path::Path::new("Cargo.toml"))
.expect("unexpected ffprobe exit should be best-effort none")
);
}