opencode_ctl/testing/
mod.rs1use std::collections::HashMap;
4use std::path::{Path, PathBuf};
5use std::sync::Mutex;
6
7use crate::liveness::ProcessProbe;
8
9pub mod fake;
10pub mod mock;
11
12pub struct TempHome {
13 path: PathBuf,
14}
15
16impl TempHome {
17 pub fn path(&self) -> &Path {
18 &self.path
19 }
20}
21
22impl Drop for TempHome {
23 fn drop(&mut self) {
24 let _ = std::fs::remove_dir_all(&self.path);
25 }
26}
27
28pub fn temp_home() -> TempHome {
29 let path = std::env::temp_dir().join(format!("opencode-ctl-test-{}", uuid::Uuid::new_v4()));
30 std::fs::create_dir_all(&path).expect("create temp home");
31 TempHome { path }
32}
33
34pub fn env_map(pairs: &[(&str, &str)]) -> impl Fn(&str) -> Option<String> {
35 let map: HashMap<String, String> = pairs
36 .iter()
37 .map(|(k, v)| (k.to_string(), v.to_string()))
38 .collect();
39 move |k| map.get(k).cloned()
40}
41
42#[cfg(unix)]
43pub fn exit_status(code: i32) -> std::process::ExitStatus {
44 use std::os::unix::process::ExitStatusExt;
45 std::process::ExitStatus::from_raw(code << 8)
46}
47
48#[cfg(windows)]
49pub fn exit_status(code: i32) -> std::process::ExitStatus {
50 use std::os::windows::process::ExitStatusExt;
51 std::process::ExitStatus::from_raw(code as u32)
52}
53
54pub struct FakeProbe {
57 pub alive: Mutex<HashMap<u32, String>>,
58 pub boot: String,
59 pub parents: Mutex<HashMap<u32, u32>>,
60}
61
62impl FakeProbe {
63 pub fn new(boot: &str) -> Self {
64 Self {
65 alive: Mutex::new(HashMap::new()),
66 boot: boot.to_string(),
67 parents: Mutex::new(HashMap::new()),
68 }
69 }
70
71 pub fn set_alive(&self, pid: u32, starttime: &str) {
72 self.alive
73 .lock()
74 .unwrap()
75 .insert(pid, starttime.to_string());
76 }
77
78 pub fn set_dead(&self, pid: u32) {
79 self.alive.lock().unwrap().remove(&pid);
80 }
81}
82
83impl ProcessProbe for FakeProbe {
84 fn is_alive(&self, pid: u32) -> bool {
85 self.alive.lock().unwrap().contains_key(&pid)
86 }
87
88 fn starttime(&self, pid: u32) -> Option<String> {
89 self.alive.lock().unwrap().get(&pid).cloned()
90 }
91
92 fn boot_id(&self) -> String {
93 self.boot.clone()
94 }
95
96 fn parent_pid(&self, pid: u32) -> Option<u32> {
97 self.parents.lock().unwrap().get(&pid).copied()
98 }
99}