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