test(windows): deflake media player invalid media assertion (#4082)

* test(windows): deflake media player invalid media assertion

The Windows sound test required MediaPlayer's MediaFailed event for invalid
media. Some runners never raise it, so the script exits through its playback
timer and the test saw "sound playback timed out" instead, panicking on the
MediaFailed assertion.

Accept either terminal error and keep the timer short under test via
HERDR_SOUND_TIMEOUT_SECONDS so a missed MediaFailed no longer waits out the
production 15 second bound.

* test(windows): keep media player timeout override test-only

Generate the short-timer player script only in tests instead of reading a
process environment override. This keeps the production script's fixed 15
second bound unchanged, and the script-content test now proves the test
variant rewrites the timer.
This commit is contained in:
JJ Liebig
2026-09-14 03:42:59 +04:00
committed by GitHub
parent 247f6d1f82
commit add3dd28f9
+25 -8
View File
@@ -167,8 +167,18 @@ if ($script:timedOut) { throw 'sound playback timed out' }
"#
}
/// Builds the same player script with a shorter timer for tests. Production
/// keeps the fixed 15 second bound in `windows_media_player_script`.
#[cfg(test)]
fn windows_media_player_script_with_timeout(timeout_seconds: u64) -> String {
windows_media_player_script().replace(
"FromSeconds(15)",
&format!("FromSeconds({timeout_seconds})"),
)
}
#[cfg(any(windows, test))]
fn windows_player_command(path: &Path) -> Command {
fn windows_player_command(path: &Path, script: &str) -> Command {
let mut command = crate::noninteractive_process::command("powershell.exe");
command
.args([
@@ -178,7 +188,7 @@ fn windows_player_command(path: &Path) -> Command {
"-ExecutionPolicy",
"Bypass",
"-Command",
windows_media_player_script(),
script,
])
.env(WINDOWS_SOUND_PATH_ENV, path);
command
@@ -186,7 +196,7 @@ fn windows_player_command(path: &Path) -> Command {
#[cfg(windows)]
fn run_windows_player(path: &Path) -> Result<Output, String> {
windows_player_command(path)
windows_player_command(path, windows_media_player_script())
.output()
.map_err(|e| format!("Windows MediaPlayer playback failed: {e}"))
}
@@ -430,7 +440,7 @@ mod tests {
fn windows_media_player_uses_process_environment_and_dispatcher() {
let script = windows_media_player_script();
let path = Path::new(r"C:\sound dir\döne.mp3");
let command = windows_player_command(path);
let command = windows_player_command(path, script);
let env_path = command.get_envs().find_map(|(key, value)| {
(key == std::ffi::OsStr::new(WINDOWS_SOUND_PATH_ENV))
.then_some(value)
@@ -443,23 +453,30 @@ mod tests {
assert!(script.contains("Dispatcher]::PushFrame"));
assert!(script.contains("add_MediaEnded"));
assert!(script.contains("add_MediaFailed"));
assert!(script.contains("FromSeconds(15)"));
assert!(windows_media_player_script_with_timeout(2).contains("FromSeconds(2)"));
assert_eq!(env_path, Some(path.as_os_str()));
assert!(!command.get_args().any(|arg| arg == path.as_os_str()));
}
#[cfg(windows)]
#[test]
fn windows_media_player_reports_invalid_media_without_waiting_for_timeout() {
fn windows_media_player_reports_invalid_media() {
let _lock = crate::integration::integration_env_lock();
let path = temp_sound_path();
std::fs::write(&path, b"not an mp3").unwrap();
let output = run_windows_player(&path).unwrap();
let script = windows_media_player_script_with_timeout(2);
// Whether the host media stack raises MediaFailed before the playback
// timeout is environment-dependent, so use a short test-only timer and
// accept either terminal error instead of the production 15 second wait.
let output = windows_player_command(&path, &script).output().unwrap();
let _ = std::fs::remove_file(path);
assert!(!output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
String::from_utf8_lossy(&output.stderr).contains("sound media failed"),
"stderr should identify a MediaFailed error"
stderr.contains("sound media failed") || stderr.contains("sound playback timed out"),
"stderr should report why playback stopped: {stderr}"
);
}
}