From 9e4bfa31a4a10094ec2fc9724402e5a78b87d0e0 Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Tue, 28 Apr 2026 19:46:18 -0700 Subject: [PATCH] tests: add no-wait helper for apply patch event tests --- codex-rs/core/tests/common/test_codex.rs | 105 ++++++++++++++++--- codex-rs/core/tests/suite/apply_patch_cli.rs | 53 +++------- 2 files changed, 104 insertions(+), 54 deletions(-) diff --git a/codex-rs/core/tests/common/test_codex.rs b/codex-rs/core/tests/common/test_codex.rs index ab6364304f..e1b48c499e 100644 --- a/codex-rs/core/tests/common/test_codex.rs +++ b/codex-rs/core/tests/common/test_codex.rs @@ -608,6 +608,11 @@ impl TestCodex { .await } + pub async fn submit_turn_without_wait(&self, prompt: &str) -> Result<()> { + self.submit_turn_without_wait_with_permission_profile(prompt, PermissionProfile::Disabled) + .await + } + pub async fn submit_turn_with_permission_profile( &self, prompt: &str, @@ -621,6 +626,19 @@ impl TestCodex { .await } + pub async fn submit_turn_without_wait_with_permission_profile( + &self, + prompt: &str, + permission_profile: PermissionProfile, + ) -> Result<()> { + self.submit_turn_without_wait_with_approval_and_permission_profile( + prompt, + AskForApproval::Never, + permission_profile, + ) + .await + } + pub async fn submit_turn_with_policy( &self, prompt: &str, @@ -681,6 +699,22 @@ impl TestCodex { .await } + pub async fn submit_turn_without_wait_with_approval_and_permission_profile( + &self, + prompt: &str, + approval_policy: AskForApproval, + permission_profile: PermissionProfile, + ) -> Result<()> { + self.submit_turn_without_wait_with_permission_profile_context( + prompt, + approval_policy, + permission_profile, + /*service_tier*/ None, + /*environments*/ None, + ) + .await + } + pub async fn submit_turn_with_environments( &self, prompt: &str, @@ -696,6 +730,24 @@ impl TestCodex { .await } + async fn submit_turn_without_wait_with_permission_profile_context( + &self, + prompt: &str, + approval_policy: AskForApproval, + permission_profile: PermissionProfile, + service_tier: Option>, + environments: Option>, + ) -> Result<()> { + self.submit_turn_op_with_context( + prompt, + approval_policy, + permission_profile, + service_tier, + environments, + ) + .await + } + async fn submit_turn_with_permission_profile_context( &self, prompt: &str, @@ -721,6 +773,40 @@ impl TestCodex { permission_profile: PermissionProfile, service_tier: Option>, environments: Option>, + ) -> Result<()> { + self.submit_turn_op_with_context( + prompt, + approval_policy, + permission_profile, + service_tier, + environments, + ) + .await?; + + let turn_id = wait_for_event_match(&self.codex, |event| match event { + EventMsg::TurnStarted(event) => Some(event.turn_id.clone()), + _ => None, + }) + .await; + wait_for_event_with_timeout( + &self.codex, + |event| match event { + EventMsg::TurnComplete(event) => event.turn_id == turn_id, + _ => false, + }, + SUBMIT_TURN_COMPLETE_TIMEOUT, + ) + .await; + Ok(()) + } + + async fn submit_turn_op_with_context( + &self, + prompt: &str, + approval_policy: AskForApproval, + permission_profile: PermissionProfile, + service_tier: Option>, + environments: Option>, ) -> Result<()> { let (sandbox_policy, permission_profile) = turn_permission_fields(permission_profile, self.config.cwd.as_path()); @@ -746,21 +832,6 @@ impl TestCodex { personality: None, }) .await?; - - let turn_id = wait_for_event_match(&self.codex, |event| match event { - EventMsg::TurnStarted(event) => Some(event.turn_id.clone()), - _ => None, - }) - .await; - wait_for_event_with_timeout( - &self.codex, - |event| match event { - EventMsg::TurnComplete(event) => event.turn_id == turn_id, - _ => false, - }, - SUBMIT_TURN_COMPLETE_TIMEOUT, - ) - .await; Ok(()) } } @@ -887,6 +958,10 @@ impl TestCodexHarness { Box::pin(self.test.submit_turn(prompt)).await } + pub async fn submit_without_wait(&self, prompt: &str) -> Result<()> { + Box::pin(self.test.submit_turn_without_wait(prompt)).await + } + pub async fn submit_with_policy( &self, prompt: &str, diff --git a/codex-rs/core/tests/suite/apply_patch_cli.rs b/codex-rs/core/tests/suite/apply_patch_cli.rs index 44c3aff165..6fa12e2d44 100644 --- a/codex-rs/core/tests/suite/apply_patch_cli.rs +++ b/codex-rs/core/tests/suite/apply_patch_cli.rs @@ -15,11 +15,7 @@ use std::time::Duration; use codex_features::Feature; use codex_protocol::models::PermissionProfile; use codex_protocol::permissions::NetworkSandboxPolicy; -use codex_protocol::protocol::AskForApproval; 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; @@ -61,33 +57,6 @@ async fn apply_patch_harness_with( Box::pin(TestCodexHarness::with_remote_aware_builder(builder)).await } -async fn submit_without_wait(harness: &TestCodexHarness, prompt: &str) -> Result<()> { - let test = harness.test(); - let session_model = test.session_configured.model.clone(); - test.codex - .submit(Op::UserTurn { - environments: None, - items: vec![UserInput::Text { - text: prompt.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: session_model, - effort: None, - summary: None, - service_tier: None, - collaboration_mode: None, - personality: None, - }) - .await?; - Ok(()) -} - fn restrictive_workspace_write_profile() -> PermissionProfile { PermissionProfile::workspace_write_with( &[], @@ -392,7 +361,9 @@ 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; - submit_without_wait(&harness, "rename without content change").await?; + harness + .submit_without_wait("rename without content change") + .await?; let mut saw_turn_diff = false; wait_for_event(&codex, |event| match event { @@ -1000,7 +971,7 @@ async fn apply_patch_custom_tool_streaming_emits_updated_changes() -> Result<()> ) .await; - submit_without_wait(&harness, "create streamed file").await?; + harness.submit_without_wait("create streamed file").await?; let mut updates = Vec::new(); wait_for_event(&codex, |event| match event { @@ -1078,7 +1049,9 @@ async fn apply_patch_shell_command_heredoc_with_cd_emits_turn_diff() -> Result<( ]; mount_sse_sequence(harness.server(), bodies).await; - submit_without_wait(&harness, "apply via shell heredoc with cd").await?; + harness + .submit_without_wait("apply via shell heredoc with cd") + .await?; let mut saw_turn_diff = None; let mut saw_patch_begin = false; @@ -1143,7 +1116,7 @@ async fn apply_patch_shell_command_failure_propagates_error_and_skips_diff() -> ]; mount_sse_sequence(harness.server(), bodies).await; - submit_without_wait(&harness, "apply patch via shell").await?; + harness.submit_without_wait("apply patch via shell").await?; let mut saw_turn_diff = false; wait_for_event(&codex, |event| match event { @@ -1279,7 +1252,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; - submit_without_wait(&harness, "emit diff").await?; + harness.submit_without_wait("emit diff").await?; let mut saw_turn_diff = None; wait_for_event(&codex, |event| match event { @@ -1327,7 +1300,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; - submit_without_wait(&harness, "rename with change").await?; + harness.submit_without_wait("rename with change").await?; let mut last_diff: Option = None; wait_for_event(&codex, |event| match event { @@ -1384,7 +1357,7 @@ async fn apply_patch_aggregates_diff_across_multiple_tool_calls() -> Result<()> ]); mount_sse_sequence(harness.server(), vec![s1, s2, s3]).await; - submit_without_wait(&harness, "aggregate diffs").await?; + harness.submit_without_wait("aggregate diffs").await?; let mut last_diff: Option = None; wait_for_event(&codex, |event| match event { @@ -1441,7 +1414,9 @@ async fn apply_patch_aggregates_diff_preserves_success_after_failure() -> Result ]; mount_sse_sequence(harness.server(), responses).await; - submit_without_wait(&harness, "apply patch twice with failure").await?; + harness + .submit_without_wait("apply patch twice with failure") + .await?; let mut last_diff: Option = None; wait_for_event_with_timeout(