Fix test fixtures for Bazel sandboxes and Windows voice runtimes (#59231)

## What changed

- Resolve Linux sandbox test binaries with `cargo_bin` and canonicalize the helper path used by the managed proxy filesystem policy so Bubblewrap can re-execute it.
- Restrict the rollout ownership test to supplementary groups mapped in the Linux user namespace, skipping when no alternate group is available.
- Exclude `gstcoreelements.dll` from the Windows startup-only voice fixture so handshakes succeed while runtime initialization still fails for missing plugins.

GitOrigin-RevId: 618376705c49d6ee3eea09f0d089b2eff4623fd2
This commit is contained in:
Dmitriy Kovalenko
2026-11-03 21:22:21 +00:00
committed by copyberry
parent 0ed9d6fa4b
commit 8da8b0c7f7
3 changed files with 49 additions and 12 deletions
@@ -18,6 +18,7 @@ use codex_protocol::permissions::FileSystemSandboxPolicyContext;
use codex_protocol::permissions::FileSystemSpecialPath;
use codex_protocol::permissions::NetworkSandboxPolicy;
use codex_utils_absolute_path::AbsolutePathBuf;
use codex_utils_cargo_bin::cargo_bin;
use pretty_assertions::assert_eq;
use std::collections::HashMap;
use std::io::Read;
@@ -180,7 +181,8 @@ fn linux_sandbox_command(
args.push("--".to_string());
args.extend(command.iter().map(|entry| (*entry).to_string()));
let mut cmd = Command::new(env!("CARGO_BIN_EXE_codex-linux-sandbox"));
let mut cmd =
Command::new(cargo_bin("codex-linux-sandbox").expect("sandbox helper should exist"));
cmd.args(args)
.current_dir(cwd)
.env_clear()
@@ -396,7 +398,8 @@ printf 'legacy proc fallback\n'
"CODEX_TEST_PROTECTED_FILE".to_string(),
protected_file.display().to_string(),
);
let mut command = Command::new(env!("CARGO_BIN_EXE_codex-linux-sandbox"));
let mut command =
Command::new(cargo_bin("codex-linux-sandbox").expect("sandbox helper should exist"));
command
.arg("--sandbox-policy-cwd")
.arg(std::env::current_dir().expect("current directory should exist"))
@@ -474,9 +477,10 @@ async fn unsupported_system_bwrap_falls_back_to_bundled_bwrap() {
let tempdir = tempfile::tempdir().expect("create isolated sandbox installation");
let sandbox_executable = tempdir.path().join("codex-linux-sandbox");
let original_executable = env!("CARGO_BIN_EXE_codex-linux-sandbox");
if std::fs::hard_link(original_executable, &sandbox_executable).is_err() {
codex_utils_cargo_bin::copy_executable(Path::new(original_executable), &sandbox_executable)
let original_executable =
cargo_bin("codex-linux-sandbox").expect("sandbox helper should exist");
if std::fs::hard_link(&original_executable, &sandbox_executable).is_err() {
codex_utils_cargo_bin::copy_executable(&original_executable, &sandbox_executable)
.expect("copy sandbox executable");
}
@@ -795,7 +799,12 @@ async fn managed_proxy_mode_routes_through_bridge_and_blocks_direct_egress() {
format!("http://127.0.0.1:{proxy_port}"),
);
let sandbox_helper_dir = std::path::Path::new(env!("CARGO_BIN_EXE_codex-linux-sandbox"))
// Bubblewrap re-executes the canonical binary, outside its Bazel runfiles alias.
let sandbox_helper = cargo_bin("codex-linux-sandbox")
.expect("sandbox helper should exist")
.canonicalize()
.expect("sandbox helper should resolve");
let sandbox_helper_dir = sandbox_helper
.parent()
.expect("sandbox helper should have a parent");
let file_system_sandbox_policy =
+28 -5
View File
@@ -755,13 +755,36 @@ async fn worker_preserves_alternate_group_through_materialization() -> anyhow::R
let original_group = fs::metadata(&path)?.gid();
let groups = Command::new("id").arg("-G").output()?;
assert!(groups.status.success());
let Some(group) = std::str::from_utf8(&groups.stdout)?
let groups = std::str::from_utf8(&groups.stdout)?
.split_whitespace()
.map(str::parse::<u32>)
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.find(|group| *group != original_group)
else {
.collect::<Result<Vec<_>, _>>()?;
#[cfg(target_os = "linux")]
let groups = {
// Unmapped supplementary groups appear as the overflow GID in Bazel's
// user namespace, but chown cannot use them.
let gid_map = fs::read_to_string("/proc/self/gid_map")?;
let mapped_groups = gid_map
.lines()
.map(|line| {
let fields = line
.split_whitespace()
.map(str::parse::<u64>)
.collect::<Result<Vec<_>, _>>()?;
anyhow::ensure!(fields.len() == 3, "invalid GID mapping: {line}");
Ok(fields[0]..fields[0] + fields[2])
})
.collect::<anyhow::Result<Vec<_>>>()?;
groups
.into_iter()
.filter(|group| {
mapped_groups
.iter()
.any(|range| range.contains(&u64::from(*group)))
})
.collect::<Vec<_>>()
};
let Some(group) = groups.into_iter().find(|group| *group != original_group) else {
eprintln!("skipping ownership regression: no alternate supplementary group");
return Ok(());
};
@@ -76,6 +76,11 @@ fn install_startup_libraries(runtime: &Path) -> Result<()> {
fs::create_dir_all(&destination)?;
for entry in fs::read_dir(source.join(libraries))? {
let entry = entry?;
// Windows keeps plugins beside startup DLLs. Omit one required plugin
// so this startup-only fixture cannot initialize the audio runtime.
if cfg!(windows) && entry.file_name() == "gstcoreelements.dll" {
continue;
}
if entry.path().is_file() {
fs::copy(entry.path(), destination.join(entry.file_name()))?;
}
@@ -121,7 +126,7 @@ async fn installed_client_rejects_mixed_builds_and_missing_helper() -> Result<()
.close()
.await?;
assert!(VoiceHost::connect(&package, "wrong-build").await.is_err());
// Startup libraries permit handshakes; the missing runtime receipt prevents readiness.
// Startup libraries permit handshakes; missing native plugins prevent readiness.
let host = VoiceHost::connect(&package, &build_commit().await?).await?;
assert!(host.initialize_runtime().await.is_err());
// The same executable elsewhere in the package must not become a fallback.