use std::sync::Arc;
use kcode_k1_peering::K1Peering;
use kcode_k1_persons::{K1Persons, PersonId, TxId};
use kcode_k1_txn_ordering::K1TxnOrdering;
use tempfile::TempDir;
fn open(root: &TempDir) -> (Arc<K1TxnOrdering>, Arc<K1Peering>, K1Persons) {
let ordering = Arc::new(K1TxnOrdering::open(&root.path().join("ordering")).unwrap());
let peering =
Arc::new(K1Peering::open(&root.path().join("peering"), ordering.clone()).unwrap());
let persons = K1Persons::open(root.path(), ordering.clone(), peering.clone()).unwrap();
(ordering, peering, persons)
}
#[test]
fn lifecycle_resolves_aliases_and_replays() {
fn require_send_sync<T: Send + Sync>() {}
require_send_sync::<K1Persons>();
let root = TempDir::new().unwrap();
let (ordering, peering, persons) = open(&root);
assert_eq!(
persons.create(String::new()).unwrap_err(),
"person name must be 1 through 128 UTF-8 bytes"
);
let first = persons.create("First".to_owned()).unwrap();
let second = persons.create("Second".to_owned()).unwrap();
let third = persons.create("Third".to_owned()).unwrap();
assert_eq!(persons.resolve(first, second).unwrap(), first);
assert_eq!(persons.get(second).unwrap().as_deref(), Some("First"));
assert_eq!(persons.resolve(second, third).unwrap(), first);
assert_eq!(persons.resolve(first, third).unwrap(), first);
persons.update(third, "Unified".to_owned()).unwrap();
for person in [first, second, third] {
assert_eq!(persons.get(person).unwrap().as_deref(), Some("Unified"));
}
let unknown = PersonId::from_tx_id(TxId::from_bytes([9; 12]));
assert_eq!(
persons.update(unknown, "No".to_owned()).unwrap_err(),
"person is unknown"
);
assert_eq!(
persons.resolve(unknown, first).unwrap_err(),
"canonical person is unknown"
);
assert_eq!(
persons.resolve(first, unknown).unwrap_err(),
"alias person is unknown"
);
drop(persons);
drop(peering);
drop(ordering);
let (_, _, reopened) = open(&root);
assert_eq!(reopened.get(first).unwrap().as_deref(), Some("Unified"));
assert_eq!(reopened.get(second).unwrap().as_deref(), Some("Unified"));
assert_eq!(reopened.get(third).unwrap().as_deref(), Some("Unified"));
}
#[test]
fn concurrent_identical_updates_correlate_by_transaction() {
let root = TempDir::new().unwrap();
let (_, _, persons) = open(&root);
let person = persons.create("Before".to_owned()).unwrap();
let persons = Arc::new(persons);
let workers: Vec<_> = (0..4)
.map(|_| {
let persons = persons.clone();
std::thread::spawn(move || persons.update(person, "After".to_owned()))
})
.collect();
for worker in workers {
worker.join().unwrap().unwrap();
}
assert_eq!(persons.get(person).unwrap().as_deref(), Some("After"));
}