use std::sync::Arc;
use std::thread;
use epoch_db::DB;
use tempfile::tempdir;
#[test]
fn test_transaction_commit_on_success() {
let temp_dir = tempdir().unwrap();
let db = DB::new(temp_dir.path()).unwrap();
db.set("user:alice", "active", None).unwrap();
db.set("user:bob", "inactive", None).unwrap();
let result = db.transaction(|tx| {
tx.remove("user:alice")?;
tx.set("user:bob", "active_transferred", None)?;
Ok(())
});
assert!(result.is_ok());
assert!(
db.get("user:alice").unwrap().is_none(),
"Alice should be removed."
);
assert_eq!(
db.get("user:bob").unwrap().unwrap(),
"active_transferred",
"Bob should have the new value."
);
}
#[test]
fn test_transaction_rollback_on_failure() {
let temp_dir = tempdir().unwrap();
let db = DB::new(temp_dir.path()).unwrap();
db.set("user:charlie", "initial_state", None).unwrap();
let result = db.transaction(|tx| {
tx.set("user:charlie", "new_state_that_should_be_rolled_back", None)?;
Err(Box::from("Something went wrong!"))
});
assert!(result.is_err());
assert_eq!(
db.get("user:charlie").unwrap().unwrap(),
"initial_state",
"Charlie's data should be rolled back to its original state."
);
}
#[test]
fn test_transaction_isolation() {
let temp_dir = tempdir().unwrap();
let db = Arc::new(DB::new(temp_dir.path()).unwrap());
db.set("counter", "0", None).unwrap();
let mut handles = vec![];
let num_threads = 10;
let increments_per_thread = 50;
for _ in 0..num_threads {
let db_clone = Arc::clone(&db);
let handle = thread::spawn(move || {
for _ in 0..increments_per_thread {
db_clone
.transaction(|tx| {
let current_val_str = tx.get("counter")?.unwrap();
let current_val: u64 = current_val_str.parse()?;
let new_val = current_val + 1;
tx.set("counter", &new_val.to_string(), None)?;
Ok(())
})
.unwrap();
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
let final_value_str = db.get("counter").unwrap().unwrap();
let final_value: u64 = final_value_str.parse().unwrap();
let expected_value = (num_threads * increments_per_thread) as u64;
assert_eq!(
final_value, expected_value,
"The final counter should be correct, proving no lost updates occurred."
);
}