use super::{GpuBackend, GpuProcess, GpuSnapshot, ProcKind};
use anyhow::Result;
pub struct StubBackend {
child: Option<std::process::Child>,
}
impl StubBackend {
pub fn new() -> Self {
Self {
child: std::process::Command::new("sleep").arg("60").spawn().ok(),
}
}
}
impl Drop for StubBackend {
fn drop(&mut self) {
if let Some(mut c) = self.child.take() {
let _ = c.kill();
let _ = c.wait();
}
}
}
impl GpuBackend for StubBackend {
fn name(&self) -> &'static str {
"stub"
}
fn poll(&mut self) -> Result<Vec<GpuSnapshot>> {
Ok(vec![GpuSnapshot {
name: "Stub GPU 0".into(),
device_id: Some("stub:0".into()),
utilization_pct: Some(50.0),
vram_used_bytes: Some(1 << 30),
vram_total_bytes: Some(8 << 30),
temperature_c: Some(50.0),
..Default::default()
}])
}
fn processes(&mut self) -> Vec<GpuProcess> {
let mut out = vec![GpuProcess {
pid: std::process::id(),
gpu_index: 0,
..Default::default()
}];
if let Some(c) = &self.child {
out.push(GpuProcess {
pid: c.id(),
gpu_index: 0,
kind: ProcKind::Compute,
..Default::default()
});
}
out
}
fn can_signal(&self) -> bool {
true
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_stub_reports_a_real_local_process_and_can_signal() {
let mut b = StubBackend::new();
assert!(b.can_signal());
let gpus = b.poll().unwrap();
assert_eq!(gpus.len(), 1);
assert_eq!(gpus[0].device_id.as_deref(), Some("stub:0"));
let procs = b.processes();
assert_eq!(procs.len(), 2, "own pid plus the child");
let child_pid = b.child.as_ref().expect("sleep spawned").id();
assert_eq!(procs[1].pid, child_pid);
assert_eq!(
unsafe { libc::kill(child_pid as i32, 0) },
0,
"the stub's child is not a live process"
);
}
}