Add fold mutations to randomized test for `WrapMap`

Antonio Scandurra created

Change summary

zed/src/editor/display_map/fold_map.rs | 81 +++++++++++++++------------
zed/src/editor/display_map/wrap_map.rs | 26 +++++---
2 files changed, 61 insertions(+), 46 deletions(-)

Detailed changes

zed/src/editor/display_map/fold_map.rs 🔗

@@ -1111,9 +1111,10 @@ impl FoldEdit {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::editor::buffer::ToPoint;
-    use crate::test::sample_text;
-    use std::mem;
+    use crate::{editor::ToPoint, test::sample_text, util::RandomCharIter};
+    use rand::prelude::*;
+    use std::{env, mem};
+    use Bias::{Left, Right};
 
     #[gpui::test]
     fn test_basic_folds(cx: &mut gpui::MutableAppContext) {
@@ -1295,12 +1296,6 @@ mod tests {
 
     #[gpui::test]
     fn test_random_folds(cx: &mut gpui::MutableAppContext) {
-        use crate::editor::ToPoint;
-        use crate::util::RandomCharIter;
-        use rand::prelude::*;
-        use std::env;
-        use Bias::{Left, Right};
-
         let iterations = env::var("ITERATIONS")
             .map(|i| i.parse().expect("invalid `ITERATIONS` variable"))
             .unwrap_or(100);
@@ -1331,33 +1326,8 @@ mod tests {
             for _ in 0..operations {
                 log::info!("text: {:?}", buffer.read(cx).text());
                 match rng.gen_range(0..=100) {
-                    0..=34 => {
-                        let buffer = buffer.read(cx);
-                        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);
-                            to_fold.push(start..end);
-                        }
-                        log::info!("folding {:?}", to_fold);
-                        let (mut writer, snapshot, edits) = map.write(cx.as_ref());
-                        snapshot_edits.push((snapshot, edits));
-                        let (snapshot, edits) = writer.fold(to_fold, cx.as_ref());
-                        snapshot_edits.push((snapshot, edits));
-                    }
-                    35..=59 if !map.folds.is_empty() => {
-                        let buffer = buffer.read(cx);
-                        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);
-                            to_unfold.push(start..end);
-                        }
-                        log::info!("unfolding {:?}", to_unfold);
-                        let (mut writer, snapshot, edits) = map.write(cx.as_ref());
-                        snapshot_edits.push((snapshot, edits));
-                        let (snapshot, edits) = writer.fold(to_unfold, cx.as_ref());
-                        snapshot_edits.push((snapshot, edits));
+                    0..=59 => {
+                        snapshot_edits.extend(map.randomly_mutate(&mut rng, cx.as_ref()));
                     }
                     _ => {
                         let edits = buffer.update(cx, |buffer, cx| {
@@ -1585,5 +1555,44 @@ mod tests {
             }
             merged_ranges
         }
+
+        pub fn randomly_mutate(
+            &mut self,
+            rng: &mut impl Rng,
+            cx: &AppContext,
+        ) -> Vec<(Snapshot, Vec<FoldEdit>)> {
+            let mut snapshot_edits = Vec::new();
+            match rng.gen_range(0..=100) {
+                0..=39 if !self.folds.is_empty() => {
+                    let buffer = self.buffer.read(cx);
+                    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);
+                        to_unfold.push(start..end);
+                    }
+                    log::info!("unfolding {:?}", to_unfold);
+                    let (mut writer, snapshot, edits) = self.write(cx.as_ref());
+                    snapshot_edits.push((snapshot, edits));
+                    let (snapshot, edits) = writer.fold(to_unfold, cx.as_ref());
+                    snapshot_edits.push((snapshot, edits));
+                }
+                _ => {
+                    let buffer = self.buffer.read(cx);
+                    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);
+                        to_fold.push(start..end);
+                    }
+                    log::info!("folding {:?}", to_fold);
+                    let (mut writer, snapshot, edits) = self.write(cx.as_ref());
+                    snapshot_edits.push((snapshot, edits));
+                    let (snapshot, edits) = writer.fold(to_fold, cx.as_ref());
+                    snapshot_edits.push((snapshot, edits));
+                }
+            }
+            snapshot_edits
+        }
     }
 }

zed/src/editor/display_map/wrap_map.rs 🔗

@@ -900,7 +900,7 @@ mod tests {
                 let text = RandomCharIter::new(&mut rng).take(len).collect::<String>();
                 Buffer::new(0, text, cx)
             });
-            let (fold_map, folds_snapshot) = cx.read(|cx| FoldMap::new(buffer.clone(), cx));
+            let (mut fold_map, folds_snapshot) = cx.read(|cx| FoldMap::new(buffer.clone(), cx));
             let (tab_map, tabs_snapshot) = TabMap::new(folds_snapshot.clone(), settings.tab_size);
             log::info!(
                 "Unwrapped text (unexpanded tabs): {:?}",
@@ -930,7 +930,6 @@ mod tests {
             );
             log::info!("Wrapped text: {:?}", actual_text);
 
-            let mut interpolated_snapshot = snapshot.clone();
             for _i in 0..operations {
                 match rng.gen_range(0..=100) {
                     0..=19 => {
@@ -942,6 +941,17 @@ mod tests {
                         log::info!("Setting wrap width to {:?}", wrap_width);
                         wrap_map.update(&mut cx, |map, cx| map.set_wrap_width(wrap_width, cx));
                     }
+                    20..=39 => {
+                        for (folds_snapshot, edits) in
+                            cx.read(|cx| fold_map.randomly_mutate(&mut rng, cx))
+                        {
+                            let (tabs_snapshot, edits) = tab_map.sync(folds_snapshot, edits);
+                            let mut snapshot = wrap_map
+                                .update(&mut cx, |map, cx| map.sync(tabs_snapshot, edits, cx));
+                            snapshot.check_invariants();
+                            snapshot.verify_chunks(&mut rng);
+                        }
+                    }
                     _ => {
                         buffer.update(&mut cx, |buffer, cx| buffer.randomly_mutate(&mut rng, cx));
                     }
@@ -954,9 +964,6 @@ mod tests {
                 );
                 let (tabs_snapshot, edits) = tab_map.sync(folds_snapshot, edits);
                 log::info!("Unwrapped text (expanded tabs): {:?}", tabs_snapshot.text());
-                interpolated_snapshot.interpolate(tabs_snapshot.clone(), &edits);
-                interpolated_snapshot.check_invariants();
-                interpolated_snapshot.verify_chunks(&mut rng);
 
                 let unwrapped_text = tabs_snapshot.text();
                 let expected_text = wrap_text(&unwrapped_text, wrap_width, &mut line_wrapper);
@@ -974,18 +981,17 @@ mod tests {
                 }
 
                 if !wrap_map.read_with(&cx, |map, _| map.is_rewrapping()) {
-                    snapshot =
+                    let mut wrapped_snapshot =
                         wrap_map.update(&mut cx, |map, cx| map.sync(tabs_snapshot, Vec::new(), cx));
-                    let actual_text = snapshot.text();
+                    let actual_text = wrapped_snapshot.text();
                     log::info!("Wrapping finished: {:?}", actual_text);
-                    snapshot.check_invariants();
-                    snapshot.verify_chunks(&mut rng);
+                    wrapped_snapshot.check_invariants();
+                    wrapped_snapshot.verify_chunks(&mut rng);
                     assert_eq!(
                         actual_text, expected_text,
                         "unwrapped text is: {:?}",
                         unwrapped_text
                     );
-                    interpolated_snapshot = snapshot.clone();
                 }
             }
         }