Stabilize Bazel tests (timeout tweaks and flake fixes) (#17791)

This commit is contained in:
David de Regt
2026-04-16 07:57:51 -07:00
committed by GitHub
parent 895e2d056f
commit 6adba99f4d
34 changed files with 200 additions and 60 deletions

View File

@@ -56,7 +56,9 @@ use tokio::net::TcpListener;
use tokio::task::JoinHandle;
use tokio::time::timeout;
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
// Bazel CI can spend tens of seconds starting app-server subprocesses or
// processing app-list RPCs under load.
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(60);
#[tokio::test]
async fn list_apps_returns_empty_when_connectors_disabled() -> Result<()> {

View File

@@ -18,7 +18,9 @@ use std::path::Path;
use tempfile::TempDir;
use tokio::time::timeout;
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
// Bazel CI can spend tens of seconds starting app-server subprocesses or
// processing turn RPCs under load.
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(60);
#[tokio::test]
async fn turn_start_forwards_client_metadata_to_responses_request_v2() -> Result<()> {

View File

@@ -21,7 +21,9 @@ use pretty_assertions::assert_eq;
use tempfile::TempDir;
use tokio::time::timeout;
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
// Bazel CI can spend tens of seconds starting app-server subprocesses or
// processing list RPCs under load.
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(60);
/// Confirms the server returns the default collaboration mode presets in a stable order.
#[tokio::test]

View File

@@ -38,6 +38,11 @@ use std::collections::BTreeMap;
use tempfile::TempDir;
use tokio::time::timeout;
// macOS and Windows Bazel CI can spend tens of seconds starting app-server
// subprocesses or processing test RPCs under load.
#[cfg(any(target_os = "macos", windows))]
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(60);
#[cfg(not(any(target_os = "macos", windows)))]
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
const AUTO_COMPACT_LIMIT: i64 = 1_000;
const COMPACT_PROMPT: &str = "Summarize the conversation.";

View File

@@ -33,7 +33,9 @@ use serde_json::json;
use tempfile::TempDir;
use tokio::time::timeout;
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
// Bazel CI can spend tens of seconds starting app-server subprocesses or
// processing config RPCs under load.
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(60);
fn write_config(codex_home: &TempDir, contents: &str) -> Result<()> {
Ok(std::fs::write(

View File

@@ -47,6 +47,12 @@ use tokio_tungstenite::tungstenite::http::HeaderValue;
use tokio_tungstenite::tungstenite::http::header::AUTHORIZATION;
use tokio_tungstenite::tungstenite::http::header::ORIGIN;
// macOS and Windows CI can spend tens of seconds starting the app-server test
// binary under Bazel before it accepts JSON-RPC or reports its websocket bind
// address.
#[cfg(any(target_os = "macos", windows))]
pub(super) const DEFAULT_READ_TIMEOUT: Duration = Duration::from_secs(60);
#[cfg(not(any(target_os = "macos", windows)))]
pub(super) const DEFAULT_READ_TIMEOUT: Duration = Duration::from_secs(10);
pub(super) type WsClient = WebSocketStream<MaybeTlsStream<tokio::net::TcpStream>>;
@@ -399,7 +405,7 @@ pub(super) async fn spawn_websocket_server_with_args(
.take()
.context("failed to capture websocket app-server stderr")?;
let mut stderr_reader = BufReader::new(stderr).lines();
let deadline = Instant::now() + Duration::from_secs(10);
let deadline = Instant::now() + DEFAULT_READ_TIMEOUT;
let bind_addr = loop {
let line = timeout(
deadline.saturating_duration_since(Instant::now()),
@@ -457,7 +463,7 @@ pub(super) async fn connect_websocket_with_bearer(
) -> Result<WsClient> {
let url = format!("ws://{}", connectable_bind_addr(bind_addr));
let request = websocket_request(url.as_str(), bearer_token, /*origin*/ None)?;
let deadline = Instant::now() + Duration::from_secs(10);
let deadline = Instant::now() + DEFAULT_READ_TIMEOUT;
loop {
match connect_async(request.clone()).await {
Ok((stream, _response)) => return Ok(stream),
@@ -524,7 +530,7 @@ async fn run_websocket_server_to_completion_with_args(
.stderr(Stdio::piped())
.env("CODEX_HOME", codex_home)
.env("RUST_LOG", "debug");
timeout(Duration::from_secs(10), cmd.output())
timeout(DEFAULT_READ_TIMEOUT, cmd.output())
.await
.context("timed out waiting for websocket app-server to exit")?
.context("failed to run websocket app-server")
@@ -536,7 +542,7 @@ async fn http_get(
path: &str,
) -> Result<reqwest::Response> {
let connectable_bind_addr = connectable_bind_addr(bind_addr);
let deadline = Instant::now() + Duration::from_secs(10);
let deadline = Instant::now() + DEFAULT_READ_TIMEOUT;
loop {
match client
.get(format!("http://{connectable_bind_addr}{path}"))

View File

@@ -34,6 +34,11 @@ use tempfile::TempDir;
use tokio::time::timeout;
use wiremock::MockServer;
// macOS and Windows Bazel CI can spend tens of seconds starting app-server
// subprocesses or processing test RPCs under load.
#[cfg(any(target_os = "macos", windows))]
const DEFAULT_READ_TIMEOUT: Duration = Duration::from_secs(60);
#[cfg(not(any(target_os = "macos", windows)))]
const DEFAULT_READ_TIMEOUT: Duration = Duration::from_secs(10);
/// Ensures dynamic tool specs are serialized into the model request payload.

View File

@@ -27,6 +27,11 @@ use std::os::unix::fs::symlink;
#[cfg(unix)]
use std::process::Command;
// macOS and Windows Bazel CI can spend tens of seconds starting app-server
// subprocesses or processing test RPCs under load.
#[cfg(any(target_os = "macos", windows))]
const DEFAULT_READ_TIMEOUT: Duration = Duration::from_secs(60);
#[cfg(not(any(target_os = "macos", windows)))]
const DEFAULT_READ_TIMEOUT: Duration = Duration::from_secs(10);
async fn initialized_mcp(codex_home: &TempDir) -> Result<McpProcess> {

View File

@@ -51,7 +51,9 @@ use wiremock::matchers::header;
use wiremock::matchers::method;
use wiremock::matchers::path;
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
// Plugin install tests wait on connector discovery after the install response path
// starts, which is noticeably slower on Windows CI.
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(60);
#[tokio::test]
async fn plugin_install_rejects_relative_marketplace_paths() -> Result<()> {

View File

@@ -43,6 +43,9 @@ use super::analytics::enable_analytics_capture;
use super::analytics::thread_initialized_event;
use super::analytics::wait_for_analytics_payload;
#[cfg(windows)]
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(25);
#[cfg(not(windows))]
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
#[tokio::test]

View File

@@ -36,6 +36,9 @@ use std::path::Path;
use tempfile::TempDir;
use tokio::time::timeout;
#[cfg(windows)]
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(25);
#[cfg(not(windows))]
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
#[tokio::test]

View File

@@ -76,6 +76,9 @@ use super::analytics::enable_analytics_capture;
use super::analytics::thread_initialized_event;
use super::analytics::wait_for_analytics_payload;
#[cfg(windows)]
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(25);
#[cfg(not(windows))]
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.";

View File

@@ -31,13 +31,17 @@ use tempfile::TempDir;
use tokio::time::timeout;
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
// Windows CI can spend most of the default read timeout launching PowerShell
// before the command finishes and the follow-up model request is sent.
const TURN_COMPLETION_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(30);
async fn wait_for_responses_request_count_to_stabilize(
server: &wiremock::MockServer,
expected_count: usize,
settle_duration: std::time::Duration,
timeout_duration: std::time::Duration,
) -> Result<()> {
timeout(DEFAULT_READ_TIMEOUT, async {
timeout(timeout_duration, async {
let mut stable_since: Option<tokio::time::Instant> = None;
loop {
let requests = server
@@ -210,6 +214,7 @@ async fn thread_unsubscribe_during_turn_keeps_turn_running() -> Result<()> {
&server,
/*expected_count*/ 2,
std::time::Duration::from_millis(200),
TURN_COMPLETION_TIMEOUT,
)
.await?;