use super::*; #[test] fn parses_media_control_state_from_launcher_file() { assert_eq!( parse_media_control_state("camera=1 microphone=0 audio=true 123"), Some(MediaControlState::new(true, false, true)) ); } #[test] /// Keeps `parses_media_control_state_with_live_device_choices` explicit because it sits on this module contract, where hidden behavior would make regressions difficult to diagnose. /// Inputs are the typed parameters; output is the return value or side effect. fn parses_media_control_state_with_live_device_choices() { let state = MediaControlState::with_devices( true, true, true, Some("Logitech BRIO".to_string()), Some("1280x720@30".to_string()), Some("alsa_input.usb-Neat Microphones".to_string()), None, ); let dir = tempfile::tempdir().expect("tempdir"); let path = dir.path().join("media.control"); write_media_control_request(&path, state.clone()).expect("write controls"); let raw = fs::read_to_string(path).expect("read controls"); assert_eq!(parse_media_control_state(&raw), Some(state)); } #[test] fn device_choices_resolve_inherit_auto_and_selected() { assert_eq!( MediaDeviceChoice::Inherit.resolve(Some("env-device")), Some("env-device".to_string()) ); assert_eq!(MediaDeviceChoice::Auto.resolve(Some("env-device")), None); assert_eq!( MediaDeviceChoice::Selected("chosen".to_string()).resolve(Some("env-device")), Some("chosen".to_string()) ); } #[test] /// Keeps `live_media_controls_refresh_after_file_changes` explicit because it sits on this module contract, where hidden behavior would make regressions difficult to diagnose. /// Inputs are the typed parameters; output is the return value or side effect. fn live_media_controls_refresh_after_file_changes() { let dir = tempfile::tempdir().expect("tempdir"); let path = dir.path().join("media.control"); write_media_control_request(&path, MediaControlState::new(true, true, false)) .expect("write initial controls"); let controls = LiveMediaControls { path: path.clone(), inner: Arc::new(Mutex::new(LiveMediaControlsInner { state: MediaControlState::new(false, false, false), })), }; assert_eq!( controls.refresh(), MediaControlState::new(true, true, false) ); std::thread::sleep(std::time::Duration::from_millis(5)); write_media_control_request(&path, MediaControlState::new(false, true, true)) .expect("write updated controls"); assert_eq!( controls.refresh(), MediaControlState::new(false, true, true) ); } #[test] fn from_env_default_path_fallback_is_safe() { let controls = LiveMediaControls::from_env(MediaControlState::new(true, false, true)); let _ = controls.refresh(); } #[test] fn parser_tolerates_unknown_tokens_and_rejects_invalid_flags() { assert_eq!( parse_media_control_state("camera=on extra=ignored microphone=no audio=off"), Some(MediaControlState::new(true, false, false)) ); assert_eq!( parse_media_control_state("camera=maybe microphone=1 audio=1"), None ); } #[test] /// Keeps `refresh_falls_back_to_all_enabled_if_lock_is_poisoned` explicit because it sits on this module contract, where hidden behavior would make regressions difficult to diagnose. /// Inputs are the typed parameters; output is the return value or side effect. fn refresh_falls_back_to_all_enabled_if_lock_is_poisoned() { let controls = LiveMediaControls { path: PathBuf::from("/definitely/not/a/real/lesavka-media.control"), inner: Arc::new(Mutex::new(LiveMediaControlsInner { state: MediaControlState::new(false, false, false), })), }; let inner = Arc::clone(&controls.inner); let _ = std::panic::catch_unwind(move || { let _guard = inner.lock().expect("lock"); panic!("poison media controls lock"); }); assert_eq!(controls.refresh(), MediaControlState::new(true, true, true)); }