From 3c0b0d7ebfee53713e7bc2067640099b07c73955 Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Tue, 7 Jul 2026 15:37:58 -0700 Subject: [PATCH] core: test Responses WebSockets with system proxy --- .../core/tests/suite/client_websockets.rs | 56 ++++++++++++++++++- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/codex-rs/core/tests/suite/client_websockets.rs b/codex-rs/core/tests/suite/client_websockets.rs index 05a93807b22..71d0965ef9d 100755 --- a/codex-rs/core/tests/suite/client_websockets.rs +++ b/codex-rs/core/tests/suite/client_websockets.rs @@ -8,6 +8,7 @@ use codex_core::Prompt; use codex_core::ResponseEvent; use codex_core::X_RESPONSESAPI_INCLUDE_TIMING_METRICS_HEADER; use codex_features::Feature; +use codex_http_client::OutboundProxyPolicy; use codex_login::CodexAuth; use codex_login::auth::AgentIdentityAuthPolicy; use codex_model_provider_info::ModelProviderInfo; @@ -102,6 +103,7 @@ fn assert_request_trace_matches(body: &serde_json::Value, expected_trace: &W3cTr struct WebsocketTestHarness { _codex_home: TempDir, client: ModelClient, + outbound_proxy_policy: OutboundProxyPolicy, session_id: SessionId, thread_id: ThreadId, model_info: ModelInfo, @@ -230,6 +232,38 @@ async fn responses_websocket_streams_without_feature_flag_when_provider_supports server.shutdown().await; } +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn responses_websocket_streams_with_system_proxy_feature() { + skip_if_no_network!(); + + let server = start_websocket_server(vec![vec![vec![ + ev_response_created("resp-1"), + ev_completed("resp-1"), + ]]]) + .await; + + let harness = websocket_harness_with_provider_options( + websocket_provider(&server), + /*runtime_metrics_enabled*/ false, + /*concurrent_reasoning_summaries_enabled*/ false, + /*enabled_features*/ &[Feature::RespectSystemProxy], + ) + .await; + assert_eq!( + harness.outbound_proxy_policy, + OutboundProxyPolicy::RespectSystemProxy + ); + let mut client_session = harness.client.new_session(); + let prompt = prompt_with_input(vec![message_item("hello")]); + + stream_until_complete(&mut client_session, &harness, &prompt).await; + + assert_eq!(server.handshakes().len(), 1); + assert_eq!(server.single_connection().len(), 1); + + server.shutdown().await; +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn responses_websocket_reuses_connection_with_per_turn_trace_payloads() { skip_if_no_network!(); @@ -389,8 +423,10 @@ async fn responses_websocket_request_prewarm_reuses_connection() { let mut provider = websocket_provider(&server); provider.name = ModelProviderInfo::create_openai_provider(/*base_url*/ None).name; let harness = websocket_harness_with_provider_options( - provider, /*runtime_metrics_enabled*/ true, + provider, + /*runtime_metrics_enabled*/ true, /*concurrent_reasoning_summaries_enabled*/ true, + /*enabled_features*/ &[], ) .await; let mut client_session = harness.client.new_session(); @@ -1005,8 +1041,10 @@ async fn responses_websocket_v2_incremental_requests_are_reused_across_turns() { let mut provider = websocket_provider(&server); provider.name = ModelProviderInfo::create_openai_provider(/*base_url*/ None).name; let harness = websocket_harness_with_provider_options( - provider, /*runtime_metrics_enabled*/ false, + provider, + /*runtime_metrics_enabled*/ false, /*concurrent_reasoning_summaries_enabled*/ false, + /*enabled_features*/ &[], ) .await; @@ -2216,6 +2254,7 @@ async fn websocket_harness_with_options( websocket_provider(server), runtime_metrics_enabled, /*concurrent_reasoning_summaries_enabled*/ false, + /*enabled_features*/ &[], ) .await } @@ -2224,6 +2263,7 @@ async fn websocket_harness_with_provider_options( provider: ModelProviderInfo, runtime_metrics_enabled: bool, concurrent_reasoning_summaries_enabled: bool, + enabled_features: &[Feature], ) -> WebsocketTestHarness { let codex_home = TempDir::new().unwrap(); let mut config = load_default_config_for_test(&codex_home).await; @@ -2240,6 +2280,15 @@ async fn websocket_harness_with_provider_options( .enable(Feature::ConcurrentReasoningSummaries) .expect("test config should allow feature update"); } + for feature in enabled_features { + config + .features + .enable(*feature) + .expect("test config should allow feature update"); + } + config.respect_system_proxy = config.features.enabled(Feature::RespectSystemProxy); + let http_client_factory = config.http_client_factory(); + let outbound_proxy_policy = http_client_factory.outbound_proxy_policy(); let config = Arc::new(config); let model_info = codex_core::test_support::construct_model_info_offline(MODEL, &config); let thread_id = ThreadId::new(); @@ -2284,12 +2333,13 @@ async fn websocket_harness_with_provider_options( .features .enabled(Feature::ConcurrentReasoningSummaries), /*attestation_provider*/ None, - config.http_client_factory(), + http_client_factory, ); WebsocketTestHarness { _codex_home: codex_home, client, + outbound_proxy_policy, session_id, thread_id, model_info,