persy 1.5.0

Transactional Persistence Engine
Documentation
mod helpers;
use helpers::create_and_drop;
use persy::ValueMode;

#[test]
fn test_snapshot_after_drop() {
    create_and_drop("after_drop", |persy| {
        let mut tx = persy.begin().unwrap();
        tx.create_segment("test").unwrap();
        tx.create_index::<u8, u8>("index", ValueMode::Replace).unwrap();
        let bytes = String::from("something").into_bytes();
        let id = tx.insert("test", &bytes).unwrap();
        tx.put::<u8, u8>("index", 10, 20).unwrap();
        let finalizer = tx.prepare().unwrap();
        finalizer.commit().unwrap();
        let snapshot = persy.snapshot().unwrap();

        let mut tx = persy.begin().unwrap();
        tx.drop_segment("test").unwrap();
        tx.drop_index("index").unwrap();
        let finalizer = tx.prepare().unwrap();
        finalizer.commit().unwrap();

        let bytes = String::from("something").into_bytes();
        let read_after = snapshot.read("test", &id).unwrap();
        assert_eq!(read_after, Some(bytes));
        assert_eq!(snapshot.get::<u8, u8>("index", &10).unwrap().next(), Some(20));
    });
}

#[test]
fn test_double_snapshot_after_drop() {
    create_and_drop("double_after_drop", |persy| {
        let mut tx = persy.begin().unwrap();
        tx.create_segment("test").unwrap();
        tx.create_index::<u8, u8>("index", ValueMode::Replace).unwrap();
        let bytes = String::from("something").into_bytes();
        let id = tx.insert("test", &bytes).unwrap();
        tx.put::<u8, u8>("index", 10, 20).unwrap();
        let finalizer = tx.prepare().unwrap();
        finalizer.commit().unwrap();
        let snapshot = persy.snapshot().unwrap();
        let snapshot1 = persy.snapshot().unwrap();

        let mut tx = persy.begin().unwrap();
        tx.drop_segment("test").unwrap();
        tx.drop_index("index").unwrap();
        let finalizer = tx.prepare().unwrap();
        finalizer.commit().unwrap();

        let bytes = String::from("something").into_bytes();
        let read_after = snapshot.read("test", &id).unwrap();
        assert_eq!(read_after, Some(bytes));
        assert_eq!(snapshot.get::<u8, u8>("index", &10).unwrap().next(), Some(20));

        let bytes = String::from("something").into_bytes();
        let read_after = snapshot1.read("test", &id).unwrap();
        assert_eq!(read_after, Some(bytes));
        assert_eq!(snapshot1.get::<u8, u8>("index", &10).unwrap().next(), Some(20));
        drop(snapshot1);

        let bytes = String::from("something").into_bytes();
        let read_after = snapshot.read("test", &id).unwrap();
        assert_eq!(read_after, Some(bytes));
        assert_eq!(snapshot.get::<u8, u8>("index", &10).unwrap().next(), Some(20));
    });
}

#[test]
fn test_snapshot_ignore_newers() {
    create_and_drop("ignore_newers", |persy| {
        let mut tx = persy.begin().unwrap();
        tx.create_segment("test").unwrap();
        tx.create_index::<u8, u8>("index", ValueMode::Replace).unwrap();
        let bytes = String::from("something").into_bytes();
        tx.insert("test", &bytes).unwrap();
        tx.put::<u8, u8>("index", 10, 20).unwrap();
        let finalizer = tx.prepare().unwrap();
        finalizer.commit().unwrap();
        let snapshot = persy.snapshot().unwrap();

        let mut tx = persy.begin().unwrap();
        let bytes = String::from("other").into_bytes();
        let id2 = tx.insert("test", &bytes).unwrap();
        tx.put::<u8, u8>("index", 11, 20).unwrap();
        let finalizer = tx.prepare().unwrap();
        finalizer.commit().unwrap();

        let read_after = snapshot.read("test", &id2).unwrap();
        assert_eq!(read_after, None);
        assert_eq!(snapshot.get::<u8, u8>("index", &11).unwrap().len(), 0);
    });
}

