From 8261455019db2fc28f3f1aa11855cfaaa6a8422b Mon Sep 17 00:00:00 2001 From: Egor Suvorov Date: Thu, 24 Nov 2022 04:46:25 +0200 Subject: [PATCH] persistent_range_query: add layer_map_test --- .../tests/layer_map_test.rs | 295 ++++++++++++++++++ 1 file changed, 295 insertions(+) create mode 100644 libs/persistent_range_query/tests/layer_map_test.rs diff --git a/libs/persistent_range_query/tests/layer_map_test.rs b/libs/persistent_range_query/tests/layer_map_test.rs new file mode 100644 index 0000000000..b26b004781 --- /dev/null +++ b/libs/persistent_range_query/tests/layer_map_test.rs @@ -0,0 +1,295 @@ +use persistent_range_query::naive::{IndexableKey, NaiveVecStorage}; +use persistent_range_query::ops::SameElementsInitializer; +use persistent_range_query::segment_tree::{MidpointableKey, PersistentSegmentTree}; +use persistent_range_query::{ + LazyRangeInitializer, PersistentVecStorage, RangeModification, RangeQueryResult, + VecReadableVersion, +}; +use std::cmp::Ordering; +use std::ops::Range; + +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)] +struct PageIndex(u32); +type LayerId = String; + +impl IndexableKey for PageIndex { + fn index(all_keys: &Range, key: &Self) -> usize { + (key.0 as usize) - (all_keys.start.0 as usize) + } + + fn element_range(all_keys: &Range, index: usize) -> Range { + PageIndex(all_keys.start.0 + index as u32)..PageIndex(all_keys.start.0 + index as u32 + 1) + } +} + +impl MidpointableKey for PageIndex { + fn midpoint(range: &Range) -> Self { + PageIndex(range.start.0 + (range.end.0 - range.start.0) / 2) + } +} + +#[derive(Clone, Debug, Eq, PartialEq)] +struct LayerMapInformation { + // Only make sense for a range of length 1. + last_layer: Option, + last_image_layer: Option, + // Work for all ranges + max_delta_layers: (usize, Range), +} + +impl LayerMapInformation { + fn last_layers(&self) -> (&Option, &Option) { + (&self.last_layer, &self.last_image_layer) + } + + fn max_delta_layers(&self) -> &(usize, Range) { + &self.max_delta_layers + } +} + +fn merge_ranges(left: &Range, right: &Range) -> Range { + if left.is_empty() { + right.clone() + } else if right.is_empty() { + left.clone() + } else if left.end == right.start { + left.start..right.end + } else { + left.clone() + } +} + +impl RangeQueryResult for LayerMapInformation { + fn new_for_empty_range() -> Self { + LayerMapInformation { + last_layer: None, + last_image_layer: None, + max_delta_layers: (0, PageIndex(0)..PageIndex(0)), + } + } + + fn combine( + left: &Self, + _left_range: &Range, + right: &Self, + _right_range: &Range, + ) -> Self { + // Note that either range may be empty. + LayerMapInformation { + last_layer: left + .last_layer + .as_ref() + .or_else(|| right.last_layer.as_ref()) + .cloned(), + last_image_layer: left + .last_image_layer + .as_ref() + .or_else(|| right.last_image_layer.as_ref()) + .cloned(), + max_delta_layers: match left.max_delta_layers.0.cmp(&right.max_delta_layers.0) { + Ordering::Less => right.max_delta_layers.clone(), + Ordering::Greater => left.max_delta_layers.clone(), + Ordering::Equal => ( + left.max_delta_layers.0, + merge_ranges(&left.max_delta_layers.1, &right.max_delta_layers.1), + ), + }, + } + } + + fn add( + left: &mut Self, + left_range: &Range, + right: &Self, + right_range: &Range, + ) { + *left = Self::combine(&left, left_range, right, right_range); + } +} + +#[derive(Clone, Debug)] +struct AddDeltaLayers { + last_layer: LayerId, + count: usize, +} + +#[derive(Clone, Debug)] +struct LayerMapModification { + add_image_layer: Option, + add_delta_layers: Option, +} + +impl LayerMapModification { + fn add_image_layer(layer: impl Into) -> Self { + LayerMapModification { + add_image_layer: Some(layer.into()), + add_delta_layers: None, + } + } + + fn add_delta_layer(layer: impl Into) -> Self { + LayerMapModification { + add_image_layer: None, + add_delta_layers: Some(AddDeltaLayers { + last_layer: layer.into(), + count: 1, + }), + } + } +} + +impl RangeModification for LayerMapModification { + type Result = LayerMapInformation; + + fn no_op() -> Self { + LayerMapModification { + add_image_layer: None, + add_delta_layers: None, + } + } + + fn is_no_op(&self) -> bool { + self.add_image_layer.is_none() && self.add_delta_layers.is_none() + } + + fn is_reinitialization(&self) -> bool { + self.add_image_layer.is_some() + } + + fn apply(&self, result: &mut Self::Result, range: &Range) { + if let Some(layer) = &self.add_image_layer { + result.last_layer = Some(layer.clone()); + result.last_image_layer = Some(layer.clone()); + result.max_delta_layers = (0, range.clone()); + } + if let Some(AddDeltaLayers { last_layer, count }) = &self.add_delta_layers { + result.last_layer = Some(last_layer.clone()); + result.max_delta_layers.0 += count; + } + } + + fn compose(later: &Self, earlier: &mut Self) { + if later.add_image_layer.is_some() { + *earlier = later.clone(); + return; + } + if let Some(AddDeltaLayers { last_layer, count }) = &later.add_delta_layers { + let res = earlier.add_delta_layers.get_or_insert(AddDeltaLayers { + last_layer: LayerId::default(), + count: 0, + }); + res.last_layer = last_layer.clone(); + res.count += count; + } + } +} + +impl LazyRangeInitializer for SameElementsInitializer<()> { + fn get(&self, range: &Range) -> LayerMapInformation { + LayerMapInformation { + last_layer: None, + last_image_layer: None, + max_delta_layers: (0, range.clone()), + } + } +} + +fn test_layer_map< + S: PersistentVecStorage, PageIndex>, +>() { + let mut s = S::new( + PageIndex(0)..PageIndex(100), + SameElementsInitializer::new(()), + ); + s.modify( + &(PageIndex(0)..PageIndex(70)), + &LayerMapModification::add_image_layer("Img0..70"), + ); + s.modify( + &(PageIndex(50)..PageIndex(100)), + &LayerMapModification::add_image_layer("Img50..100"), + ); + s.modify( + &(PageIndex(10)..PageIndex(60)), + &LayerMapModification::add_delta_layer("Delta10..60"), + ); + let s_before_last_delta = s.freeze(); + s.modify( + &(PageIndex(20)..PageIndex(80)), + &LayerMapModification::add_delta_layer("Delta20..80"), + ); + + assert_eq!( + s.get(&(PageIndex(5)..PageIndex(6))).last_layers(), + (&Some("Img0..70".to_owned()), &Some("Img0..70".to_owned())) + ); + assert_eq!( + s.get(&(PageIndex(15)..PageIndex(16))).last_layers(), + ( + &Some("Delta10..60".to_owned()), + &Some("Img0..70".to_owned()) + ) + ); + assert_eq!( + s.get(&(PageIndex(25)..PageIndex(26))).last_layers(), + ( + &Some("Delta20..80".to_owned()), + &Some("Img0..70".to_owned()) + ) + ); + assert_eq!( + s.get(&(PageIndex(65)..PageIndex(66))).last_layers(), + ( + &Some("Delta20..80".to_owned()), + &Some("Img50..100".to_owned()) + ) + ); + assert_eq!( + s.get(&(PageIndex(95)..PageIndex(96))).last_layers(), + ( + &Some("Img50..100".to_owned()), + &Some("Img50..100".to_owned()) + ) + ); + + assert_eq!( + s.get(&(PageIndex(0)..PageIndex(100))).max_delta_layers(), + &(2, PageIndex(20)..PageIndex(60)), + ); + assert_eq!( + *s_before_last_delta + .get(&(PageIndex(0)..PageIndex(100))) + .max_delta_layers(), + (1, PageIndex(10)..PageIndex(60)), + ); + + assert_eq!( + *s.get(&(PageIndex(10)..PageIndex(30))).max_delta_layers(), + (2, PageIndex(20)..PageIndex(30)) + ); + assert_eq!( + *s.get(&(PageIndex(10)..PageIndex(20))).max_delta_layers(), + (1, PageIndex(10)..PageIndex(20)) + ); + + assert_eq!( + *s.get(&(PageIndex(70)..PageIndex(80))).max_delta_layers(), + (1, PageIndex(70)..PageIndex(80)) + ); + assert_eq!( + *s_before_last_delta + .get(&(PageIndex(70)..PageIndex(80))) + .max_delta_layers(), + (0, PageIndex(70)..PageIndex(80)) + ); +} + +#[test] +fn test_naive() { + test_layer_map::>(); +} + +#[test] +fn test_segment_tree() { + test_layer_map::>(); +}