From 9a59289fbea0e7e829c06aecfdd627651854da0f Mon Sep 17 00:00:00 2001 From: jif Date: Fri, 9 Oct 2026 14:11:18 +0000 Subject: [PATCH] Fix races in remote environment and session replacement tests (#52591) ## Why The remote environment test can steer before the wait tool call is recorded, discarding the call. The session replacement test can close the client while agents overview RPCs are still pending, leaving the proxy writing to a closed socket. ## What changed - Wait for the `wait-for-active-environment` function call event before steering the active turn. - Wait for `AgentsOverviewThreadsLoaded` before shutting down session replacement test cases that open the agents overview. GitOrigin-RevId: 886112a56ff6e1016efe30dbbd0256807bc1cc85 --- codex-rs/core/tests/suite/remote_env.rs | 10 +++++++++- codex-rs/tui/src/app/tests/new_session_tests.rs | 12 +++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/codex-rs/core/tests/suite/remote_env.rs b/codex-rs/core/tests/suite/remote_env.rs index 273936769f..c658fd8faa 100644 --- a/codex-rs/core/tests/suite/remote_env.rs +++ b/codex-rs/core/tests/suite/remote_env.rs @@ -61,6 +61,7 @@ use codex_protocol::models::ActivePermissionProfile; use codex_protocol::models::FileSystemPermissions; use codex_protocol::models::PermissionProfile; use codex_protocol::models::PermissionProfileSnapshot; +use codex_protocol::models::ResponseItem; use codex_protocol::models::SandboxPermissions; use codex_protocol::permissions::FileSystemAccessMode; use codex_protocol::permissions::FileSystemPath; @@ -2438,7 +2439,14 @@ async fn future_pending_environment_can_finish_without_retargeting_the_active_tu }]) }; thread.start_or_steer_turn(request("wait")).await?; - wait_for_response_request_count(&response_mock, /*expected_count*/ 1).await; + // The HTTP request can arrive before its tool call is recorded. Steering + // at that point can preempt the response and discard the wait call. + wait_for_event(&thread, |event| { + matches!(event, EventMsg::RawResponseItem(raw) + if matches!(&raw.item, ResponseItem::FunctionCall { call_id, .. } + if call_id == "wait-for-active-environment")) + }) + .await; assert!(matches!( thread .start_or_steer_turn( diff --git a/codex-rs/tui/src/app/tests/new_session_tests.rs b/codex-rs/tui/src/app/tests/new_session_tests.rs index c816f2dc94..9f03f668a2 100644 --- a/codex-rs/tui/src/app/tests/new_session_tests.rs +++ b/codex-rs/tui/src/app/tests/new_session_tests.rs @@ -152,7 +152,7 @@ async fn replacement_uses_server_defaults_and_preserves_explicit_launch_settings "medium", ), ] { - let (mut app, _events, _ops) = make_test_app_with_channels().await; + let (mut app, mut events, _ops) = make_test_app_with_channels().await; let server_home = tempdir()?; let client_home = tempdir()?; std::fs::write( @@ -308,6 +308,16 @@ async fn replacement_uses_server_defaults_and_preserves_explicit_launch_settings server-model high ยท "); } + if explicit.starts_with("profile_summary") { + // Opening the overview starts background RPCs. Let them finish before + // closing the client so the proxy is not writing to a closed socket. + loop { + let event = events.recv().await.expect("agents overview refresh"); + if matches!(event, AppEvent::AgentsOverviewThreadsLoaded { .. }) { + break; + } + } + } server.shutdown().await?; proxy.await??; }