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:
Nathan Sobo
2025-09-04 17:14:53 +02:00
committed by GitHub
co-authored by Antonio Scandurra
parent a05f86f97b
commit 1ae326432e
64 changed files with 1569 additions and 473 deletions
+29 -30
View File
@@ -1552,15 +1552,15 @@ pub mod tests {
.map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
.unwrap_or(10);
let mut tab_size = rng.gen_range(1..=4);
let buffer_start_excerpt_header_height = rng.gen_range(1..=5);
let excerpt_header_height = rng.gen_range(1..=5);
let mut tab_size = rng.random_range(1..=4);
let buffer_start_excerpt_header_height = rng.random_range(1..=5);
let excerpt_header_height = rng.random_range(1..=5);
let font_size = px(14.0);
let max_wrap_width = 300.0;
let mut wrap_width = if rng.gen_bool(0.1) {
let mut wrap_width = if rng.random_bool(0.1) {
None
} else {
Some(px(rng.gen_range(0.0..=max_wrap_width)))
Some(px(rng.random_range(0.0..=max_wrap_width)))
};
log::info!("tab size: {}", tab_size);
@@ -1571,8 +1571,8 @@ pub mod tests {
});
let buffer = cx.update(|cx| {
if rng.r#gen() {
let len = rng.gen_range(0..10);
if rng.random() {
let len = rng.random_range(0..10);
let text = util::RandomCharIter::new(&mut rng)
.take(len)
.collect::<String>();
@@ -1609,12 +1609,12 @@ pub mod tests {
log::info!("display text: {:?}", snapshot.text());
for _i in 0..operations {
match rng.gen_range(0..100) {
match rng.random_range(0..100) {
0..=19 => {
wrap_width = if rng.gen_bool(0.2) {
wrap_width = if rng.random_bool(0.2) {
None
} else {
Some(px(rng.gen_range(0.0..=max_wrap_width)))
Some(px(rng.random_range(0.0..=max_wrap_width)))
};
log::info!("setting wrap width to {:?}", wrap_width);
map.update(cx, |map, cx| map.set_wrap_width(wrap_width, cx));
@@ -1634,28 +1634,27 @@ pub mod tests {
}
30..=44 => {
map.update(cx, |map, cx| {
if rng.r#gen() || blocks.is_empty() {
if rng.random() || blocks.is_empty() {
let buffer = map.snapshot(cx).buffer_snapshot;
let block_properties = (0..rng.gen_range(1..=1))
let block_properties = (0..rng.random_range(1..=1))
.map(|_| {
let position =
buffer.anchor_after(buffer.clip_offset(
rng.gen_range(0..=buffer.len()),
Bias::Left,
));
let position = buffer.anchor_after(buffer.clip_offset(
rng.random_range(0..=buffer.len()),
Bias::Left,
));
let placement = if rng.r#gen() {
let placement = if rng.random() {
BlockPlacement::Above(position)
} else {
BlockPlacement::Below(position)
};
let height = rng.gen_range(1..5);
let height = rng.random_range(1..5);
log::info!(
"inserting block {:?} with height {}",
placement.as_ref().map(|p| p.to_point(&buffer)),
height
);
let priority = rng.gen_range(1..100);
let priority = rng.random_range(1..100);
BlockProperties {
placement,
style: BlockStyle::Fixed,
@@ -1668,9 +1667,9 @@ pub mod tests {
blocks.extend(map.insert_blocks(block_properties, cx));
} else {
blocks.shuffle(&mut rng);
let remove_count = rng.gen_range(1..=4.min(blocks.len()));
let remove_count = rng.random_range(1..=4.min(blocks.len()));
let block_ids_to_remove = (0..remove_count)
.map(|_| blocks.remove(rng.gen_range(0..blocks.len())))
.map(|_| blocks.remove(rng.random_range(0..blocks.len())))
.collect();
log::info!("removing block ids {:?}", block_ids_to_remove);
map.remove_blocks(block_ids_to_remove, cx);
@@ -1679,16 +1678,16 @@ pub mod tests {
}
45..=79 => {
let mut ranges = Vec::new();
for _ in 0..rng.gen_range(1..=3) {
for _ in 0..rng.random_range(1..=3) {
buffer.read_with(cx, |buffer, cx| {
let buffer = buffer.read(cx);
let end = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Right);
let start = buffer.clip_offset(rng.gen_range(0..=end), Left);
let end = buffer.clip_offset(rng.random_range(0..=buffer.len()), Right);
let start = buffer.clip_offset(rng.random_range(0..=end), Left);
ranges.push(start..end);
});
}
if rng.r#gen() && fold_count > 0 {
if rng.random() && fold_count > 0 {
log::info!("unfolding ranges: {:?}", ranges);
map.update(cx, |map, cx| {
map.unfold_intersecting(ranges, true, cx);
@@ -1727,8 +1726,8 @@ pub mod tests {
// Line boundaries
let buffer = &snapshot.buffer_snapshot;
for _ in 0..5 {
let row = rng.gen_range(0..=buffer.max_point().row);
let column = rng.gen_range(0..=buffer.line_len(MultiBufferRow(row)));
let row = rng.random_range(0..=buffer.max_point().row);
let column = rng.random_range(0..=buffer.line_len(MultiBufferRow(row)));
let point = buffer.clip_point(Point::new(row, column), Left);
let (prev_buffer_bound, prev_display_bound) = snapshot.prev_line_boundary(point);
@@ -1776,8 +1775,8 @@ pub mod tests {
let min_point = snapshot.clip_point(DisplayPoint::new(DisplayRow(0), 0), Left);
let max_point = snapshot.clip_point(snapshot.max_point(), Right);
for _ in 0..5 {
let row = rng.gen_range(0..=snapshot.max_point().row().0);
let column = rng.gen_range(0..=snapshot.line_len(DisplayRow(row)));
let row = rng.random_range(0..=snapshot.max_point().row().0);
let column = rng.random_range(0..=snapshot.line_len(DisplayRow(row)));
let point = snapshot.clip_point(DisplayPoint::new(DisplayRow(row), column), Left);
log::info!("Moving from point {:?}", point);
+28 -28
View File
@@ -128,10 +128,10 @@ impl<T> BlockPlacement<T> {
}
}
fn sort_order(&self) -> u8 {
fn tie_break(&self) -> u8 {
match self {
BlockPlacement::Above(_) => 0,
BlockPlacement::Replace(_) => 1,
BlockPlacement::Replace(_) => 0,
BlockPlacement::Above(_) => 1,
BlockPlacement::Near(_) => 2,
BlockPlacement::Below(_) => 3,
}
@@ -143,7 +143,7 @@ impl BlockPlacement<Anchor> {
self.start()
.cmp(other.start(), buffer)
.then_with(|| other.end().cmp(self.end(), buffer))
.then_with(|| self.sort_order().cmp(&other.sort_order()))
.then_with(|| self.tie_break().cmp(&other.tie_break()))
}
fn to_wrap_row(&self, wrap_snapshot: &WrapSnapshot) -> Option<BlockPlacement<WrapRow>> {
@@ -847,6 +847,7 @@ impl BlockMap {
.start()
.cmp(placement_b.start())
.then_with(|| placement_b.end().cmp(placement_a.end()))
.then_with(|| placement_a.tie_break().cmp(&placement_b.tie_break()))
.then_with(|| {
if block_a.is_header() {
Ordering::Less
@@ -856,7 +857,6 @@ impl BlockMap {
Ordering::Equal
}
})
.then_with(|| placement_a.sort_order().cmp(&placement_b.sort_order()))
.then_with(|| match (block_a, block_b) {
(
Block::ExcerptBoundary {
@@ -2922,21 +2922,21 @@ mod tests {
.map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
.unwrap_or(10);
let wrap_width = if rng.gen_bool(0.2) {
let wrap_width = if rng.random_bool(0.2) {
None
} else {
Some(px(rng.gen_range(0.0..=100.0)))
Some(px(rng.random_range(0.0..=100.0)))
};
let tab_size = 1.try_into().unwrap();
let font_size = px(14.0);
let buffer_start_header_height = rng.gen_range(1..=5);
let excerpt_header_height = rng.gen_range(1..=5);
let buffer_start_header_height = rng.random_range(1..=5);
let excerpt_header_height = rng.random_range(1..=5);
log::info!("Wrap width: {:?}", wrap_width);
log::info!("Excerpt Header Height: {:?}", excerpt_header_height);
let is_singleton = rng.r#gen();
let is_singleton = rng.random();
let buffer = if is_singleton {
let len = rng.gen_range(0..10);
let len = rng.random_range(0..10);
let text = RandomCharIter::new(&mut rng).take(len).collect::<String>();
log::info!("initial singleton buffer text: {:?}", text);
cx.update(|cx| MultiBuffer::build_simple(&text, cx))
@@ -2966,30 +2966,30 @@ mod tests {
for _ in 0..operations {
let mut buffer_edits = Vec::new();
match rng.gen_range(0..=100) {
match rng.random_range(0..=100) {
0..=19 => {
let wrap_width = if rng.gen_bool(0.2) {
let wrap_width = if rng.random_bool(0.2) {
None
} else {
Some(px(rng.gen_range(0.0..=100.0)))
Some(px(rng.random_range(0.0..=100.0)))
};
log::info!("Setting wrap width to {:?}", wrap_width);
wrap_map.update(cx, |map, cx| map.set_wrap_width(wrap_width, cx));
}
20..=39 => {
let block_count = rng.gen_range(1..=5);
let block_count = rng.random_range(1..=5);
let block_properties = (0..block_count)
.map(|_| {
let buffer = cx.update(|cx| buffer.read(cx).read(cx).clone());
let offset =
buffer.clip_offset(rng.gen_range(0..=buffer.len()), Bias::Left);
buffer.clip_offset(rng.random_range(0..=buffer.len()), Bias::Left);
let mut min_height = 0;
let placement = match rng.gen_range(0..3) {
let placement = match rng.random_range(0..3) {
0 => {
min_height = 1;
let start = buffer.anchor_after(offset);
let end = buffer.anchor_after(buffer.clip_offset(
rng.gen_range(offset..=buffer.len()),
rng.random_range(offset..=buffer.len()),
Bias::Left,
));
BlockPlacement::Replace(start..=end)
@@ -2998,7 +2998,7 @@ mod tests {
_ => BlockPlacement::Below(buffer.anchor_after(offset)),
};
let height = rng.gen_range(min_height..5);
let height = rng.random_range(min_height..5);
BlockProperties {
style: BlockStyle::Fixed,
placement,
@@ -3040,7 +3040,7 @@ mod tests {
}
}
40..=59 if !block_map.custom_blocks.is_empty() => {
let block_count = rng.gen_range(1..=4.min(block_map.custom_blocks.len()));
let block_count = rng.random_range(1..=4.min(block_map.custom_blocks.len()));
let block_ids_to_remove = block_map
.custom_blocks
.choose_multiple(&mut rng, block_count)
@@ -3095,8 +3095,8 @@ mod tests {
let mut folded_count = folded_buffers.len();
let mut unfolded_count = unfolded_buffers.len();
let fold = !unfolded_buffers.is_empty() && rng.gen_bool(0.5);
let unfold = !folded_buffers.is_empty() && rng.gen_bool(0.5);
let fold = !unfolded_buffers.is_empty() && rng.random_bool(0.5);
let unfold = !folded_buffers.is_empty() && rng.random_bool(0.5);
if !fold && !unfold {
log::info!(
"Noop fold/unfold operation. Unfolded buffers: {unfolded_count}, folded buffers: {folded_count}"
@@ -3107,7 +3107,7 @@ mod tests {
buffer.update(cx, |buffer, cx| {
if fold {
let buffer_to_fold =
unfolded_buffers[rng.gen_range(0..unfolded_buffers.len())];
unfolded_buffers[rng.random_range(0..unfolded_buffers.len())];
log::info!("Folding {buffer_to_fold:?}");
let related_excerpts = buffer_snapshot
.excerpts()
@@ -3133,7 +3133,7 @@ mod tests {
}
if unfold {
let buffer_to_unfold =
folded_buffers[rng.gen_range(0..folded_buffers.len())];
folded_buffers[rng.random_range(0..folded_buffers.len())];
log::info!("Unfolding {buffer_to_unfold:?}");
unfolded_count += 1;
folded_count -= 1;
@@ -3146,7 +3146,7 @@ mod tests {
}
_ => {
buffer.update(cx, |buffer, cx| {
let mutation_count = rng.gen_range(1..=5);
let mutation_count = rng.random_range(1..=5);
let subscription = buffer.subscribe();
buffer.randomly_mutate(&mut rng, mutation_count, cx);
buffer_snapshot = buffer.snapshot(cx);
@@ -3331,7 +3331,7 @@ mod tests {
);
for start_row in 0..expected_row_count {
let end_row = rng.gen_range(start_row + 1..=expected_row_count);
let end_row = rng.random_range(start_row + 1..=expected_row_count);
let mut expected_text = expected_lines[start_row..end_row].join("\n");
if end_row < expected_row_count {
expected_text.push('\n');
@@ -3426,8 +3426,8 @@ mod tests {
);
for _ in 0..10 {
let end_row = rng.gen_range(1..=expected_lines.len());
let start_row = rng.gen_range(0..end_row);
let end_row = rng.random_range(1..=expected_lines.len());
let start_row = rng.random_range(0..end_row);
let mut expected_longest_rows_in_range = vec![];
let mut longest_line_len_in_range = 0;
+26 -22
View File
@@ -1771,9 +1771,9 @@ mod tests {
.map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
.unwrap_or(10);
let len = rng.gen_range(0..10);
let len = rng.random_range(0..10);
let text = RandomCharIter::new(&mut rng).take(len).collect::<String>();
let buffer = if rng.r#gen() {
let buffer = if rng.random() {
MultiBuffer::build_simple(&text, cx)
} else {
MultiBuffer::build_random(&mut rng, cx)
@@ -1790,7 +1790,7 @@ mod tests {
log::info!("text: {:?}", buffer_snapshot.text());
let mut buffer_edits = Vec::new();
let mut inlay_edits = Vec::new();
match rng.gen_range(0..=100) {
match rng.random_range(0..=100) {
0..=39 => {
snapshot_edits.extend(map.randomly_mutate(&mut rng));
}
@@ -1800,7 +1800,7 @@ mod tests {
}
_ => buffer.update(cx, |buffer, cx| {
let subscription = buffer.subscribe();
let edit_count = rng.gen_range(1..=5);
let edit_count = rng.random_range(1..=5);
buffer.randomly_mutate(&mut rng, edit_count, cx);
buffer_snapshot = buffer.snapshot(cx);
let edits = subscription.consume().into_inner();
@@ -1917,10 +1917,14 @@ mod tests {
}
for _ in 0..5 {
let mut start = snapshot
.clip_offset(FoldOffset(rng.gen_range(0..=snapshot.len().0)), Bias::Left);
let mut end = snapshot
.clip_offset(FoldOffset(rng.gen_range(0..=snapshot.len().0)), Bias::Right);
let mut start = snapshot.clip_offset(
FoldOffset(rng.random_range(0..=snapshot.len().0)),
Bias::Left,
);
let mut end = snapshot.clip_offset(
FoldOffset(rng.random_range(0..=snapshot.len().0)),
Bias::Right,
);
if start > end {
mem::swap(&mut start, &mut end);
}
@@ -1975,8 +1979,8 @@ mod tests {
for _ in 0..5 {
let end =
buffer_snapshot.clip_offset(rng.gen_range(0..=buffer_snapshot.len()), Right);
let start = buffer_snapshot.clip_offset(rng.gen_range(0..=end), Left);
buffer_snapshot.clip_offset(rng.random_range(0..=buffer_snapshot.len()), Right);
let start = buffer_snapshot.clip_offset(rng.random_range(0..=end), Left);
let expected_folds = map
.snapshot
.folds
@@ -2001,10 +2005,10 @@ mod tests {
let text = snapshot.text();
for _ in 0..5 {
let start_row = rng.gen_range(0..=snapshot.max_point().row());
let start_column = rng.gen_range(0..=snapshot.line_len(start_row));
let end_row = rng.gen_range(0..=snapshot.max_point().row());
let end_column = rng.gen_range(0..=snapshot.line_len(end_row));
let start_row = rng.random_range(0..=snapshot.max_point().row());
let start_column = rng.random_range(0..=snapshot.line_len(start_row));
let end_row = rng.random_range(0..=snapshot.max_point().row());
let end_column = rng.random_range(0..=snapshot.line_len(end_row));
let mut start =
snapshot.clip_point(FoldPoint::new(start_row, start_column), Bias::Left);
let mut end = snapshot.clip_point(FoldPoint::new(end_row, end_column), Bias::Right);
@@ -2109,17 +2113,17 @@ mod tests {
rng: &mut impl Rng,
) -> Vec<(FoldSnapshot, Vec<FoldEdit>)> {
let mut snapshot_edits = Vec::new();
match rng.gen_range(0..=100) {
match rng.random_range(0..=100) {
0..=39 if !self.snapshot.folds.is_empty() => {
let inlay_snapshot = self.snapshot.inlay_snapshot.clone();
let buffer = &inlay_snapshot.buffer;
let mut to_unfold = Vec::new();
for _ in 0..rng.gen_range(1..=3) {
let end = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Right);
let start = buffer.clip_offset(rng.gen_range(0..=end), Left);
for _ in 0..rng.random_range(1..=3) {
let end = buffer.clip_offset(rng.random_range(0..=buffer.len()), Right);
let start = buffer.clip_offset(rng.random_range(0..=end), Left);
to_unfold.push(start..end);
}
let inclusive = rng.r#gen();
let inclusive = rng.random();
log::info!("unfolding {:?} (inclusive: {})", to_unfold, inclusive);
let (mut writer, snapshot, edits) = self.write(inlay_snapshot, vec![]);
snapshot_edits.push((snapshot, edits));
@@ -2130,9 +2134,9 @@ mod tests {
let inlay_snapshot = self.snapshot.inlay_snapshot.clone();
let buffer = &inlay_snapshot.buffer;
let mut to_fold = Vec::new();
for _ in 0..rng.gen_range(1..=2) {
let end = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Right);
let start = buffer.clip_offset(rng.gen_range(0..=end), Left);
for _ in 0..rng.random_range(1..=2) {
let end = buffer.clip_offset(rng.random_range(0..=buffer.len()), Right);
let start = buffer.clip_offset(rng.random_range(0..=end), Left);
to_fold.push((start..end, FoldPlaceholder::test()));
}
log::info!("folding {:?}", to_fold);
+20 -16
View File
@@ -719,14 +719,18 @@ impl InlayMap {
let mut to_remove = Vec::new();
let mut to_insert = Vec::new();
let snapshot = &mut self.snapshot;
for i in 0..rng.gen_range(1..=5) {
if self.inlays.is_empty() || rng.r#gen() {
for i in 0..rng.random_range(1..=5) {
if self.inlays.is_empty() || rng.random() {
let position = snapshot.buffer.random_byte_range(0, rng).start;
let bias = if rng.r#gen() { Bias::Left } else { Bias::Right };
let len = if rng.gen_bool(0.01) {
let bias = if rng.random() {
Bias::Left
} else {
Bias::Right
};
let len = if rng.random_bool(0.01) {
0
} else {
rng.gen_range(1..=5)
rng.random_range(1..=5)
};
let text = util::RandomCharIter::new(&mut *rng)
.filter(|ch| *ch != '\r')
@@ -1665,8 +1669,8 @@ mod tests {
.map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
.unwrap_or(10);
let len = rng.gen_range(0..30);
let buffer = if rng.r#gen() {
let len = rng.random_range(0..30);
let buffer = if rng.random() {
let text = util::RandomCharIter::new(&mut rng)
.take(len)
.collect::<String>();
@@ -1683,7 +1687,7 @@ mod tests {
let mut prev_inlay_text = inlay_snapshot.text();
let mut buffer_edits = Vec::new();
match rng.gen_range(0..=100) {
match rng.random_range(0..=100) {
0..=50 => {
let (snapshot, edits) = inlay_map.randomly_mutate(&mut next_inlay_id, &mut rng);
log::info!("mutated text: {:?}", snapshot.text());
@@ -1691,7 +1695,7 @@ mod tests {
}
_ => buffer.update(cx, |buffer, cx| {
let subscription = buffer.subscribe();
let edit_count = rng.gen_range(1..=5);
let edit_count = rng.random_range(1..=5);
buffer.randomly_mutate(&mut rng, edit_count, cx);
buffer_snapshot = buffer.snapshot(cx);
let edits = subscription.consume().into_inner();
@@ -1740,7 +1744,7 @@ mod tests {
}
let mut text_highlights = TextHighlights::default();
let text_highlight_count = rng.gen_range(0_usize..10);
let text_highlight_count = rng.random_range(0_usize..10);
let mut text_highlight_ranges = (0..text_highlight_count)
.map(|_| buffer_snapshot.random_byte_range(0, &mut rng))
.collect::<Vec<_>>();
@@ -1762,10 +1766,10 @@ mod tests {
let mut inlay_highlights = InlayHighlights::default();
if !inlays.is_empty() {
let inlay_highlight_count = rng.gen_range(0..inlays.len());
let inlay_highlight_count = rng.random_range(0..inlays.len());
let mut inlay_indices = BTreeSet::default();
while inlay_indices.len() < inlay_highlight_count {
inlay_indices.insert(rng.gen_range(0..inlays.len()));
inlay_indices.insert(rng.random_range(0..inlays.len()));
}
let new_highlights = TreeMap::from_ordered_entries(
inlay_indices
@@ -1782,8 +1786,8 @@ mod tests {
}),
n => {
let inlay_text = inlay.text.to_string();
let mut highlight_end = rng.gen_range(1..n);
let mut highlight_start = rng.gen_range(0..highlight_end);
let mut highlight_end = rng.random_range(1..n);
let mut highlight_start = rng.random_range(0..highlight_end);
while !inlay_text.is_char_boundary(highlight_end) {
highlight_end += 1;
}
@@ -1805,9 +1809,9 @@ mod tests {
}
for _ in 0..5 {
let mut end = rng.gen_range(0..=inlay_snapshot.len().0);
let mut end = rng.random_range(0..=inlay_snapshot.len().0);
end = expected_text.clip_offset(end, Bias::Right);
let mut start = rng.gen_range(0..=end);
let mut start = rng.random_range(0..=end);
start = expected_text.clip_offset(start, Bias::Right);
let range = InlayOffset(start)..InlayOffset(end);
+7 -7
View File
@@ -736,9 +736,9 @@ mod tests {
#[gpui::test(iterations = 100)]
fn test_random_tabs(cx: &mut gpui::App, mut rng: StdRng) {
let tab_size = NonZeroU32::new(rng.gen_range(1..=4)).unwrap();
let len = rng.gen_range(0..30);
let buffer = if rng.r#gen() {
let tab_size = NonZeroU32::new(rng.random_range(1..=4)).unwrap();
let len = rng.random_range(0..30);
let buffer = if rng.random() {
let text = util::RandomCharIter::new(&mut rng)
.take(len)
.collect::<String>();
@@ -769,11 +769,11 @@ mod tests {
);
for _ in 0..5 {
let end_row = rng.gen_range(0..=text.max_point().row);
let end_column = rng.gen_range(0..=text.line_len(end_row));
let end_row = rng.random_range(0..=text.max_point().row);
let end_column = rng.random_range(0..=text.line_len(end_row));
let mut end = TabPoint(text.clip_point(Point::new(end_row, end_column), Bias::Right));
let start_row = rng.gen_range(0..=text.max_point().row);
let start_column = rng.gen_range(0..=text.line_len(start_row));
let start_row = rng.random_range(0..=text.max_point().row);
let start_column = rng.random_range(0..=text.line_len(start_row));
let mut start =
TabPoint(text.clip_point(Point::new(start_row, start_column), Bias::Left));
if start > end {
+12 -12
View File
@@ -1215,12 +1215,12 @@ mod tests {
.unwrap_or(10);
let text_system = cx.read(|cx| cx.text_system().clone());
let mut wrap_width = if rng.gen_bool(0.1) {
let mut wrap_width = if rng.random_bool(0.1) {
None
} else {
Some(px(rng.gen_range(0.0..=1000.0)))
Some(px(rng.random_range(0.0..=1000.0)))
};
let tab_size = NonZeroU32::new(rng.gen_range(1..=4)).unwrap();
let tab_size = NonZeroU32::new(rng.random_range(1..=4)).unwrap();
let font = test_font();
let _font_id = text_system.resolve_font(&font);
@@ -1230,10 +1230,10 @@ mod tests {
log::info!("Wrap width: {:?}", wrap_width);
let buffer = cx.update(|cx| {
if rng.r#gen() {
if rng.random() {
MultiBuffer::build_random(&mut rng, cx)
} else {
let len = rng.gen_range(0..10);
let len = rng.random_range(0..10);
let text = util::RandomCharIter::new(&mut rng)
.take(len)
.collect::<String>();
@@ -1281,12 +1281,12 @@ mod tests {
log::info!("{} ==============================================", _i);
let mut buffer_edits = Vec::new();
match rng.gen_range(0..=100) {
match rng.random_range(0..=100) {
0..=19 => {
wrap_width = if rng.gen_bool(0.2) {
wrap_width = if rng.random_bool(0.2) {
None
} else {
Some(px(rng.gen_range(0.0..=1000.0)))
Some(px(rng.random_range(0.0..=1000.0)))
};
log::info!("Setting wrap width to {:?}", wrap_width);
wrap_map.update(cx, |map, cx| map.set_wrap_width(wrap_width, cx));
@@ -1317,7 +1317,7 @@ mod tests {
_ => {
buffer.update(cx, |buffer, cx| {
let subscription = buffer.subscribe();
let edit_count = rng.gen_range(1..=5);
let edit_count = rng.random_range(1..=5);
buffer.randomly_mutate(&mut rng, edit_count, cx);
buffer_snapshot = buffer.snapshot(cx);
buffer_edits.extend(subscription.consume());
@@ -1341,7 +1341,7 @@ mod tests {
snapshot.verify_chunks(&mut rng);
edits.push((snapshot, wrap_edits));
if wrap_map.read_with(cx, |map, _| map.is_rewrapping()) && rng.gen_bool(0.4) {
if wrap_map.read_with(cx, |map, _| map.is_rewrapping()) && rng.random_bool(0.4) {
log::info!("Waiting for wrapping to finish");
while wrap_map.read_with(cx, |map, _| map.is_rewrapping()) {
notifications.next().await.unwrap();
@@ -1479,8 +1479,8 @@ mod tests {
impl WrapSnapshot {
fn verify_chunks(&mut self, rng: &mut impl Rng) {
for _ in 0..5 {
let mut end_row = rng.gen_range(0..=self.max_point().row());
let start_row = rng.gen_range(0..=end_row);
let mut end_row = rng.random_range(0..=self.max_point().row());
let start_row = rng.random_range(0..=end_row);
end_row += 1;
let mut expected_text = self.text_chunks(start_row).collect::<String>();
+2 -2
View File
@@ -164,7 +164,7 @@ use project::{
DiagnosticSeverity, GitGutterSetting, GoToDiagnosticSeverityFilter, ProjectSettings,
},
};
use rand::{seq::SliceRandom, thread_rng};
use rand::seq::SliceRandom;
use rpc::{ErrorCode, ErrorExt, proto::PeerId};
use scroll::{Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide};
use selections_collection::{
@@ -10971,7 +10971,7 @@ impl Editor {
}
pub fn shuffle_lines(&mut self, _: &ShuffleLines, window: &mut Window, cx: &mut Context<Self>) {
self.manipulate_immutable_lines(window, cx, |lines| lines.shuffle(&mut thread_rng()))
self.manipulate_immutable_lines(window, cx, |lines| lines.shuffle(&mut rand::rng()))
}
fn manipulate_lines<M>(
+4 -4
View File
@@ -1107,7 +1107,7 @@ mod tests {
init_test(cx);
let fs = FakeFs::new(cx.executor());
let buffer_initial_text_len = rng.gen_range(5..15);
let buffer_initial_text_len = rng.random_range(5..15);
let mut buffer_initial_text = Rope::from(
RandomCharIter::new(&mut rng)
.take(buffer_initial_text_len)
@@ -1159,7 +1159,7 @@ mod tests {
git_blame.update(cx, |blame, cx| blame.check_invariants(cx));
for _ in 0..operations {
match rng.gen_range(0..100) {
match rng.random_range(0..100) {
0..=19 => {
log::info!("quiescing");
cx.executor().run_until_parked();
@@ -1202,8 +1202,8 @@ mod tests {
let mut blame_entries = Vec::new();
for ix in 0..5 {
if last_row < max_row {
let row_start = rng.gen_range(last_row..max_row);
let row_end = rng.gen_range(row_start + 1..cmp::min(row_start + 3, max_row) + 1);
let row_start = rng.random_range(last_row..max_row);
let row_end = rng.random_range(row_start + 1..cmp::min(row_start + 3, max_row) + 1);
blame_entries.push(blame_entry(&ix.to_string(), row_start..row_end));
last_row = row_end;
} else {