diff options
| author | JJ Liebig <jonathan.liebig@gmail.com> | 2026-09-14 03:42:59 +0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-09-14 02:42:59 +0300 |
| commit | add3dd28f91db1a2b33e9582c60ac9c1809c1bf5 (patch) | |
| tree | 19854157ba4827eeec6ce923eff180d3ed059034 | |
| parent | 247f6d1f82a524dba87dd9f2fe9cb2aedb01932e (diff) | |
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.
| -rw-r--r-- | src/sound.rs | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/src/sound.rs b/src/sound.rs index d1b4fc90..b8870b8b 100644 --- a/src/sound.rs +++ b/src/sound.rs @@ -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}" ); } } |
