diff --git a/json-ptr b/json-ptr index 5e973c8..dc91a6f 160000 --- a/json-ptr +++ b/json-ptr @@ -1 +1 @@ -Subproject commit 5e973c8ee7ecd37cef944865fdd95cc1e93d4788 +Subproject commit dc91a6fbd0e5c77e6a3aa0870197f8d5f2891acc diff --git a/patch-db/Cargo.toml b/patch-db/Cargo.toml index a38bfd1..273619c 100644 --- a/patch-db/Cargo.toml +++ b/patch-db/Cargo.toml @@ -51,3 +51,4 @@ tokio = { version = "1.0.1", features = [ "io-util", "macros", ] } +rand = "0.8.4" diff --git a/patch-db/src/locker/proptest.rs b/patch-db/src/locker/proptest.rs index fb999bd..1f6daf8 100644 --- a/patch-db/src/locker/proptest.rs +++ b/patch-db/src/locker/proptest.rs @@ -270,6 +270,50 @@ mod tests { } } + proptest! { + #[test] + fn trie_lock_inverse_identity(lock_order in proptest::collection::vec(arb_lock_info(1, 5), 1..30)) { + use crate::locker::trie::LockTrie; + use rand::seq::SliceRandom; + let mut trie = LockTrie::default(); + for i in &lock_order { + trie.try_lock(i).expect(&format!("try_lock failed: {}", i)); + } + let mut release_order = lock_order.clone(); + let slice: &mut [LockInfo] = &mut release_order[..]; + slice.shuffle(&mut rand::thread_rng()); + for i in &release_order { + trie.unlock(i); + } + prop_assert_eq!(trie, LockTrie::default()) + } + } + + proptest! { + #[test] + fn existence_ancestors_dont_block_descendent_writes(s0 in arb_handle_id(10), s1 in arb_handle_id(10), mut ptr0 in arb_json_ptr(3), ptr1 in arb_json_ptr(3)) { + use crate::locker::trie::LockTrie; + prop_assume!(s0 != s1); + let mut trie = LockTrie::default(); + let li0 = LockInfo { + handle_id: s0, + ty: LockType::Exist, + ptr: ptr0.clone() + }; + println!("{}", ptr0); + ptr0.append(&ptr1); + println!("{}", ptr0); + let li1 = LockInfo { + handle_id: s1, + ty: LockType::Write, + ptr: ptr0.clone() + }; + trie.try_lock(&li0).unwrap(); + println!("{:?}", trie); + trie.try_lock(&li1).expect("E locks don't prevent child locks"); + } + } + proptest! { #[test] fn zero_or_one_write_lock_per_traversal(x in 0..10) { diff --git a/patch-db/src/locker/trie.rs b/patch-db/src/locker/trie.rs index 10f3d9f..b56dd21 100644 --- a/patch-db/src/locker/trie.rs +++ b/patch-db/src/locker/trie.rs @@ -3,9 +3,10 @@ use std::collections::BTreeMap; use imbl::{ordset, OrdSet}; use json_ptr::{JsonPointer, SegList}; -use crate::{handle::HandleId, LockType}; - -use super::{natural::Natural, LockInfo}; +use super::natural::Natural; +use super::LockInfo; +use crate::handle::HandleId; +use crate::LockType; #[derive(Debug, Clone, PartialEq, Eq)] enum LockState { @@ -351,7 +352,7 @@ impl Default for LockState { } } -#[derive(Debug, Default)] +#[derive(Debug, Default, PartialEq, Eq)] pub(super) struct LockTrie { state: LockState, @@ -596,9 +597,10 @@ impl LockTrie { #[cfg(test)] mod proptest { - use super::*; use ::proptest::prelude::*; + use super::*; + fn lock_type_gen() -> BoxedStrategy { prop_oneof![ Just(crate::LockType::Exist),