Fix Locator::from_index

Max Brunsfeld and Nathan Sobo created

Enhance language::tests::test_random_collaborators so that it checks buffer invariants.

Co-Authored-By: Nathan Sobo <nathan@zed.dev>

Change summary

crates/language/src/tests.rs |  4 +++
crates/text/src/locator.rs   |  2 
crates/text/src/tests.rs     | 33 ------------------------------
crates/text/src/text.rs      | 41 ++++++++++++++++++++++++++++++++++++++
4 files changed, 46 insertions(+), 34 deletions(-)

Detailed changes

crates/language/src/tests.rs 🔗

@@ -941,6 +941,10 @@ fn test_random_collaboration(cx: &mut MutableAppContext, mut rng: StdRng) {
         now += Duration::from_millis(rng.gen_range(0..=200));
         buffers.extend(new_buffer);
 
+        for buffer in &buffers {
+            buffer.read(cx).check_invariants();
+        }
+
         if mutation_count == 0 && network.is_idle() {
             break;
         }

crates/text/src/locator.rs 🔗

@@ -20,7 +20,7 @@ impl Locator {
     }
 
     pub fn from_index(ix: usize, count: usize) -> Self {
-        let id = ((ix as u128 * u64::MAX as u128) / count as u128) as u64;
+        let id = (1 + ix as u64) * (u64::MAX / (count as u64 + 2));
         Self(smallvec![id])
     }
 

crates/text/src/tests.rs 🔗

@@ -602,36 +602,3 @@ fn test_random_concurrent_edits(mut rng: StdRng) {
         buffer.check_invariants();
     }
 }
-
-impl Buffer {
-    fn check_invariants(&self) {
-        // Ensure every fragment is ordered by locator in the fragment tree and corresponds
-        // to an insertion fragment in the insertions tree.
-        let mut prev_fragment_id = Locator::min();
-        for fragment in self.snapshot.fragments.items(&None) {
-            assert!(fragment.id > prev_fragment_id);
-            prev_fragment_id = fragment.id.clone();
-
-            let insertion_fragment = self
-                .snapshot
-                .insertions
-                .get(
-                    &InsertionFragmentKey {
-                        timestamp: fragment.insertion_timestamp.local(),
-                        split_offset: fragment.insertion_offset,
-                    },
-                    &(),
-                )
-                .unwrap();
-            assert_eq!(insertion_fragment.fragment_id, fragment.id);
-        }
-
-        let mut cursor = self.snapshot.fragments.cursor::<Option<&Locator>>();
-        for insertion_fragment in self.snapshot.insertions.cursor::<()>() {
-            cursor.seek(&Some(&insertion_fragment.fragment_id), Bias::Left, &None);
-            let fragment = cursor.item().unwrap();
-            assert_eq!(insertion_fragment.fragment_id, fragment.id);
-            assert_eq!(insertion_fragment.split_offset, fragment.insertion_offset);
-        }
-    }
-}

crates/text/src/text.rs 🔗

@@ -1244,6 +1244,47 @@ impl Buffer {
 
 #[cfg(any(test, feature = "test-support"))]
 impl Buffer {
+    pub fn check_invariants(&self) {
+        // Ensure every fragment is ordered by locator in the fragment tree and corresponds
+        // to an insertion fragment in the insertions tree.
+        let mut prev_fragment_id = Locator::min();
+        for fragment in self.snapshot.fragments.items(&None) {
+            assert!(fragment.id > prev_fragment_id);
+            prev_fragment_id = fragment.id.clone();
+
+            let insertion_fragment = self
+                .snapshot
+                .insertions
+                .get(
+                    &InsertionFragmentKey {
+                        timestamp: fragment.insertion_timestamp.local(),
+                        split_offset: fragment.insertion_offset,
+                    },
+                    &(),
+                )
+                .unwrap();
+            assert_eq!(insertion_fragment.fragment_id, fragment.id);
+        }
+
+        let mut cursor = self.snapshot.fragments.cursor::<Option<&Locator>>();
+        for insertion_fragment in self.snapshot.insertions.cursor::<()>() {
+            cursor.seek(&Some(&insertion_fragment.fragment_id), Bias::Left, &None);
+            let fragment = cursor.item().unwrap();
+            assert_eq!(insertion_fragment.fragment_id, fragment.id);
+            assert_eq!(insertion_fragment.split_offset, fragment.insertion_offset);
+        }
+
+        let fragment_summary = self.snapshot.fragments.summary();
+        assert_eq!(
+            fragment_summary.text.visible,
+            self.snapshot.visible_text.len()
+        );
+        assert_eq!(
+            fragment_summary.text.deleted,
+            self.snapshot.deleted_text.len()
+        );
+    }
+
     pub fn set_group_interval(&mut self, group_interval: Duration) {
         self.history.group_interval = group_interval;
     }