Extract a scheduler crate from GPUI to enable unified integration testing of client and server code (#37326)
Extracts and cleans up GPUI's scheduler code into a new `scheduler` crate, making it pluggable by external runtimes. This will enable deterministic integration testing with cloud components by providing a unified test scheduler across Zed and backend code. In Zed, it will replace the existing GPUI scheduler for consistent async task management across platforms. ## Changes - **Core Implementation**: `TestScheduler` with seed-based randomization, session tracking (`SessionId`), and foreground/background task separation for reproducible testing. - **Executors**: `ForegroundExecutor` (!Send, thread-local) and `BackgroundExecutor` (Send, with blocking/timeout support) as GPUI-compatible wrappers. - **Clock and Timer**: Controllable `TestClock` and future-based `Timer` for time-sensitive tests. - **Testing APIs**: `once()`, `with_seed()`, and `many()` methods for configurable test runs. - **Dependencies**: Added `async-task`, `chrono`, `futures`, etc., with updates to `Cargo.toml` and lock file. ## Benefits - **Integration Testing**: Facilitates reliable async tests involving cloud sessions, reducing flakiness via deterministic execution. - **Pluggability**: Trait-based design (`Scheduler`) allows easy integration into non-GPUI runtimes while maintaining GPUI compatibility. - **Cleanup**: Refactors GPUI scheduler logic for clarity, correctness (no `unwrap()`, proper error handling), and extensibility. Follows Rust guidelines; run `./script/clippy` for verification. - [x] Define and test a core scheduler that we think can power our cloud code and GPUI - [ ] Replace GPUI's scheduler Release Notes: - N/A --------- Co-authored-by: Antonio Scandurra <me@as-cii.com>
This commit is contained in:
co-authored by
Antonio Scandurra
parent
a05f86f97b
commit
1ae326432e
@@ -945,7 +945,7 @@ mod tests {
|
||||
let mut new_len = 0;
|
||||
|
||||
while new_len < new.len() {
|
||||
let mut chunk_len = rng.gen_range(1..=new.len() - new_len);
|
||||
let mut chunk_len = rng.random_range(1..=new.len() - new_len);
|
||||
while !new.is_char_boundary(new_len + chunk_len) {
|
||||
chunk_len += 1;
|
||||
}
|
||||
@@ -1034,14 +1034,14 @@ mod tests {
|
||||
|
||||
fn randomly_edit(text: &str, rng: &mut impl Rng) -> String {
|
||||
let mut result = String::from(text);
|
||||
let edit_count = rng.gen_range(1..=5);
|
||||
let edit_count = rng.random_range(1..=5);
|
||||
|
||||
fn random_char_range(text: &str, rng: &mut impl Rng) -> (usize, usize) {
|
||||
let mut start = rng.gen_range(0..=text.len());
|
||||
let mut start = rng.random_range(0..=text.len());
|
||||
while !text.is_char_boundary(start) {
|
||||
start -= 1;
|
||||
}
|
||||
let mut end = rng.gen_range(start..=text.len());
|
||||
let mut end = rng.random_range(start..=text.len());
|
||||
while !text.is_char_boundary(end) {
|
||||
end += 1;
|
||||
}
|
||||
@@ -1049,11 +1049,11 @@ mod tests {
|
||||
}
|
||||
|
||||
for _ in 0..edit_count {
|
||||
match rng.gen_range(0..3) {
|
||||
match rng.random_range(0..3) {
|
||||
0 => {
|
||||
// Insert
|
||||
let (pos, _) = random_char_range(&result, rng);
|
||||
let insert_len = rng.gen_range(1..=5);
|
||||
let insert_len = rng.random_range(1..=5);
|
||||
let insert_text: String = random_text(rng, insert_len);
|
||||
result.insert_str(pos, &insert_text);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user