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