From 1c4923e1c8b1c853ef81915d3737ec969c66bc82 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 28 Oct 2025 02:37:41 +0100 Subject: [PATCH] gpui: Add a timeout to `#[gpui::test]` tests (#41303) Release Notes: - N/A *or* Added/Fixed/Improved ... --- crates/extension/src/extension_builder.rs | 14 +++++++++++--- .../extension_host/src/extension_store_test.rs | 7 ++----- crates/gpui/src/executor.rs | 9 ++++++++- crates/zlog/src/zlog.rs | 18 ++++++++++++------ 4 files changed, 33 insertions(+), 15 deletions(-) diff --git a/crates/extension/src/extension_builder.rs b/crates/extension/src/extension_builder.rs index 15ff230ec7d1d1b99f4fd91400065f78b88b0b9d..7804910633ad2dbefdbda7a0dfef27a6797eeb97 100644 --- a/crates/extension/src/extension_builder.rs +++ b/crates/extension/src/extension_builder.rs @@ -5,7 +5,7 @@ use crate::{ use anyhow::{Context as _, Result, bail}; use async_compression::futures::bufread::GzipDecoder; use async_tar::Archive; -use futures::io::BufReader; +use futures::{AsyncReadExt, io::Cursor}; use heck::ToSnakeCase; use http_client::{self, AsyncBody, HttpClient}; use serde::Deserialize; @@ -411,6 +411,8 @@ impl ExtensionBuilder { let mut clang_path = wasi_sdk_dir.clone(); clang_path.extend(["bin", &format!("clang{}", env::consts::EXE_SUFFIX)]); + log::info!("downloading wasi-sdk to {}", wasi_sdk_dir.display()); + if fs::metadata(&clang_path).is_ok_and(|metadata| metadata.is_file()) { return Ok(clang_path); } @@ -423,13 +425,19 @@ impl ExtensionBuilder { log::info!("downloading wasi-sdk to {}", wasi_sdk_dir.display()); let mut response = self.http.get(&url, AsyncBody::default(), true).await?; - let body = BufReader::new(response.body_mut()); - let body = GzipDecoder::new(body); + let body = GzipDecoder::new({ + // stream the entire request into memory at once as the artifact is quite big (100MB+) + let mut b = vec![]; + response.body_mut().read_to_end(&mut b).await?; + Cursor::new(b) + }); let tar = Archive::new(body); + log::info!("un-tarring wasi-sdk to {}", wasi_sdk_dir.display()); tar.unpack(&tar_out_dir) .await .context("failed to unpack wasi-sdk archive")?; + log::info!("finished downloading wasi-sdk"); let inner_dir = fs::read_dir(&tar_out_dir)? .next() diff --git a/crates/extension_host/src/extension_store_test.rs b/crates/extension_host/src/extension_store_test.rs index 41b7b35d463a520888d4419f141ffdeca332fdac..af09b3e4fb28be1a7f339ac4be6b1e789bcff0f0 100644 --- a/crates/extension_host/src/extension_store_test.rs +++ b/crates/extension_host/src/extension_store_test.rs @@ -31,7 +31,8 @@ use util::test::TempTree; #[cfg(test)] #[ctor::ctor] fn init_logger() { - zlog::init_test(); + // show info logs while we debug the extension_store tests hanging. + zlog::init_test_with("info"); } #[gpui::test] @@ -529,10 +530,6 @@ async fn test_extension_store(cx: &mut TestAppContext) { }); } -// todo(windows) -// Disable this test on Windows for now. Because this test hangs at -// `let fake_server = fake_servers.next().await.unwrap();`. -// Reenable this test when we figure out why. #[gpui::test] async fn test_extension_store_with_test_extension(cx: &mut TestAppContext) { init_test(cx); diff --git a/crates/gpui/src/executor.rs b/crates/gpui/src/executor.rs index 841fbe924cd011bd2afa7d8d344e3a1c5a51e7a1..ecb3f296c88bdacbac716ff6eae8c3e77701c5ce 100644 --- a/crates/gpui/src/executor.rs +++ b/crates/gpui/src/executor.rs @@ -281,6 +281,8 @@ impl BackgroundExecutor { }); let mut cx = std::task::Context::from_waker(&waker); + let mut test_should_end_by = Instant::now() + Duration::from_secs(500); + loop { match future.as_mut().poll(&mut cx) { Poll::Ready(result) => return Ok(result), @@ -313,7 +315,12 @@ impl BackgroundExecutor { ) } dispatcher.set_unparker(unparker.clone()); - parker.park(); + parker.park_timeout( + test_should_end_by.saturating_duration_since(Instant::now()), + ); + if Instant::now() > test_should_end_by { + panic!("test timed out with allow_parking") + } } } } diff --git a/crates/zlog/src/zlog.rs b/crates/zlog/src/zlog.rs index 8254866b6f97f6479f55bd570d1bc63ab26b10d4..b65a2f34bc468c1fccd334487a0b386da238ce52 100644 --- a/crates/zlog/src/zlog.rs +++ b/crates/zlog/src/zlog.rs @@ -10,22 +10,28 @@ pub use sink::{flush, init_output_file, init_output_stderr, init_output_stdout}; pub const SCOPE_DEPTH_MAX: usize = 4; pub fn init() { - if let Err(err) = try_init() { + if let Err(err) = try_init(None) { log::error!("{err}"); eprintln!("{err}"); } } -pub fn try_init() -> anyhow::Result<()> { +pub fn try_init(filter: Option) -> anyhow::Result<()> { log::set_logger(&ZLOG)?; log::set_max_level(log::LevelFilter::max()); - process_env(); + process_env(filter); filter::refresh_from_settings(&std::collections::HashMap::default()); Ok(()) } pub fn init_test() { - if get_env_config().is_some() && try_init().is_ok() { + if get_env_config().is_some() && try_init(None).is_ok() { + init_output_stdout(); + } +} + +pub fn init_test_with(filter: &str) { + if try_init(Some(filter.to_owned())).is_ok() { init_output_stdout(); } } @@ -36,8 +42,8 @@ fn get_env_config() -> Option { .ok() } -pub fn process_env() { - let Some(env_config) = get_env_config() else { +pub fn process_env(filter: Option) { + let Some(env_config) = get_env_config().or(filter) else { return; }; match env_config::parse(&env_config) {