#[test]
fn test_snapshot_list_after_drop() {
    create_and_drop("after_drop_list", |persy| {
        let mut tx = persy.begin().unwrap();
        tx.create_segment("test").unwrap();
        tx.create_index::<u8, u8>("index", ValueMode::Replace).unwrap();
        let bytes = String::from("something").into_bytes();
        tx.insert("test", &bytes).unwrap();
        tx.put::<u8, u8>("index", 10, 20).unwrap();
        let finalizer = tx.prepare().unwrap();
        finalizer.commit().unwrap();
        let snapshot = persy.snapshot().unwrap();

        let mut tx = persy.begin().unwrap();
        tx.drop_segment("test").unwrap();
        tx.drop_index("index").unwrap();
        let finalizer = tx.prepare().unwrap();
        finalizer.commit().unwrap();

        let read_after = snapshot.list_segments().unwrap();
        assert_eq!(read_after.len(), 1);
        assert_eq!(
            read_after.into_iter().next().map(|(name, _)| (name)),
            Some("test".to_string())
        );
        let read_after = snapshot.list_indexes().unwrap();
        assert_eq!(read_after.len(), 1);
        assert_eq!(
            read_after.into_iter().next().map(|(name, _)| (name)),
            Some("index".to_string())
        );
    });
}

#[test]
fn test_snapshot_scan_after_drop() {
    create_and_drop("after_drop_scan", |persy| {
        let mut tx = persy.begin().unwrap();
        tx.create_segment("test").unwrap();
        tx.create_index::<u8, u8>("index", ValueMode::Replace).unwrap();
        let bytes = String::from("something").into_bytes();
        tx.insert("test", &bytes).unwrap();
        tx.put::<u8, u8>("index", 10, 20).unwrap();
        let finalizer = tx.prepare().unwrap();
        finalizer.commit().unwrap();
        let snapshot = persy.snapshot().unwrap();

        let mut tx = persy.begin().unwrap();
        tx.drop_segment("test").unwrap();
        tx.drop_index("index").unwrap();
        let finalizer = tx.prepare().unwrap();
        finalizer.commit().unwrap();

        let read_after = snapshot.scan("test").unwrap();
        assert_eq!(read_after.into_iter().next().map(|(_, content)| (content)), Some(bytes));
        let mut read_after = snapshot.range::<u8, u8, _>("index", ..).unwrap();
        assert_eq!(
            read_after.next().map(|(_, value)| (value.into_iter().next().unwrap())),
            Some(20)
        );
    });
}

#[test]
fn test_snapshot_after_remove_scan() {
    create_and_drop("after_remove_scan", |persy| {
        let mut tx = persy.begin().unwrap();
        tx.create_segment("test").unwrap();
        tx.create_index::<u8, u8>("index", ValueMode::Replace).unwrap();
        let bytes = String::from("something").into_bytes();
        let id = tx.insert("test", &bytes).unwrap();
        tx.put::<u8, u8>("index", 10, 20).unwrap();
        let finalizer = tx.prepare().unwrap();
        finalizer.commit().unwrap();
        let snapshot = persy.snapshot().unwrap();

        let mut tx = persy.begin().unwrap();
        tx.delete("test", &id).unwrap();
        tx.remove::<u8, u8>("index", 10, None).unwrap();
        let finalizer = tx.prepare().unwrap();
        finalizer.commit().unwrap();

        let read_after = snapshot.read("test", &id).unwrap();
        assert_eq!(read_after, Some(bytes.clone()));
        assert_eq!(snapshot.get::<u8, u8>("index", &10).unwrap().next(), Some(20));
        let mut read_after = snapshot.scan("test").unwrap();
        assert_eq!(read_after.next().map(|(_, v)| v), Some(bytes));
        assert_eq!(
            snapshot
                .range::<u8, u8, _>("index", ..)
                .unwrap()
                .into_iter()
                .next()
                .map(|(_, v)| v.into_iter().next().unwrap()),
            Some(20)
        );
    });
}

#[test]
fn test_snapshot_after_scan_after_delete_many() {
    create_and_drop("after_remove_scan", |persy| {
        let mut tx = persy.begin().unwrap();
        tx.create_segment("test").unwrap();
        let bytes = String::from("something").into_bytes();
        for _ in 0..5000 {
            tx.insert("test", &bytes).unwrap();
        }
        let finalizer = tx.prepare().unwrap();
        finalizer.commit().unwrap();
        let snapshot = persy.snapshot().unwrap();

        let read_after = snapshot.scan("test").unwrap();

        let mut tx = persy.begin().unwrap();
        let recs = persy.scan("test").unwrap().map(|(id, ..)| id).collect::<Vec<_>>();
        //Reverse delete for some internal tweak forward delete works everytime
        for id in recs.iter().rev() {
            tx.delete("test", &id).unwrap();
        }
        let finalizer = tx.prepare().unwrap();
        finalizer.commit().unwrap();

        assert_eq!(read_after.count(), 5000);
    });
}