Start on a randomized test for BlockMap
This is currently passing and ensures we maintain the input coordinate space correctly. Co-Authored-By: Max Brunsfeld <max@zed.dev>
This commit is contained in:
co-authored by
Max Brunsfeld
parent
d721c2ba4b
commit
c8e47a8c63
@@ -11,7 +11,9 @@ struct BlockMap {
|
||||
|
||||
struct BlockMapWriter<'a>(&'a mut BlockMap);
|
||||
|
||||
struct BlockSnapshot {}
|
||||
struct BlockSnapshot {
|
||||
transforms: SumTree<Transform>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Transform {
|
||||
@@ -42,7 +44,9 @@ impl BlockMap {
|
||||
|
||||
fn read(&self, wrap_snapshot: WrapSnapshot, edits: Vec<WrapEdit>) -> BlockSnapshot {
|
||||
self.sync(wrap_snapshot, edits);
|
||||
BlockSnapshot {}
|
||||
BlockSnapshot {
|
||||
transforms: self.transforms.lock().clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn write(&mut self, wrap_snapshot: WrapSnapshot, edits: Vec<WrapEdit>) -> BlockMapWriter {
|
||||
@@ -51,7 +55,7 @@ impl BlockMap {
|
||||
}
|
||||
|
||||
fn sync(&self, wrap_snapshot: WrapSnapshot, edits: Vec<WrapEdit>) {
|
||||
let transforms = self.transforms.lock();
|
||||
let mut transforms = self.transforms.lock();
|
||||
let mut new_transforms = SumTree::new();
|
||||
let mut cursor = transforms.cursor::<InputRow>();
|
||||
let mut edits = edits.into_iter().peekable();
|
||||
@@ -76,8 +80,9 @@ impl BlockMap {
|
||||
|
||||
if let Some(next_edit) = edits.peek() {
|
||||
if edit.old.end >= next_edit.old.start {
|
||||
let delta = next_edit.new.len() as i32 - next_edit.old.len() as i32;
|
||||
edit.old.end = cmp::max(next_edit.old.end, edit.old.end);
|
||||
edit.new.end += (edit.new.len() as i32 - edit.old.len() as i32) as u32;
|
||||
edit.new.end = (edit.new.end as i32 + delta) as u32;
|
||||
edits.next();
|
||||
} else {
|
||||
break;
|
||||
@@ -98,6 +103,8 @@ impl BlockMap {
|
||||
}
|
||||
}
|
||||
new_transforms.push_tree(cursor.suffix(&()), &());
|
||||
drop(cursor);
|
||||
*transforms = new_transforms;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,3 +147,71 @@ impl<'a> sum_tree::Dimension<'a, TransformSummary> for OutputRow {
|
||||
self.0 += summary.output_rows;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::BlockMap;
|
||||
use crate::display_map::{fold_map::FoldMap, tab_map::TabMap, wrap_map::WrapMap};
|
||||
use buffer::RandomCharIter;
|
||||
use language::Buffer;
|
||||
use rand::prelude::*;
|
||||
use std::env;
|
||||
|
||||
#[gpui::test(iterations = 100)]
|
||||
fn test_random(cx: &mut gpui::MutableAppContext, mut rng: StdRng) {
|
||||
let operations = env::var("OPERATIONS")
|
||||
.map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
|
||||
.unwrap_or(10);
|
||||
|
||||
let wrap_width = Some(rng.gen_range(0.0..=1000.0));
|
||||
let tab_size = 1;
|
||||
let family_id = cx.font_cache().load_family(&["Helvetica"]).unwrap();
|
||||
let font_id = cx
|
||||
.font_cache()
|
||||
.select_font(family_id, &Default::default())
|
||||
.unwrap();
|
||||
let font_size = 14.0;
|
||||
|
||||
log::info!("Tab size: {}", tab_size);
|
||||
log::info!("Wrap width: {:?}", wrap_width);
|
||||
|
||||
let buffer = cx.add_model(|cx| {
|
||||
let len = rng.gen_range(0..10);
|
||||
let text = RandomCharIter::new(&mut rng).take(len).collect::<String>();
|
||||
Buffer::new(0, text, cx)
|
||||
});
|
||||
let (fold_map, folds_snapshot) = FoldMap::new(buffer.clone(), cx);
|
||||
let (tab_map, tabs_snapshot) = TabMap::new(folds_snapshot.clone(), tab_size);
|
||||
let (wrap_map, wraps_snapshot) =
|
||||
WrapMap::new(tabs_snapshot, font_id, font_size, wrap_width, cx);
|
||||
let block_map = BlockMap::new(wraps_snapshot);
|
||||
|
||||
for _ in 0..operations {
|
||||
match rng.gen_range(0..=100) {
|
||||
0..=19 => {
|
||||
let wrap_width = if rng.gen_bool(0.2) {
|
||||
None
|
||||
} else {
|
||||
Some(rng.gen_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));
|
||||
}
|
||||
_ => {
|
||||
buffer.update(cx, |buffer, _| buffer.randomly_edit(&mut rng, 5));
|
||||
}
|
||||
}
|
||||
|
||||
let (folds_snapshot, fold_edits) = fold_map.read(cx);
|
||||
let (tabs_snapshot, tab_edits) = tab_map.sync(folds_snapshot, fold_edits);
|
||||
let (wraps_snapshot, wrap_edits) = wrap_map.update(cx, |wrap_map, cx| {
|
||||
wrap_map.sync(tabs_snapshot, tab_edits, cx)
|
||||
});
|
||||
let blocks_snapshot = block_map.read(wraps_snapshot.clone(), wrap_edits);
|
||||
assert_eq!(
|
||||
blocks_snapshot.transforms.summary().input_rows,
|
||||
wraps_snapshot.max_point().row() + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user