#![cfg(feature = "serializable")]
#![allow(clippy::unwrap_used, clippy::expect_used)]
use proptest::prelude::*;
use txn_db::Db;
const KEY_SPACE: u8 = 8;
proptest! {
#[test]
fn write_skew_never_lets_both_commit(
x in 0..KEY_SPACE,
y in 0..KEY_SPACE,
vx in any::<u8>(),
vy in any::<u8>(),
) {
prop_assume!(x != y);
let db = Db::new();
let mut seed = db.begin();
seed.put(vec![x], vec![1]);
seed.put(vec![y], vec![1]);
prop_assert!(seed.commit().is_ok());
let mut t1 = db.begin_serializable();
let mut t2 = db.begin_serializable();
let _ = t1.get(&[x])?;
let _ = t1.get(&[y])?;
let _ = t2.get(&[x])?;
let _ = t2.get(&[y])?;
t1.put(vec![x], vec![vx]);
t2.put(vec![y], vec![vy]);
let r1 = t1.commit();
let r2 = t2.commit();
prop_assert!(!(r1.is_ok() && r2.is_ok()));
prop_assert!(r1.is_ok());
let r2_err = r2.unwrap_err();
prop_assert!(r2_err.is_retryable());
}
#[test]
fn disjoint_serializable_transactions_both_commit(
a in 0..KEY_SPACE,
b in 0..KEY_SPACE,
va in any::<u8>(),
vb in any::<u8>(),
) {
prop_assume!(a != b);
let db = Db::new();
let mut t1 = db.begin_serializable();
let mut t2 = db.begin_serializable();
let _ = t1.get(&[a])?;
let _ = t2.get(&[b])?;
t1.put(vec![a], vec![va]);
t2.put(vec![b], vec![vb]);
prop_assert!(t1.commit().is_ok());
prop_assert!(t2.commit().is_ok());
}
#[test]
fn uncontended_serializable_transaction_commits(
reads in prop::collection::vec(0..KEY_SPACE, 0..8),
key in 0..KEY_SPACE,
value in any::<u8>(),
) {
let db = Db::new();
let mut tx = db.begin_serializable();
for k in reads {
let _ = tx.get(&[k])?;
}
tx.put(vec![key], vec![value]);
prop_assert!(tx.commit().is_ok());
}
#[test]
fn serializable_read_only_always_commits(reads in prop::collection::vec(0..KEY_SPACE, 0..8)) {
let db = Db::new();
let mut seed = db.begin();
seed.put(vec![0], vec![9]);
prop_assert!(seed.commit().is_ok());
let snapshot_tx = {
let tx = db.begin_serializable();
for k in &reads {
let _ = tx.get(&[*k])?;
}
tx
};
let mut writer = db.begin();
writer.put(vec![0], vec![5]);
prop_assert!(writer.commit().is_ok());
prop_assert!(snapshot_tx.commit().is_ok());
}
}