From 992e81d9b525446660169ee6e7321ebc13c023fd Mon Sep 17 00:00:00 2001 From: David Z Hao Date: Thu, 14 Aug 2025 14:23:06 -0700 Subject: [PATCH] test(core): add seatbelt sem lock tests (#1823) ## Summary - add a unit test to ensure the macOS seatbelt policy allows POSIX semaphores - add a macOS-only test that runs a Python multiprocessing Lock under Seatbelt ## Testing - `cargo test -p codex_core seatbelt_base_policy_allows_ipc_posix_sem --no-fail-fast` (failed: failed to download from `https://static.crates.io/crates/tokio-stream/0.1.17/download`) - `cargo test -p codex_core seatbelt_base_policy_allows_ipc_posix_sem --no-fail-fast --offline` (failed: attempting to make an HTTP request, but --offline was specified) - `cargo test --all-features --no-fail-fast --offline` (failed: attempting to make an HTTP request, but --offline was specified) - `just fmt` (failed: command not found: just) - `just fix` (failed: command not found: just) Ran tests locally to confirm it passes on master and failed before my previous change ------ https://chatgpt.com/codex/tasks/task_i_6890f221e0a4833381cfb53e11499bcc --- codex-rs/core/src/seatbelt.rs | 53 +++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/codex-rs/core/src/seatbelt.rs b/codex-rs/core/src/seatbelt.rs index ff9dbaa7..893ae8d0 100644 --- a/codex-rs/core/src/seatbelt.rs +++ b/codex-rs/core/src/seatbelt.rs @@ -301,6 +301,59 @@ mod tests { assert_eq!(expected_args, args); } + #[test] + fn seatbelt_base_policy_allows_ipc_posix_sem() { + assert!( + MACOS_SEATBELT_BASE_POLICY.contains("(allow ipc-posix-sem)"), + "base policy should allow ipc-posix-sem" + ); + } + + #[cfg(target_os = "macos")] + #[tokio::test] + async fn python_multiprocessing_lock_works_under_seatbelt() { + use super::spawn_command_under_seatbelt; + use crate::spawn::StdioPolicy; + use std::collections::HashMap; + + let policy = SandboxPolicy::WorkspaceWrite { + writable_roots: vec![], + network_access: false, + include_default_writable_roots: true, + }; + + let python_code = r#"import multiprocessing +from multiprocessing import Lock, Process + +def f(lock): + with lock: + print("Lock acquired in child process") + +if __name__ == '__main__': + lock = Lock() + p = Process(target=f, args=(lock,)) + p.start() + p.join() +"#; + + let mut child = spawn_command_under_seatbelt( + vec![ + "python3".to_string(), + "-c".to_string(), + python_code.to_string(), + ], + &policy, + std::env::current_dir().expect("should be able to get current dir"), + StdioPolicy::RedirectForShellTool, + HashMap::new(), + ) + .await + .expect("should be able to spawn python under seatbelt"); + + let status = child.wait().await.expect("should wait for child process"); + assert!(status.success(), "python exited with {status:?}"); + } + struct PopulatedTmp { root_with_git: PathBuf, root_without_git: PathBuf,