removed tests
This commit is contained in:
parent
82e386a48c
commit
4f1552fcdb
4 changed files with 0 additions and 734 deletions
284
Cargo.lock
generated
284
Cargo.lock
generated
|
|
@ -2,12 +2,6 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "2.0.1"
|
||||
|
|
@ -28,111 +22,11 @@ dependencies = [
|
|||
"virtue",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3"
|
||||
dependencies = [
|
||||
"bit-vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-vec"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
||||
|
||||
[[package]]
|
||||
name = "btree"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"proptest",
|
||||
"rand",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"wasip2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.178"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -144,31 +38,6 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proptest"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40"
|
||||
dependencies = [
|
||||
"bit-set",
|
||||
"bit-vec",
|
||||
"bitflags",
|
||||
"num-traits",
|
||||
"rand",
|
||||
"rand_chacha",
|
||||
"rand_xorshift",
|
||||
"regex-syntax",
|
||||
"rusty-fork",
|
||||
"tempfile",
|
||||
"unarray",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.42"
|
||||
|
|
@ -178,81 +47,6 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "5.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
|
||||
dependencies = [
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_xorshift"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusty-fork"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"quick-error",
|
||||
"tempfile",
|
||||
"wait-timeout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
|
|
@ -293,25 +87,6 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16"
|
||||
dependencies = [
|
||||
"fastrand",
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unarray"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.22"
|
||||
|
|
@ -329,62 +104,3 @@ name = "virtue"
|
|||
version = "0.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1"
|
||||
|
||||
[[package]]
|
||||
name = "wait-timeout"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasip2"
|
||||
version = "1.0.1+wasi-0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
|
||||
dependencies = [
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -5,6 +5,3 @@ edition = "2024"
|
|||
|
||||
[dependencies]
|
||||
bincode = "2.0.1"
|
||||
proptest = "1.9.0"
|
||||
rand = "0.9.2"
|
||||
tempfile = "3.23.0"
|
||||
|
|
|
|||
207
src/btree.rs
207
src/btree.rs
|
|
@ -388,210 +388,3 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::config::test_config::*;
|
||||
use crate::file_storage::FileStorage;
|
||||
use proptest::prelude::*;
|
||||
use std::collections::BTreeMap;
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
fn temp_storage() -> FileStorage {
|
||||
let file = NamedTempFile::new().unwrap();
|
||||
FileStorage::new(file.path().to_str().unwrap())
|
||||
}
|
||||
|
||||
fn arb_record() -> impl Strategy<Value = Record> {
|
||||
prop::array::uniform7(any::<i32>())
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum Op {
|
||||
Insert(Record),
|
||||
Find(i32),
|
||||
}
|
||||
|
||||
fn arb_op() -> impl Strategy<Value = Op> {
|
||||
prop_oneof![
|
||||
3 => arb_record().prop_map(Op::Insert),
|
||||
1 => any::<i32>().prop_map(Op::Find),
|
||||
]
|
||||
}
|
||||
|
||||
proptest! {
|
||||
#![proptest_config(ProptestConfig {
|
||||
cases: PROPTEST_CASES,
|
||||
..ProptestConfig::default()
|
||||
})]
|
||||
|
||||
#[test]
|
||||
fn prop_matches_btreemap(ops in prop::collection::vec(arb_op(), MIN_OPS..MAX_OPS)) {
|
||||
let storage = temp_storage();
|
||||
let mut tree = BPlusTree::open(storage);
|
||||
let mut model = BTreeMap::<i32, Record>::new();
|
||||
|
||||
for op in ops {
|
||||
match op {
|
||||
Op::Insert(record) => {
|
||||
tree.insert(record);
|
||||
model.insert(record[0], record);
|
||||
}
|
||||
Op::Find(key) => {
|
||||
prop_assert_eq!(tree.find(key), model.get(&key).copied());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proptest! {
|
||||
#![proptest_config(ProptestConfig {
|
||||
cases: PROPTEST_CASES,
|
||||
..ProptestConfig::default()
|
||||
})]
|
||||
|
||||
#[test]
|
||||
fn prop_all_inserted_findable(
|
||||
records in prop::collection::vec(arb_record(), MIN_RECORDS..MAX_RECORDS)
|
||||
) {
|
||||
let storage = temp_storage();
|
||||
let mut tree = BPlusTree::open(storage);
|
||||
let mut model = BTreeMap::<i32, Record>::new();
|
||||
|
||||
for rec in records {
|
||||
tree.insert(rec);
|
||||
model.insert(rec[0], rec);
|
||||
}
|
||||
|
||||
for (&key, &value) in &model {
|
||||
let found = tree.find(key);
|
||||
if found != Some(value) {
|
||||
// Debug output on failure
|
||||
println!("Failed to find key: {}", key);
|
||||
tree.dump_tree();
|
||||
}
|
||||
prop_assert_eq!(found, Some(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proptest! {
|
||||
#![proptest_config(ProptestConfig {
|
||||
cases: PROPTEST_CASES / 2,
|
||||
..ProptestConfig::default()
|
||||
})]
|
||||
|
||||
#[test]
|
||||
fn prop_sequential_inserts(start in any::<i32>(), count in 0usize..MAX_RECORDS/2) {
|
||||
let storage = temp_storage();
|
||||
let mut tree = BPlusTree::open(storage);
|
||||
let mut model = BTreeMap::<i32, Record>::new();
|
||||
|
||||
for i in 0..count {
|
||||
let key = start.wrapping_add(i as i32);
|
||||
let record = [key, 0, 0, 0, 0, 0, 0];
|
||||
tree.insert(record);
|
||||
model.insert(key, record);
|
||||
}
|
||||
|
||||
for (&key, &value) in &model {
|
||||
prop_assert_eq!(tree.find(key), Some(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proptest! {
|
||||
#![proptest_config(ProptestConfig {
|
||||
cases: PROPTEST_CASES / 2,
|
||||
..ProptestConfig::default()
|
||||
})]
|
||||
|
||||
#[test]
|
||||
fn prop_updates_overwrite(
|
||||
records in prop::collection::vec(arb_record(), 1..MAX_RECORDS/4)
|
||||
) {
|
||||
let storage = temp_storage();
|
||||
let mut tree = BPlusTree::open(storage);
|
||||
|
||||
for rec in &records {
|
||||
tree.insert(*rec);
|
||||
}
|
||||
|
||||
let mut final_values = BTreeMap::new();
|
||||
for rec in &records {
|
||||
let key = rec[0];
|
||||
let updated = [key, 99, 88, 77, 66, 55, 44];
|
||||
tree.insert(updated);
|
||||
final_values.insert(key, updated);
|
||||
}
|
||||
|
||||
for (&key, &value) in &final_values {
|
||||
prop_assert_eq!(tree.find(key), Some(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sanity_single_insert() {
|
||||
let storage = temp_storage();
|
||||
let mut tree = BPlusTree::open(storage);
|
||||
|
||||
let rec = [42, 1, 2, 3, 4, 5, 6];
|
||||
tree.insert(rec);
|
||||
|
||||
assert_eq!(tree.find(42), Some(rec));
|
||||
assert_eq!(tree.find(7), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sanity_update_overwrites() {
|
||||
let storage = temp_storage();
|
||||
let mut tree = BPlusTree::open(storage);
|
||||
|
||||
let r1 = [1, 1, 1, 1, 1, 1, 1];
|
||||
let r2 = [1, 9, 9, 9, 9, 9, 9];
|
||||
|
||||
tree.insert(r1);
|
||||
tree.insert(r2);
|
||||
|
||||
assert_eq!(tree.find(1), Some(r2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sanity_empty_tree() {
|
||||
let storage = temp_storage();
|
||||
let mut tree = BPlusTree::open(storage);
|
||||
|
||||
assert_eq!(tree.find(1), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sanity_multiple_inserts() {
|
||||
let storage = temp_storage();
|
||||
let mut tree = BPlusTree::open(storage);
|
||||
|
||||
for i in 0..20 {
|
||||
tree.insert([i, i, i, i, i, i, i]);
|
||||
}
|
||||
|
||||
for i in 0..20 {
|
||||
assert_eq!(tree.find(i), Some([i, i, i, i, i, i, i]));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compensation_triggers_correctly() {
|
||||
let storage = temp_storage();
|
||||
let mut tree = BPlusTree::open(storage);
|
||||
|
||||
for i in 0..(MAX_KEYS * 3) {
|
||||
tree.insert([i as i32, 0, 0, 0, 0, 0, 0]);
|
||||
}
|
||||
|
||||
for i in 0..(MAX_KEYS * 3) {
|
||||
assert_eq!(tree.find(i as i32), Some([i as i32, 0, 0, 0, 0, 0, 0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,243 +98,3 @@ impl FileStorage {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
config::MAX_KEYS,
|
||||
node::{InternalNode, LeafNode, Node},
|
||||
record::Record,
|
||||
};
|
||||
use proptest::prelude::*;
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
fn temp_storage() -> FileStorage {
|
||||
let file = NamedTempFile::new().unwrap();
|
||||
FileStorage::new(file.path().to_str().unwrap())
|
||||
}
|
||||
|
||||
fn sample_leaf() -> Node {
|
||||
Node::Leaf(LeafNode {
|
||||
keys: vec![1, 2, 3],
|
||||
values: vec![[1; 7], [2; 7], [3; 7]],
|
||||
next: Some(42),
|
||||
})
|
||||
}
|
||||
|
||||
fn sample_internal() -> Node {
|
||||
Node::Internal(InternalNode {
|
||||
keys: vec![10, 20],
|
||||
children: vec![1, 2, 3],
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn write_and_read_leaf_node() {
|
||||
let mut storage = temp_storage();
|
||||
let node = sample_leaf();
|
||||
|
||||
storage.write_node(0, &node);
|
||||
let read_back = storage.read_node(0);
|
||||
|
||||
assert_eq!(read_back.unwrap(), node);
|
||||
assert_eq!(storage.page_reads, 1);
|
||||
assert_eq!(storage.page_writes, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn write_and_read_internal_node() {
|
||||
let mut storage = temp_storage();
|
||||
let node = sample_internal();
|
||||
|
||||
storage.write_node(5, &node);
|
||||
let read_back = storage.read_node(5);
|
||||
|
||||
assert_eq!(read_back.unwrap(), node);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_empty_page_returns_none() {
|
||||
let mut storage = temp_storage();
|
||||
|
||||
let result = storage.read_node(0);
|
||||
|
||||
assert!(result.is_none());
|
||||
assert_eq!(storage.page_reads, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn total_nodes_is_correct() {
|
||||
let mut storage = temp_storage();
|
||||
|
||||
storage.write_node(0, &sample_leaf());
|
||||
storage.write_node(1, &sample_internal());
|
||||
|
||||
assert_eq!(storage.total_nodes(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn overwrite_existing_node() {
|
||||
let mut storage = temp_storage();
|
||||
|
||||
let node1 = sample_leaf();
|
||||
let node2 = sample_internal();
|
||||
|
||||
storage.write_node(0, &node1);
|
||||
storage.write_node(0, &node2);
|
||||
|
||||
let read_back = storage.read_node(0).unwrap();
|
||||
assert_eq!(read_back, node2);
|
||||
}
|
||||
|
||||
fn arb_record() -> impl Strategy<Value = Record> {
|
||||
prop::array::uniform7(any::<i32>())
|
||||
}
|
||||
|
||||
fn arb_node() -> impl Strategy<Value = Node> {
|
||||
let max = MAX_KEYS * 2 + 2;
|
||||
|
||||
prop_oneof![
|
||||
(
|
||||
prop::collection::vec(any::<i32>(), 0..=max),
|
||||
prop::collection::vec(arb_record(), 0..=max),
|
||||
proptest::option::of(any::<usize>()),
|
||||
)
|
||||
.prop_map(|(keys, values, next)| { Node::Leaf(LeafNode { keys, values, next }) }),
|
||||
(
|
||||
prop::collection::vec(any::<i32>(), 0..=max),
|
||||
prop::collection::vec(any::<usize>(), 0..=max + 1),
|
||||
)
|
||||
.prop_map(|(keys, children)| { Node::Internal(InternalNode { keys, children }) })
|
||||
]
|
||||
}
|
||||
|
||||
fn arb_nodes() -> impl Strategy<Value = Vec<Node>> {
|
||||
prop::collection::vec(arb_node(), 0..100)
|
||||
}
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn node_roundtrip(node in arb_node()) {
|
||||
let mut storage = temp_storage();
|
||||
|
||||
storage.write_node(0, &node);
|
||||
let read_back = storage.read_node(0).unwrap();
|
||||
|
||||
prop_assert_eq!(node, read_back);
|
||||
}
|
||||
}
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn prop_multiple_nodes_roundtrip(nodes in arb_nodes()) {
|
||||
let mut storage = temp_storage();
|
||||
|
||||
for (i, node) in nodes.iter().enumerate() {
|
||||
storage.write_node(i, node);
|
||||
}
|
||||
|
||||
for (i, node) in nodes.iter().enumerate() {
|
||||
let read_back = storage.read_node(i).unwrap();
|
||||
prop_assert_eq!(read_back, node.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn prop_overwrite_last_wins(nodes in arb_nodes()) {
|
||||
let mut storage = temp_storage();
|
||||
|
||||
for node in &nodes {
|
||||
storage.write_node(0, node);
|
||||
}
|
||||
|
||||
if let Some(last) = nodes.last() {
|
||||
let read_back = storage.read_node(0).unwrap();
|
||||
prop_assert_eq!(read_back, last.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn prop_sparse_writes_are_isolated(
|
||||
a in arb_node(),
|
||||
b in arb_node(),
|
||||
loc_a in 0usize..20,
|
||||
loc_b in 0usize..20,
|
||||
) {
|
||||
prop_assume!(loc_a != loc_b);
|
||||
|
||||
let mut storage = temp_storage();
|
||||
|
||||
storage.write_node(loc_a, &a);
|
||||
storage.write_node(loc_b, &b);
|
||||
|
||||
let ra = storage.read_node(loc_a).unwrap();
|
||||
let rb = storage.read_node(loc_b).unwrap();
|
||||
|
||||
prop_assert_eq!(ra, a);
|
||||
prop_assert_eq!(rb, b);
|
||||
}
|
||||
}
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn prop_total_nodes_matches_highest_write(
|
||||
nodes in arb_nodes()
|
||||
) {
|
||||
let mut storage = temp_storage();
|
||||
|
||||
for (i, node) in nodes.iter().enumerate() {
|
||||
storage.write_node(i * 2, node); // deliberately sparse
|
||||
}
|
||||
|
||||
if !nodes.is_empty() {
|
||||
let expected_min = (nodes.len() - 1) * 2 + 1;
|
||||
prop_assert!(storage.total_nodes() >= expected_min);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn prop_reads_do_not_mutate_data(nodes in arb_nodes()) {
|
||||
let mut storage = temp_storage();
|
||||
|
||||
for (i, node) in nodes.iter().enumerate() {
|
||||
storage.write_node(i, node);
|
||||
}
|
||||
|
||||
for i in 0..nodes.len() {
|
||||
let _ = storage.read_node(i);
|
||||
}
|
||||
|
||||
for (i, node) in nodes.iter().enumerate() {
|
||||
let read_back = storage.read_node(i).unwrap();
|
||||
prop_assert_eq!(read_back, node.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn prop_unwritten_pages_return_none(
|
||||
nodes in arb_nodes(),
|
||||
extra in 1usize..20
|
||||
) {
|
||||
let mut storage = temp_storage();
|
||||
|
||||
for (i, node) in nodes.iter().enumerate() {
|
||||
storage.write_node(i, node);
|
||||
}
|
||||
|
||||
let loc = nodes.len() + extra;
|
||||
let result = storage.read_node(loc);
|
||||
|
||||
prop_assert!(result.is_none());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue