Skip to content

Commit 1fed948

Browse files
authored
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`
1 parent 1dae578 commit 1fed948

1 file changed

Lines changed: 25 additions & 194 deletions

File tree

codex-rs/core/tests/suite/apply_patch_cli.rs

Lines changed: 25 additions & 194 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,9 @@ use std::sync::atomic::Ordering;
1313
use std::time::Duration;
1414

1515
use codex_features::Feature;
16-
use codex_protocol::protocol::AskForApproval;
16+
use codex_protocol::models::PermissionProfile;
17+
use codex_protocol::permissions::NetworkSandboxPolicy;
1718
use codex_protocol::protocol::EventMsg;
18-
use codex_protocol::protocol::Op;
19-
use codex_protocol::protocol::SandboxPolicy;
20-
use codex_protocol::user_input::UserInput;
2119
#[cfg(target_os = "linux")]
2220
use codex_sandboxing::landlock::CODEX_LINUX_SANDBOX_ARG0;
2321
use core_test_support::assert_regex_match;
@@ -59,6 +57,15 @@ async fn apply_patch_harness_with(
5957
Box::pin(TestCodexHarness::with_remote_aware_builder(builder)).await
6058
}
6159

60+
fn restrictive_workspace_write_profile() -> PermissionProfile {
61+
PermissionProfile::workspace_write_with(
62+
&[],
63+
NetworkSandboxPolicy::Restricted,
64+
/*exclude_tmpdir_env_var*/ true,
65+
/*exclude_slash_tmp*/ true,
66+
)
67+
}
68+
6269
pub async fn mount_apply_patch(
6370
harness: &TestCodexHarness,
6471
call_id: &str,
@@ -354,28 +361,7 @@ async fn apply_patch_cli_move_without_content_change_has_no_turn_diff(
354361
let call_id = "apply-move-no-change";
355362
mount_apply_patch(&harness, call_id, patch, "ok", model_output).await;
356363

357-
let model = test.session_configured.model.clone();
358-
codex
359-
.submit(Op::UserTurn {
360-
environments: None,
361-
items: vec![UserInput::Text {
362-
text: "rename without content change".into(),
363-
text_elements: Vec::new(),
364-
}],
365-
final_output_json_schema: None,
366-
cwd: harness.cwd().to_path_buf(),
367-
approval_policy: AskForApproval::Never,
368-
approvals_reviewer: None,
369-
sandbox_policy: SandboxPolicy::DangerFullAccess,
370-
permission_profile: None,
371-
model,
372-
effort: None,
373-
summary: None,
374-
service_tier: None,
375-
collaboration_mode: None,
376-
personality: None,
377-
})
378-
.await?;
364+
harness.submit("rename without content change").await?;
379365

380366
let mut saw_turn_diff = false;
381367
wait_for_event(&codex, |event| match event {
@@ -641,16 +627,10 @@ async fn apply_patch_cli_rejects_path_traversal_outside_workspace(
641627
let call_id = "apply-path-traversal";
642628
mount_apply_patch(&harness, call_id, patch, "fail", model_output).await;
643629

644-
let sandbox_policy = SandboxPolicy::WorkspaceWrite {
645-
writable_roots: vec![],
646-
network_access: false,
647-
exclude_tmpdir_env_var: true,
648-
exclude_slash_tmp: true,
649-
};
650630
harness
651-
.submit_with_policy(
631+
.submit_with_permission_profile(
652632
"attempt to escape workspace via apply_patch",
653-
sandbox_policy,
633+
restrictive_workspace_write_profile(),
654634
)
655635
.await?;
656636

@@ -696,14 +676,11 @@ async fn apply_patch_cli_rejects_move_path_traversal_outside_workspace(
696676
let call_id = "apply-move-traversal";
697677
mount_apply_patch(&harness, call_id, patch, "fail", model_output).await;
698678

699-
let sandbox_policy = SandboxPolicy::WorkspaceWrite {
700-
writable_roots: vec![],
701-
network_access: false,
702-
exclude_tmpdir_env_var: true,
703-
exclude_slash_tmp: true,
704-
};
705679
harness
706-
.submit_with_policy("attempt move traversal via apply_patch", sandbox_policy)
680+
.submit_with_permission_profile(
681+
"attempt move traversal via apply_patch",
682+
restrictive_workspace_write_profile(),
683+
)
707684
.await?;
708685

709686
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<()>
992969
)
993970
.await;
994971

995-
codex
996-
.submit(Op::UserTurn {
997-
environments: None,
998-
items: vec![UserInput::Text {
999-
text: "create streamed file".into(),
1000-
text_elements: Vec::new(),
1001-
}],
1002-
final_output_json_schema: None,
1003-
cwd: harness.cwd().to_path_buf(),
1004-
approval_policy: AskForApproval::Never,
1005-
approvals_reviewer: None,
1006-
sandbox_policy: SandboxPolicy::DangerFullAccess,
1007-
permission_profile: None,
1008-
model: test.session_configured.model.clone(),
1009-
effort: None,
1010-
summary: None,
1011-
service_tier: None,
1012-
collaboration_mode: None,
1013-
personality: None,
1014-
})
1015-
.await?;
972+
harness.submit("create streamed file").await?;
1016973

1017974
let mut updates = Vec::new();
1018975
wait_for_event(&codex, |event| match event {
@@ -1090,28 +1047,7 @@ async fn apply_patch_shell_command_heredoc_with_cd_emits_turn_diff() -> Result<(
10901047
];
10911048
mount_sse_sequence(harness.server(), bodies).await;
10921049

1093-
let model = test.session_configured.model.clone();
1094-
codex
1095-
.submit(Op::UserTurn {
1096-
environments: None,
1097-
items: vec![UserInput::Text {
1098-
text: "apply via shell heredoc with cd".into(),
1099-
text_elements: Vec::new(),
1100-
}],
1101-
final_output_json_schema: None,
1102-
cwd: harness.cwd().to_path_buf(),
1103-
approval_policy: AskForApproval::Never,
1104-
approvals_reviewer: None,
1105-
sandbox_policy: SandboxPolicy::DangerFullAccess,
1106-
permission_profile: None,
1107-
model,
1108-
effort: None,
1109-
summary: None,
1110-
service_tier: None,
1111-
collaboration_mode: None,
1112-
personality: None,
1113-
})
1114-
.await?;
1050+
harness.submit("apply via shell heredoc with cd").await?;
11151051

11161052
let mut saw_turn_diff = None;
11171053
let mut saw_patch_begin = false;
@@ -1176,28 +1112,7 @@ async fn apply_patch_shell_command_failure_propagates_error_and_skips_diff() ->
11761112
];
11771113
mount_sse_sequence(harness.server(), bodies).await;
11781114

1179-
let model = test.session_configured.model.clone();
1180-
codex
1181-
.submit(Op::UserTurn {
1182-
environments: None,
1183-
items: vec![UserInput::Text {
1184-
text: "apply patch via shell".into(),
1185-
text_elements: Vec::new(),
1186-
}],
1187-
final_output_json_schema: None,
1188-
cwd: harness.cwd().to_path_buf(),
1189-
approval_policy: AskForApproval::Never,
1190-
approvals_reviewer: None,
1191-
sandbox_policy: SandboxPolicy::DangerFullAccess,
1192-
permission_profile: None,
1193-
model,
1194-
effort: None,
1195-
summary: None,
1196-
service_tier: None,
1197-
collaboration_mode: None,
1198-
personality: None,
1199-
})
1200-
.await?;
1115+
harness.submit("apply patch via shell").await?;
12011116

12021117
let mut saw_turn_diff = false;
12031118
wait_for_event(&codex, |event| match event {
@@ -1333,28 +1248,7 @@ async fn apply_patch_emits_turn_diff_event_with_unified_diff(
13331248
let patch = format!("*** Begin Patch\n*** Add File: {file}\n+hello\n*** End Patch\n");
13341249
mount_apply_patch(&harness, call_id, patch.as_str(), "ok", model_output).await;
13351250

1336-
let model = test.session_configured.model.clone();
1337-
codex
1338-
.submit(Op::UserTurn {
1339-
environments: None,
1340-
items: vec![UserInput::Text {
1341-
text: "emit diff".into(),
1342-
text_elements: Vec::new(),
1343-
}],
1344-
final_output_json_schema: None,
1345-
cwd: harness.cwd().to_path_buf(),
1346-
approval_policy: AskForApproval::Never,
1347-
approvals_reviewer: None,
1348-
sandbox_policy: SandboxPolicy::DangerFullAccess,
1349-
permission_profile: None,
1350-
model,
1351-
effort: None,
1352-
summary: None,
1353-
service_tier: None,
1354-
collaboration_mode: None,
1355-
personality: None,
1356-
})
1357-
.await?;
1251+
harness.submit("emit diff").await?;
13581252

13591253
let mut saw_turn_diff = None;
13601254
wait_for_event(&codex, |event| match event {
@@ -1402,28 +1296,7 @@ async fn apply_patch_turn_diff_for_rename_with_content_change(
14021296
let patch = "*** Begin Patch\n*** Update File: old.txt\n*** Move to: new.txt\n@@\n-old\n+new\n*** End Patch";
14031297
mount_apply_patch(&harness, call_id, patch, "ok", model_output).await;
14041298

1405-
let model = test.session_configured.model.clone();
1406-
codex
1407-
.submit(Op::UserTurn {
1408-
environments: None,
1409-
items: vec![UserInput::Text {
1410-
text: "rename with change".into(),
1411-
text_elements: Vec::new(),
1412-
}],
1413-
final_output_json_schema: None,
1414-
cwd: harness.cwd().to_path_buf(),
1415-
approval_policy: AskForApproval::Never,
1416-
approvals_reviewer: None,
1417-
sandbox_policy: SandboxPolicy::DangerFullAccess,
1418-
permission_profile: None,
1419-
model,
1420-
effort: None,
1421-
summary: None,
1422-
service_tier: None,
1423-
collaboration_mode: None,
1424-
personality: None,
1425-
})
1426-
.await?;
1299+
harness.submit("rename with change").await?;
14271300

14281301
let mut last_diff: Option<String> = None;
14291302
wait_for_event(&codex, |event| match event {
@@ -1480,28 +1353,7 @@ async fn apply_patch_aggregates_diff_across_multiple_tool_calls() -> Result<()>
14801353
]);
14811354
mount_sse_sequence(harness.server(), vec![s1, s2, s3]).await;
14821355

1483-
let model = test.session_configured.model.clone();
1484-
codex
1485-
.submit(Op::UserTurn {
1486-
environments: None,
1487-
items: vec![UserInput::Text {
1488-
text: "aggregate diffs".into(),
1489-
text_elements: Vec::new(),
1490-
}],
1491-
final_output_json_schema: None,
1492-
cwd: harness.cwd().to_path_buf(),
1493-
approval_policy: AskForApproval::Never,
1494-
approvals_reviewer: None,
1495-
sandbox_policy: SandboxPolicy::DangerFullAccess,
1496-
permission_profile: None,
1497-
model,
1498-
effort: None,
1499-
summary: None,
1500-
service_tier: None,
1501-
collaboration_mode: None,
1502-
personality: None,
1503-
})
1504-
.await?;
1356+
harness.submit("aggregate diffs").await?;
15051357

15061358
let mut last_diff: Option<String> = None;
15071359
wait_for_event(&codex, |event| match event {
@@ -1558,28 +1410,7 @@ async fn apply_patch_aggregates_diff_preserves_success_after_failure() -> Result
15581410
];
15591411
mount_sse_sequence(harness.server(), responses).await;
15601412

1561-
let model = test.session_configured.model.clone();
1562-
codex
1563-
.submit(Op::UserTurn {
1564-
environments: None,
1565-
items: vec![UserInput::Text {
1566-
text: "apply patch twice with failure".into(),
1567-
text_elements: Vec::new(),
1568-
}],
1569-
final_output_json_schema: None,
1570-
cwd: harness.cwd().to_path_buf(),
1571-
approval_policy: AskForApproval::Never,
1572-
approvals_reviewer: None,
1573-
sandbox_policy: SandboxPolicy::DangerFullAccess,
1574-
permission_profile: None,
1575-
model,
1576-
effort: None,
1577-
summary: None,
1578-
service_tier: None,
1579-
collaboration_mode: None,
1580-
personality: None,
1581-
})
1582-
.await?;
1413+
harness.submit("apply patch twice with failure").await?;
15831414

15841415
let mut last_diff: Option<String> = None;
15851416
wait_for_event_with_timeout(

0 commit comments

Comments
 (0)