Add facet incremental indexing snapshot tests + fix bug

This commit is contained in:
Loïc Lecrenier 2022-09-01 11:33:50 +02:00 committed by Loïc Lecrenier
parent 07ff92c663
commit 36296bbb20
49 changed files with 1028 additions and 22 deletions

View file

@ -297,7 +297,7 @@ impl FacetsUpdateIncremental {
.prefix_iter::<_, ByteSlice, FacetGroupValueCodec>(&txn, &highest_level_prefix)?;
let mut to_add = vec![];
for _ in 0..group_size {
for _ in 0..self.min_level_size {
let mut first_key = None;
let mut values = RoaringBitmap::new();
for _ in 0..group_size {
@ -459,3 +459,680 @@ impl FacetsUpdateIncremental {
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::milli_snap;
use crate::{
heed_codec::facet::new::{
ordered_f64_codec::OrderedF64Codec, str_ref::StrRefCodec, FacetGroupValueCodec,
FacetKeyCodec, MyByteSlice,
},
search::facet::{get_highest_level, test::FacetIndex},
};
use heed::{types::ByteSlice, BytesDecode, BytesEncode};
use rand::Rng;
use rand::{seq::SliceRandom, SeedableRng};
use roaring::RoaringBitmap;
pub fn verify_structure_validity<C>(index: &FacetIndex<C>, field_id: u16)
where
for<'a> C: BytesDecode<'a> + BytesEncode<'a, EItem = <C as BytesDecode<'a>>::DItem>,
{
let FacetIndex { env, db, .. } = index;
let txn = env.write_txn().unwrap();
let mut field_id_prefix = vec![];
field_id_prefix.extend_from_slice(&field_id.to_be_bytes());
let highest_level = get_highest_level(&txn, index.db.content, field_id).unwrap();
txn.commit().unwrap();
let txn = env.read_txn().unwrap();
for level_no in (1..=highest_level).rev() {
let mut level_no_prefix = vec![];
level_no_prefix.extend_from_slice(&field_id.to_be_bytes());
level_no_prefix.push(level_no);
let mut iter = db
.content
.as_polymorph()
.prefix_iter::<_, ByteSlice, FacetGroupValueCodec>(&txn, &level_no_prefix)
.unwrap();
while let Some(el) = iter.next() {
let (key, value) = el.unwrap();
let key = FacetKeyCodec::<MyByteSlice>::bytes_decode(&key).unwrap();
let mut prefix_start_below = vec![];
prefix_start_below.extend_from_slice(&field_id.to_be_bytes());
prefix_start_below.push(level_no - 1);
prefix_start_below.extend_from_slice(&key.left_bound);
let start_below = {
let mut start_below_iter = db
.content
.as_polymorph()
.prefix_iter::<_, ByteSlice, FacetGroupValueCodec>(
&txn,
&prefix_start_below,
)
.unwrap();
let (key_bytes, _) = start_below_iter.next().unwrap().unwrap();
FacetKeyCodec::<MyByteSlice>::bytes_decode(&key_bytes).unwrap()
};
assert!(value.size > 0 && (value.size as usize) < db.max_group_size);
let mut actual_size = 0;
let mut values_below = RoaringBitmap::new();
let mut iter_below =
db.content.range(&txn, &(start_below..)).unwrap().take(value.size as usize);
while let Some(el) = iter_below.next() {
let (_, value) = el.unwrap();
actual_size += 1;
values_below |= value.bitmap;
}
assert_eq!(actual_size, value.size, "{key:?} start_below: {start_below:?}");
assert_eq!(value.bitmap, values_below);
}
}
}
#[test]
fn append() {
let index = FacetIndex::<OrderedF64Codec>::new(4, 8);
for i in 0..256u16 {
let mut bitmap = RoaringBitmap::new();
bitmap.insert(i as u32);
let mut txn = index.env.write_txn().unwrap();
index.insert(&mut txn, 0, &(i as f64), &bitmap);
txn.commit().unwrap();
}
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"));
}
#[test]
fn many_field_ids_append() {
let index = FacetIndex::<OrderedF64Codec>::new(4, 8);
for i in 0..256u16 {
let mut bitmap = RoaringBitmap::new();
bitmap.insert(i as u32);
let mut txn = index.env.write_txn().unwrap();
index.insert(&mut txn, 0, &(i as f64), &bitmap);
txn.commit().unwrap();
}
for i in 0..256u16 {
let mut bitmap = RoaringBitmap::new();
bitmap.insert(i as u32);
let mut txn = index.env.write_txn().unwrap();
index.insert(&mut txn, 2, &(i as f64), &bitmap);
txn.commit().unwrap();
}
for i in 0..256u16 {
let mut bitmap = RoaringBitmap::new();
bitmap.insert(i as u32);
let mut txn = index.env.write_txn().unwrap();
index.insert(&mut txn, 1, &(i as f64), &bitmap);
txn.commit().unwrap();
}
verify_structure_validity(&index, 0);
verify_structure_validity(&index, 1);
verify_structure_validity(&index, 2);
milli_snap!(format!("{index}"));
}
#[test]
fn many_field_ids_prepend() {
let index = FacetIndex::<OrderedF64Codec>::new(4, 8);
for i in (0..256).into_iter().rev() {
let mut bitmap = RoaringBitmap::new();
bitmap.insert(i as u32);
let mut txn = index.env.write_txn().unwrap();
index.insert(&mut txn, 0, &(i as f64), &bitmap);
txn.commit().unwrap();
}
for i in (0..256).into_iter().rev() {
let mut bitmap = RoaringBitmap::new();
bitmap.insert(i as u32);
let mut txn = index.env.write_txn().unwrap();
index.insert(&mut txn, 2, &(i as f64), &bitmap);
txn.commit().unwrap();
}
for i in (0..256).into_iter().rev() {
let mut bitmap = RoaringBitmap::new();
bitmap.insert(i as u32);
let mut txn = index.env.write_txn().unwrap();
index.insert(&mut txn, 1, &(i as f64), &bitmap);
txn.commit().unwrap();
}
verify_structure_validity(&index, 0);
verify_structure_validity(&index, 1);
verify_structure_validity(&index, 2);
milli_snap!(format!("{index}"));
}
#[test]
fn prepend() {
let index = FacetIndex::<OrderedF64Codec>::new(4, 8);
let mut txn = index.env.write_txn().unwrap();
for i in (0..256).into_iter().rev() {
let mut bitmap = RoaringBitmap::new();
bitmap.insert(i);
index.insert(&mut txn, 0, &(i as f64), &bitmap);
}
txn.commit().unwrap();
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"));
}
#[test]
fn shuffled() {
let index = FacetIndex::<OrderedF64Codec>::new(4, 8);
let mut txn = index.env.write_txn().unwrap();
let mut keys = (0..256).into_iter().collect::<Vec<_>>();
let mut rng = rand::rngs::SmallRng::from_seed([0; 32]);
keys.shuffle(&mut rng);
for (_i, key) in keys.into_iter().enumerate() {
let mut bitmap = RoaringBitmap::new();
bitmap.insert(key);
index.insert(&mut txn, 0, &(key as f64), &bitmap);
}
txn.commit().unwrap();
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"));
}
#[test]
fn merge_values() {
let index = FacetIndex::<OrderedF64Codec>::new(4, 8);
let mut keys = (0..256).into_iter().collect::<Vec<_>>();
let mut rng = rand::rngs::SmallRng::from_seed([0; 32]);
keys.shuffle(&mut rng);
for (_i, key) in keys.into_iter().enumerate() {
let mut bitmap = RoaringBitmap::new();
bitmap.insert(key);
bitmap.insert(rng.gen_range(256..512));
verify_structure_validity(&index, 0);
let mut txn = index.env.write_txn().unwrap();
index.insert(&mut txn, 0, &(key as f64), &bitmap);
txn.commit().unwrap();
}
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"));
}
#[test]
fn delete_from_end() {
let index = FacetIndex::<OrderedF64Codec>::new(4, 8);
for i in 0..256 {
let mut bitmap = RoaringBitmap::new();
bitmap.insert(i);
verify_structure_validity(&index, 0);
let mut txn = index.env.write_txn().unwrap();
index.insert(&mut txn, 0, &(&(i as f64)), &bitmap);
txn.commit().unwrap();
}
for i in (200..256).into_iter().rev() {
verify_structure_validity(&index, 0);
let mut txn = index.env.write_txn().unwrap();
index.delete(&mut txn, 0, &(i as f64), i as u32);
txn.commit().unwrap();
}
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"), 200);
for i in (150..200).into_iter().rev() {
verify_structure_validity(&index, 0);
let mut txn = index.env.write_txn().unwrap();
index.delete(&mut txn, 0, &(i as f64), i as u32);
txn.commit().unwrap();
}
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"), 150);
for i in (100..150).into_iter().rev() {
verify_structure_validity(&index, 0);
let mut txn = index.env.write_txn().unwrap();
index.delete(&mut txn, 0, &(i as f64), i as u32);
txn.commit().unwrap();
}
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"), 100);
for i in (17..100).into_iter().rev() {
verify_structure_validity(&index, 0);
let mut txn = index.env.write_txn().unwrap();
index.delete(&mut txn, 0, &(i as f64), i as u32);
txn.commit().unwrap();
}
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"), 17);
let mut txn = index.env.write_txn().unwrap();
for i in (15..17).into_iter().rev() {
index.delete(&mut txn, 0, &(i as f64), i as u32);
}
txn.commit().unwrap();
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"), 15);
for i in (0..15).into_iter().rev() {
verify_structure_validity(&index, 0);
let mut txn = index.env.write_txn().unwrap();
index.delete(&mut txn, 0, &(i as f64), i as u32);
txn.commit().unwrap();
}
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"), 0);
}
#[test]
fn delete_from_start() {
let index = FacetIndex::<OrderedF64Codec>::new(4, 8);
for i in 0..256 {
let mut bitmap = RoaringBitmap::new();
bitmap.insert(i);
verify_structure_validity(&index, 0);
let mut txn = index.env.write_txn().unwrap();
index.insert(&mut txn, 0, &(i as f64), &bitmap);
txn.commit().unwrap();
}
for i in 0..128 {
let mut txn = index.env.write_txn().unwrap();
index.delete(&mut txn, 0, &(i as f64), i as u32);
txn.commit().unwrap();
}
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"), 127);
for i in 128..216 {
verify_structure_validity(&index, 0);
let mut txn = index.env.write_txn().unwrap();
index.delete(&mut txn, 0, &(i as f64), i as u32);
txn.commit().unwrap();
}
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"), 215);
for i in 216..256 {
verify_structure_validity(&index, 0);
let mut txn = index.env.write_txn().unwrap();
index.delete(&mut txn, 0, &(i as f64), i as u32);
txn.commit().unwrap();
}
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"), 255);
}
#[test]
fn delete_shuffled() {
let index = FacetIndex::<OrderedF64Codec>::new(4, 8);
for i in 0..256 {
let mut bitmap = RoaringBitmap::new();
bitmap.insert(i);
verify_structure_validity(&index, 0);
let mut txn = index.env.write_txn().unwrap();
index.insert(&mut txn, 0, &(i as f64), &bitmap);
txn.commit().unwrap();
}
let mut keys = (0..256).into_iter().collect::<Vec<_>>();
let mut rng = rand::rngs::SmallRng::from_seed([0; 32]);
keys.shuffle(&mut rng);
for i in 0..128 {
let key = keys[i];
verify_structure_validity(&index, 0);
let mut txn = index.env.write_txn().unwrap();
index.delete(&mut txn, 0, &(key as f64), key as u32);
txn.commit().unwrap();
}
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"), 127);
for i in 128..216 {
let key = keys[i];
verify_structure_validity(&index, 0);
let mut txn = index.env.write_txn().unwrap();
index.delete(&mut txn, 0, &(key as f64), key as u32);
txn.commit().unwrap();
}
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"), 215);
for i in 216..256 {
let key = keys[i];
verify_structure_validity(&index, 0);
let mut txn = index.env.write_txn().unwrap();
index.delete(&mut txn, 0, &(key as f64), key as u32);
txn.commit().unwrap();
}
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"), 255);
}
#[test]
fn in_place_level0_insert() {
let index = FacetIndex::<OrderedF64Codec>::new(4, 8);
let mut keys = (0..16).into_iter().collect::<Vec<_>>();
let mut rng = rand::rngs::SmallRng::from_seed([0; 32]);
keys.shuffle(&mut rng);
for i in 0..4 {
for &key in keys.iter() {
let mut bitmap = RoaringBitmap::new();
bitmap.insert(rng.gen_range(i * 256..(i + 1) * 256));
verify_structure_validity(&index, 0);
let mut txn = index.env.write_txn().unwrap();
index.insert(&mut txn, 0, &(key as f64), &bitmap);
txn.commit().unwrap();
}
}
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"));
}
#[test]
fn in_place_level0_delete() {
let index = FacetIndex::<OrderedF64Codec>::new(4, 8);
let mut keys = (0..64).into_iter().collect::<Vec<_>>();
let mut rng = rand::rngs::SmallRng::from_seed([0; 32]);
keys.shuffle(&mut rng);
for &key in keys.iter() {
let mut bitmap = RoaringBitmap::new();
bitmap.insert(key);
bitmap.insert(key + 100);
verify_structure_validity(&index, 0);
let mut txn = index.env.write_txn().unwrap();
index.insert(&mut txn, 0, &(key as f64), &bitmap);
txn.commit().unwrap();
}
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"));
for &key in keys.iter() {
verify_structure_validity(&index, 0);
let mut txn = index.env.write_txn().unwrap();
index.delete(&mut txn, 0, &(key as f64), key + 100);
txn.commit().unwrap();
}
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"));
}
#[test]
fn shuffle_merge_string() {
let index = FacetIndex::<StrRefCodec>::new(4, 8);
let mut keys = (1000..1064).into_iter().collect::<Vec<_>>();
let mut rng = rand::rngs::SmallRng::from_seed([0; 32]);
keys.shuffle(&mut rng);
for &key in keys.iter() {
let mut bitmap = RoaringBitmap::new();
bitmap.insert(key);
bitmap.insert(key + 100);
verify_structure_validity(&index, 0);
let mut txn = index.env.write_txn().unwrap();
index.insert(&mut txn, 0, &format!("{key:x}").as_str(), &bitmap);
txn.commit().unwrap();
}
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"), 1);
for &key in keys.iter() {
verify_structure_validity(&index, 0);
let mut txn = index.env.write_txn().unwrap();
index.delete(&mut txn, 0, &format!("{key:x}").as_str(), key + 100);
txn.commit().unwrap();
}
verify_structure_validity(&index, 0);
milli_snap!(format!("{index}"), 2);
}
// fuzz tests
}
// #[cfg(all(test, fuzzing))]
// mod fuzz {
// use crate::codec::U16Codec;
// use super::tests::verify_structure_validity;
// use super::*;
// use fuzzcheck::mutators::integer_within_range::U16WithinRangeMutator;
// use fuzzcheck::DefaultMutator;
// use roaring::RoaringBitmap;
// use std::collections::BTreeMap;
// use std::collections::HashMap;
// #[derive(Default)]
// pub struct TrivialDatabase<T> {
// pub elements: BTreeMap<u16, BTreeMap<T, RoaringBitmap>>,
// }
// impl<T> TrivialDatabase<T>
// where
// T: Ord + Clone + Copy + Eq + std::fmt::Debug,
// {
// pub fn insert(&mut self, field_id: u16, new_key: T, new_values: &RoaringBitmap) {
// if new_values.is_empty() {
// return;
// }
// let values_field_id = self.elements.entry(field_id).or_default();
// let values = values_field_id.entry(new_key).or_default();
// *values |= new_values;
// }
// pub fn delete(&mut self, field_id: u16, key: T, value: u32) {
// if let Some(values_field_id) = self.elements.get_mut(&field_id) {
// if let Some(values) = values_field_id.get_mut(&key) {
// values.remove(value);
// if values.is_empty() {
// values_field_id.remove(&key);
// }
// }
// if values_field_id.is_empty() {
// self.elements.remove(&field_id);
// }
// }
// }
// }
// #[derive(Clone, DefaultMutator, serde::Serialize, serde::Deserialize)]
// struct Operation<Key> {
// key: Key,
// #[field_mutator(U16WithinRangeMutator = { U16WithinRangeMutator::new(..=3) })]
// field_id: u16,
// kind: OperationKind,
// }
// #[derive(Clone, DefaultMutator, serde::Serialize, serde::Deserialize)]
// enum OperationKind {
// Insert(Vec<u8>),
// Delete(u8),
// }
// fn compare_with_trivial_database(
// tempdir: Rc<TempDir>,
// group_size: u8,
// max_group_size: u8,
// operations: &[Operation<u16>],
// ) {
// let index = FacetIndex::<OrderedF64Codec>::open_from_tempdir(tempdir, group_size, max_group_size);
// let mut trivial_db = TrivialDatabase::<u16>::default();
// let mut value_to_keys = HashMap::<u8, Vec<u16>>::new();
// let mut txn = index.env.write_txn().unwrap();
// for Operation { key, field_id, kind } in operations {
// match kind {
// OperationKind::Insert(values) => {
// let mut bitmap = RoaringBitmap::new();
// for value in values {
// bitmap.insert(*value as u32);
// value_to_keys.entry(*value).or_default().push(*key);
// }
// index.insert(&mut txn, *field_id, key, &bitmap);
// trivial_db.insert(*field_id, *key, &bitmap);
// }
// OperationKind::Delete(value) => {
// if let Some(keys) = value_to_keys.get(value) {
// for key in keys {
// index.delete(&mut txn, *field_id, key, *value as u32);
// trivial_db.delete(*field_id, *key, *value as u32);
// }
// }
// }
// }
// }
// for (field_id, values_field_id) in trivial_db.elements.iter() {
// let level0iter = index
// .db
// .content
// .as_polymorph()
// .prefix_iter::<_, ByteSlice, FacetGroupValueCodec>(
// &mut txn,
// &field_id.to_be_bytes(),
// )
// .unwrap();
// for ((key, values), group) in values_field_id.iter().zip(level0iter) {
// let (group_key, group_values) = group.unwrap();
// let group_key = FacetKeyCodec::<U16Codec>::bytes_decode(group_key).unwrap();
// assert_eq!(key, &group_key.left_bound);
// assert_eq!(values, &group_values.bitmap);
// }
// }
// txn.commit().unwrap();
// let mut txn = index.env.write_txn().unwrap();
// for (field_id, values_field_id) in trivial_db.elements.iter() {
// let level0iter = index
// .db
// .content
// .as_polymorph()
// .prefix_iter::<_, ByteSlice, FacetGroupValueCodec>(&txn, &field_id.to_be_bytes())
// .unwrap();
// for ((key, values), group) in values_field_id.iter().zip(level0iter) {
// let (group_key, group_values) = group.unwrap();
// let group_key = FacetKeyCodec::<U16Codec>::bytes_decode(group_key).unwrap();
// assert_eq!(key, &group_key.left_bound);
// assert_eq!(values, &group_values.bitmap);
// }
// verify_structure_validity(&index, *field_id);
// }
// index.db.content.clear(&mut txn).unwrap();
// txn.commit().unwrap();
// }
// #[test]
// fn fuzz() {
// let tempdir = Rc::new(TempDir::new().unwrap());
// let tempdir_cloned = tempdir.clone();
// let result = fuzzcheck::fuzz_test(move |x: &(u8, u8, Vec<Operation<u16>>)| {
// compare_with_trivial_database(tempdir_cloned.clone(), x.0, x.1, &x.2)
// })
// .default_mutator()
// .serde_serializer()
// .default_sensor_and_pool_with_custom_filter(|file, function| {
// if file.is_relative()
// && !function.contains("serde")
// && !function.contains("tests::")
// && !function.contains("fuzz::")
// && !function.contains("display_bitmap")
// {
// true
// } else {
// false
// }
// })
// .arguments_from_cargo_fuzzcheck()
// .launch();
// assert!(!result.found_test_failure);
// }
// #[test]
// fn reproduce_bug() {
// let operations = r#"
// [
// {"key":0, "field_id": 0, "kind":{"Insert":[109]}},
// {"key":143, "field_id": 0, "kind":{"Insert":[243]}},
// {"key":90, "field_id": 0, "kind":{"Insert":[217]}},
// {"key":172, "field_id": 0, "kind":{"Insert":[94]}},
// {"key":27, "field_id": 0, "kind":{"Insert":[4]}},
// {"key":124, "field_id": 0, "kind":{"Insert":[0]}},
// {"key":123, "field_id": 0, "kind":{"Insert":[0]}},
// {"key":67, "field_id": 0, "kind":{"Insert":[109]}},
// {"key":13, "field_id": 0, "kind":{"Insert":[0]}},
// {"key":162, "field_id": 0, "kind":{"Insert":[213]}},
// {"key":235, "field_id": 0, "kind":{"Insert":[67]}},
// {"key":251, "field_id": 0, "kind":{"Insert":[50]}},
// {"key":218, "field_id": 0, "kind":{"Insert":[164]}},
// {"key":166, "field_id": 0, "kind":{"Insert":[67]}},
// {"key":64, "field_id": 0, "kind":{"Insert":[61]}},
// {"key":183, "field_id": 0, "kind":{"Insert":[210]}},
// {"key":250, "field_id": 0, "kind":{"Delete":50}}
// ]
// "#;
// let operations: Vec<Operation<u16>> = serde_json::from_str(operations).unwrap();
// let tempdir = TempDir::new().unwrap();
// compare_with_trivial_database(Rc::new(tempdir), 4, 8, &operations);
// }
// #[test]
// fn reproduce_bug2() {
// let operations = r#"
// [
// {"key":102, "field_id": 0, "kind":{"Insert":[122]}},
// {"key":73, "field_id": 0, "kind":{"Insert":[132]}},
// {"key":20, "field_id": 0, "kind":{"Insert":[215]}},
// {"key":39, "field_id": 0, "kind":{"Insert":[152]}},
// {"key":151, "field_id": 0, "kind":{"Insert":[226]}},
// {"key":17, "field_id": 0, "kind":{"Insert":[101]}},
// {"key":74, "field_id": 0, "kind":{"Insert":[210]}},
// {"key":2, "field_id": 0, "kind":{"Insert":[130]}},
// {"key":64, "field_id": 0, "kind":{"Insert":[180]}},
// {"key":83, "field_id": 0, "kind":{"Insert":[250]}},
// {"key":80, "field_id": 0, "kind":{"Insert":[210]}},
// {"key":113, "field_id": 0, "kind":{"Insert":[63]}},
// {"key":201, "field_id": 0, "kind":{"Insert":[210]}},
// {"key":200, "field_id": 0, "kind":{"Insert":[5]}},
// {"key":93, "field_id": 0, "kind":{"Insert":[98]}},
// {"key":162, "field_id": 0, "kind":{"Insert":[5]}},
// {"key":80, "field_id": 0, "kind":{"Delete":210}}
// ]
// "#;
// let operations: Vec<Operation<u16>> = serde_json::from_str(operations).unwrap();
// let tempdir = TempDir::new().unwrap();
// compare_with_trivial_database(Rc::new(tempdir), 4, 8, &operations);
// }
// #[test]
// fn reproduce_bug3() {
// let operations = r#"
// [
// {"key":27488, "field_id": 0, "kind":{"Insert":[206]}},
// {"key":64716, "field_id": 0, "kind":{"Insert":[216]}},
// {"key":60886, "field_id": 0, "kind":{"Insert":[206]}},
// {"key":59509, "field_id": 0, "kind":{"Insert":[187,231]}},
// {"key":55057, "field_id": 0, "kind":{"Insert":[37]}},
// {"key":45200, "field_id": 0, "kind":{"Insert":[206]}},
// {"key":55056, "field_id": 0, "kind":{"Insert":[37]}},
// {"key":63679, "field_id": 0, "kind":{"Insert":[206]}},
// {"key":52155, "field_id": 0, "kind":{"Insert":[74]}},
// {"key":20648, "field_id": 0, "kind":{"Insert":[47,138,157]}}
// ]
// "#;
// let operations: Vec<Operation<u16>> = serde_json::from_str(operations).unwrap();
// let tempdir = TempDir::new().unwrap();
// compare_with_trivial_database(Rc::new(tempdir), 0, 7, &operations);
// }
// #[test]
// fn reproduce_bug4() {
// let operations = r#"
// [{"key":63499, "field_id": 0, "kind":{"Insert":[87]}},{"key":25374, "field_id": 0, "kind":{"Insert":[14]}},{"key":64481, "field_id": 0, "kind":{"Delete":87}},{"key":23038, "field_id": 0, "kind":{"Insert":[173]}},{"key":14862, "field_id": 0, "kind":{"Insert":[8]}},{"key":13145, "field_id": 0, "kind":{"Insert":[5,64]}},{"key":23446, "field_id": 0, "kind":{"Insert":[86,59]}},{"key":17972, "field_id": 0, "kind":{"Insert":[58,137]}},{"key":21273, "field_id": 0, "kind":{"Insert":[121,132,81,147]}},{"key":28264, "field_id": 0, "kind":{"Insert":[36]}},{"key":46659, "field_id": 0, "kind":{"Insert":[]}}]
// "#;
// let operations: Vec<Operation<u16>> = serde_json::from_str(operations).unwrap();
// let tempdir = TempDir::new().unwrap();
// compare_with_trivial_database(Rc::new(tempdir), 2, 1, &operations);
// }
// }