mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
core tests: migrate apply patch turns to profiles (#20040)
## Summary - Removes `SandboxPolicy` from the apply-patch CLI test suite. - Uses the harness' profile-backed submit helper for danger/no-sandbox turns instead of constructing `Op::UserTurn` manually with legacy fields. - Converts the workspace-write traversal cases to submit `PermissionProfile::workspace_write_with(...)` directly. ## Verification - `cargo check -p codex-core --tests` - `just fmt`
This commit is contained in:
committed by
GitHub
Unverified
parent
1dae5788e1
commit
1fed948c66
@@ -13,11 +13,9 @@ use std::sync::atomic::Ordering;
|
||||
use std::time::Duration;
|
||||
|
||||
use codex_features::Feature;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::permissions::NetworkSandboxPolicy;
|
||||
use codex_protocol::protocol::EventMsg;
|
||||
use codex_protocol::protocol::Op;
|
||||
use codex_protocol::protocol::SandboxPolicy;
|
||||
use codex_protocol::user_input::UserInput;
|
||||
#[cfg(target_os = "linux")]
|
||||
use codex_sandboxing::landlock::CODEX_LINUX_SANDBOX_ARG0;
|
||||
use core_test_support::assert_regex_match;
|
||||
@@ -59,6 +57,15 @@ async fn apply_patch_harness_with(
|
||||
Box::pin(TestCodexHarness::with_remote_aware_builder(builder)).await
|
||||
}
|
||||
|
||||
fn restrictive_workspace_write_profile() -> PermissionProfile {
|
||||
PermissionProfile::workspace_write_with(
|
||||
&[],
|
||||
NetworkSandboxPolicy::Restricted,
|
||||
/*exclude_tmpdir_env_var*/ true,
|
||||
/*exclude_slash_tmp*/ true,
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn mount_apply_patch(
|
||||
harness: &TestCodexHarness,
|
||||
call_id: &str,
|
||||
@@ -354,28 +361,7 @@ async fn apply_patch_cli_move_without_content_change_has_no_turn_diff(
|
||||
let call_id = "apply-move-no-change";
|
||||
mount_apply_patch(&harness, call_id, patch, "ok", model_output).await;
|
||||
|
||||
let model = test.session_configured.model.clone();
|
||||
codex
|
||||
.submit(Op::UserTurn {
|
||||
environments: None,
|
||||
items: vec![UserInput::Text {
|
||||
text: "rename without content change".into(),
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
final_output_json_schema: None,
|
||||
cwd: harness.cwd().to_path_buf(),
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
})
|
||||
.await?;
|
||||
harness.submit("rename without content change").await?;
|
||||
|
||||
let mut saw_turn_diff = false;
|
||||
wait_for_event(&codex, |event| match event {
|
||||
@@ -641,16 +627,10 @@ async fn apply_patch_cli_rejects_path_traversal_outside_workspace(
|
||||
let call_id = "apply-path-traversal";
|
||||
mount_apply_patch(&harness, call_id, patch, "fail", model_output).await;
|
||||
|
||||
let sandbox_policy = SandboxPolicy::WorkspaceWrite {
|
||||
writable_roots: vec![],
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
};
|
||||
harness
|
||||
.submit_with_policy(
|
||||
.submit_with_permission_profile(
|
||||
"attempt to escape workspace via apply_patch",
|
||||
sandbox_policy,
|
||||
restrictive_workspace_write_profile(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -696,14 +676,11 @@ async fn apply_patch_cli_rejects_move_path_traversal_outside_workspace(
|
||||
let call_id = "apply-move-traversal";
|
||||
mount_apply_patch(&harness, call_id, patch, "fail", model_output).await;
|
||||
|
||||
let sandbox_policy = SandboxPolicy::WorkspaceWrite {
|
||||
writable_roots: vec![],
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
};
|
||||
harness
|
||||
.submit_with_policy("attempt move traversal via apply_patch", sandbox_policy)
|
||||
.submit_with_permission_profile(
|
||||
"attempt move traversal via apply_patch",
|
||||
restrictive_workspace_write_profile(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let out = harness.apply_patch_output(call_id, model_output).await;
|
||||
@@ -992,27 +969,7 @@ async fn apply_patch_custom_tool_streaming_emits_updated_changes() -> Result<()>
|
||||
)
|
||||
.await;
|
||||
|
||||
codex
|
||||
.submit(Op::UserTurn {
|
||||
environments: None,
|
||||
items: vec![UserInput::Text {
|
||||
text: "create streamed file".into(),
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
final_output_json_schema: None,
|
||||
cwd: harness.cwd().to_path_buf(),
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model: test.session_configured.model.clone(),
|
||||
effort: None,
|
||||
summary: None,
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
})
|
||||
.await?;
|
||||
harness.submit("create streamed file").await?;
|
||||
|
||||
let mut updates = Vec::new();
|
||||
wait_for_event(&codex, |event| match event {
|
||||
@@ -1090,28 +1047,7 @@ async fn apply_patch_shell_command_heredoc_with_cd_emits_turn_diff() -> Result<(
|
||||
];
|
||||
mount_sse_sequence(harness.server(), bodies).await;
|
||||
|
||||
let model = test.session_configured.model.clone();
|
||||
codex
|
||||
.submit(Op::UserTurn {
|
||||
environments: None,
|
||||
items: vec![UserInput::Text {
|
||||
text: "apply via shell heredoc with cd".into(),
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
final_output_json_schema: None,
|
||||
cwd: harness.cwd().to_path_buf(),
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
})
|
||||
.await?;
|
||||
harness.submit("apply via shell heredoc with cd").await?;
|
||||
|
||||
let mut saw_turn_diff = None;
|
||||
let mut saw_patch_begin = false;
|
||||
@@ -1176,28 +1112,7 @@ async fn apply_patch_shell_command_failure_propagates_error_and_skips_diff() ->
|
||||
];
|
||||
mount_sse_sequence(harness.server(), bodies).await;
|
||||
|
||||
let model = test.session_configured.model.clone();
|
||||
codex
|
||||
.submit(Op::UserTurn {
|
||||
environments: None,
|
||||
items: vec![UserInput::Text {
|
||||
text: "apply patch via shell".into(),
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
final_output_json_schema: None,
|
||||
cwd: harness.cwd().to_path_buf(),
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
})
|
||||
.await?;
|
||||
harness.submit("apply patch via shell").await?;
|
||||
|
||||
let mut saw_turn_diff = false;
|
||||
wait_for_event(&codex, |event| match event {
|
||||
@@ -1333,28 +1248,7 @@ async fn apply_patch_emits_turn_diff_event_with_unified_diff(
|
||||
let patch = format!("*** Begin Patch\n*** Add File: {file}\n+hello\n*** End Patch\n");
|
||||
mount_apply_patch(&harness, call_id, patch.as_str(), "ok", model_output).await;
|
||||
|
||||
let model = test.session_configured.model.clone();
|
||||
codex
|
||||
.submit(Op::UserTurn {
|
||||
environments: None,
|
||||
items: vec![UserInput::Text {
|
||||
text: "emit diff".into(),
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
final_output_json_schema: None,
|
||||
cwd: harness.cwd().to_path_buf(),
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
})
|
||||
.await?;
|
||||
harness.submit("emit diff").await?;
|
||||
|
||||
let mut saw_turn_diff = None;
|
||||
wait_for_event(&codex, |event| match event {
|
||||
@@ -1402,28 +1296,7 @@ async fn apply_patch_turn_diff_for_rename_with_content_change(
|
||||
let patch = "*** Begin Patch\n*** Update File: old.txt\n*** Move to: new.txt\n@@\n-old\n+new\n*** End Patch";
|
||||
mount_apply_patch(&harness, call_id, patch, "ok", model_output).await;
|
||||
|
||||
let model = test.session_configured.model.clone();
|
||||
codex
|
||||
.submit(Op::UserTurn {
|
||||
environments: None,
|
||||
items: vec![UserInput::Text {
|
||||
text: "rename with change".into(),
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
final_output_json_schema: None,
|
||||
cwd: harness.cwd().to_path_buf(),
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
})
|
||||
.await?;
|
||||
harness.submit("rename with change").await?;
|
||||
|
||||
let mut last_diff: Option<String> = None;
|
||||
wait_for_event(&codex, |event| match event {
|
||||
@@ -1480,28 +1353,7 @@ async fn apply_patch_aggregates_diff_across_multiple_tool_calls() -> Result<()>
|
||||
]);
|
||||
mount_sse_sequence(harness.server(), vec![s1, s2, s3]).await;
|
||||
|
||||
let model = test.session_configured.model.clone();
|
||||
codex
|
||||
.submit(Op::UserTurn {
|
||||
environments: None,
|
||||
items: vec![UserInput::Text {
|
||||
text: "aggregate diffs".into(),
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
final_output_json_schema: None,
|
||||
cwd: harness.cwd().to_path_buf(),
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
})
|
||||
.await?;
|
||||
harness.submit("aggregate diffs").await?;
|
||||
|
||||
let mut last_diff: Option<String> = None;
|
||||
wait_for_event(&codex, |event| match event {
|
||||
@@ -1558,28 +1410,7 @@ async fn apply_patch_aggregates_diff_preserves_success_after_failure() -> Result
|
||||
];
|
||||
mount_sse_sequence(harness.server(), responses).await;
|
||||
|
||||
let model = test.session_configured.model.clone();
|
||||
codex
|
||||
.submit(Op::UserTurn {
|
||||
environments: None,
|
||||
items: vec![UserInput::Text {
|
||||
text: "apply patch twice with failure".into(),
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
final_output_json_schema: None,
|
||||
cwd: harness.cwd().to_path_buf(),
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: None,
|
||||
sandbox_policy: SandboxPolicy::DangerFullAccess,
|
||||
permission_profile: None,
|
||||
model,
|
||||
effort: None,
|
||||
summary: None,
|
||||
service_tier: None,
|
||||
collaboration_mode: None,
|
||||
personality: None,
|
||||
})
|
||||
.await?;
|
||||
harness.submit("apply patch twice with failure").await?;
|
||||
|
||||
let mut last_diff: Option<String> = None;
|
||||
wait_for_event_with_timeout(
|
||||
|
||||
Reference in New Issue
Block a user