mod common;
use std::{io::Write, time::Duration};
use common::{
PROTOCOL_VERSION, hello_frame, read_frame, spawn_frame, start_daemon_raw, stop_daemon,
wait_until,
};
#[test]
fn spawn_runs_under_the_hello_env() {
let (dir, mut daemon, mut stream) = start_daemon_raw("cliexenv", |cmd| {
cmd.env("FLEETCOM_DAEMON_ONLY", "leaked");
});
let cwd = dir.display().to_string();
let path = std::env::var("PATH").unwrap_or_default();
let env: Vec<(&[u8], &[u8])> = vec![
(b"PATH".as_slice(), path.as_bytes()),
(b"SHELL".as_slice(), b"/bin/sh".as_slice()),
(b"FLEETCOM_MARKER".as_slice(), b"from-client".as_slice()),
(b"FLEETCOM_BAD".as_slice(), b"ok\xff\xfe".as_slice()),
];
stream
.write_all(&hello_frame(PROTOCOL_VERSION, &env, &cwd))
.unwrap();
let (_, payload) = read_frame(&mut stream).expect("no reply to hello");
assert!(
String::from_utf8_lossy(&payload).contains("hello_ok"),
"hello was refused: {}",
String::from_utf8_lossy(&payload)
);
let out = dir.join("out");
let command = format!(
r#"printf '%s:%s' "$FLEETCOM_MARKER" "${{FLEETCOM_DAEMON_ONLY:-absent}}" > {}"#,
out.display()
);
stream
.write_all(&spawn_frame(&command, dir.as_path()))
.unwrap();
let wrote = wait_until(Duration::from_secs(5), || {
std::fs::read_to_string(&out).is_ok_and(|c| !c.is_empty())
});
assert!(wrote, "the spawned job never wrote its output");
assert_eq!(
std::fs::read_to_string(&out).unwrap(),
"from-client:absent",
"job must see the client's env and not the daemon's"
);
stop_daemon(&mut daemon);
let _ = std::fs::remove_dir_all(&dir);
}