use std::io::Read;
use std::time::Duration;
const ALONE: &str = "NUCLEI_TEST_ALONE";
pub(crate) fn alone(name: &str) -> bool {
if std::env::var_os(ALONE).is_some() {
return true;
}
let mut child = std::process::Command::new(std::env::current_exe().unwrap())
.args(["--exact", name, "--test-threads=1"])
.env(ALONE, "1")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap();
let deadline = std::time::Instant::now() + Duration::from_secs(120);
let mut backoff = Duration::from_millis(1);
let status = loop {
if let Some(status) = child.try_wait().unwrap() {
break status;
}
if std::time::Instant::now() > deadline {
let _ = child.kill();
panic!("{name} did not finish in its own process");
}
std::thread::sleep(backoff);
backoff = (backoff * 2).min(Duration::from_millis(100));
};
let mut out = String::new();
child
.stdout
.take()
.unwrap()
.read_to_string(&mut out)
.unwrap();
assert!(status.success(), "{name} failed in its own process:\n{out}");
assert!(
out.contains("test result: ok. 1 passed"),
"{name} did not run in its own process:\n{out}"
);
false
}
#[cfg(unix)]
pub(crate) fn open_descriptors() -> Vec<i32> {
#[cfg(target_os = "linux")]
const LISTING: Option<&str> = Some("/proc/self/fd");
#[cfg(target_os = "macos")]
const LISTING: Option<&str> = Some("/dev/fd");
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
const LISTING: Option<&str> = None;
if let Some(dir) = LISTING {
let listed = std::fs::read_dir(dir).map(|entries| {
entries
.filter_map(|e| e.ok()?.file_name().to_str()?.parse::<i32>().ok())
.collect::<Vec<_>>()
});
if let Ok(fds) = listed {
return fds;
}
}
let mut limit: libc::rlimit = unsafe { core::mem::zeroed() };
let soft = if unsafe { libc::getrlimit(libc::RLIMIT_NOFILE, &mut limit) } == 0 {
limit.rlim_cur.min(1 << 20) as i32
} else {
1024
};
(0..soft)
.filter(|&fd| unsafe { libc::fcntl(fd, libc::F_GETFD) } >= 0)
.collect()
}