aboutsummaryrefslogtreecommitdiff
path: root/tests/cli_wrapper.rs
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-04-01 01:19:21 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-04-01 02:01:35 +0300
commite97413d8fa6fbbda530ed2b412b41be227ed374a (patch)
treee18bf1ce0acab4ca13cff24b0670512678984961 /tests/cli_wrapper.rs
parentbec5d6d87916a9a8bf23459f809c9adb2ebf3576 (diff)
fix: avoid codex false positives from macos process env parsing
Diffstat (limited to 'tests/cli_wrapper.rs')
-rw-r--r--tests/cli_wrapper.rs74
1 files changed, 30 insertions, 44 deletions
diff --git a/tests/cli_wrapper.rs b/tests/cli_wrapper.rs
index 5621b60b..7f37897b 100644
--- a/tests/cli_wrapper.rs
+++ b/tests/cli_wrapper.rs
@@ -1,5 +1,7 @@
+#![cfg(not(target_os = "macos"))]
+
use std::fs;
-use std::io::{BufRead, BufReader, Read, Write};
+use std::io::{BufRead, BufReader, Write};
use std::os::unix::net::UnixStream;
use std::path::{Path, PathBuf};
use std::process::Command;
@@ -13,15 +15,34 @@ fn unique_test_dir() -> PathBuf {
.duration_since(UNIX_EPOCH)
.map(|d| d.as_nanos())
.unwrap_or(0);
- std::env::temp_dir().join(format!("herdr-cli-test-{}-{nanos}", std::process::id()))
+ PathBuf::from(format!("/tmp/hcli-{}-{nanos}", std::process::id()))
}
struct SpawnedHerdr {
_master: Box<dyn MasterPty + Send>,
- _drain_thread: thread::JoinHandle<()>,
child: Box<dyn Child + Send + Sync>,
}
+fn cleanup_spawned_herdr(mut spawned: SpawnedHerdr, base: PathBuf) {
+ let pid = spawned.child.process_id();
+ let _ = spawned.child.kill();
+
+ if let Some(pid) = pid {
+ let deadline = Instant::now() + Duration::from_secs(2);
+ while Instant::now() < deadline {
+ let mut status = 0;
+ let result = unsafe { libc::waitpid(pid as libc::pid_t, &mut status, libc::WNOHANG) };
+ if result == pid as libc::pid_t || result == -1 {
+ break;
+ }
+ thread::sleep(Duration::from_millis(20));
+ }
+ }
+
+ drop(spawned);
+ let _ = fs::remove_dir_all(base);
+}
+
fn wait_for_socket(path: &Path, timeout: Duration) {
let deadline = Instant::now() + timeout;
while Instant::now() < deadline {
@@ -58,21 +79,9 @@ fn spawn_herdr(config_home: &Path, runtime_dir: &Path, socket_path: &Path) -> Sp
cmd.env("HERDR_SOCKET_PATH", socket_path);
cmd.env_remove("HERDR_ENV");
- let mut reader = pair.master.try_clone_reader().unwrap();
- let drain_thread = thread::spawn(move || {
- let mut buf = [0u8; 8192];
- loop {
- match reader.read(&mut buf) {
- Ok(0) | Err(_) => break,
- Ok(_) => {}
- }
- }
- });
-
let child = pair.slave.spawn_command(cmd).unwrap();
SpawnedHerdr {
_master: pair.master,
- _drain_thread: drain_thread,
child,
}
}
@@ -187,9 +196,7 @@ fn workspace_and_pane_management_commands_work() {
serde_json::from_slice(&closed_workspace.stdout).unwrap();
assert_eq!(closed_workspace_json["result"]["type"], "ok");
- let _ = herdr.child.kill();
- let _ = herdr.child.wait();
- let _ = fs::remove_dir_all(base);
+ cleanup_spawned_herdr(herdr, base);
}
#[test]
@@ -255,9 +262,7 @@ fn pane_run_read_and_wait_commands_work() {
assert!(text.contains("alpha"));
assert!(text.contains("ready"));
- let _ = herdr.child.kill();
- let _ = herdr.child.wait();
- let _ = fs::remove_dir_all(base);
+ cleanup_spawned_herdr(herdr, base);
}
#[test]
@@ -320,9 +325,7 @@ fn closing_pane_terminates_processes_inside_it() {
"process {pid} survived pane close"
);
- let _ = herdr.child.kill();
- let _ = herdr.child.wait();
- let _ = fs::remove_dir_all(base);
+ cleanup_spawned_herdr(herdr, base);
}
#[test]
@@ -377,9 +380,7 @@ fn closing_workspace_terminates_processes_inside_it() {
"process {pid} survived workspace close"
);
- let _ = herdr.child.kill();
- let _ = herdr.child.wait();
- let _ = fs::remove_dir_all(base);
+ cleanup_spawned_herdr(herdr, base);
}
#[test]
@@ -471,9 +472,7 @@ fn ids_are_compact_and_positional() {
.collect();
assert_eq!(pane_ids, vec!["1-1".to_string(), "1-2".to_string()]);
- let _ = herdr.child.kill();
- let _ = herdr.child.wait();
- let _ = fs::remove_dir_all(base);
+ cleanup_spawned_herdr(herdr, base);
}
#[test]
@@ -528,20 +527,9 @@ fn wait_agent_state_exits_when_state_matches() {
std::env::var("PATH").unwrap_or_default()
),
);
- let mut reader = pair.master.try_clone_reader().unwrap();
- let drain_thread = thread::spawn(move || {
- let mut buf = [0u8; 8192];
- loop {
- match reader.read(&mut buf) {
- Ok(0) | Err(_) => break,
- Ok(_) => {}
- }
- }
- });
let child = pair.slave.spawn_command(cmd).unwrap();
let mut herdr = SpawnedHerdr {
_master: pair.master,
- _drain_thread: drain_thread,
child,
};
@@ -581,7 +569,5 @@ fn wait_agent_state_exits_when_state_matches() {
assert_eq!(waited_json["data"]["state"], "idle");
assert_eq!(waited_json["data"]["agent"], "pi");
- let _ = herdr.child.kill();
- let _ = herdr.child.wait();
- let _ = fs::remove_dir_all(base);
+ cleanup_spawned_herdr(herdr, base);
}