Skip to main content

commonware_storage/index/
mod.rs

1//! Memory-efficient index structures for mapping translated keys to values.
2//!
3//! # Multiple Values for a Key
4//!
5//! Keys are translated into a compressed, fixed-size representation using a `Translator`. Depending
6//! on the size of the representation, this can lead to a non-negligible number of collisions (even
7//! if the original keys are collision-free). To workaround this issue, `get` returns all values
8//! that map to the same translated key. If the same key is inserted multiple times (and old values
9//! are not `removed`), all values will be returned.
10//!
11//! # Warning
12//!
13//! If the `Translator` maps many keys to the same translated key, the performance of `Index` will
14//! degrade substantially (each conflicting key may contain the desired value).
15
16use crate::translator::Translator;
17use commonware_runtime::Metrics;
18
19mod storage;
20
21pub mod ordered;
22pub mod partitioned;
23pub mod unordered;
24
25/// A mutable iterator over the values associated with a translated key, allowing in-place
26/// modifications.
27///
28/// The [Cursor] provides a way to traverse and modify the chain of values associated with a
29/// translated key by an index while maintaining its structure. It supports:
30///
31/// - Iteration via `next()` to access values.
32/// - Modification via `update()` to change the current value.
33/// - Insertion via `insert()` to add new values.
34/// - Deletion via `delete()` to remove values.
35///
36/// # Usage
37///
38/// - Must call `next()` before `update()`, `insert()`, or `delete()` to establish a valid position.
39/// - Once `next()` returns `None`, only `insert()` can be called.
40/// - The cursor mutates the chain of values in place. If the sole element is deleted, dropping the
41///   cursor removes the map entry.
42///
43/// _If you don't need advanced functionality, just use `insert()`, `insert_and_retain()`, or
44/// `remove()` from [Unordered] instead._
45pub trait Cursor: Send + Sync {
46    /// The type of values the cursor iterates over.
47    type Value: Send + Sync;
48
49    /// Advances the cursor to the next value in the chain, returning a reference to it.
50    ///
51    /// This method must be called before any other operations (`insert()`, `delete()`, etc.). If
52    /// either `insert()` or `delete()` is called, `next()` must be called to set a new active item.
53    /// If after `insert()`, the next active item is the item after the inserted item. If after
54    /// `delete()`, the next active item is the item after the deleted item.
55    ///
56    /// Advances through cursor states and adjusts for deletions. Returns `None` when the chain is
57    /// exhausted. It is safe to call `next()` even after it returns `None`.
58    #[allow(clippy::should_implement_trait)]
59    fn next(&mut self) -> Option<&Self::Value>;
60
61    /// Inserts a new value at the current position.
62    fn insert(&mut self, value: Self::Value);
63
64    /// Deletes the current value, adjusting the chain structure.
65    fn delete(&mut self);
66
67    /// Updates the value at the current position in the iteration.
68    ///
69    /// Panics if called before `next()` or after iteration is complete.
70    fn update(&mut self, value: Self::Value);
71
72    /// Retains only the values in the cursor for which `should_retain` returns `true`. All other
73    /// values are removed.
74    fn retain(&mut self, should_retain: &impl Fn(&Self::Value) -> bool) {
75        while let Some(old) = self.next() {
76            if !should_retain(old) {
77                self.delete();
78            }
79        }
80    }
81
82    /// Advances the cursor until finding a value matching the predicate.
83    ///
84    /// Returns `true` if a matching value is found, with the cursor positioned at that element.
85    /// Returns `false` if no match is found and the cursor is exhausted.
86    ///
87    /// After a successful find (returning `true`), the cursor is positioned at the found element,
88    /// allowing operations like `update()` or `delete()` to be called on it without requiring
89    /// another call to `next()`.
90    ///
91    /// This method follows similar semantics to `Iterator::find`, consuming items until a match is
92    /// found or the iterator is exhausted.
93    ///
94    /// # Examples
95    ///
96    /// ```ignore
97    /// let mut cursor = index.get_mut(&key)?;
98    /// if cursor.find(|&value| value == 42) {
99    ///     // Cursor is positioned at the element with value 42
100    ///     cursor.update(100); // Update it to 100
101    /// }
102    /// ```
103    fn find(&mut self, predicate: impl Fn(&Self::Value) -> bool) -> bool {
104        loop {
105            match self.next() {
106                Some(value) if predicate(value) => return true,
107                Some(_) => continue,
108                None => return false,
109            }
110        }
111    }
112}
113
114/// A trait defining the operations provided by a memory-efficient index that maps translated keys
115/// to arbitrary values, with no ordering assumed over the key space.
116pub trait Unordered: Send + Sync {
117    /// The type of values the index stores.
118    type Value: Send + Sync;
119
120    /// The type of cursor returned by this index to iterate over values with conflicting keys.
121    type Cursor<'a>: Cursor<Value = Self::Value>
122    where
123        Self: 'a;
124
125    /// Returns an iterator over all values associated with a translated key.
126    ///
127    /// The iteration order is implementation-defined.
128    fn get<'a>(&'a self, key: &[u8]) -> impl Iterator<Item = &'a Self::Value> + Send + 'a
129    where
130        Self::Value: 'a;
131
132    /// Visits every value associated with each key, calling `visit(key_idx, value)`.
133    ///
134    /// Probe order is implementation-defined: implementations may reorder probes for locality,
135    /// so visits are identified by `key_idx` rather than issued in input order.
136    fn get_many<'a, K: AsRef<[u8]>>(
137        &'a self,
138        keys: &[K],
139        mut visit: impl FnMut(usize, &'a Self::Value),
140    ) where
141        Self::Value: 'a,
142    {
143        for (key_idx, key) in keys.iter().enumerate() {
144            for value in self.get(key.as_ref()) {
145                visit(key_idx, value);
146            }
147        }
148    }
149
150    /// Provides mutable access to the values associated with a translated key, if the key exists.
151    fn get_mut<'a>(&'a mut self, key: &[u8]) -> Option<Self::Cursor<'a>>;
152
153    /// Provides mutable access to the values associated with a translated key (if the key exists),
154    /// otherwise inserts a new value and returns `None`.
155    fn get_mut_or_insert<'a>(
156        &'a mut self,
157        key: &[u8],
158        value: Self::Value,
159    ) -> Option<Self::Cursor<'a>>;
160
161    /// Inserts a new value for the translated key.
162    fn insert(&mut self, key: &[u8], value: Self::Value);
163
164    /// Insert a value at the given translated key, and remove any values for which
165    /// `should_retain` returns `false`.
166    ///
167    /// If `should_retain` returns `false` for the new value, it will not be inserted.
168    fn insert_and_retain(
169        &mut self,
170        key: &[u8],
171        value: Self::Value,
172        should_retain: impl Fn(&Self::Value) -> bool,
173    );
174
175    /// Retain only the values associated with a translated key for which `should_retain` returns
176    /// `true`. All other values are removed.
177    fn retain(&mut self, key: &[u8], should_retain: impl Fn(&Self::Value) -> bool) {
178        if let Some(mut cursor) = self.get_mut(key) {
179            cursor.retain(&should_retain);
180        }
181    }
182
183    /// Remove all values associated with a translated key.
184    fn remove(&mut self, key: &[u8]);
185
186    /// Returns the number of translated keys in the index.
187    #[cfg(test)]
188    fn keys(&self) -> usize;
189
190    /// Returns the number of items in the index, for use in testing. The number of items is always
191    /// at least as large as the number of keys, but may be larger in the case of collisions.
192    #[cfg(test)]
193    fn items(&self) -> usize;
194
195    /// Returns the total number of items pruned from the index, for use in testing.
196    #[cfg(test)]
197    fn pruned(&self) -> usize;
198}
199
200/// A trait for index types that can be constructed from a metrics context and translator.
201pub trait Factory<T: Translator>: Unordered + Sized {
202    /// Create a new index with the given metrics context and translator.
203    fn new(ctx: impl Metrics, translator: T) -> Self;
204}
205
206/// A trait defining the additional operations provided by a memory-efficient index that allows
207/// ordered traversal of the indexed keys.
208pub trait Ordered: Unordered + Send + Sync {
209    // Returns an iterator over all values associated with a translated key that lexicographically
210    // precedes the result of translating `key`. The implementation will cycle around to the last
211    // translated key if `key` is less than or equal to the first translated key. The returned
212    // boolean indicates whether the result is from cycling. Returns None if there are no keys in
213    // the index.
214    fn prev_translated_key<'a>(
215        &'a self,
216        key: &[u8],
217    ) -> Option<(impl Iterator<Item = &'a Self::Value> + Send + 'a, bool)>
218    where
219        Self::Value: 'a;
220
221    // Returns an iterator over all values associated with a translated key that lexicographically
222    // follows the result of translating `key`. The implementation will cycle around to the first
223    // translated key if `key` is greater than or equal to the last translated key. The returned
224    // boolean indicates whether the result is from cycling. Returns None if there are no keys in
225    // the index.
226    ///
227    /// For example, if the translator is looking only at the first byte of a key, and the index
228    /// contains values for translated keys 0b, 1c, and 2d, then `get_next([0b, 01, 02, ...])` would
229    /// return the values associated with 1c, `get_next([2a, 01, 02, ...])` would return the values
230    /// associated with 2d, and `get_next([2d])` would "cycle around" to the values associated with
231    /// 0b, returning true for the bool. Because values associated with the same translated key can
232    /// appear in any order, keys with the same first byte in this example would need to be ordered
233    /// by the caller if a full ordering over the untranslated keyspace is desired.
234    fn next_translated_key<'a>(
235        &'a self,
236        key: &[u8],
237    ) -> Option<(impl Iterator<Item = &'a Self::Value> + Send + 'a, bool)>
238    where
239        Self::Value: 'a;
240
241    // Returns an iterator over all values associated with the lexicographically first translated
242    // key, or None if there are no keys in the index.
243    fn first_translated_key<'a>(
244        &'a self,
245    ) -> Option<impl Iterator<Item = &'a Self::Value> + Send + 'a>
246    where
247        Self::Value: 'a;
248
249    // Returns an iterator over all values associated with the lexicographically last translated
250    // key, or None if there are no keys in the index.
251    fn last_translated_key<'a>(
252        &'a self,
253    ) -> Option<impl Iterator<Item = &'a Self::Value> + Send + 'a>
254    where
255        Self::Value: 'a;
256}
257
258#[cfg(test)]
259mod tests {
260    use super::*;
261    use crate::{
262        index::partitioned::{
263            ordered::Index as PartitionedOrdered, unordered::Index as PartitionedUnordered,
264        },
265        translator::{EightCap, OneCap, TwoCap},
266    };
267    use commonware_macros::test_traced;
268    use commonware_runtime::{deterministic, Runner, Supervisor as _};
269    use commonware_utils::sync::Mutex;
270    use rand::RngExt as _;
271    use std::{
272        collections::{HashMap, HashSet},
273        sync::Arc,
274        thread,
275    };
276
277    fn values<I: Unordered<Value = u64>>(index: &I, key: &[u8]) -> Vec<u64> {
278        index.get(key).copied().collect()
279    }
280
281    fn assert_values<I: Unordered<Value = u64>>(index: &I, key: &[u8], expected: &[u64]) {
282        let mut actual = values(index, key);
283        actual.sort_unstable();
284        let mut expected = expected.to_vec();
285        expected.sort_unstable();
286        assert_eq!(actual, expected);
287    }
288
289    fn run_index_basic<I: Unordered<Value = u64>>(index: &mut I) {
290        // Generate a collision and check metrics to make sure it's captured
291        let key = b"duplicate".as_slice();
292        index.insert(key, 1);
293        index.insert(key, 2);
294        index.insert(key, 3);
295        assert_eq!(index.keys(), 1);
296
297        assert_values(index, key, &[1, 2, 3]);
298
299        // Ensure cursor terminates
300        {
301            let mut cursor = index.get_mut(key).unwrap();
302            let mut seen = Vec::new();
303            while let Some(value) = cursor.next() {
304                seen.push(*value);
305            }
306            seen.sort_unstable();
307            assert_eq!(seen, vec![1, 2, 3]);
308            assert!(cursor.next().is_none());
309        }
310
311        // Make sure we can remove keys with a predicate
312        index.insert(key, 3);
313        index.insert(key, 4);
314        index.retain(key, |i| *i != 3);
315        assert_values(index, key, &[1, 2, 4]);
316        index.retain(key, |_| false);
317        // Try removing all of a keys values.
318        assert_eq!(
319            index.get(key).copied().collect::<Vec<_>>(),
320            Vec::<u64>::new()
321        );
322        assert_eq!(index.keys(), 0);
323
324        assert!(index.get_mut(key).is_none());
325
326        // Removing a key that doesn't exist should be a no-op.
327        index.retain(key, |_| false);
328    }
329
330    fn new_unordered(context: deterministic::Context) -> unordered::Index<TwoCap, u64> {
331        unordered::Index::new(context, TwoCap)
332    }
333
334    fn new_ordered(context: deterministic::Context) -> ordered::Index<TwoCap, u64> {
335        ordered::Index::new(context, TwoCap)
336    }
337
338    fn new_partitioned_unordered(
339        context: deterministic::Context,
340    ) -> PartitionedUnordered<OneCap, u64, 1> {
341        // A one byte prefix and a OneCap translator yields behavior that matches TwoCap translator
342        // on an un-partitioned index.
343        PartitionedUnordered::new(context, OneCap)
344    }
345
346    fn new_partitioned_ordered(
347        context: deterministic::Context,
348    ) -> PartitionedOrdered<OneCap, u64, 1> {
349        // Same translator choice as the unordered variant to keep collision behavior consistent.
350        PartitionedOrdered::new(context, OneCap)
351    }
352
353    /// A partitioned ordered index with a tiny spill threshold, so partitions convert to the
354    /// spilled `BTreeMap` representation almost immediately. Routing the generic battery through
355    /// this fixture re-validates every behavior against the spilled cursor / nav / value paths.
356    fn new_partitioned_ordered_spilling(
357        context: deterministic::Context,
358    ) -> PartitionedOrdered<OneCap, u64, 1> {
359        PartitionedOrdered::with_threshold(context, OneCap, 2)
360    }
361
362    /// Run the generic index battery against the spilling fixture, so the spilled-partition
363    /// representation is exercised by the same assertions as the inline (SoA) representation.
364    #[test_traced]
365    fn test_partitioned_ordered_spilling() {
366        let runner = deterministic::Runner::default();
367        runner.start(|mut context| async move {
368            macro_rules! spilled {
369                ($($h:ident),+ $(,)?) => {$(
370                    $h(&mut new_partitioned_ordered_spilling(
371                        context.child(concat!("spill_", stringify!($h))),
372                    ));
373                )+};
374            }
375            spilled!(
376                run_index_basic,
377                run_index_get_many,
378                run_index_cursor_find,
379                run_index_key_lengths_and_metrics,
380                run_index_values,
381                run_index_remove_specific,
382                run_index_empty_key,
383                run_index_mutate_through_iterator,
384                run_index_mutate_middle_of_four,
385                run_index_remove_through_iterator,
386                run_index_insert_through_iterator,
387                run_index_cursor_insert_after_done_appends,
388                run_index_remove_to_nothing_then_add,
389                run_index_insert_and_remove_cursor,
390                run_index_insert_and_retain_vacant,
391                run_index_insert_and_retain_vacant_not_retained,
392                run_index_insert_and_retain_replace_one,
393                run_index_insert_and_retain_dead_insert,
394                run_index_insert_and_retain_single_value,
395                run_index_remove_middle_then_next,
396                run_index_remove_to_nothing,
397                run_index_cursor_insert_with_next,
398                run_index_cursor_delete_last_then_next,
399                run_index_delete_in_middle_then_continue,
400                run_index_delete_first,
401                run_index_delete_first_and_insert,
402                run_index_insert_at_entry_then_next,
403                run_index_delete_last_then_insert_while_done,
404                run_index_drop_mid_iteration_preserves_chain,
405                run_index_entry_replacement_not_a_collision,
406                run_index_large_collision_chain,
407            );
408
409            let mut index = new_partitioned_ordered_spilling(context.child("spill_many_keys"));
410            run_index_many_keys(&mut index, |bytes| context.fill(bytes));
411
412            // Make sure that the final test in this suite actually exercises spilling.
413            assert!(
414                index.spilled_count() > 0,
415                "routing battery should exercise the spilled representation"
416            );
417        });
418    }
419
420    /// Verify ordered navigation returns keys in lexicographic order even when some keys are
421    /// shorter than the partition prefix (the case the partitioned router must place correctly).
422    /// Each key is inserted with its lexicographic rank as its value, and the keys have distinct
423    /// translated keys under `EightCap`, so a correct ordering yields the ranks in order with no
424    /// collision ambiguity. Run against both the flat and partitioned ordered indices below, which
425    /// must agree.
426    fn run_ordered_short_keys<I: Ordered<Value = u64>>(index: &mut I) {
427        // Lexicographically increasing keys; `[0x01]` and `[0x03]` are shorter than the 2-byte
428        // prefix and must still sort between their 2-byte neighbors.
429        let keys: [&[u8]; 5] = [
430            &[0x00, 0x05],
431            &[0x01],
432            &[0x02, 0x09, 0xAB],
433            &[0x03],
434            &[0xFF, 0xFF],
435        ];
436        for (rank, &key) in keys.iter().enumerate() {
437            index.insert(key, rank as u64);
438        }
439
440        let first: Vec<u64> = index.first_translated_key().unwrap().copied().collect();
441        let last: Vec<u64> = index.last_translated_key().unwrap().copied().collect();
442        assert_eq!(first, vec![0], "first key");
443        assert_eq!(last, vec![4], "last key");
444
445        let n = keys.len() as u64;
446        for (i, &key) in keys.iter().enumerate() {
447            let i = i as u64;
448            let (it, next_cycled) = index.next_translated_key(key).unwrap();
449            let next: Vec<u64> = it.copied().collect();
450            let (it, prev_cycled) = index.prev_translated_key(key).unwrap();
451            let prev: Vec<u64> = it.copied().collect();
452            if i + 1 < n {
453                assert_eq!(
454                    (next, next_cycled),
455                    (vec![i + 1], false),
456                    "next of rank {i}"
457                );
458            } else {
459                assert_eq!((next, next_cycled), (vec![0], true), "next wraps past last");
460            }
461            if i > 0 {
462                assert_eq!(
463                    (prev, prev_cycled),
464                    (vec![i - 1], false),
465                    "prev of rank {i}"
466                );
467            } else {
468                assert_eq!(
469                    (prev, prev_cycled),
470                    (vec![n - 1], true),
471                    "prev wraps before first"
472                );
473            }
474        }
475    }
476
477    #[test_traced]
478    fn test_ordered_short_keys_flat() {
479        let runner = deterministic::Runner::default();
480        runner.start(|context| async move {
481            let mut index = ordered::Index::<EightCap, u64>::new(context, EightCap);
482            run_ordered_short_keys(&mut index);
483        });
484    }
485
486    #[test_traced]
487    fn test_ordered_short_keys_partitioned() {
488        let runner = deterministic::Runner::default();
489        runner.start(|context| async move {
490            // P=2 with EightCap on the 6-byte remainder orders by the same (<=8-byte) full key as
491            // the flat EightCap index above, so both must produce identical navigation results.
492            let mut index = PartitionedOrdered::<EightCap, u64, 2>::new(context, EightCap);
493            run_ordered_short_keys(&mut index);
494        });
495    }
496
497    #[test_traced]
498    fn test_hash_index_basic() {
499        let runner = deterministic::Runner::default();
500        runner.start(|context| async move {
501            let mut index = new_unordered(context);
502            assert_eq!(index.keys(), 0);
503            run_index_basic(&mut index);
504            assert_eq!(index.keys(), 0);
505        });
506    }
507
508    #[test_traced]
509    fn test_ordered_index_basic() {
510        let runner = deterministic::Runner::default();
511        runner.start(|context| async move {
512            let mut index = new_ordered(context);
513            assert_eq!(index.keys(), 0);
514            run_index_basic(&mut index);
515            assert_eq!(index.keys(), 0);
516        });
517    }
518
519    #[test_traced]
520    fn test_partitioned_index_basic() {
521        let runner = deterministic::Runner::default();
522        runner.start(|context| async move {
523            {
524                let mut index = new_partitioned_unordered(context.child("unordered"));
525                assert_eq!(index.keys(), 0);
526                run_index_basic(&mut index);
527                assert_eq!(index.keys(), 0);
528            }
529            {
530                let mut index = new_partitioned_ordered(context.child("ordered"));
531                assert_eq!(index.keys(), 0);
532                run_index_basic(&mut index);
533                assert_eq!(index.keys(), 0);
534            }
535        });
536    }
537
538    fn run_index_get_many<I: Unordered<Value = u64>>(index: &mut I) {
539        // "ab" and "abX" share a translated bucket; "zz" lives in a different bucket (and a
540        // different partition for partitioned indexes).
541        index.insert(b"ab", 1);
542        index.insert(b"ab", 2);
543        index.insert(b"abX", 3);
544        index.insert(b"zz", 4);
545
546        // Visits must be attributed to the requesting slot regardless of probe order, missing
547        // keys produce no visits, and duplicate input keys are visited once per slot.
548        let keys: Vec<&[u8]> = vec![b"zz", b"missing", b"ab", b"zz"];
549        let mut visits: Vec<Vec<u64>> = vec![Vec::new(); keys.len()];
550        index.get_many(&keys, |key_idx, value| visits[key_idx].push(*value));
551        visits[2].sort_unstable();
552        assert_eq!(visits[0], vec![4]);
553        assert!(visits[1].is_empty());
554        assert_eq!(visits[2], vec![1, 2, 3]);
555        assert_eq!(visits[3], vec![4]);
556
557        // Empty input visits nothing.
558        index.get_many::<&[u8]>(&[], |_, _| panic!("no visits expected"));
559    }
560
561    #[test_traced]
562    fn test_hash_index_get_many() {
563        let runner = deterministic::Runner::default();
564        runner.start(|context| async move {
565            let mut index = new_unordered(context);
566            run_index_get_many(&mut index);
567        });
568    }
569
570    #[test_traced]
571    fn test_ordered_index_get_many() {
572        let runner = deterministic::Runner::default();
573        runner.start(|context| async move {
574            let mut index = new_ordered(context);
575            run_index_get_many(&mut index);
576        });
577    }
578
579    #[test_traced]
580    fn test_partitioned_index_get_many() {
581        let runner = deterministic::Runner::default();
582        runner.start(|context| async move {
583            {
584                let mut index = new_partitioned_unordered(context.child("unordered"));
585                run_index_get_many(&mut index);
586            }
587            {
588                let mut index = new_partitioned_ordered(context.child("ordered"));
589                run_index_get_many(&mut index);
590            }
591        });
592    }
593
594    fn run_index_cursor_find<I: Unordered<Value = u64>>(index: &mut I) {
595        let key = b"test_key";
596
597        // Insert multiple values with collisions
598        index.insert(key, 10);
599        index.insert(key, 20);
600        index.insert(key, 30);
601        index.insert(key, 40);
602
603        // Test finding an element that exists
604        {
605            let mut cursor = index.get_mut(key).unwrap();
606            assert!(cursor.find(|&v| v == 30));
607            // Cursor should be positioned at 30, so we can update it
608            cursor.update(35);
609        }
610
611        // Verify the update worked
612        let values: Vec<u64> = index.get(key).copied().collect();
613        assert!(values.contains(&35));
614        assert!(!values.contains(&30));
615
616        // Test finding an element that doesn't exist
617        {
618            let mut cursor = index.get_mut(key).unwrap();
619            assert!(!cursor.find(|&v| v == 100));
620            // Cursor should be exhausted, so next() returns None
621            assert!(cursor.next().is_none());
622        }
623
624        // Test finding and deleting
625        {
626            let mut cursor = index.get_mut(key).unwrap();
627            assert!(cursor.find(|&v| v == 20));
628            cursor.delete();
629        }
630
631        // Verify the delete worked
632        let values: Vec<u64> = index.get(key).copied().collect();
633        assert!(!values.contains(&20));
634        assert_eq!(values.len(), 3); // 10, 35, 40
635    }
636
637    #[test_traced]
638    fn test_unordered_index_cursor_find() {
639        let runner = deterministic::Runner::default();
640        runner.start(|context| async move {
641            let mut index = new_unordered(context);
642            run_index_cursor_find(&mut index);
643        });
644    }
645
646    #[test_traced]
647    fn test_ordered_index_cursor_find() {
648        let runner = deterministic::Runner::default();
649        runner.start(|context| async move {
650            let mut index = new_ordered(context);
651            run_index_cursor_find(&mut index);
652        });
653    }
654
655    #[test_traced]
656    fn test_partitioned_index_cursor_find() {
657        let runner = deterministic::Runner::default();
658        runner.start(|context| async move {
659            {
660                let mut index = new_partitioned_unordered(context.child("unordered"));
661                run_index_cursor_find(&mut index);
662            }
663            {
664                let mut index = new_partitioned_ordered(context.child("ordered"));
665                run_index_cursor_find(&mut index);
666            }
667        });
668    }
669
670    fn run_index_many_keys<I: Unordered<Value = u64>>(
671        index: &mut I,
672        mut fill: impl FnMut(&mut [u8]),
673    ) {
674        let mut expected = HashMap::new();
675        let mut translated = HashSet::new();
676        cfg_if::cfg_if! {
677            if #[cfg(miri)] {
678                // Miri is very slow on the atomic-heavy metrics used by partitioned indices, so
679                // keep collision coverage but reduce the generated key count.
680                const NUM_KEYS: usize = 200;
681            } else {
682                const NUM_KEYS: usize = 2000;
683            }
684        }
685        while expected.len() < NUM_KEYS {
686            let mut key_array = [0u8; 32];
687            fill(&mut key_array);
688            translated.insert([key_array[0], key_array[1]]);
689            let key = key_array.to_vec();
690
691            let loc = expected.len() as u64;
692            index.insert(&key, loc);
693            expected.insert(key, loc);
694        }
695        assert_eq!(index.keys(), translated.len());
696        assert_eq!(index.items(), NUM_KEYS);
697
698        for (key, loc) in expected.iter() {
699            let mut values = index.get(key);
700            let res = values.find(|i| *i == loc);
701            assert!(res.is_some());
702        }
703    }
704
705    #[test_traced]
706    fn test_hash_index_many_keys() {
707        let runner = deterministic::Runner::default();
708        runner.start(|mut context| async move {
709            let mut index = new_unordered(context.child("storage"));
710            run_index_many_keys(&mut index, |bytes| context.fill(bytes));
711        });
712    }
713
714    #[test_traced]
715    fn test_ordered_index_many_keys() {
716        let runner = deterministic::Runner::default();
717        runner.start(|mut context| async move {
718            let mut index = new_ordered(context.child("storage"));
719            run_index_many_keys(&mut index, |bytes| context.fill(bytes));
720        });
721    }
722
723    #[test_traced]
724    fn test_partitioned_index_many_keys() {
725        let runner = deterministic::Runner::default();
726        runner.start(|mut context| async move {
727            {
728                let mut index = new_partitioned_unordered(context.child("unordered"));
729                run_index_many_keys(&mut index, |bytes| context.fill(bytes));
730            }
731        });
732
733        // Since we use context's random byte generator we need to run the two variants from the
734        // same initial context state to ensure the expected identical outcome.
735        let runner = deterministic::Runner::default();
736        runner.start(|mut context| async move {
737            let mut index = new_partitioned_ordered(context.child("storage"));
738            run_index_many_keys(&mut index, |bytes| context.fill(bytes));
739        });
740    }
741
742    fn run_index_key_lengths_and_metrics<I: Unordered<Value = u64>>(index: &mut I) {
743        index.insert(b"a", 1);
744        index.insert(b"ab", 2);
745        index.insert(b"abc", 3);
746
747        assert_values(index, b"ab", &[2, 3]);
748        assert_values(index, b"abc", &[2, 3]);
749
750        index.insert(b"ab", 4);
751        assert_values(index, b"ab", &[2, 3, 4]);
752        assert_eq!(index.keys(), 2);
753        assert_eq!(index.items(), 4);
754
755        index.retain(b"ab", |v| *v != 4);
756        assert_values(index, b"ab", &[2, 3]);
757        assert_eq!(index.keys(), 2);
758        assert_eq!(index.items(), 3);
759
760        index.retain(b"ab", |_| false);
761        assert_eq!(
762            index.get(b"ab").copied().collect::<Vec<_>>(),
763            Vec::<u64>::new()
764        );
765        assert_eq!(index.keys(), 1);
766        assert_eq!(index.items(), 1);
767        assert_values(index, b"a", &[1]);
768    }
769
770    #[test_traced]
771    fn test_hash_index_key_lengths_and_key_item_metrics() {
772        let runner = deterministic::Runner::default();
773        runner.start(|context| async move {
774            let mut index = new_unordered(context);
775            run_index_key_lengths_and_metrics(&mut index);
776        });
777    }
778
779    #[test_traced]
780    fn test_ordered_index_key_lengths_and_key_item_metrics() {
781        let runner = deterministic::Runner::default();
782        runner.start(|context| async move {
783            let mut index = new_ordered(context);
784            run_index_key_lengths_and_metrics(&mut index);
785        });
786    }
787
788    #[test_traced]
789    fn test_partitioned_index_key_lengths_and_key_item_metrics() {
790        let runner = deterministic::Runner::default();
791        runner.start(|context| async move {
792            {
793                let mut index = new_partitioned_unordered(context.child("unordered"));
794                run_index_key_lengths_and_metrics(&mut index);
795            }
796            {
797                let mut index = new_partitioned_ordered(context.child("ordered"));
798                run_index_key_lengths_and_metrics(&mut index);
799            }
800        });
801    }
802
803    fn run_index_values<I: Unordered<Value = u64>>(index: &mut I) {
804        index.insert(b"key", 1);
805        index.insert(b"key", 2);
806        index.insert(b"key", 3);
807        assert_values(index, b"key", &[1, 2, 3]);
808    }
809
810    #[test_traced]
811    fn test_hash_index_values() {
812        let runner = deterministic::Runner::default();
813        runner.start(|context| async move {
814            let mut index = new_unordered(context);
815            run_index_values(&mut index);
816        });
817    }
818
819    #[test_traced]
820    fn test_ordered_index_values() {
821        let runner = deterministic::Runner::default();
822        runner.start(|context| async move {
823            let mut index = new_ordered(context);
824            run_index_values(&mut index);
825        });
826    }
827
828    #[test_traced]
829    fn test_partitioned_index_values() {
830        let runner = deterministic::Runner::default();
831        runner.start(|context| async move {
832            {
833                let mut index = new_partitioned_unordered(context.child("unordered"));
834                run_index_values(&mut index);
835            }
836            {
837                let mut index = new_partitioned_ordered(context.child("ordered"));
838                run_index_values(&mut index);
839            }
840        });
841    }
842
843    fn run_index_remove_specific<I: Unordered<Value = u64>>(index: &mut I) {
844        index.insert(b"key", 1);
845        index.insert(b"key", 2);
846        index.insert(b"key", 3);
847        index.retain(b"key", |v| *v != 2);
848        assert_values(index, b"key", &[1, 3]);
849        index.retain(b"key", |v| *v != 1);
850        assert_values(index, b"key", &[3]);
851    }
852
853    #[test_traced]
854    fn test_hash_index_remove_specific() {
855        let runner = deterministic::Runner::default();
856        runner.start(|context| async move {
857            let mut index = new_unordered(context);
858            run_index_remove_specific(&mut index);
859        });
860    }
861
862    #[test_traced]
863    fn test_ordered_index_remove_specific() {
864        let runner = deterministic::Runner::default();
865        runner.start(|context| async move {
866            let mut index = new_ordered(context);
867            run_index_remove_specific(&mut index);
868        });
869    }
870
871    #[test_traced]
872    fn test_partitioned_index_remove_specific() {
873        let runner = deterministic::Runner::default();
874        runner.start(|context| async move {
875            {
876                let mut index = new_partitioned_unordered(context.child("unordered"));
877                run_index_remove_specific(&mut index);
878            }
879            {
880                let mut index = new_partitioned_ordered(context.child("ordered"));
881                run_index_remove_specific(&mut index);
882            }
883        });
884    }
885
886    fn run_index_empty_key<I: Unordered<Value = u64>>(index: &mut I) {
887        index.insert(b"", 0);
888        index.insert(b"\0", 1);
889        index.insert(b"\0\0", 2);
890
891        let mut values = index.get(b"").copied().collect::<Vec<_>>();
892        values.sort();
893        assert_eq!(values, vec![0, 1, 2]);
894        let mut values = index.get(b"\0").copied().collect::<Vec<_>>();
895        values.sort();
896        assert_eq!(values, vec![0, 1, 2]);
897        let mut values = index.get(b"\0\0").copied().collect::<Vec<_>>();
898        values.sort();
899        assert_eq!(values, vec![0, 1, 2]);
900
901        index.retain(b"", |v| *v != 1);
902        let mut values = index.get(b"").copied().collect::<Vec<_>>();
903        values.sort();
904        assert_eq!(values, vec![0, 2]);
905    }
906
907    #[test_traced]
908    fn test_hash_index_empty_key() {
909        let runner = deterministic::Runner::default();
910        runner.start(|context| async move {
911            let mut index = new_unordered(context);
912            run_index_empty_key(&mut index);
913        });
914    }
915
916    #[test_traced]
917    fn test_ordered_index_empty_key() {
918        let runner = deterministic::Runner::default();
919        runner.start(|context| async move {
920            let mut index = new_ordered(context);
921            run_index_empty_key(&mut index);
922        });
923    }
924
925    #[test_traced]
926    fn test_partitioned_index_empty_key() {
927        let runner = deterministic::Runner::default();
928        runner.start(|context| async move {
929            {
930                let mut index = new_partitioned_unordered(context.child("unordered"));
931                run_index_empty_key(&mut index);
932            }
933            {
934                let mut index = new_partitioned_ordered(context.child("ordered"));
935                run_index_empty_key(&mut index);
936            }
937        });
938    }
939
940    fn run_index_mutate_through_iterator<I: Unordered<Value = u64>>(index: &mut I) {
941        index.insert(b"key", 1);
942        index.insert(b"key", 2);
943        index.insert(b"key", 3);
944        {
945            let mut cursor = index.get_mut(b"key").unwrap();
946            while let Some(old) = cursor.next().copied() {
947                cursor.update(old + 10);
948            }
949        }
950        assert_values(index, b"key", &[11, 12, 13]);
951    }
952
953    #[test_traced]
954    fn test_hash_index_mutate_through_iterator() {
955        let runner = deterministic::Runner::default();
956        runner.start(|context| async move {
957            let mut index = new_unordered(context);
958            run_index_mutate_through_iterator(&mut index);
959        });
960    }
961
962    #[test_traced]
963    fn test_ordered_index_mutate_through_index() {
964        let runner = deterministic::Runner::default();
965        runner.start(|context| async move {
966            let mut index = new_ordered(context);
967            run_index_mutate_through_iterator(&mut index);
968        });
969    }
970
971    #[test_traced]
972    fn test_partitioned_index_mutate_through_iterator() {
973        let runner = deterministic::Runner::default();
974        runner.start(|context| async move {
975            {
976                let mut index = new_partitioned_unordered(context.child("unordered"));
977                run_index_mutate_through_iterator(&mut index);
978            }
979            {
980                let mut index = new_partitioned_ordered(context.child("ordered"));
981                run_index_mutate_through_iterator(&mut index);
982            }
983        });
984    }
985
986    fn run_index_mutate_middle_of_four<I: Unordered<Value = u64>>(index: &mut I) {
987        index.insert(b"key", 1);
988        index.insert(b"key", 2);
989        index.insert(b"key", 3);
990        index.insert(b"key", 4);
991        let mut expected = values(index, b"key");
992        {
993            let mut cursor = index.get_mut(b"key").unwrap();
994            assert_eq!(*cursor.next().unwrap(), expected[0]);
995            assert_eq!(*cursor.next().unwrap(), expected[1]);
996            let _ = cursor.next().unwrap();
997            cursor.update(99);
998        }
999        expected[2] = 99;
1000        assert_eq!(values(index, b"key"), expected);
1001    }
1002
1003    #[test_traced]
1004    fn test_hash_index_mutate_middle_of_four() {
1005        let runner = deterministic::Runner::default();
1006        runner.start(|context| async move {
1007            let mut index = new_unordered(context);
1008            run_index_mutate_middle_of_four(&mut index);
1009        });
1010    }
1011
1012    #[test_traced]
1013    fn test_ordered_index_mutate_middle_of_four() {
1014        let runner = deterministic::Runner::default();
1015        runner.start(|context| async move {
1016            let mut index = new_ordered(context);
1017            run_index_mutate_middle_of_four(&mut index);
1018        });
1019    }
1020
1021    #[test_traced]
1022    fn test_partitioned_index_mutate_middle_of_four() {
1023        let runner = deterministic::Runner::default();
1024        runner.start(|context| async move {
1025            {
1026                let mut index = new_partitioned_unordered(context.child("unordered"));
1027                run_index_mutate_middle_of_four(&mut index);
1028            }
1029            {
1030                let mut index = new_partitioned_ordered(context.child("ordered"));
1031                run_index_mutate_middle_of_four(&mut index);
1032            }
1033        });
1034    }
1035
1036    fn run_index_remove_through_iterator<I: Unordered<Value = u64>>(index: &mut I) {
1037        index.insert(b"key", 10);
1038        index.insert(b"key", 20);
1039        index.insert(b"key", 30);
1040        index.insert(b"key", 40);
1041        let mut expected = values(index, b"key");
1042        assert_values(index, b"key", &[10, 20, 30, 40]);
1043        assert_eq!(index.pruned(), 0);
1044        {
1045            let mut cursor = index.get_mut(b"key").unwrap();
1046            assert_eq!(*cursor.next().unwrap(), expected[0]);
1047            cursor.delete();
1048        }
1049        expected.remove(0);
1050        assert_eq!(index.pruned(), 1);
1051        assert_eq!(values(index, b"key"), expected);
1052        index.insert(b"key", 50);
1053        expected.push(50);
1054        assert_values(index, b"key", &expected);
1055        expected = values(index, b"key");
1056        {
1057            let mut cursor = index.get_mut(b"key").unwrap();
1058            assert_eq!(*cursor.next().unwrap(), expected[0]);
1059            assert_eq!(*cursor.next().unwrap(), expected[1]);
1060            assert_eq!(*cursor.next().unwrap(), expected[2]);
1061            cursor.delete();
1062        }
1063        expected.remove(2);
1064        assert_eq!(index.pruned(), 2);
1065        assert_eq!(values(index, b"key"), expected);
1066        index.insert(b"key", 60);
1067        expected.push(60);
1068        assert_values(index, b"key", &expected);
1069        expected = values(index, b"key");
1070        {
1071            let mut cursor = index.get_mut(b"key").unwrap();
1072            for value in &expected {
1073                assert_eq!(*cursor.next().unwrap(), *value);
1074            }
1075            cursor.delete();
1076        }
1077        expected.pop();
1078        assert_eq!(index.pruned(), 3);
1079        assert_eq!(values(index, b"key"), expected);
1080        index.remove(b"key");
1081        assert_eq!(index.keys(), 0);
1082        assert_eq!(index.items(), 0);
1083        assert_eq!(index.pruned(), 6);
1084    }
1085
1086    #[test_traced]
1087    fn test_hash_index_remove_through_iterator() {
1088        let runner = deterministic::Runner::default();
1089        runner.start(|context| async move {
1090            let mut index = new_unordered(context);
1091            run_index_remove_through_iterator(&mut index);
1092        });
1093    }
1094
1095    #[test_traced]
1096    fn test_ordered_index_remove_through_iterator() {
1097        let runner = deterministic::Runner::default();
1098        runner.start(|context| async move {
1099            let mut index = new_ordered(context);
1100            run_index_remove_through_iterator(&mut index);
1101        });
1102    }
1103
1104    #[test_traced]
1105    fn test_partitioned_index_remove_through_iterator() {
1106        let runner = deterministic::Runner::default();
1107        runner.start(|context| async move {
1108            {
1109                let mut index = new_partitioned_unordered(context.child("unordered"));
1110                run_index_remove_through_iterator(&mut index);
1111            }
1112            {
1113                let mut index = new_partitioned_ordered(context.child("ordered"));
1114                run_index_remove_through_iterator(&mut index);
1115            }
1116        });
1117    }
1118    fn run_index_insert_through_iterator<I: Unordered<Value = u64>>(index: &mut I)
1119    where
1120        I::Value: PartialEq<u64> + Eq,
1121    {
1122        index.insert(b"key", 1);
1123        {
1124            let mut cursor = index.get_mut(b"key").unwrap();
1125            assert_eq!(*cursor.next().unwrap(), 1);
1126            cursor.insert(3);
1127        }
1128        assert_eq!(index.get(b"key").copied().collect::<Vec<_>>(), vec![1, 3]);
1129        assert_eq!(index.keys(), 1);
1130        assert_eq!(index.items(), 2);
1131        {
1132            let mut cursor = index.get_mut(b"key").unwrap();
1133            assert_eq!(*cursor.next().unwrap(), 1);
1134            cursor.insert(42);
1135        }
1136        assert_eq!(index.keys(), 1);
1137        assert_eq!(index.items(), 3);
1138        {
1139            let mut iter = index.get(b"key");
1140            assert_eq!(*iter.next().unwrap(), 1);
1141            assert_eq!(*iter.next().unwrap(), 42);
1142        }
1143        index.insert(b"key", 100);
1144        assert_values(index, b"key", &[1, 3, 42, 100]);
1145    }
1146
1147    #[test_traced]
1148    fn test_hash_index_insert_through_iterator() {
1149        let runner = deterministic::Runner::default();
1150        runner.start(|context| async move {
1151            let mut index = new_unordered(context);
1152            run_index_insert_through_iterator(&mut index);
1153        });
1154    }
1155
1156    #[test_traced]
1157    fn test_ordered_index_insert_through_iterator() {
1158        let runner = deterministic::Runner::default();
1159        runner.start(|context| async move {
1160            let mut index = new_ordered(context);
1161            run_index_insert_through_iterator(&mut index);
1162        });
1163    }
1164
1165    #[test_traced]
1166    fn test_partitioned_index_insert_through_iterator() {
1167        let runner = deterministic::Runner::default();
1168        runner.start(|context| async move {
1169            {
1170                let mut index = new_partitioned_unordered(context.child("unordered"));
1171                run_index_insert_through_iterator(&mut index);
1172            }
1173            {
1174                let mut index = new_partitioned_ordered(context.child("ordered"));
1175                run_index_insert_through_iterator(&mut index);
1176            }
1177        });
1178    }
1179
1180    fn run_index_cursor_insert_after_done_appends<I: Unordered<Value = u64>>(index: &mut I) {
1181        index.insert(b"key", 10);
1182        {
1183            let mut cursor = index.get_mut(b"key").unwrap();
1184            assert_eq!(*cursor.next().unwrap(), 10);
1185            assert!(cursor.next().is_none());
1186            cursor.insert(20);
1187        }
1188        assert_eq!(index.get(b"key").copied().collect::<Vec<_>>(), vec![10, 20]);
1189    }
1190
1191    #[test_traced]
1192    fn test_hash_index_cursor_insert_after_done_appends() {
1193        let runner = deterministic::Runner::default();
1194        runner.start(|context| async move {
1195            let mut index = new_unordered(context);
1196            run_index_cursor_insert_after_done_appends(&mut index);
1197        });
1198    }
1199
1200    #[test_traced]
1201    fn test_ordered_index_cursor_insert_after_done_appends() {
1202        let runner = deterministic::Runner::default();
1203        runner.start(|context| async move {
1204            let mut index = new_ordered(context);
1205            run_index_cursor_insert_after_done_appends(&mut index);
1206        });
1207    }
1208
1209    #[test_traced]
1210    fn test_partitioned_index_cursor_insert_after_done_appends() {
1211        let runner = deterministic::Runner::default();
1212        runner.start(|context| async move {
1213            {
1214                let mut index = new_partitioned_unordered(context.child("unordered"));
1215                run_index_cursor_insert_after_done_appends(&mut index);
1216            }
1217            {
1218                let mut index = new_partitioned_ordered(context.child("ordered"));
1219                run_index_cursor_insert_after_done_appends(&mut index);
1220            }
1221        });
1222    }
1223
1224    fn run_index_remove_to_nothing_then_add<I: Unordered<Value = u64>>(index: &mut I) {
1225        for i in 0..4 {
1226            index.insert(b"key", i);
1227        }
1228        {
1229            let mut cursor = index.get_mut(b"key").unwrap();
1230            let mut removed = Vec::new();
1231            while let Some(value) = cursor.next().copied() {
1232                removed.push(value);
1233                cursor.delete();
1234            }
1235            removed.sort_unstable();
1236            assert_eq!(removed, vec![0, 1, 2, 3]);
1237            assert_eq!(cursor.next(), None);
1238            cursor.insert(4);
1239            assert_eq!(cursor.next(), None);
1240            cursor.insert(5);
1241        }
1242        assert_eq!(index.get(b"key").copied().collect::<Vec<_>>(), vec![4, 5]);
1243    }
1244
1245    #[test_traced]
1246    fn test_hash_index_remove_to_nothing_then_add() {
1247        let runner = deterministic::Runner::default();
1248        runner.start(|context| async move {
1249            let mut index = new_unordered(context);
1250            run_index_remove_to_nothing_then_add(&mut index);
1251        });
1252    }
1253
1254    #[test_traced]
1255    fn test_ordered_index_remove_to_nothing_then_add() {
1256        let runner = deterministic::Runner::default();
1257        runner.start(|context| async move {
1258            let mut index = new_ordered(context);
1259            run_index_remove_to_nothing_then_add(&mut index);
1260        });
1261    }
1262
1263    #[test_traced]
1264    fn test_partitioned_index_remove_to_nothing_then_add() {
1265        let runner = deterministic::Runner::default();
1266        runner.start(|context| async move {
1267            {
1268                let mut index = new_partitioned_unordered(context.child("unordered"));
1269                run_index_remove_to_nothing_then_add(&mut index);
1270            }
1271            {
1272                let mut index = new_partitioned_ordered(context.child("ordered"));
1273                run_index_remove_to_nothing_then_add(&mut index);
1274            }
1275        });
1276    }
1277
1278    fn run_index_insert_and_remove_cursor<I: Unordered<Value = u64>>(index: &mut I) {
1279        index.insert(b"key", 0);
1280        {
1281            let mut cursor = index.get_mut(b"key").unwrap();
1282            assert_eq!(*cursor.next().unwrap(), 0);
1283            cursor.delete();
1284        }
1285        index.remove(b"key");
1286        assert!(index.get(b"key").copied().collect::<Vec<_>>().is_empty());
1287    }
1288
1289    #[test_traced]
1290    fn test_hash_index_insert_and_remove_cursor() {
1291        let runner = deterministic::Runner::default();
1292        runner.start(|context| async move {
1293            let mut index = new_unordered(context);
1294            run_index_insert_and_remove_cursor(&mut index);
1295        });
1296    }
1297
1298    #[test_traced]
1299    fn test_ordered_index_insert_and_remove_cursor() {
1300        let runner = deterministic::Runner::default();
1301        runner.start(|context| async move {
1302            let mut index = new_ordered(context);
1303            run_index_insert_and_remove_cursor(&mut index);
1304        });
1305    }
1306
1307    #[test_traced]
1308    fn test_partitioned_index_insert_and_remove_cursor() {
1309        let runner = deterministic::Runner::default();
1310        runner.start(|context| async move {
1311            {
1312                let mut index = new_partitioned_unordered(context.child("unordered"));
1313                run_index_insert_and_remove_cursor(&mut index);
1314            }
1315            {
1316                let mut index = new_partitioned_ordered(context.child("ordered"));
1317                run_index_insert_and_remove_cursor(&mut index);
1318            }
1319        });
1320    }
1321
1322    fn run_index_insert_and_retain_vacant<I: Unordered<Value = u64>>(index: &mut I) {
1323        index.insert_and_retain(b"key", 1u64, |_| true);
1324        assert_eq!(index.get(b"key").copied().collect::<Vec<_>>(), vec![1]);
1325        assert_eq!(index.items(), 1);
1326        assert_eq!(index.keys(), 1);
1327        assert_eq!(index.pruned(), 0);
1328    }
1329
1330    #[test_traced]
1331    fn test_hash_index_insert_and_retain_vacant() {
1332        let runner = deterministic::Runner::default();
1333        runner.start(|context| async move {
1334            let mut index = new_unordered(context);
1335            run_index_insert_and_retain_vacant(&mut index);
1336        });
1337    }
1338
1339    #[test_traced]
1340    fn test_ordered_index_insert_and_retain_vacant() {
1341        let runner = deterministic::Runner::default();
1342        runner.start(|context| async move {
1343            let mut index = new_ordered(context);
1344            run_index_insert_and_retain_vacant(&mut index);
1345        });
1346    }
1347
1348    #[test_traced]
1349    fn test_partitioned_index_insert_and_retain_vacant() {
1350        let runner = deterministic::Runner::default();
1351        runner.start(|context| async move {
1352            {
1353                let mut index = new_partitioned_unordered(context.child("unordered"));
1354                run_index_insert_and_retain_vacant(&mut index);
1355            }
1356            {
1357                let mut index = new_partitioned_ordered(context.child("ordered"));
1358                run_index_insert_and_retain_vacant(&mut index);
1359            }
1360        });
1361    }
1362
1363    fn run_index_insert_and_retain_vacant_not_retained<I: Unordered<Value = u64>>(index: &mut I) {
1364        index.insert_and_retain(b"key", 1u64, |_| false);
1365        assert_eq!(
1366            index.get(b"key").copied().collect::<Vec<_>>(),
1367            Vec::<u64>::new()
1368        );
1369        assert_eq!(index.items(), 0);
1370        assert_eq!(index.keys(), 0);
1371        assert_eq!(index.pruned(), 0);
1372    }
1373
1374    #[test_traced]
1375    fn test_hash_index_insert_and_retain_vacant_not_retained() {
1376        let runner = deterministic::Runner::default();
1377        runner.start(|context| async move {
1378            let mut index = new_unordered(context);
1379            run_index_insert_and_retain_vacant_not_retained(&mut index);
1380        });
1381    }
1382
1383    #[test_traced]
1384    fn test_ordered_index_insert_and_retain_vacant_not_retained() {
1385        let runner = deterministic::Runner::default();
1386        runner.start(|context| async move {
1387            let mut index = new_ordered(context);
1388            run_index_insert_and_retain_vacant_not_retained(&mut index);
1389        });
1390    }
1391
1392    #[test_traced]
1393    fn test_partitioned_index_insert_and_retain_vacant_not_retained() {
1394        let runner = deterministic::Runner::default();
1395        runner.start(|context| async move {
1396            {
1397                let mut index = new_partitioned_unordered(context.child("unordered"));
1398                run_index_insert_and_retain_vacant_not_retained(&mut index);
1399            }
1400            {
1401                let mut index = new_partitioned_ordered(context.child("ordered"));
1402                run_index_insert_and_retain_vacant_not_retained(&mut index);
1403            }
1404        });
1405    }
1406
1407    fn run_index_insert_and_retain_replace_one<I: Unordered<Value = u64>>(index: &mut I) {
1408        index.insert(b"key", 1u64);
1409        index.insert_and_retain(b"key", 2u64, |v| *v != 1);
1410        assert_eq!(index.get(b"key").copied().collect::<Vec<_>>(), vec![2]);
1411        assert_eq!(index.items(), 1);
1412        assert_eq!(index.keys(), 1);
1413        assert_eq!(index.pruned(), 1);
1414    }
1415
1416    #[test_traced]
1417    fn test_hash_index_insert_and_retain_replace_one() {
1418        let runner = deterministic::Runner::default();
1419        runner.start(|context| async move {
1420            let mut index = new_unordered(context);
1421            run_index_insert_and_retain_replace_one(&mut index);
1422        });
1423    }
1424
1425    #[test_traced]
1426    fn test_ordered_index_insert_and_retain_replace_one() {
1427        let runner = deterministic::Runner::default();
1428        runner.start(|context| async move {
1429            let mut index = new_ordered(context);
1430            run_index_insert_and_retain_replace_one(&mut index);
1431        });
1432    }
1433
1434    #[test_traced]
1435    fn test_partitioned_index_insert_and_retain_replace_one() {
1436        let runner = deterministic::Runner::default();
1437        runner.start(|context| async move {
1438            {
1439                let mut index = new_partitioned_unordered(context.child("unordered"));
1440                run_index_insert_and_retain_replace_one(&mut index);
1441            }
1442            {
1443                let mut index = new_partitioned_ordered(context.child("ordered"));
1444                run_index_insert_and_retain_replace_one(&mut index);
1445            }
1446        });
1447    }
1448
1449    fn run_index_insert_and_retain_dead_insert<I: Unordered<Value = u64>>(index: &mut I) {
1450        index.insert(b"key", 10u64);
1451        index.insert(b"key", 20u64);
1452        index.insert_and_retain(b"key", 30u64, |_| false);
1453        assert_eq!(
1454            index.get(b"key").copied().collect::<Vec<u64>>(),
1455            Vec::<u64>::new()
1456        );
1457        assert_eq!(index.items(), 0);
1458        assert_eq!(index.keys(), 0);
1459        assert_eq!(index.pruned(), 2);
1460    }
1461
1462    #[test_traced]
1463    fn test_hash_index_insert_and_retain_dead_insert() {
1464        let runner = deterministic::Runner::default();
1465        runner.start(|context| async move {
1466            let mut index = new_unordered(context);
1467            run_index_insert_and_retain_dead_insert(&mut index);
1468        });
1469    }
1470
1471    #[test_traced]
1472    fn test_ordered_index_insert_and_retain_dead_insert() {
1473        let runner = deterministic::Runner::default();
1474        runner.start(|context| async move {
1475            let mut index = new_ordered(context);
1476            run_index_insert_and_retain_dead_insert(&mut index);
1477        });
1478    }
1479
1480    #[test_traced]
1481    fn test_partitioned_index_insert_and_retain_dead_insert() {
1482        let runner = deterministic::Runner::default();
1483        runner.start(|context| async move {
1484            {
1485                let mut index = new_partitioned_unordered(context.child("unordered"));
1486                run_index_insert_and_retain_dead_insert(&mut index);
1487            }
1488            {
1489                let mut index = new_partitioned_ordered(context.child("ordered"));
1490                run_index_insert_and_retain_dead_insert(&mut index);
1491            }
1492        });
1493    }
1494
1495    /// Exercises `insert_and_retain` on single-value (collision-free) keys, covering each
1496    /// combination of retaining the existing and new values.
1497    fn run_index_insert_and_retain_single_value<I: Unordered<Value = u64>>(index: &mut I) {
1498        // Retain both: the new value joins the chain after the existing one.
1499        index.insert(b"both", 1u64);
1500        index.insert_and_retain(b"both", 2u64, |_| true);
1501        assert_eq!(index.get(b"both").copied().collect::<Vec<_>>(), vec![1, 2]);
1502
1503        // Retain the existing value, drop the new one: a no-op.
1504        index.insert(b"keep", 1u64);
1505        index.insert_and_retain(b"keep", 2u64, |v| *v == 1);
1506        assert_eq!(index.get(b"keep").copied().collect::<Vec<_>>(), vec![1]);
1507
1508        // Drop both: the key is removed.
1509        index.insert(b"drop", 1u64);
1510        index.insert_and_retain(b"drop", 2u64, |_| false);
1511        assert!(index.get(b"drop").next().is_none());
1512
1513        assert_eq!(index.keys(), 2); // "both" and "keep" remain
1514        assert_eq!(index.items(), 3); // both -> [1, 2], keep -> [1]
1515        assert_eq!(index.pruned(), 1); // the dropped "drop" value
1516    }
1517
1518    #[test_traced]
1519    fn test_hash_index_insert_and_retain_single_value() {
1520        let runner = deterministic::Runner::default();
1521        runner.start(|context| async move {
1522            let mut index = new_unordered(context);
1523            run_index_insert_and_retain_single_value(&mut index);
1524        });
1525    }
1526
1527    #[test_traced]
1528    fn test_ordered_index_insert_and_retain_single_value() {
1529        let runner = deterministic::Runner::default();
1530        runner.start(|context| async move {
1531            let mut index = new_ordered(context);
1532            run_index_insert_and_retain_single_value(&mut index);
1533        });
1534    }
1535
1536    #[test_traced]
1537    fn test_partitioned_index_insert_and_retain_single_value() {
1538        let runner = deterministic::Runner::default();
1539        runner.start(|context| async move {
1540            {
1541                let mut index = new_partitioned_unordered(context.child("unordered"));
1542                run_index_insert_and_retain_single_value(&mut index);
1543            }
1544            {
1545                let mut index = new_partitioned_ordered(context.child("ordered"));
1546                run_index_insert_and_retain_single_value(&mut index);
1547            }
1548        });
1549    }
1550
1551    fn run_index_cursor_across_threads<I>(index: Arc<Mutex<I>>)
1552    where
1553        I: Unordered<Value = u64> + Send + 'static,
1554    {
1555        // Insert some initial data
1556        {
1557            let mut index = index.lock();
1558            index.insert(b"test_key1", 100);
1559            index.insert(b"test_key2", 200);
1560        }
1561
1562        // Spawn a thread that will get a cursor and modify values
1563        let index_clone = Arc::clone(&index);
1564        let handle = thread::spawn(move || {
1565            // Limit the lifetime of the lock and the cursor so they drop before returning
1566            let result = {
1567                let mut index = index_clone.lock();
1568                let mut updated = false;
1569                if let Some(mut cursor) = index.get_mut(b"test_key2") {
1570                    if cursor.find(|&value| value == 200) {
1571                        cursor.update(250);
1572                        updated = true;
1573                    }
1574                }
1575                updated
1576            };
1577            result
1578        });
1579
1580        // Wait for the thread to complete
1581        let result = handle.join().unwrap();
1582        assert!(result);
1583
1584        // Verify the update was applied (and collision retained)
1585        {
1586            let index = index.lock();
1587            let values: Vec<u64> = index.get(b"test_key2").copied().collect();
1588            assert!(values.contains(&100));
1589            assert!(values.contains(&250));
1590            assert!(!values.contains(&200));
1591        }
1592    }
1593
1594    #[test_traced]
1595    fn test_hash_index_cursor_across_threads() {
1596        let runner = deterministic::Runner::default();
1597        runner.start(|context| async move {
1598            let index = Arc::new(Mutex::new(new_unordered(context)));
1599            run_index_cursor_across_threads(index);
1600        });
1601    }
1602
1603    #[test_traced]
1604    fn test_ordered_index_cursor_across_threads() {
1605        let runner = deterministic::Runner::default();
1606        runner.start(|context| async move {
1607            let index = Arc::new(Mutex::new(new_ordered(context)));
1608            run_index_cursor_across_threads(index);
1609        });
1610    }
1611
1612    #[test_traced]
1613    fn test_partitioned_index_cursor_across_threads() {
1614        let runner = deterministic::Runner::default();
1615        runner.start(|context| async move {
1616            {
1617                let index = Arc::new(Mutex::new(new_partitioned_unordered(
1618                    context.child("unordered"),
1619                )));
1620                run_index_cursor_across_threads(index);
1621            }
1622            {
1623                let index = Arc::new(Mutex::new(new_partitioned_ordered(
1624                    context.child("ordered"),
1625                )));
1626                run_index_cursor_across_threads(index);
1627            }
1628        });
1629    }
1630
1631    fn run_index_remove_middle_then_next<I: Unordered<Value = u64>>(index: &mut I) {
1632        for i in 0..4 {
1633            index.insert(b"key", i);
1634        }
1635        let expected = values(index, b"key");
1636        {
1637            let mut cursor = index.get_mut(b"key").unwrap();
1638            assert_eq!(*cursor.next().unwrap(), expected[0]);
1639            assert_eq!(*cursor.next().unwrap(), expected[1]);
1640            cursor.delete();
1641            assert_eq!(*cursor.next().unwrap(), expected[2]);
1642            cursor.delete();
1643        }
1644        assert_eq!(values(index, b"key"), vec![expected[0], expected[3]]);
1645    }
1646
1647    #[test_traced]
1648    fn test_hash_index_remove_middle_then_next() {
1649        let runner = deterministic::Runner::default();
1650        runner.start(|context| async move {
1651            let mut index = new_unordered(context);
1652            run_index_remove_middle_then_next(&mut index);
1653        });
1654    }
1655
1656    #[test_traced]
1657    fn test_ordered_index_remove_middle_then_next() {
1658        let runner = deterministic::Runner::default();
1659        runner.start(|context| async move {
1660            let mut index = new_ordered(context);
1661            run_index_remove_middle_then_next(&mut index);
1662        });
1663    }
1664
1665    #[test_traced]
1666    fn test_partitioned_index_remove_middle_then_next() {
1667        let runner = deterministic::Runner::default();
1668        runner.start(|context| async move {
1669            {
1670                let mut index = new_partitioned_unordered(context.child("unordered"));
1671                run_index_remove_middle_then_next(&mut index);
1672            }
1673            {
1674                let mut index = new_partitioned_ordered(context.child("ordered"));
1675                run_index_remove_middle_then_next(&mut index);
1676            }
1677        });
1678    }
1679
1680    fn run_index_remove_to_nothing<I: Unordered<Value = u64>>(index: &mut I) {
1681        for i in 0..4 {
1682            index.insert(b"key", i);
1683        }
1684        {
1685            let mut cursor = index.get_mut(b"key").unwrap();
1686            let mut removed = Vec::new();
1687            while let Some(value) = cursor.next().copied() {
1688                removed.push(value);
1689                cursor.delete();
1690            }
1691            removed.sort_unstable();
1692            assert_eq!(removed, vec![0, 1, 2, 3]);
1693            assert_eq!(cursor.next(), None);
1694        }
1695        assert_eq!(index.keys(), 0);
1696        assert_eq!(index.items(), 0);
1697    }
1698
1699    #[test_traced]
1700    fn test_hash_index_remove_to_nothing() {
1701        let runner = deterministic::Runner::default();
1702        runner.start(|context| async move {
1703            let mut index = new_unordered(context);
1704            run_index_remove_to_nothing(&mut index);
1705        });
1706    }
1707
1708    #[test_traced]
1709    fn test_ordered_index_remove_to_nothing() {
1710        let runner = deterministic::Runner::default();
1711        runner.start(|context| async move {
1712            let mut index = new_ordered(context);
1713            run_index_remove_to_nothing(&mut index);
1714        });
1715    }
1716
1717    #[test_traced]
1718    fn test_partitioned_index_remove_to_nothing() {
1719        let runner = deterministic::Runner::default();
1720        runner.start(|context| async move {
1721            {
1722                let mut index = new_partitioned_unordered(context.child("unordered"));
1723                run_index_remove_to_nothing(&mut index);
1724            }
1725            {
1726                let mut index = new_partitioned_ordered(context.child("ordered"));
1727                run_index_remove_to_nothing(&mut index);
1728            }
1729        });
1730    }
1731
1732    fn run_index_cursor_update_before_next_panics<I: Unordered<Value = u64>>(index: &mut I) {
1733        index.insert(b"key", 123);
1734        let mut cursor = index.get_mut(b"key").unwrap();
1735        cursor.update(321);
1736    }
1737
1738    #[test_traced]
1739    #[should_panic(expected = "must call Cursor::next()")]
1740    fn test_hash_index_cursor_update_before_next_panics() {
1741        let runner = deterministic::Runner::default();
1742        runner.start(|context| async move {
1743            let mut index = new_unordered(context);
1744            run_index_cursor_update_before_next_panics(&mut index);
1745        });
1746    }
1747
1748    #[test_traced]
1749    #[should_panic(expected = "must call Cursor::next()")]
1750    fn test_ordered_index_cursor_update_before_next_panics() {
1751        let runner = deterministic::Runner::default();
1752        runner.start(|context| async move {
1753            let mut index = new_ordered(context);
1754            run_index_cursor_update_before_next_panics(&mut index);
1755        });
1756    }
1757
1758    #[test_traced]
1759    #[should_panic(expected = "must call Cursor::next()")]
1760    fn test_partitioned_index_cursor_update_before_next_panics() {
1761        let runner = deterministic::Runner::default();
1762        runner.start(|context| async move {
1763            {
1764                let mut index = new_partitioned_unordered(context.child("unordered"));
1765                run_index_cursor_update_before_next_panics(&mut index);
1766            }
1767            {
1768                let mut index = new_partitioned_ordered(context.child("ordered"));
1769                run_index_cursor_update_before_next_panics(&mut index);
1770            }
1771        });
1772    }
1773
1774    fn run_index_cursor_delete_before_next_panics<I: Unordered<Value = u64>>(index: &mut I) {
1775        index.insert(b"key", 123);
1776        let mut cursor = index.get_mut(b"key").unwrap();
1777        cursor.delete();
1778    }
1779
1780    #[test_traced]
1781    #[should_panic(expected = "must call Cursor::next()")]
1782    fn test_hash_index_cursor_delete_before_next_panics() {
1783        let runner = deterministic::Runner::default();
1784        runner.start(|context| async move {
1785            let mut index = new_unordered(context);
1786            run_index_cursor_delete_before_next_panics(&mut index);
1787        });
1788    }
1789
1790    #[test_traced]
1791    #[should_panic(expected = "must call Cursor::next()")]
1792    fn test_ordered_index_cursor_delete_before_next_panics() {
1793        let runner = deterministic::Runner::default();
1794        runner.start(|context| async move {
1795            let mut index = new_ordered(context);
1796            run_index_cursor_delete_before_next_panics(&mut index);
1797        });
1798    }
1799
1800    #[test_traced]
1801    #[should_panic(expected = "must call Cursor::next()")]
1802    fn test_partitioned_index_cursor_delete_before_next_panics() {
1803        let runner = deterministic::Runner::default();
1804        runner.start(|context| async move {
1805            {
1806                let mut index = new_partitioned_unordered(context.child("unordered"));
1807                run_index_cursor_delete_before_next_panics(&mut index);
1808            }
1809            {
1810                let mut index = new_partitioned_ordered(context.child("ordered"));
1811                run_index_cursor_delete_before_next_panics(&mut index);
1812            }
1813        });
1814    }
1815
1816    fn run_index_cursor_update_after_done<I: Unordered<Value = u64>>(index: &mut I) {
1817        index.insert(b"key", 123);
1818        let mut cursor = index.get_mut(b"key").unwrap();
1819        assert_eq!(*cursor.next().unwrap(), 123);
1820        assert!(cursor.next().is_none());
1821        cursor.update(321);
1822    }
1823
1824    #[test_traced]
1825    #[should_panic(expected = "no active item in Cursor")]
1826    fn test_hash_index_cursor_update_after_done() {
1827        let runner = deterministic::Runner::default();
1828        runner.start(|context| async move {
1829            let mut index = new_unordered(context);
1830            run_index_cursor_update_after_done(&mut index);
1831        });
1832    }
1833
1834    #[test_traced]
1835    #[should_panic(expected = "no active item in Cursor")]
1836    fn test_ordered_index_cursor_update_after_done() {
1837        let runner = deterministic::Runner::default();
1838        runner.start(|context| async move {
1839            let mut index = new_ordered(context);
1840            run_index_cursor_update_after_done(&mut index);
1841        });
1842    }
1843
1844    #[test_traced]
1845    #[should_panic(expected = "no active item in Cursor")]
1846    fn test_partitioned_index_cursor_update_after_done() {
1847        let runner = deterministic::Runner::default();
1848        runner.start(|context| async move {
1849            {
1850                let mut index = new_partitioned_unordered(context.child("unordered"));
1851                run_index_cursor_update_after_done(&mut index);
1852            }
1853            {
1854                let mut index = new_partitioned_ordered(context.child("ordered"));
1855                run_index_cursor_update_after_done(&mut index);
1856            }
1857        });
1858    }
1859
1860    fn run_index_cursor_insert_before_next<I: Unordered<Value = u64>>(index: &mut I) {
1861        index.insert(b"key", 123);
1862        let mut cursor = index.get_mut(b"key").unwrap();
1863        cursor.insert(321);
1864    }
1865
1866    #[test_traced]
1867    #[should_panic(expected = "must call Cursor::next()")]
1868    fn test_hash_index_cursor_insert_before_next() {
1869        let runner = deterministic::Runner::default();
1870        runner.start(|context| async move {
1871            let mut index = new_unordered(context);
1872            run_index_cursor_insert_before_next(&mut index);
1873        });
1874    }
1875
1876    #[test_traced]
1877    #[should_panic(expected = "must call Cursor::next()")]
1878    fn test_ordered_index_cursor_insert_before_next() {
1879        let runner = deterministic::Runner::default();
1880        runner.start(|context| async move {
1881            let mut index = new_ordered(context);
1882            run_index_cursor_insert_before_next(&mut index);
1883        });
1884    }
1885
1886    #[test_traced]
1887    #[should_panic(expected = "must call Cursor::next()")]
1888    fn test_partitioned_index_cursor_insert_before_next() {
1889        let runner = deterministic::Runner::default();
1890        runner.start(|context| async move {
1891            {
1892                let mut index = new_partitioned_unordered(context.child("unordered"));
1893                run_index_cursor_insert_before_next(&mut index);
1894            }
1895            {
1896                let mut index = new_partitioned_ordered(context.child("ordered"));
1897                run_index_cursor_insert_before_next(&mut index);
1898            }
1899        });
1900    }
1901
1902    fn run_index_cursor_delete_after_done<I: Unordered<Value = u64>>(index: &mut I) {
1903        index.insert(b"key", 123);
1904        let mut cursor = index.get_mut(b"key").unwrap();
1905        assert_eq!(*cursor.next().unwrap(), 123);
1906        assert!(cursor.next().is_none());
1907        cursor.delete();
1908    }
1909
1910    #[test_traced]
1911    #[should_panic(expected = "no active item in Cursor")]
1912    fn test_hash_index_cursor_delete_after_done() {
1913        let runner = deterministic::Runner::default();
1914        runner.start(|context| async move {
1915            let mut index = new_unordered(context);
1916            run_index_cursor_delete_after_done(&mut index);
1917        });
1918    }
1919
1920    #[test_traced]
1921    #[should_panic(expected = "no active item in Cursor")]
1922    fn test_ordered_index_cursor_delete_after_done() {
1923        let runner = deterministic::Runner::default();
1924        runner.start(|context| async move {
1925            let mut index = new_ordered(context);
1926            run_index_cursor_delete_after_done(&mut index);
1927        });
1928    }
1929
1930    #[test_traced]
1931    #[should_panic(expected = "no active item in Cursor")]
1932    fn test_partitioned_index_cursor_delete_after_done() {
1933        let runner = deterministic::Runner::default();
1934        runner.start(|context| async move {
1935            {
1936                let mut index = new_partitioned_unordered(context.child("unordered"));
1937                run_index_cursor_delete_after_done(&mut index);
1938            }
1939            {
1940                let mut index = new_partitioned_ordered(context.child("ordered"));
1941                run_index_cursor_delete_after_done(&mut index);
1942            }
1943        });
1944    }
1945
1946    fn run_index_cursor_insert_with_next<I: Unordered<Value = u64>>(index: &mut I) {
1947        index.insert(b"key", 123);
1948        index.insert(b"key", 456);
1949        let expected = values(index, b"key");
1950        let mut cursor = index.get_mut(b"key").unwrap();
1951        assert_eq!(*cursor.next().unwrap(), expected[0]);
1952        assert_eq!(*cursor.next().unwrap(), expected[1]);
1953        cursor.insert(789);
1954        assert_eq!(cursor.next(), None);
1955        cursor.insert(999);
1956        drop(cursor);
1957        let mut values = index.get(b"key").copied().collect::<Vec<_>>();
1958        values.sort();
1959        assert_eq!(values, vec![123, 456, 789, 999]);
1960    }
1961
1962    #[test_traced]
1963    fn test_hash_index_cursor_insert_with_next() {
1964        let runner = deterministic::Runner::default();
1965        runner.start(|context| async move {
1966            let mut index = new_unordered(context);
1967            run_index_cursor_insert_with_next(&mut index);
1968        });
1969    }
1970
1971    #[test_traced]
1972    fn test_ordered_index_cursor_insert_with_next() {
1973        let runner = deterministic::Runner::default();
1974        runner.start(|context| async move {
1975            let mut index = new_ordered(context);
1976            run_index_cursor_insert_with_next(&mut index);
1977        });
1978    }
1979
1980    #[test_traced]
1981    fn test_partitioned_index_cursor_insert_with_next() {
1982        let runner = deterministic::Runner::default();
1983        runner.start(|context| async move {
1984            {
1985                let mut index = new_partitioned_unordered(context.child("unordered"));
1986                run_index_cursor_insert_with_next(&mut index);
1987            }
1988            {
1989                let mut index = new_partitioned_ordered(context.child("ordered"));
1990                run_index_cursor_insert_with_next(&mut index);
1991            }
1992        });
1993    }
1994
1995    fn run_index_cursor_double_delete<I: Unordered<Value = u64>>(index: &mut I) {
1996        index.insert(b"key", 123);
1997        index.insert(b"key", 456);
1998        let mut cursor = index.get_mut(b"key").unwrap();
1999        assert!(cursor.next().is_some());
2000        cursor.delete();
2001        cursor.delete();
2002    }
2003
2004    #[test_traced]
2005    #[should_panic(expected = "must call Cursor::next()")]
2006    fn test_hash_index_cursor_double_delete() {
2007        let runner = deterministic::Runner::default();
2008        runner.start(|context| async move {
2009            let mut index = new_unordered(context);
2010            run_index_cursor_double_delete(&mut index);
2011        });
2012    }
2013
2014    #[test_traced]
2015    #[should_panic(expected = "must call Cursor::next()")]
2016    fn test_ordered_index_cursor_double_delete() {
2017        let runner = deterministic::Runner::default();
2018        runner.start(|context| async move {
2019            let mut index = new_ordered(context);
2020            run_index_cursor_double_delete(&mut index);
2021        });
2022    }
2023
2024    fn run_index_cursor_delete_last_then_next<I: Unordered<Value = u64>>(index: &mut I) {
2025        index.insert(b"key", 1);
2026        index.insert(b"key", 2);
2027        let expected = values(index, b"key");
2028        {
2029            let mut cursor = index.get_mut(b"key").unwrap();
2030            assert_eq!(*cursor.next().unwrap(), expected[0]);
2031            assert_eq!(*cursor.next().unwrap(), expected[1]);
2032            cursor.delete();
2033            assert!(cursor.next().is_none());
2034            assert!(cursor.next().is_none());
2035        }
2036        assert_eq!(index.keys(), 1);
2037        assert_eq!(index.items(), 1);
2038    }
2039
2040    #[test_traced]
2041    fn test_hash_index_cursor_delete_last_then_next() {
2042        let runner = deterministic::Runner::default();
2043        runner.start(|context| async move {
2044            let mut index = new_unordered(context);
2045            run_index_cursor_delete_last_then_next(&mut index);
2046        });
2047    }
2048
2049    #[test_traced]
2050    fn test_ordered_index_cursor_delete_last_then_next() {
2051        let runner = deterministic::Runner::default();
2052        runner.start(|context| async move {
2053            let mut index = new_ordered(context);
2054            run_index_cursor_delete_last_then_next(&mut index);
2055        });
2056    }
2057
2058    #[test_traced]
2059    fn test_partitioned_index_cursor_delete_last_then_next() {
2060        let runner = deterministic::Runner::default();
2061        runner.start(|context| async move {
2062            {
2063                let mut index = new_partitioned_unordered(context.child("unordered"));
2064                run_index_cursor_delete_last_then_next(&mut index);
2065            }
2066            {
2067                let mut index = new_partitioned_ordered(context.child("ordered"));
2068                run_index_cursor_delete_last_then_next(&mut index);
2069            }
2070        });
2071    }
2072
2073    fn run_index_delete_in_middle_then_continue<I: Unordered<Value = u64>>(index: &mut I) {
2074        index.insert(b"key", 1);
2075        index.insert(b"key", 2);
2076        index.insert(b"key", 3);
2077        let expected = values(index, b"key");
2078        let mut cur = index.get_mut(b"key").unwrap();
2079        assert_eq!(*cur.next().unwrap(), expected[0]);
2080        assert_eq!(*cur.next().unwrap(), expected[1]);
2081        cur.delete();
2082        assert_eq!(*cur.next().unwrap(), expected[2]);
2083        assert!(cur.next().is_none());
2084        assert!(cur.next().is_none());
2085    }
2086
2087    #[test_traced]
2088    fn test_hash_index_delete_in_middle_then_continue() {
2089        let runner = deterministic::Runner::default();
2090        runner.start(|context| async move {
2091            let mut index = new_unordered(context);
2092            run_index_delete_in_middle_then_continue(&mut index);
2093        });
2094    }
2095
2096    #[test_traced]
2097    fn test_ordered_index_delete_in_middle_then_continue() {
2098        let runner = deterministic::Runner::default();
2099        runner.start(|context| async move {
2100            let mut index = new_ordered(context);
2101            run_index_delete_in_middle_then_continue(&mut index);
2102        });
2103    }
2104
2105    fn run_index_delete_first<I: Unordered<Value = u64>>(index: &mut I) {
2106        index.insert(b"key", 1);
2107        index.insert(b"key", 2);
2108        index.insert(b"key", 3);
2109        let expected = values(index, b"key");
2110        {
2111            let mut cur = index.get_mut(b"key").unwrap();
2112            assert_eq!(*cur.next().unwrap(), expected[0]);
2113            cur.delete();
2114            assert_eq!(*cur.next().unwrap(), expected[1]);
2115            assert_eq!(*cur.next().unwrap(), expected[2]);
2116            assert!(cur.next().is_none());
2117            assert!(cur.next().is_none());
2118        }
2119        assert_eq!(values(index, b"key"), expected[1..]);
2120    }
2121
2122    #[test_traced]
2123    fn test_hash_index_delete_first() {
2124        let runner = deterministic::Runner::default();
2125        runner.start(|context| async move {
2126            let mut index = new_unordered(context);
2127            run_index_delete_first(&mut index);
2128        });
2129    }
2130
2131    #[test_traced]
2132    fn test_ordered_index_delete_first() {
2133        let runner = deterministic::Runner::default();
2134        runner.start(|context| async move {
2135            let mut index = new_ordered(context);
2136            run_index_delete_first(&mut index);
2137        });
2138    }
2139
2140    fn run_index_delete_first_and_insert<I: Unordered<Value = u64>>(index: &mut I) {
2141        index.insert(b"key", 1);
2142        index.insert(b"key", 2);
2143        index.insert(b"key", 3);
2144        let expected = values(index, b"key");
2145        {
2146            let mut cur = index.get_mut(b"key").unwrap();
2147            assert_eq!(*cur.next().unwrap(), expected[0]);
2148            cur.delete();
2149            assert_eq!(*cur.next().unwrap(), expected[1]);
2150            cur.insert(4);
2151            assert_eq!(*cur.next().unwrap(), expected[2]);
2152            assert!(cur.next().is_none());
2153            assert!(cur.next().is_none());
2154        }
2155        assert_eq!(values(index, b"key"), vec![expected[1], 4, expected[2]]);
2156    }
2157
2158    #[test_traced]
2159    fn test_hash_index_delete_first_and_insert() {
2160        let runner = deterministic::Runner::default();
2161        runner.start(|context| async move {
2162            let mut index = new_unordered(context);
2163            run_index_delete_first_and_insert(&mut index);
2164        });
2165    }
2166
2167    #[test_traced]
2168    fn test_ordered_index_delete_first_and_insert() {
2169        let runner = deterministic::Runner::default();
2170        runner.start(|context| async move {
2171            let mut index = new_ordered(context);
2172            run_index_delete_first_and_insert(&mut index);
2173        });
2174    }
2175
2176    #[test_traced]
2177    fn test_partitioned_index_delete_first_and_insert() {
2178        let runner = deterministic::Runner::default();
2179        runner.start(|context| async move {
2180            {
2181                let mut index = new_partitioned_unordered(context.child("unordered"));
2182                run_index_delete_first_and_insert(&mut index);
2183            }
2184            {
2185                let mut index = new_partitioned_ordered(context.child("ordered"));
2186                run_index_delete_first_and_insert(&mut index);
2187            }
2188        });
2189    }
2190
2191    fn run_index_insert_at_entry_then_next<I: Unordered<Value = u64>>(index: &mut I) {
2192        index.insert(b"key", 1);
2193        index.insert(b"key", 2);
2194        let expected = values(index, b"key");
2195        let mut cur = index.get_mut(b"key").unwrap();
2196        assert_eq!(*cur.next().unwrap(), expected[0]);
2197        cur.insert(99);
2198        assert_eq!(*cur.next().unwrap(), expected[1]);
2199        assert!(cur.next().is_none());
2200    }
2201
2202    #[test_traced]
2203    fn test_hash_index_insert_at_entry_then_next() {
2204        let runner = deterministic::Runner::default();
2205        runner.start(|context| async move {
2206            let mut index = new_unordered(context);
2207            run_index_insert_at_entry_then_next(&mut index);
2208        });
2209    }
2210
2211    #[test_traced]
2212    fn test_ordered_index_insert_at_entry_then_next() {
2213        let runner = deterministic::Runner::default();
2214        runner.start(|context| async move {
2215            let mut index = new_ordered(context);
2216            run_index_insert_at_entry_then_next(&mut index);
2217        });
2218    }
2219
2220    #[test_traced]
2221    fn test_partitioned_index_insert_at_entry_then_next() {
2222        let runner = deterministic::Runner::default();
2223        runner.start(|context| async move {
2224            {
2225                let mut index = new_partitioned_unordered(context.child("unordered"));
2226                run_index_insert_at_entry_then_next(&mut index);
2227            }
2228            {
2229                let mut index = new_partitioned_ordered(context.child("ordered"));
2230                run_index_insert_at_entry_then_next(&mut index);
2231            }
2232        });
2233    }
2234
2235    fn run_index_insert_at_entry_then_delete_head<I: Unordered<Value = u64>>(index: &mut I) {
2236        index.insert(b"key", 10);
2237        index.insert(b"key", 20);
2238        let mut cur = index.get_mut(b"key").unwrap();
2239        assert!(cur.next().is_some());
2240        cur.insert(15);
2241        cur.delete();
2242    }
2243
2244    #[test_traced]
2245    #[should_panic(expected = "must call Cursor::next()")]
2246    fn test_hash_index_insert_at_entry_then_delete_head() {
2247        let runner = deterministic::Runner::default();
2248        runner.start(|context| async move {
2249            let mut index = new_unordered(context);
2250            run_index_insert_at_entry_then_delete_head(&mut index);
2251        });
2252    }
2253
2254    #[test_traced]
2255    #[should_panic(expected = "must call Cursor::next()")]
2256    fn test_ordered_index_insert_at_entry_then_delete_head() {
2257        let runner = deterministic::Runner::default();
2258        runner.start(|context| async move {
2259            let mut index = new_ordered(context);
2260            run_index_insert_at_entry_then_delete_head(&mut index);
2261        });
2262    }
2263
2264    #[test_traced]
2265    #[should_panic(expected = "must call Cursor::next()")]
2266    fn test_partitioned_index_insert_at_entry_then_delete_head() {
2267        let runner = deterministic::Runner::default();
2268        runner.start(|context| async move {
2269            {
2270                let mut index = new_partitioned_unordered(context.child("unordered"));
2271                run_index_insert_at_entry_then_delete_head(&mut index);
2272            }
2273            {
2274                let mut index = new_partitioned_ordered(context.child("ordered"));
2275                run_index_insert_at_entry_then_delete_head(&mut index);
2276            }
2277        });
2278    }
2279
2280    fn run_index_delete_then_insert_without_next<I: Unordered<Value = u64>>(index: &mut I) {
2281        index.insert(b"key", 10);
2282        index.insert(b"key", 20);
2283        let mut cur = index.get_mut(b"key").unwrap();
2284        assert!(cur.next().is_some());
2285        assert!(cur.next().is_some());
2286        cur.delete();
2287        cur.insert(15);
2288    }
2289
2290    #[test_traced]
2291    #[should_panic(expected = "must call Cursor::next()")]
2292    fn test_hash_index_delete_then_insert_without_next() {
2293        let runner = deterministic::Runner::default();
2294        runner.start(|context| async move {
2295            let mut index = new_unordered(context);
2296            run_index_delete_then_insert_without_next(&mut index);
2297        });
2298    }
2299
2300    #[test_traced]
2301    #[should_panic(expected = "must call Cursor::next()")]
2302    fn test_ordered_index_delete_then_insert_without_next() {
2303        let runner = deterministic::Runner::default();
2304        runner.start(|context| async move {
2305            let mut index = new_ordered(context);
2306            run_index_delete_then_insert_without_next(&mut index);
2307        });
2308    }
2309
2310    #[test_traced]
2311    #[should_panic(expected = "must call Cursor::next()")]
2312    fn test_partitioned_index_delete_then_insert_without_next() {
2313        let runner = deterministic::Runner::default();
2314        runner.start(|context| async move {
2315            {
2316                let mut index = new_partitioned_unordered(context.child("unordered"));
2317                run_index_delete_then_insert_without_next(&mut index);
2318            }
2319            {
2320                let mut index = new_partitioned_ordered(context.child("ordered"));
2321                run_index_delete_then_insert_without_next(&mut index);
2322            }
2323        });
2324    }
2325
2326    fn run_index_inserts_without_next<I: Unordered<Value = u64>>(index: &mut I) {
2327        index.insert(b"key", 10);
2328        index.insert(b"key", 20);
2329        let mut cur = index.get_mut(b"key").unwrap();
2330        assert!(cur.next().is_some());
2331        cur.insert(15);
2332        cur.insert(25);
2333    }
2334
2335    #[test_traced]
2336    #[should_panic(expected = "must call Cursor::next()")]
2337    fn test_hash_index_inserts_without_next() {
2338        let runner = deterministic::Runner::default();
2339        runner.start(|context| async move {
2340            let mut index = new_unordered(context);
2341            run_index_inserts_without_next(&mut index);
2342        });
2343    }
2344
2345    #[test_traced]
2346    #[should_panic(expected = "must call Cursor::next()")]
2347    fn test_ordered_index_inserts_without_next() {
2348        let runner = deterministic::Runner::default();
2349        runner.start(|context| async move {
2350            let mut index = new_ordered(context);
2351            run_index_inserts_without_next(&mut index);
2352        });
2353    }
2354
2355    #[test_traced]
2356    #[should_panic(expected = "must call Cursor::next()")]
2357    fn test_partitioned_index_inserts_without_next() {
2358        let runner = deterministic::Runner::default();
2359        runner.start(|context| async move {
2360            {
2361                let mut index = new_partitioned_unordered(context.child("unordered"));
2362                run_index_inserts_without_next(&mut index);
2363            }
2364            {
2365                let mut index = new_partitioned_ordered(context.child("ordered"));
2366                run_index_inserts_without_next(&mut index);
2367            }
2368        });
2369    }
2370
2371    fn run_index_delete_last_then_insert_while_done<I: Unordered<Value = u64>>(index: &mut I) {
2372        index.insert(b"k", 7);
2373        {
2374            let mut cur = index.get_mut(b"k").unwrap();
2375            assert_eq!(*cur.next().unwrap(), 7);
2376            cur.delete();
2377            assert!(cur.next().is_none());
2378            cur.insert(8);
2379            assert!(cur.next().is_none());
2380            cur.insert(9);
2381            assert!(cur.next().is_none());
2382        }
2383        assert_eq!(index.keys(), 1);
2384        assert_eq!(index.items(), 2);
2385        assert_eq!(index.get(b"k").copied().collect::<Vec<_>>(), vec![8, 9]);
2386    }
2387
2388    #[test_traced]
2389    fn test_hash_index_delete_last_then_insert_while_done() {
2390        let runner = deterministic::Runner::default();
2391        runner.start(|context| async move {
2392            let mut index = new_unordered(context);
2393            run_index_delete_last_then_insert_while_done(&mut index);
2394        });
2395    }
2396
2397    #[test_traced]
2398    fn test_ordered_index_delete_last_then_insert_while_done() {
2399        let runner = deterministic::Runner::default();
2400        runner.start(|context| async move {
2401            let mut index = new_ordered(context);
2402            run_index_delete_last_then_insert_while_done(&mut index);
2403        });
2404    }
2405
2406    #[test_traced]
2407    fn test_partitioned_index_delete_last_then_insert_while_done() {
2408        let runner = deterministic::Runner::default();
2409        runner.start(|context| async move {
2410            {
2411                let mut index = new_partitioned_unordered(context.child("unordered"));
2412                run_index_delete_last_then_insert_while_done(&mut index);
2413            }
2414            {
2415                let mut index = new_partitioned_ordered(context.child("ordered"));
2416                run_index_delete_last_then_insert_while_done(&mut index);
2417            }
2418        });
2419    }
2420
2421    fn run_index_drop_mid_iteration_preserves_chain<I: Unordered<Value = u64>>(index: &mut I) {
2422        for i in 0..5 {
2423            index.insert(b"z", i);
2424        }
2425        let expected = values(index, b"z");
2426        {
2427            let mut cur = index.get_mut(b"z").unwrap();
2428            cur.next();
2429            cur.next();
2430        }
2431        assert_eq!(values(index, b"z"), expected);
2432    }
2433
2434    #[test_traced]
2435    fn test_hash_index_drop_mid_iteration_preserves_chain() {
2436        let runner = deterministic::Runner::default();
2437        runner.start(|context| async move {
2438            let mut index = new_unordered(context);
2439            run_index_drop_mid_iteration_preserves_chain(&mut index);
2440        });
2441    }
2442
2443    #[test_traced]
2444    fn test_ordered_index_drop_mid_iteration_preserves_chain() {
2445        let runner = deterministic::Runner::default();
2446        runner.start(|context| async move {
2447            let mut index = new_ordered(context);
2448            run_index_drop_mid_iteration_preserves_chain(&mut index);
2449        });
2450    }
2451
2452    #[test_traced]
2453    fn test_partitioned_index_drop_mid_iteration_preserves_chain() {
2454        let runner = deterministic::Runner::default();
2455        runner.start(|context| async move {
2456            {
2457                let mut index = new_partitioned_unordered(context.child("unordered"));
2458                run_index_drop_mid_iteration_preserves_chain(&mut index);
2459            }
2460            {
2461                let mut index = new_partitioned_ordered(context.child("ordered"));
2462                run_index_drop_mid_iteration_preserves_chain(&mut index);
2463            }
2464        });
2465    }
2466
2467    fn run_index_update_before_next_panics<I: Unordered<Value = u64>>(index: &mut I) {
2468        index.insert(b"p", 1);
2469        let mut cur = index.get_mut(b"p").unwrap();
2470        cur.update(2);
2471    }
2472
2473    #[test_traced]
2474    #[should_panic(expected = "must call Cursor::next()")]
2475    fn test_hash_index_update_before_next_panics() {
2476        let runner = deterministic::Runner::default();
2477        runner.start(|context| async move {
2478            let mut index = new_unordered(context);
2479            run_index_update_before_next_panics(&mut index);
2480        });
2481    }
2482
2483    #[test_traced]
2484    #[should_panic(expected = "must call Cursor::next()")]
2485    fn test_ordered_index_update_before_next_panics() {
2486        let runner = deterministic::Runner::default();
2487        runner.start(|context| async move {
2488            let mut index = new_ordered(context);
2489            run_index_update_before_next_panics(&mut index);
2490        });
2491    }
2492
2493    #[test_traced]
2494    #[should_panic(expected = "must call Cursor::next()")]
2495    fn test_partitioned_index_update_before_next_panics() {
2496        let runner = deterministic::Runner::default();
2497        runner.start(|context| async move {
2498            {
2499                let mut index = new_partitioned_unordered(context.child("unordered"));
2500                run_index_update_before_next_panics(&mut index);
2501            }
2502            {
2503                let mut index = new_partitioned_ordered(context.child("ordered"));
2504                run_index_update_before_next_panics(&mut index);
2505            }
2506        });
2507    }
2508
2509    fn run_index_entry_replacement_not_a_collision<I: Unordered<Value = u64>>(index: &mut I) {
2510        index.insert(b"a", 1);
2511        {
2512            let mut cur = index.get_mut(b"a").unwrap();
2513            cur.next();
2514            cur.delete();
2515            cur.next();
2516            cur.insert(2);
2517        }
2518        assert_eq!(index.keys(), 1);
2519        assert_eq!(index.items(), 1);
2520    }
2521
2522    #[test_traced]
2523    fn test_hash_index_entry_replacement_not_a_collision() {
2524        let runner = deterministic::Runner::default();
2525        runner.start(|context| async move {
2526            let mut index = new_unordered(context);
2527            run_index_entry_replacement_not_a_collision(&mut index);
2528        });
2529    }
2530
2531    #[test_traced]
2532    fn test_ordered_index_entry_replacement_not_a_collision() {
2533        let runner = deterministic::Runner::default();
2534        runner.start(|context| async move {
2535            let mut index = new_ordered(context);
2536            run_index_entry_replacement_not_a_collision(&mut index);
2537        });
2538    }
2539
2540    #[test_traced]
2541    fn test_partitioned_index_entry_replacement_not_a_collision() {
2542        let runner = deterministic::Runner::default();
2543        runner.start(|context| async move {
2544            {
2545                let mut index = new_partitioned_unordered(context.child("unordered"));
2546                run_index_entry_replacement_not_a_collision(&mut index);
2547            }
2548            {
2549                let mut index = new_partitioned_ordered(context.child("ordered"));
2550                run_index_entry_replacement_not_a_collision(&mut index);
2551            }
2552        });
2553    }
2554
2555    /// Exercises a single translated key holding a very large overflow chain, ensuring inserts and
2556    /// the resulting `Vec` overflow stay correct at scale.
2557    fn run_index_large_collision_chain<I: Unordered<Value = u64>>(index: &mut I) {
2558        const ITEMS: usize = 50_000;
2559        for i in 0..ITEMS {
2560            index.insert(b"", i as u64);
2561        }
2562        assert_eq!(index.keys(), 1);
2563        assert_eq!(index.items(), ITEMS);
2564        let expected: Vec<u64> = (0..ITEMS as u64).collect();
2565        assert_values(index, b"", &expected);
2566    }
2567
2568    #[test_traced]
2569    fn test_hash_index_large_collision_chain() {
2570        let runner = deterministic::Runner::default();
2571        runner.start(|context| async move {
2572            let mut index = new_unordered(context);
2573            run_index_large_collision_chain(&mut index);
2574        });
2575    }
2576
2577    #[test_traced]
2578    fn test_ordered_index_large_collision_chain() {
2579        let runner = deterministic::Runner::default();
2580        runner.start(|context| async move {
2581            let mut index = new_ordered(context);
2582            run_index_large_collision_chain(&mut index);
2583        });
2584    }
2585
2586    #[test_traced]
2587    fn test_partitioned_index_large_collision_chain() {
2588        let runner = deterministic::Runner::default();
2589        runner.start(|context| async move {
2590            {
2591                let mut index = new_partitioned_unordered(context.child("unordered"));
2592                run_index_large_collision_chain(&mut index);
2593            }
2594            {
2595                let mut index = new_partitioned_ordered(context.child("ordered"));
2596                run_index_large_collision_chain(&mut index);
2597            }
2598        });
2599    }
2600}