Files
codex/codex-rs/model-provider/src/models_endpoint_timeout_tests.rs
jif 4b9e7f6473 Use paused time in sampler and model catalog timeout tests (#46519)
## Why

Timeout tests can avoid waiting for real deadlines by advancing Tokio's clock, but automatic advancement can expire requests before they reach the mock server.

## What changed

Pause Tokio time in the stalled-header sampling and model catalog deadline tests. Keep polling until the mock server receives each request, then explicitly advance past the relevant timeout. Add bounded wall-clock waits and fail if a request completes before reaching the server.

Preserve assertions for sampling retry exhaustion, connection permit recovery, and the catalog's `RequestTimeout` error.

GitOrigin-RevId: 252be25d75d73c713a4b8ccac1ff20ad820df556
2026-09-18 23:58:56 +00:00

68 lines
2.2 KiB
Rust

use super::*;
use codex_http_client::OutboundProxyPolicy;
use codex_protocol::error::CodexErrorDetails;
use wiremock::Mock;
use wiremock::MockServer;
use wiremock::ResponseTemplate;
use wiremock::matchers::method;
use wiremock::matchers::path;
#[tokio::test]
async fn catalog_deadline_returns_request_timeout() {
let server = MockServer::start().await;
let mock = Mock::given(method("GET"))
.and(path("/models"))
.respond_with(
ResponseTemplate::new(200)
.set_body_json(serde_json::json!({ "models": [] }))
.set_delay(Duration::from_secs(/*secs*/ 60)),
)
.expect(1)
.mount_as_scoped(&server)
.await;
let endpoint = OpenAiModelsEndpoint::new(
ModelProviderInfo::create_openai_provider(Some(server.uri())),
/*auth_manager*/ None,
/*gateway_auth_manager*/ None,
);
tokio::time::pause();
let request = tokio::time::timeout(
MODELS_REFRESH_TIMEOUT * 2,
endpoint.list_models(
"0.0.0",
HttpClientFactory::new(OutboundProxyPolicy::ReqwestDefault),
),
);
tokio::pin!(request);
let received = mock.wait_until_satisfied();
tokio::pin!(received);
let deadline = std::time::Instant::now() + Duration::from_secs(/*secs*/ 30);
// Keep the paused runtime runnable until the request reaches the server.
// Otherwise auto-advance can expire the catalog deadline during dispatch.
loop {
assert!(
std::time::Instant::now() < deadline,
"server did not receive the catalog request"
);
tokio::select! {
() = &mut received => break,
result = &mut request => {
panic!("catalog request finished before reaching the server: {result:?}");
}
() = tokio::task::yield_now() => {}
}
}
tokio::time::advance(MODELS_REFRESH_TIMEOUT + Duration::from_millis(/*millis*/ 1)).await;
let error = request
.await
.expect("catalog deadline should expire")
.expect_err("delayed catalog request should time out");
tokio::time::resume();
assert!(
matches!(error.details(), CodexErrorDetails::RequestTimeout),
"{error}"
);
}