Add fragmentation support
This commit is contained in:
188
libraries/persistent_store/tests/fragment.rs
Normal file
188
libraries/persistent_store/tests/fragment.rs
Normal file
@@ -0,0 +1,188 @@
|
||||
// Copyright 2021 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use persistent_store::fragment;
|
||||
|
||||
mod config;
|
||||
|
||||
#[test]
|
||||
fn read_empty_entry() {
|
||||
let store = config::MINIMAL.new_store();
|
||||
assert_eq!(fragment::read(&store, &(0..4)), Ok(None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_single_chunk() {
|
||||
let mut store = config::MINIMAL.new_store();
|
||||
let value = b"hello".to_vec();
|
||||
assert_eq!(store.insert(0, &value), Ok(()));
|
||||
assert_eq!(fragment::read(&store, &(0..4)), Ok(Some(value)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_multiple_chunks() {
|
||||
let mut store = config::MINIMAL.new_store();
|
||||
let value: Vec<_> = (0..60).collect();
|
||||
assert_eq!(store.insert(0, &value[..52]), Ok(()));
|
||||
assert_eq!(store.insert(1, &value[52..]), Ok(()));
|
||||
assert_eq!(fragment::read(&store, &(0..4)), Ok(Some(value)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_range_first_chunk() {
|
||||
let mut store = config::MINIMAL.new_store();
|
||||
let value: Vec<_> = (0..60).collect();
|
||||
assert_eq!(store.insert(0, &value[..52]), Ok(()));
|
||||
assert_eq!(store.insert(1, &value[52..]), Ok(()));
|
||||
assert_eq!(
|
||||
fragment::read_range(&store, &(0..4), 0..10),
|
||||
Ok(Some((0..10).collect()))
|
||||
);
|
||||
assert_eq!(
|
||||
fragment::read_range(&store, &(0..4), 10..20),
|
||||
Ok(Some((10..20).collect()))
|
||||
);
|
||||
assert_eq!(
|
||||
fragment::read_range(&store, &(0..4), 40..52),
|
||||
Ok(Some((40..52).collect()))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_range_second_chunk() {
|
||||
let mut store = config::MINIMAL.new_store();
|
||||
let value: Vec<_> = (0..60).collect();
|
||||
assert_eq!(store.insert(0, &value[..52]), Ok(()));
|
||||
assert_eq!(store.insert(1, &value[52..]), Ok(()));
|
||||
assert_eq!(
|
||||
fragment::read_range(&store, &(0..4), 52..53),
|
||||
Ok(Some(vec![52]))
|
||||
);
|
||||
assert_eq!(
|
||||
fragment::read_range(&store, &(0..4), 53..54),
|
||||
Ok(Some(vec![53]))
|
||||
);
|
||||
assert_eq!(
|
||||
fragment::read_range(&store, &(0..4), 59..60),
|
||||
Ok(Some(vec![59]))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_range_both_chunks() {
|
||||
let mut store = config::MINIMAL.new_store();
|
||||
let value: Vec<_> = (0..60).collect();
|
||||
assert_eq!(store.insert(0, &value[..52]), Ok(()));
|
||||
assert_eq!(store.insert(1, &value[52..]), Ok(()));
|
||||
assert_eq!(
|
||||
fragment::read_range(&store, &(0..4), 40..60),
|
||||
Ok(Some((40..60).collect()))
|
||||
);
|
||||
assert_eq!(
|
||||
fragment::read_range(&store, &(0..4), 0..60),
|
||||
Ok(Some((0..60).collect()))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_range_outside() {
|
||||
let mut store = config::MINIMAL.new_store();
|
||||
let value: Vec<_> = (0..60).collect();
|
||||
assert_eq!(store.insert(0, &value[..52]), Ok(()));
|
||||
assert_eq!(store.insert(1, &value[52..]), Ok(()));
|
||||
assert_eq!(
|
||||
fragment::read_range(&store, &(0..4), 40..100),
|
||||
Ok(Some((40..60).collect()))
|
||||
);
|
||||
assert_eq!(
|
||||
fragment::read_range(&store, &(0..4), 60..100),
|
||||
Ok(Some(vec![]))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn write_single_chunk() {
|
||||
let mut store = config::MINIMAL.new_store();
|
||||
let value = b"hello".to_vec();
|
||||
assert_eq!(fragment::write(&mut store, &(0..4), &value), Ok(()));
|
||||
assert_eq!(store.find(0), Ok(Some(value)));
|
||||
assert_eq!(store.find(1), Ok(None));
|
||||
assert_eq!(store.find(2), Ok(None));
|
||||
assert_eq!(store.find(3), Ok(None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn write_multiple_chunks() {
|
||||
let mut store = config::MINIMAL.new_store();
|
||||
let value: Vec<_> = (0..60).collect();
|
||||
assert_eq!(fragment::write(&mut store, &(0..4), &value), Ok(()));
|
||||
assert_eq!(store.find(0), Ok(Some((0..52).collect())));
|
||||
assert_eq!(store.find(1), Ok(Some((52..60).collect())));
|
||||
assert_eq!(store.find(2), Ok(None));
|
||||
assert_eq!(store.find(3), Ok(None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn overwrite_less_chunks() {
|
||||
let mut store = config::MINIMAL.new_store();
|
||||
let value: Vec<_> = (0..60).collect();
|
||||
assert_eq!(store.insert(0, &value[..52]), Ok(()));
|
||||
assert_eq!(store.insert(1, &value[52..]), Ok(()));
|
||||
let value: Vec<_> = (42..69).collect();
|
||||
assert_eq!(fragment::write(&mut store, &(0..4), &value), Ok(()));
|
||||
assert_eq!(store.find(0), Ok(Some((42..69).collect())));
|
||||
assert_eq!(store.find(1), Ok(None));
|
||||
assert_eq!(store.find(2), Ok(None));
|
||||
assert_eq!(store.find(3), Ok(None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn overwrite_needed_chunks() {
|
||||
let mut store = config::MINIMAL.new_store();
|
||||
let mut value: Vec<_> = (0..60).collect();
|
||||
assert_eq!(store.insert(0, &value[..52]), Ok(()));
|
||||
assert_eq!(store.insert(1, &value[52..]), Ok(()));
|
||||
// Current lifetime is 2 words of overhead (2 insert) and 60 bytes of data.
|
||||
let mut lifetime = 2 + 60 / 4;
|
||||
assert_eq!(store.lifetime().unwrap().used(), lifetime);
|
||||
// Update the value.
|
||||
value.extend(60..80);
|
||||
assert_eq!(fragment::write(&mut store, &(0..4), &value), Ok(()));
|
||||
// Added lifetime is 1 word of overhead (1 insert) and (80 - 52) bytes of data.
|
||||
lifetime += 1 + (80 - 52) / 4;
|
||||
assert_eq!(store.lifetime().unwrap().used(), lifetime);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn delete_empty() {
|
||||
let mut store = config::MINIMAL.new_store();
|
||||
assert_eq!(fragment::delete(&mut store, &(0..4)), Ok(()));
|
||||
assert_eq!(store.find(0), Ok(None));
|
||||
assert_eq!(store.find(1), Ok(None));
|
||||
assert_eq!(store.find(2), Ok(None));
|
||||
assert_eq!(store.find(3), Ok(None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn delete_chunks() {
|
||||
let mut store = config::MINIMAL.new_store();
|
||||
let value: Vec<_> = (0..60).collect();
|
||||
assert_eq!(store.insert(0, &value[..52]), Ok(()));
|
||||
assert_eq!(store.insert(1, &value[52..]), Ok(()));
|
||||
assert_eq!(fragment::delete(&mut store, &(0..4)), Ok(()));
|
||||
assert_eq!(store.find(0), Ok(None));
|
||||
assert_eq!(store.find(1), Ok(None));
|
||||
assert_eq!(store.find(2), Ok(None));
|
||||
assert_eq!(store.find(3), Ok(None));
|
||||
}
|
||||
Reference in New Issue
Block a user