From c49426f6af29747622b524925d9e59c82d4fb0c2 Mon Sep 17 00:00:00 2001 From: Jeremy Whiting Date: Tue, 9 Apr 2024 12:56:09 -0600 Subject: [PATCH 1/4] ProcessManager: Add a ProcessManager so we can cancel/pause/resume. In order to be able to pause/resume/cancel some operations that could take some time we need to keep track of those processes and give callers an id to pause/resume/cancel them with later. In these long running cases, return an object path that can be used to pause/resume/cancel when told to. TODO: - Add some tests and manually test that the right things happen --- Cargo.toml | 4 +- com.steampowered.SteamOSManager1.xml | 69 ++++++++++++++++-- src/manager.rs | 68 +++++++++++------- src/process.rs | 104 ++++++++++++++++++++++++++- 4 files changed, 207 insertions(+), 38 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f16357e..2a9142b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,8 +14,8 @@ strip="symbols" anyhow = "1" clap = { version = "4.5", default-features = false, features = ["derive", "help", "std", "usage"] } inotify = { version = "0.10", default-features = false, features = ["stream"] } -nix = { version = "0.28", default-features = false, features = ["fs"] } -tokio = { version = "1", default-features = false, features = ["fs", "io-util", "macros", "rt-multi-thread", "signal", "sync"] } +nix = { version = "0.28", default-features = false, features = ["fs", "signal"] } +tokio = { version = "1", default-features = false, features = ["fs", "io-std", "io-util", "macros", "process", "rt-multi-thread", "signal", "sync"] } tokio-stream = { version = "0.1", default-features = false } tokio-util = { version = "0.7", default-features = false } tracing = { version = "0.1", default-features = false } diff --git a/com.steampowered.SteamOSManager1.xml b/com.steampowered.SteamOSManager1.xml index 3748618..b500f9c 100644 --- a/com.steampowered.SteamOSManager1.xml +++ b/com.steampowered.SteamOSManager1.xml @@ -104,19 +104,27 @@ UpdateBios: Perform a BIOS update. + + @objectpath: An object path that can be used to pause/resume/cancel/kill the operation - Version available: 7 + Version available: 8 --> - + + + - + + + - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/manager.rs b/src/manager.rs index 2a69fa8..ac34260 100644 --- a/src/manager.rs +++ b/src/manager.rs @@ -17,7 +17,7 @@ use crate::power::{ get_gpu_clocks, get_gpu_performance_level, get_tdp_limit, set_gpu_clocks, set_gpu_performance_level, set_tdp_limit, GPUPerformanceLevel, }; -use crate::process::{run_script, script_output}; +use crate::process::{run_script, script_output, ProcessManager}; use crate::wifi::{ get_wifi_backend, get_wifi_power_management_state, set_wifi_backend, set_wifi_debug_mode, set_wifi_power_management_state, WifiBackend, WifiDebugMode, WifiPowerManagement, @@ -38,6 +38,8 @@ pub struct SteamOSManager { // Whether we should use trace-cmd or not. // True on galileo devices, false otherwise should_trace: bool, + // Used by ProcessManager but need to only have one of these + next_process: u32, } impl SteamOSManager { @@ -47,6 +49,7 @@ impl SteamOSManager { connection, wifi_debug_mode: WifiDebugMode::Off, should_trace: variant().await? == HardwareVariant::Galileo, + next_process: 0, }) } } @@ -142,47 +145,60 @@ impl SteamOSManager { } } - async fn update_bios(&self) -> zbus::fdo::Result<()> { + async fn update_bios(&mut self) -> zbus::fdo::Result { // Update the bios as needed - run_script("/usr/bin/jupiter-biosupdate", &["--auto"]) - .await - .inspect_err(|message| error!("Error updating BIOS: {message}")) - .map_err(to_zbus_fdo_error) - } - - async fn update_dock(&self) -> zbus::fdo::Result<()> { - // Update the dock firmware as needed - run_script( - "/usr/lib/jupiter-dock-updater/jupiter-dock-updater.sh", - &[] as &[String; 0], + ProcessManager::get_command_object_path( + "/usr/bin/jupiter-biosupdate", + &["--auto"], + &mut self.connection, + &mut self.next_process, + "updating BIOS", ) .await - .inspect_err(|message| error!("Error updating dock: {message}")) - .map_err(to_zbus_fdo_error) } - async fn trim_devices(&self) -> zbus::fdo::Result<()> { + async fn update_dock(&mut self) -> zbus::fdo::Result { + // Update the dock firmware as needed + ProcessManager::get_command_object_path( + "/usr/lib/jupiter-dock-updater/jupiter-dock-updater.sh", + &[] as &[String; 0], + &mut self.connection, + &mut self.next_process, + "updating dock", + ) + .await + } + + async fn trim_devices(&mut self) -> zbus::fdo::Result { // Run steamos-trim-devices script - run_script("/usr/lib/hwsupport/trim-devices.sh", &[] as &[String; 0]) - .await - .inspect_err(|message| error!("Error updating trimming devices: {message}")) - .map_err(to_zbus_fdo_error) + ProcessManager::get_command_object_path( + "/usr/lib/hwsupport/trim-devices.sh", + &[] as &[String; 0], + &mut self.connection, + &mut self.next_process, + "trimming devices", + ) + .await } async fn format_device( - &self, + &mut self, device: &str, label: &str, validate: bool, - ) -> zbus::fdo::Result<()> { + ) -> zbus::fdo::Result { let mut args = vec!["--label", label, "--device", device]; if !validate { args.push("--skip-validation"); } - run_script("/usr/lib/hwsupport/format-device.sh", args.as_ref()) - .await - .inspect_err(|message| error!("Error formatting {device}: {message}")) - .map_err(to_zbus_fdo_error) + ProcessManager::get_command_object_path( + "/usr/lib/hwsupport/format-device.sh", + args.as_ref(), + &mut self.connection, + &mut self.next_process, + format!("formatting {device}").as_str(), + ) + .await } #[zbus(property(emits_changed_signal = "false"))] diff --git a/src/process.rs b/src/process.rs index 5a6b88d..c23e3a9 100644 --- a/src/process.rs +++ b/src/process.rs @@ -5,10 +5,108 @@ * SPDX-License-Identifier: MIT */ -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, bail, Result}; +use nix::sys::signal; +use nix::sys::signal::Signal; +use nix::unistd::Pid; use std::ffi::OsStr; -#[cfg(not(test))] -use tokio::process::Command; +use tokio::process::{Child, Command}; +use tracing::error; +use zbus::interface; + +use crate::{to_zbus_fdo_error}; + +const PROCESS_PREFIX: &str = "/com/steampowered/SteamOSManager1/Process"; + +pub struct ProcessManager { + process: Child, +} + +impl ProcessManager { + pub async fn get_command_object_path( + executable: &str, + args: &[impl AsRef], + connection: &mut zbus::Connection, + next_process: &mut u32, + operation_name: &str, + ) -> zbus::fdo::Result { + // Run the given executable and give back an object path + let path = format!("{}{}", PROCESS_PREFIX, next_process); + *next_process += 1; + let pm = ProcessManager::run_long_command(executable, args) + .await + .inspect_err(|message| error!("Error {operation_name}: {message}")) + .map_err(to_zbus_fdo_error)?; + connection.object_server().at(path.as_str(), pm).await?; + zbus::zvariant::OwnedObjectPath::try_from(path).map_err(to_zbus_fdo_error) + } + + fn send_signal(&self, signal: nix::sys::signal::Signal) -> Result<()> { + // if !self.processes.contains_key(&id) { + // println!("no process found with id {id}"); + // return Err(anyhow!("No process found with id {id}")); + // } + + let command = &self.process; + let pid: Result = match command.id() { + Some(id) => match id.try_into() { + Ok(raw_pid) => Ok(raw_pid), + Err(message) => { + bail!("Unable to get pid_t from command {message}"); + } + }, + None => { + bail!("Unable to get pid from command, it likely finished running"); + } + }; + signal::kill(Pid::from_raw(pid.unwrap()), signal)?; + Ok(()) + } + + async fn exit_code_internal(&mut self) -> Result { + let status = self.process.wait().await?; + match status.code() { + Some(code) => Ok(code), + None => bail!("Process exited without giving a code somehow."), + } + } + + pub async fn run_long_command( + executable: &str, + args: &[impl AsRef], + ) -> Result { + // Run the given executable with the given arguments + // Return an id that can be used later to pause/cancel/resume as needed + let child = Command::new(executable).args(args).spawn()?; + Ok(ProcessManager { process: child }) + } +} + +#[interface(name = "com.steampowered.SteamOSManager1.ProcessManager")] +impl ProcessManager { + pub async fn pause(&self) -> zbus::fdo::Result<()> { + // Pause the given process if possible + // Return true on success, false otherwise + self.send_signal(Signal::SIGSTOP).map_err(to_zbus_fdo_error) + } + + pub async fn resume(&self) -> zbus::fdo::Result<()> { + // Resume the given process if possible + self.send_signal(Signal::SIGCONT).map_err(to_zbus_fdo_error) + } + + pub async fn cancel(&self) -> zbus::fdo::Result<()> { + self.send_signal(Signal::SIGTERM).map_err(to_zbus_fdo_error) + } + + pub async fn kill(&self) -> zbus::fdo::Result<()> { + self.send_signal(signal::SIGKILL).map_err(to_zbus_fdo_error) + } + + pub async fn exit_code(&mut self) -> zbus::fdo::Result { + self.exit_code_internal().await.map_err(to_zbus_fdo_error) + } +} #[cfg(not(test))] pub async fn script_exit_code(executable: &str, args: &[impl AsRef]) -> Result { From cf1bf84d30e583c8b1dbf54dfc9413b9f0e555e3 Mon Sep 17 00:00:00 2001 From: Jeremy Whiting Date: Thu, 2 May 2024 15:08:18 -0600 Subject: [PATCH 2/4] ProcessManager: Add some tests for various ProcessManager functions. Keep track of whether we paused or resumed processes. Don't try to wait for a paused process when exit_code() is called. Make sure pause/resume work as expected, and error when expected. --- src/process.rs | 67 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 5 deletions(-) diff --git a/src/process.rs b/src/process.rs index c23e3a9..3bb63fe 100644 --- a/src/process.rs +++ b/src/process.rs @@ -20,6 +20,7 @@ const PROCESS_PREFIX: &str = "/com/steampowered/SteamOSManager1/Process"; pub struct ProcessManager { process: Child, + paused: bool, } impl ProcessManager { @@ -78,21 +79,34 @@ impl ProcessManager { // Run the given executable with the given arguments // Return an id that can be used later to pause/cancel/resume as needed let child = Command::new(executable).args(args).spawn()?; - Ok(ProcessManager { process: child }) + Ok(ProcessManager { + process: child, + paused: false, + }) } } #[interface(name = "com.steampowered.SteamOSManager1.ProcessManager")] impl ProcessManager { - pub async fn pause(&self) -> zbus::fdo::Result<()> { + pub async fn pause(&mut self) -> zbus::fdo::Result<()> { + if self.paused { + return Err(zbus::fdo::Error::Failed("Already paused".to_string())); + } // Pause the given process if possible // Return true on success, false otherwise - self.send_signal(Signal::SIGSTOP).map_err(to_zbus_fdo_error) + let result = self.send_signal(Signal::SIGSTOP).map_err(to_zbus_fdo_error); + self.paused = true; + result } - pub async fn resume(&self) -> zbus::fdo::Result<()> { + pub async fn resume(&mut self) -> zbus::fdo::Result<()> { // Resume the given process if possible - self.send_signal(Signal::SIGCONT).map_err(to_zbus_fdo_error) + if !self.paused { + return Err(zbus::fdo::Error::Failed("Not paused".to_string())); + } + let result = self.send_signal(Signal::SIGCONT).map_err(to_zbus_fdo_error); + self.paused = false; + result } pub async fn cancel(&self) -> zbus::fdo::Result<()> { @@ -104,6 +118,9 @@ impl ProcessManager { } pub async fn exit_code(&mut self) -> zbus::fdo::Result { + if self.paused { + return Err(zbus::fdo::Error::Failed("Process is paused".to_string())); + } self.exit_code_internal().await.map_err(to_zbus_fdo_error) } } @@ -170,6 +187,46 @@ mod test { Err(anyhow!("oops!")) } + #[tokio::test] + async fn test_process_manager() { + let _h = testing::start(); + + let mut false_process = ProcessManager::run_long_command("/bin/false", &[""]) + .await + .unwrap(); + let mut true_process = ProcessManager::run_long_command("/bin/true", &[""]) + .await + .unwrap(); + + let mut pause_process = ProcessManager::run_long_command("/usr/bin/sleep", &["5"]) + .await + .unwrap(); + let _ = pause_process.pause().await; + + assert_eq!( + pause_process.pause().await.unwrap_err(), + zbus::fdo::Error::Failed("Already paused".to_string()) + ); + + assert_eq!( + pause_process.exit_code().await.unwrap_err(), + zbus::fdo::Error::Failed("Process is paused".to_string()) + ); + + let _ = pause_process.resume().await; + + assert_eq!( + pause_process.resume().await.unwrap_err(), + zbus::fdo::Error::Failed("Not paused".to_string()) + ); + + // Sleep gives 0 exit code when done + assert_eq!(pause_process.exit_code().await.unwrap(), 0); + + assert_eq!(false_process.exit_code().await.unwrap(), 1); + assert_eq!(true_process.exit_code().await.unwrap(), 0); + } + #[tokio::test] async fn test_run_script() { let h = testing::start(); From 88ce0ee12376edd6f5aeed9a56e383ec242f5f99 Mon Sep 17 00:00:00 2001 From: Jeremy Whiting Date: Thu, 2 May 2024 21:25:44 -0600 Subject: [PATCH 3/4] Change a bit to have separate SubProcess vs ProcessManager. Keep next_process, connection, etc. in ProcessManager instead of SteamOSManager. Also change exit_code to only give the exit code if known. Added wait to do the wait and get the proper exit code on completion. Also added libc::pid_t use in process.rs. --- Cargo.lock | 5 +- Cargo.toml | 1 + com.steampowered.SteamOSManager1.xml | 15 ++- src/manager.rs | 63 +++++------ src/process.rs | 151 +++++++++++++++++---------- 5 files changed, 139 insertions(+), 96 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bc112d8..1794720 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -588,9 +588,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" [[package]] name = "linux-raw-sys" @@ -938,6 +938,7 @@ dependencies = [ "anyhow", "clap", "inotify", + "libc", "nix", "tempfile", "tokio", diff --git a/Cargo.toml b/Cargo.toml index 2a9142b..11b8855 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ strip="symbols" anyhow = "1" clap = { version = "4.5", default-features = false, features = ["derive", "help", "std", "usage"] } inotify = { version = "0.10", default-features = false, features = ["stream"] } +libc = "0.2" nix = { version = "0.28", default-features = false, features = ["fs", "signal"] } tokio = { version = "1", default-features = false, features = ["fs", "io-std", "io-util", "macros", "process", "rt-multi-thread", "signal", "sync"] } tokio-stream = { version = "0.1", default-features = false } diff --git a/com.steampowered.SteamOSManager1.xml b/com.steampowered.SteamOSManager1.xml index b500f9c..6904b6d 100644 --- a/com.steampowered.SteamOSManager1.xml +++ b/com.steampowered.SteamOSManager1.xml @@ -280,12 +280,12 @@ - + @@ -311,7 +311,16 @@ + + + + + diff --git a/src/manager.rs b/src/manager.rs index ac34260..992e710 100644 --- a/src/manager.rs +++ b/src/manager.rs @@ -38,18 +38,17 @@ pub struct SteamOSManager { // Whether we should use trace-cmd or not. // True on galileo devices, false otherwise should_trace: bool, - // Used by ProcessManager but need to only have one of these - next_process: u32, + process_manager: ProcessManager, } impl SteamOSManager { pub async fn new(connection: Connection) -> Result { Ok(SteamOSManager { fan_control: FanControl::new(connection.clone()), - connection, wifi_debug_mode: WifiDebugMode::Off, should_trace: variant().await? == HardwareVariant::Galileo, - next_process: 0, + process_manager: ProcessManager::new(connection.clone()), + connection, }) } } @@ -147,38 +146,31 @@ impl SteamOSManager { async fn update_bios(&mut self) -> zbus::fdo::Result { // Update the bios as needed - ProcessManager::get_command_object_path( - "/usr/bin/jupiter-biosupdate", - &["--auto"], - &mut self.connection, - &mut self.next_process, - "updating BIOS", - ) - .await + self.process_manager + .get_command_object_path("/usr/bin/jupiter-biosupdate", &["--auto"], "updating BIOS") + .await } async fn update_dock(&mut self) -> zbus::fdo::Result { // Update the dock firmware as needed - ProcessManager::get_command_object_path( - "/usr/lib/jupiter-dock-updater/jupiter-dock-updater.sh", - &[] as &[String; 0], - &mut self.connection, - &mut self.next_process, - "updating dock", - ) - .await + self.process_manager + .get_command_object_path( + "/usr/lib/jupiter-dock-updater/jupiter-dock-updater.sh", + &[] as &[String; 0], + "updating dock", + ) + .await } async fn trim_devices(&mut self) -> zbus::fdo::Result { // Run steamos-trim-devices script - ProcessManager::get_command_object_path( - "/usr/lib/hwsupport/trim-devices.sh", - &[] as &[String; 0], - &mut self.connection, - &mut self.next_process, - "trimming devices", - ) - .await + self.process_manager + .get_command_object_path( + "/usr/lib/hwsupport/trim-devices.sh", + &[] as &[String; 0], + "trimming devices", + ) + .await } async fn format_device( @@ -191,14 +183,13 @@ impl SteamOSManager { if !validate { args.push("--skip-validation"); } - ProcessManager::get_command_object_path( - "/usr/lib/hwsupport/format-device.sh", - args.as_ref(), - &mut self.connection, - &mut self.next_process, - format!("formatting {device}").as_str(), - ) - .await + self.process_manager + .get_command_object_path( + "/usr/lib/hwsupport/format-device.sh", + args.as_ref(), + format!("formatting {device}").as_str(), + ) + .await } #[zbus(property(emits_changed_signal = "false"))] diff --git a/src/process.rs b/src/process.rs index 3bb63fe..537f5ec 100644 --- a/src/process.rs +++ b/src/process.rs @@ -6,6 +6,7 @@ */ use anyhow::{anyhow, bail, Result}; +use libc::pid_t; use nix::sys::signal; use nix::sys::signal::Signal; use nix::unistd::Pid; @@ -14,80 +15,106 @@ use tokio::process::{Child, Command}; use tracing::error; use zbus::interface; -use crate::{to_zbus_fdo_error}; +use crate::to_zbus_fdo_error; const PROCESS_PREFIX: &str = "/com/steampowered/SteamOSManager1/Process"; pub struct ProcessManager { + // The thing that manages subprocesses. + // Keeps a handle to the zbus connection and + // what the next process id on the bus should be + connection: zbus::Connection, + next_process: u32, +} + +pub struct SubProcess { process: Child, paused: bool, + exit_code: Option, } impl ProcessManager { + pub fn new(conn: zbus::Connection) -> ProcessManager { + ProcessManager { + connection: conn, + next_process: 0, + } + } + pub async fn get_command_object_path( + &mut self, executable: &str, args: &[impl AsRef], - connection: &mut zbus::Connection, - next_process: &mut u32, operation_name: &str, ) -> zbus::fdo::Result { // Run the given executable and give back an object path - let path = format!("{}{}", PROCESS_PREFIX, next_process); - *next_process += 1; + let path = format!("{}{}", PROCESS_PREFIX, self.next_process); + self.next_process += 1; let pm = ProcessManager::run_long_command(executable, args) .await .inspect_err(|message| error!("Error {operation_name}: {message}")) .map_err(to_zbus_fdo_error)?; - connection.object_server().at(path.as_str(), pm).await?; + self.connection + .object_server() + .at(path.as_str(), pm) + .await?; zbus::zvariant::OwnedObjectPath::try_from(path).map_err(to_zbus_fdo_error) } - fn send_signal(&self, signal: nix::sys::signal::Signal) -> Result<()> { - // if !self.processes.contains_key(&id) { - // println!("no process found with id {id}"); - // return Err(anyhow!("No process found with id {id}")); - // } - - let command = &self.process; - let pid: Result = match command.id() { - Some(id) => match id.try_into() { - Ok(raw_pid) => Ok(raw_pid), - Err(message) => { - bail!("Unable to get pid_t from command {message}"); - } - }, - None => { - bail!("Unable to get pid from command, it likely finished running"); - } - }; - signal::kill(Pid::from_raw(pid.unwrap()), signal)?; - Ok(()) - } - - async fn exit_code_internal(&mut self) -> Result { - let status = self.process.wait().await?; - match status.code() { - Some(code) => Ok(code), - None => bail!("Process exited without giving a code somehow."), - } - } - pub async fn run_long_command( executable: &str, args: &[impl AsRef], - ) -> Result { + ) -> Result { // Run the given executable with the given arguments // Return an id that can be used later to pause/cancel/resume as needed let child = Command::new(executable).args(args).spawn()?; - Ok(ProcessManager { + Ok(SubProcess { process: child, paused: false, + exit_code: None, }) } } -#[interface(name = "com.steampowered.SteamOSManager1.ProcessManager")] -impl ProcessManager { +impl SubProcess { + fn send_signal(&self, signal: nix::sys::signal::Signal) -> Result<()> { + let pid = match self.process.id() { + Some(id) => id, + None => { + bail!("Unable to get pid from command, it likely finished running"); + } + }; + let pid: pid_t = match pid.try_into() { + Ok(pid) => pid, + Err(message) => { + bail!("Unable to get pid_t from command {message}"); + } + }; + signal::kill(Pid::from_raw(pid), signal)?; + Ok(()) + } + + async fn exit_code_internal(&mut self) -> Result { + match self.exit_code { + // Just give the exit_code if we have it already. + Some(code) => Ok(code), + None => { + // Otherwise wait for the process + let status = self.process.wait().await?; + match status.code() { + Some(code) => { + self.exit_code = Some(code); + Ok(code) + } + None => bail!("Process exited without giving a code."), + } + } + } + } +} + +#[interface(name = "com.steampowered.SteamOSManager1.SubProcess")] +impl SubProcess { pub async fn pause(&mut self) -> zbus::fdo::Result<()> { if self.paused { return Err(zbus::fdo::Error::Failed("Already paused".to_string())); @@ -117,11 +144,30 @@ impl ProcessManager { self.send_signal(signal::SIGKILL).map_err(to_zbus_fdo_error) } - pub async fn exit_code(&mut self) -> zbus::fdo::Result { + pub async fn wait(&mut self) -> zbus::fdo::Result { if self.paused { - return Err(zbus::fdo::Error::Failed("Process is paused".to_string())); + self.resume().await?; + } + + let code = match self.exit_code_internal().await.map_err(to_zbus_fdo_error) { + Ok(v) => v, + Err(_) => { + return Err(zbus::fdo::Error::Failed( + "Unable to get exit code".to_string(), + )); + } + }; + self.exit_code = Some(code); + Ok(code) + } + + pub async fn exit_code(&mut self) -> zbus::fdo::Result { + match self.exit_code_internal().await { + Ok(i) => Ok(i), + Err(_) => Err(zbus::fdo::Error::Failed( + "Unable to get exit code.".to_string(), + )), } - self.exit_code_internal().await.map_err(to_zbus_fdo_error) } } @@ -191,14 +237,14 @@ mod test { async fn test_process_manager() { let _h = testing::start(); - let mut false_process = ProcessManager::run_long_command("/bin/false", &[""]) + let mut false_process = ProcessManager::run_long_command("/bin/false", &[] as &[String; 0]) .await .unwrap(); - let mut true_process = ProcessManager::run_long_command("/bin/true", &[""]) + let mut true_process = ProcessManager::run_long_command("/bin/true", &[] as &[String; 0]) .await .unwrap(); - let mut pause_process = ProcessManager::run_long_command("/usr/bin/sleep", &["5"]) + let mut pause_process = ProcessManager::run_long_command("/usr/bin/sleep", &["1"]) .await .unwrap(); let _ = pause_process.pause().await; @@ -208,11 +254,6 @@ mod test { zbus::fdo::Error::Failed("Already paused".to_string()) ); - assert_eq!( - pause_process.exit_code().await.unwrap_err(), - zbus::fdo::Error::Failed("Process is paused".to_string()) - ); - let _ = pause_process.resume().await; assert_eq!( @@ -220,11 +261,11 @@ mod test { zbus::fdo::Error::Failed("Not paused".to_string()) ); - // Sleep gives 0 exit code when done - assert_eq!(pause_process.exit_code().await.unwrap(), 0); + // Sleep gives 0 exit code when done, -1 when we haven't waited for it yet + assert_eq!(pause_process.wait().await.unwrap(), 0); - assert_eq!(false_process.exit_code().await.unwrap(), 1); - assert_eq!(true_process.exit_code().await.unwrap(), 0); + assert_eq!(false_process.wait().await.unwrap(), 1); + assert_eq!(true_process.wait().await.unwrap(), 0); } #[tokio::test] From 9e55f946f3d8f0f71913acf65725c2aca0d80813 Mon Sep 17 00:00:00 2001 From: Jeremy Whiting Date: Mon, 6 May 2024 14:56:58 -0600 Subject: [PATCH 4/4] Fix user_manager test by adding mismatched return types. Also add a note in failing argument length test about which method we are checking for easier finding the problems. --- src/user_manager.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/user_manager.rs b/src/user_manager.rs index a3d1f59..43220eb 100644 --- a/src/user_manager.rs +++ b/src/user_manager.rs @@ -144,15 +144,15 @@ impl SteamOSManagerUser { } } - async fn update_bios(&self) -> zbus::fdo::Result<()> { + async fn update_bios(&self) -> zbus::fdo::Result { method!(self, "UpdateBios") } - async fn update_dock(&self) -> zbus::fdo::Result<()> { + async fn update_dock(&self) -> zbus::fdo::Result { method!(self, "UpdateDock") } - async fn trim_devices(&self) -> zbus::fdo::Result<()> { + async fn trim_devices(&self) -> zbus::fdo::Result { method!(self, "TrimDevices") } @@ -161,7 +161,7 @@ impl SteamOSManagerUser { device: &str, label: &str, validate: bool, - ) -> zbus::fdo::Result<()> { + ) -> zbus::fdo::Result { method!(self, "FormatDevice", device, label, validate) } @@ -351,7 +351,13 @@ mod test { let remote_method = remote_methods.get(*key).expect(key); assert_eq!(local_method.name(), remote_method.name()); - assert_eq!(local_method.args().len(), remote_method.args().len()); + assert_eq!( + local_method.args().len(), + remote_method.args().len(), + "Testing {:?} against {:?}", + local_method, + remote_method + ); for (local_arg, remote_arg) in zip(local_method.args().iter(), remote_method.args().iter()) {