From bf6213151d4ba55737dba5c6df7a19fce2dc8f85 Mon Sep 17 00:00:00 2001 From: viyatb-oai Date: Tue, 14 Apr 2026 12:50:35 -0700 Subject: [PATCH] chore: drop unrelated app-server test fixes Co-authored-by: Codex --- codex-rs/app-server/BUILD.bazel | 1 - .../app-server/src/codex_message_processor.rs | 11 ++-- codex-rs/app-server/src/message_processor.rs | 2 +- .../app-server/tests/suite/v2/analytics.rs | 15 ++--- .../tests/suite/v2/realtime_conversation.rs | 57 +++++++++++-------- .../app-server/tests/suite/v2/thread_fork.rs | 4 +- .../tests/suite/v2/thread_resume.rs | 4 +- .../app-server/tests/suite/v2/thread_start.rs | 10 +++- 8 files changed, 56 insertions(+), 48 deletions(-) diff --git a/codex-rs/app-server/BUILD.bazel b/codex-rs/app-server/BUILD.bazel index 331e9ced8d..872f533be1 100644 --- a/codex-rs/app-server/BUILD.bazel +++ b/codex-rs/app-server/BUILD.bazel @@ -3,7 +3,6 @@ load("//:defs.bzl", "codex_rust_crate") codex_rust_crate( name = "app-server", crate_name = "codex_app_server", - integration_test_args = ["--test-threads=1"], integration_test_timeout = "long", test_tags = ["no-sandbox"], ) diff --git a/codex-rs/app-server/src/codex_message_processor.rs b/codex-rs/app-server/src/codex_message_processor.rs index fc4d4fb62a..b381317d70 100644 --- a/codex-rs/app-server/src/codex_message_processor.rs +++ b/codex-rs/app-server/src/codex_message_processor.rs @@ -2495,7 +2495,6 @@ impl CodexMessageProcessor { }; } - let thread_general_analytics_enabled = config.features.enabled(Feature::GeneralAnalytics); let instruction_sources = Self::instruction_sources_from_config(&config).await; let dynamic_tools = dynamic_tools.unwrap_or_default(); let core_dynamic_tools = if dynamic_tools.is_empty() { @@ -2634,7 +2633,7 @@ impl CodexMessageProcessor { sandbox: config_snapshot.sandbox_policy.into(), reasoning_effort: config_snapshot.reasoning_effort, }; - if thread_general_analytics_enabled { + if listener_task_context.general_analytics_enabled { listener_task_context .analytics_events_client .track_response( @@ -7929,8 +7928,8 @@ impl CodexMessageProcessor { thread_manager, thread_state_manager, pending_thread_unloads, - analytics_events_client, - general_analytics_enabled, + analytics_events_client: _, + general_analytics_enabled: _, thread_watch_manager, fallback_model_provider, codex_home, @@ -8006,7 +8005,9 @@ impl CodexMessageProcessor { conversation_id, conversation.clone(), thread_manager.clone(), - general_analytics_enabled.then(|| analytics_events_client.clone()), + listener_task_context + .general_analytics_enabled + .then(|| listener_task_context.analytics_events_client.clone()), thread_outgoing, thread_state.clone(), thread_watch_manager.clone(), diff --git a/codex-rs/app-server/src/message_processor.rs b/codex-rs/app-server/src/message_processor.rs index cd59784f15..48072cce6d 100644 --- a/codex-rs/app-server/src/message_processor.rs +++ b/codex-rs/app-server/src/message_processor.rs @@ -751,7 +751,7 @@ impl MessageProcessor { | ClientRequest::TurnSteer { request_id, .. } = &codex_request { self.analytics_events_client.track_request( - connection_request_id.connection_id.0, + connection_id.0, request_id.clone(), codex_request.clone(), ); diff --git a/codex-rs/app-server/tests/suite/v2/analytics.rs b/codex-rs/app-server/tests/suite/v2/analytics.rs index 3934b14fd6..a3ecdbc1f4 100644 --- a/codex-rs/app-server/tests/suite/v2/analytics.rs +++ b/codex-rs/app-server/tests/suite/v2/analytics.rs @@ -116,29 +116,26 @@ pub(crate) async fn mount_analytics_capture(server: &MockServer, codex_home: &Pa Ok(()) } -pub(crate) async fn wait_for_thread_initialized_payload( +pub(crate) async fn wait_for_analytics_payload( server: &MockServer, read_timeout: Duration, ) -> Result { - timeout(read_timeout, async { + let body = timeout(read_timeout, async { loop { let Some(requests) = server.received_requests().await else { tokio::time::sleep(Duration::from_millis(25)).await; continue; }; - for request in requests.iter().filter(|request| { + if let Some(request) = requests.iter().find(|request| { request.method == "POST" && request.url.path() == "/codex/analytics-events/events" }) { - let payload: Value = serde_json::from_slice(&request.body) - .map_err(|err| anyhow::anyhow!("invalid analytics payload: {err}"))?; - if thread_initialized_event(&payload).is_ok() { - return Ok(payload); - } + break request.body.clone(); } tokio::time::sleep(Duration::from_millis(25)).await; } }) - .await? + .await?; + serde_json::from_slice(&body).map_err(|err| anyhow::anyhow!("invalid analytics payload: {err}")) } pub(crate) async fn wait_for_analytics_event( diff --git a/codex-rs/app-server/tests/suite/v2/realtime_conversation.rs b/codex-rs/app-server/tests/suite/v2/realtime_conversation.rs index ef107a91c3..ab593381b2 100644 --- a/codex-rs/app-server/tests/suite/v2/realtime_conversation.rs +++ b/codex-rs/app-server/tests/suite/v2/realtime_conversation.rs @@ -1135,7 +1135,23 @@ async fn realtime_webrtc_start_emits_sdp_notification() -> Result<()> { ); let body = String::from_utf8(request.body).context("multipart body should be utf-8")?; let session = r#"{"tool_choice":"auto","type":"realtime","model":"gpt-realtime-1.5","instructions":"backend prompt\n\nstartup context","output_modalities":["audio"],"audio":{"input":{"format":{"type":"audio/pcm","rate":24000},"noise_reduction":{"type":"near_field"},"turn_detection":{"type":"server_vad","interrupt_response":true,"create_response":true}},"output":{"format":{"type":"audio/pcm","rate":24000},"voice":"marin"}},"tools":[{"type":"function","name":"background_agent","description":"Send a user request to the background agent. Use this as the default action. Do not rephrase the user's ask or rewrite it in your own words; pass along the user's own words. If the background agent is idle, this starts a new task and returns the final result to the user. If the background agent is already working on a task, this sends the request as guidance to steer that previous task. If the user asks to do something next, later, after this, or once current work finishes, call this tool so the work is actually queued instead of merely promising to do it later.","parameters":{"type":"object","properties":{"prompt":{"type":"string","description":"The user request to delegate to the background agent."}},"required":["prompt"],"additionalProperties":false}}]}"#; - assert_call_create_body(&body, "v=offer\r\n", session)?; + assert_eq!( + body, + format!( + "--codex-realtime-call-boundary\r\n\ + Content-Disposition: form-data; name=\"sdp\"\r\n\ + Content-Type: application/sdp\r\n\ + \r\n\ + v=offer\r\n\ + \r\n\ + --codex-realtime-call-boundary\r\n\ + Content-Disposition: form-data; name=\"session\"\r\n\ + Content-Type: application/json\r\n\ + \r\n\ + {session}\r\n\ + --codex-realtime-call-boundary--\r\n" + ) + ); realtime_server.shutdown().await; Ok(()) @@ -2165,31 +2181,22 @@ fn assert_call_create_multipart( Some("multipart/form-data; boundary=codex-realtime-call-boundary") ); let body = String::from_utf8(request.body).context("multipart body should be utf-8")?; - assert_call_create_body(&body, offer_sdp, session)?; - Ok(()) -} - -fn assert_call_create_body(body: &str, offer_sdp: &str, session: &str) -> Result<()> { - let expected_prefix = format!( - "--codex-realtime-call-boundary\r\n\ - Content-Disposition: form-data; name=\"sdp\"\r\n\ - Content-Type: application/sdp\r\n\ - \r\n\ - {offer_sdp}\r\n\ - --codex-realtime-call-boundary\r\n\ - Content-Disposition: form-data; name=\"session\"\r\n\ - Content-Type: application/json\r\n\ - \r\n" + assert_eq!( + body, + format!( + "--codex-realtime-call-boundary\r\n\ + Content-Disposition: form-data; name=\"sdp\"\r\n\ + Content-Type: application/sdp\r\n\ + \r\n\ + {offer_sdp}\r\n\ + --codex-realtime-call-boundary\r\n\ + Content-Disposition: form-data; name=\"session\"\r\n\ + Content-Type: application/json\r\n\ + \r\n\ + {session}\r\n\ + --codex-realtime-call-boundary--\r\n" + ) ); - let session_body = body - .strip_prefix(&expected_prefix) - .and_then(|value| value.strip_suffix("\r\n--codex-realtime-call-boundary--\r\n")) - .context("multipart body should contain expected sdp part and session json part")?; - let actual_session: Value = - serde_json::from_str(session_body).context("session part should be json")?; - let expected_session: Value = - serde_json::from_str(session).context("expected session should be json")?; - assert_eq!(actual_session, expected_session); Ok(()) } diff --git a/codex-rs/app-server/tests/suite/v2/thread_fork.rs b/codex-rs/app-server/tests/suite/v2/thread_fork.rs index 3731511cfd..19bf00f64a 100644 --- a/codex-rs/app-server/tests/suite/v2/thread_fork.rs +++ b/codex-rs/app-server/tests/suite/v2/thread_fork.rs @@ -41,7 +41,7 @@ use wiremock::matchers::path; use super::analytics::assert_basic_thread_initialized_event; use super::analytics::enable_analytics_capture; use super::analytics::thread_initialized_event; -use super::analytics::wait_for_thread_initialized_payload; +use super::analytics::wait_for_analytics_payload; const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10); @@ -221,7 +221,7 @@ async fn thread_fork_tracks_thread_initialized_analytics() -> Result<()> { .await??; let ThreadForkResponse { thread, .. } = to_response::(fork_resp)?; - let payload = wait_for_thread_initialized_payload(&server, DEFAULT_READ_TIMEOUT).await?; + let payload = wait_for_analytics_payload(&server, DEFAULT_READ_TIMEOUT).await?; let event = thread_initialized_event(&payload)?; assert_basic_thread_initialized_event(event, &thread.id, "mock-model", "forked"); Ok(()) diff --git a/codex-rs/app-server/tests/suite/v2/thread_resume.rs b/codex-rs/app-server/tests/suite/v2/thread_resume.rs index 12682d949d..0a302c2380 100644 --- a/codex-rs/app-server/tests/suite/v2/thread_resume.rs +++ b/codex-rs/app-server/tests/suite/v2/thread_resume.rs @@ -73,7 +73,7 @@ use wiremock::matchers::path; use super::analytics::assert_basic_thread_initialized_event; use super::analytics::enable_analytics_capture; use super::analytics::thread_initialized_event; -use super::analytics::wait_for_thread_initialized_payload; +use super::analytics::wait_for_analytics_payload; const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10); const CODEX_5_2_INSTRUCTIONS_TEMPLATE_DEFAULT: &str = "You are Codex, a coding agent based on GPT-5. You and the user share the same workspace and collaborate to achieve the user's goals."; @@ -194,7 +194,7 @@ async fn thread_resume_tracks_thread_initialized_analytics() -> Result<()> { .await??; let ThreadResumeResponse { thread, .. } = to_response::(resume_resp)?; - let payload = wait_for_thread_initialized_payload(&server, DEFAULT_READ_TIMEOUT).await?; + let payload = wait_for_analytics_payload(&server, DEFAULT_READ_TIMEOUT).await?; let event = thread_initialized_event(&payload)?; assert_basic_thread_initialized_event(event, &thread.id, "gpt-5.2-codex", "resumed"); Ok(()) diff --git a/codex-rs/app-server/tests/suite/v2/thread_start.rs b/codex-rs/app-server/tests/suite/v2/thread_start.rs index 6f08c661c4..978260f8e2 100644 --- a/codex-rs/app-server/tests/suite/v2/thread_start.rs +++ b/codex-rs/app-server/tests/suite/v2/thread_start.rs @@ -43,7 +43,7 @@ use super::analytics::assert_basic_thread_initialized_event; use super::analytics::mount_analytics_capture; use super::analytics::thread_initialized_event; use super::analytics::wait_for_analytics_event; -use super::analytics::wait_for_thread_initialized_payload; +use super::analytics::wait_for_analytics_payload; const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10); @@ -248,7 +248,7 @@ async fn thread_start_tracks_thread_initialized_analytics() -> Result<()> { .await??; let ThreadStartResponse { thread, .. } = to_response::(resp)?; - let payload = wait_for_thread_initialized_payload(&server, DEFAULT_READ_TIMEOUT).await?; + let payload = wait_for_analytics_payload(&server, DEFAULT_READ_TIMEOUT).await?; assert_eq!(payload["events"].as_array().expect("events array").len(), 1); let event = thread_initialized_event(&payload)?; assert_basic_thread_initialized_event(event, &thread.id, "mock-model", "new"); @@ -891,7 +891,11 @@ fn create_config_toml_with_chatgpt_base_url( chatgpt_base_url: &str, general_analytics_enabled: bool, ) -> std::io::Result<()> { - let general_analytics_toml = format!("general_analytics = {general_analytics_enabled}"); + let general_analytics_toml = if general_analytics_enabled { + "\ngeneral_analytics = true".to_string() + } else { + "\ngeneral_analytics = false".to_string() + }; let config_toml = codex_home.join("config.toml"); std::fs::write( config_toml,