use crate::core::context::Context;
use crate::core::error::Result;
use std::path::Path;
pub mod io;
#[cfg(feature = "qemu")]
pub mod qemu;
pub trait Runner: Send + Sync {
fn run(&self, ctx: &Context, image_path: &Path) -> Result<RunResult>;
fn run_with_io(
&self,
ctx: &Context,
image_path: &Path,
handler: &mut dyn io::IoHandler,
) -> Result<RunResult> {
let _ = handler;
self.run(ctx, image_path)
}
fn is_available(&self) -> bool;
fn validate(&self, ctx: &Context) -> Result<()> {
if !self.is_available() {
return Err(crate::core::error::Error::runner(format!(
"{} is not available on this system",
self.name()
)));
}
let _ = ctx;
Ok(())
}
fn name(&self) -> &str;
}
#[derive(Debug)]
pub struct RunResult {
pub exit_code: i32,
pub success: bool,
pub captured_output: Option<CapturedOutput>,
pub timed_out: bool,
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct CapturedOutput {
pub stdout: String,
pub stderr: String,
pub serial: Option<String>,
}
impl RunResult {
pub fn new(exit_code: i32, success: bool) -> Self {
Self {
exit_code,
success,
captured_output: None,
timed_out: false,
}
}
pub fn success() -> Self {
Self {
exit_code: 0,
success: true,
captured_output: None,
timed_out: false,
}
}
pub fn failed(exit_code: i32) -> Self {
Self {
exit_code,
success: false,
captured_output: None,
timed_out: false,
}
}
pub fn with_output(mut self, stdout: String, stderr: String) -> Self {
self.captured_output = Some(CapturedOutput {
stdout,
stderr,
serial: None,
});
self
}
pub fn with_serial(mut self, serial: String) -> Self {
if let Some(ref mut output) = self.captured_output {
output.serial = Some(serial);
} else {
self.captured_output = Some(CapturedOutput {
stdout: String::new(),
stderr: String::new(),
serial: Some(serial),
});
}
self
}
pub fn with_timeout(mut self) -> Self {
self.timed_out = true;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_run_result_success() {
let result = RunResult::success();
assert_eq!(result.exit_code, 0);
assert!(result.success);
}
#[test]
fn test_run_result_failed() {
let result = RunResult::failed(1);
assert_eq!(result.exit_code, 1);
assert!(!result.success);
}
#[test]
fn test_run_result_custom() {
let result = RunResult::new(33, true);
assert_eq!(result.exit_code, 33);
assert!(result.success);
}
}