mirror of
https://github.com/openai/codex.git
synced 2026-11-01 19:33:35 +00:00
## Why Concurrent Linux test spawns can inherit writable descriptors for executable fixtures, preventing those fixtures from being executed even after the writing test closes its descriptor. ## What changed Replace direct executable fixture writes and copies across the Rust tests with `codex_utils_cargo_bin::write_executable` and `copy_executable`. These existing helpers complete writes and copies in separate processes on Linux. Remove the empty temporary inode before creating fake bubblewrap executables, and stage tampered bubblewrap bytes in a separate data file before copying them into the executable fixture. Add the required test dependencies. GitOrigin-RevId: c875c83088731a4933ef1574e8d79d8cecc12f54
60 lines
2.3 KiB
Rust
60 lines
2.3 KiB
Rust
//! Linux executable lookup must match the compatibility launcher's PATH semantics.
|
|
|
|
use pretty_assertions::assert_eq;
|
|
|
|
use crate::Command;
|
|
use crate::ProcessMode;
|
|
|
|
#[tokio::test]
|
|
async fn path_search_stops_at_invalid_candidates() -> anyhow::Result<()> {
|
|
let root = tempfile::tempdir()?;
|
|
std::fs::create_dir(root.path().join("bin"))?;
|
|
std::os::unix::fs::symlink("loop", root.path().join("loop"))?;
|
|
let script = root.path().join("bin/server");
|
|
codex_utils_cargo_bin::write_executable(&script, "#!/bin/sh\nprintf later\n")?;
|
|
for candidate in ["loop".to_owned(), "x".repeat(256)] {
|
|
let mut command = Command::new("server");
|
|
command
|
|
.current_dir(root.path())
|
|
.env("PATH", format!("{candidate}:bin"));
|
|
let expected = command
|
|
.inner
|
|
.spawn()
|
|
.expect_err("invalid first candidate must stop lookup");
|
|
command.process_mode(ProcessMode::NewSession);
|
|
let actual = command.spawn().err().expect("native lookup must stop too");
|
|
assert_eq!(actual.raw_os_error(), expected.raw_os_error());
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn empty_path_entries_preserve_script_argv0() -> anyhow::Result<()> {
|
|
// A sibling test can fork while the script is open for writing, retaining
|
|
// the writable descriptor and making exec fail with ETXTBSY.
|
|
if std::env::var_os("CODEX_TEST_PATH_ARGV0").is_none() {
|
|
let output = std::process::Command::new(std::env::current_exe()?)
|
|
.args([
|
|
"--exact",
|
|
"child_command::linux_tests::empty_path_entries_preserve_script_argv0",
|
|
"--nocapture",
|
|
])
|
|
.env("CODEX_TEST_PATH_ARGV0", "1")
|
|
.output()?;
|
|
assert!(output.status.success(), "{output:?}");
|
|
return Ok(());
|
|
}
|
|
let root = tempfile::tempdir()?;
|
|
let script = root.path().join("server");
|
|
codex_utils_cargo_bin::write_executable(&script, "#!/bin/sh\nprintf '%s' \"$0\"\n")?;
|
|
for path in ["", ":missing", "missing:", ".", "./"] {
|
|
let mut command = Command::new("server");
|
|
command.current_dir(root.path()).env("PATH", path);
|
|
let expected = command.inner.output().await?;
|
|
command.process_mode(ProcessMode::NewSession);
|
|
let actual = command.spawn()?.wait_with_output().await?;
|
|
assert_eq!(actual, expected);
|
|
}
|
|
Ok(())
|
|
}
|