persy 1.5.2

Transactional Persistence Engine
Documentation
use super::{Allocator, Cache, FreeList};
use crate::{
    config::Config,
    device::{MemoryDevice, PageOps, ReadPage},
};
use std::{sync::Arc, time::Duration};

#[test]
fn test_reuse_freed_page() {
    let disc = Box::new(MemoryDevice::new(None).unwrap());
    let (_, allocator) = Allocator::init(disc, &Config::new()).unwrap();
    // This is needed to avoid the 0 page
    allocator.allocate(10).unwrap();
    let first = allocator.allocate(10).unwrap().get_index();
    let second = allocator.allocate(10).unwrap().get_index();
    let third = allocator.allocate(11).unwrap().get_index();
    let _forth_to_avoid_trim = allocator.allocate(11).unwrap();

    allocator.free(first).unwrap();
    allocator.free(second).unwrap();
    allocator.free(third).unwrap();

    let val = allocator.allocate(10).unwrap().get_index();
    assert_eq!(val, first);
    let val = allocator.allocate(10).unwrap().get_index();
    assert_eq!(val, second);
    let val = allocator.allocate(10).unwrap().get_index();
    assert!(val != first);
    assert!(val != second);
    let val = allocator.allocate(11).unwrap().get_index();
    assert_eq!(val, third);
    let val = allocator.allocate(11).unwrap().get_index();
    assert!(val != third);
}

#[test]
fn test_remove_freed_page() {
    let disc = Box::new(MemoryDevice::new(None).unwrap());
    let (_, allocator) = Allocator::init(disc, &Config::new()).unwrap();
    // This is needed to avoid the 0 page
    allocator.allocate(5).unwrap();
    let first = allocator.allocate(10).unwrap().get_index();
    let second = allocator.allocate(10).unwrap().get_index();
    let third = allocator.allocate(10).unwrap().get_index();
    let _forth_to_avoid_trim = allocator.allocate(11).unwrap();
    allocator.free(first).unwrap();
    allocator.free(second).unwrap();
    allocator.free(third).unwrap();
    allocator.remove_from_free(second, 10).unwrap();
    let val = allocator.allocate(10).unwrap().get_index();
    assert_eq!(val, first);
    let val = allocator.allocate(10).unwrap().get_index();
    assert_eq!(val, third);
}

#[test]
fn test_cache_limit_evict() {
    let mut cache = Cache::new(1050 as u64, Duration::from_secs(3600));
    cache.put(10, ReadPage::new(Arc::new(Vec::new()), 0, 10, 9));
    cache.put(20, ReadPage::new(Arc::new(Vec::new()), 0, 10, 9));
    cache.put(30, ReadPage::new(Arc::new(Vec::new()), 0, 10, 9));
    assert!(cache.size() < 1050);
    assert_eq!(cache.entry_count(), 2);
    let ten = 10 as u64;
    match cache.get(ten) {
        Some(_) => assert!(false),
        None => assert!(true),
    }
    let ten = 20 as u64;
    match cache.get(ten) {
        Some(_) => assert!(true),
        None => assert!(false),
    }
    let ten = 30 as u64;
    match cache.get(ten) {
        Some(_) => assert!(true),
        None => assert!(false),
    }
}

#[test]
fn test_cache_limit_refresh_evict() {
    let mut cache = Cache::new(1050 as u64, Duration::from_secs(3600));
    cache.put(10, ReadPage::new(Arc::new(Vec::new()), 0, 10, 9));
    cache.put(20, ReadPage::new(Arc::new(Vec::new()), 0, 10, 9));
    let ten = 10 as u64;
    match cache.get(ten) {
        Some(_) => assert!(true),
        None => assert!(false),
    }

    cache.put(30, ReadPage::new(Arc::new(Vec::new()), 0, 10, 9));
    assert!(cache.size() < 1050);
    assert_eq!(cache.entry_count(), 2);
    let ten = 10 as u64;
    match cache.get(ten) {
        Some(_) => assert!(true),
        None => assert!(false),
    }
    let ten = 20 as u64;
    match cache.get(ten) {
        Some(_) => assert!(false),
        None => assert!(true),
    }
    let ten = 30 as u64;
    match cache.get(ten) {
        Some(_) => assert!(true),
        None => assert!(false),
    }
}

#[test]
fn test_read_write_free_list() {
    use super::free_list::LISTS_COUNT;
    let mut heads = [0u64; LISTS_COUNT];
    for p in 0..heads.len() {
        // Random value do not matter
        heads[p] = p as u64 + 10 * 3;
    }
    let mut tails = [0u64; LISTS_COUNT];
    for p in 0..tails.len() {
        // Random value do not matter
        tails[p] = p as u64 + 10 * 3;
    }
    let buf = FreeList::write_free_list(&heads, &tails);
    let (read_heads, read_tails) = FreeList::read_free_list(&buf);
    assert_eq!(heads, read_heads);
    assert_eq!(tails, read_tails);
}

#[test]
fn test_cache_limit_remove() {
    let mut cache = Cache::new(1050 as u64, Duration::from_secs(3600));
    cache.put(10, ReadPage::new(Arc::new(Vec::new()), 0, 10, 9));
    cache.put(20, ReadPage::new(Arc::new(Vec::new()), 0, 10, 9));
    cache.put(30, ReadPage::new(Arc::new(Vec::new()), 0, 10, 9));
    assert!(cache.size() < 1050);
    assert_eq!(cache.entry_count(), 2);
    cache.remove(20);
    cache.remove(30);
    assert_eq!(cache.size(), 0);
}

#[test]
fn test_cache_replace_limit_stay() {
    let mut cache = Cache::new(100000 as u64, Duration::from_secs(3600));
    cache.put(10, ReadPage::new(Arc::new(Vec::new()), 0, 10, 9));
    cache.put(20, ReadPage::new(Arc::new(Vec::new()), 0, 10, 9));
    cache.put(30, ReadPage::new(Arc::new(Vec::new()), 0, 10, 9));
    let pre = cache.size();
    cache.put(20, ReadPage::new(Arc::new(Vec::new()), 0, 10, 9));
    assert_eq!(cache.size(), pre);
    cache.put(20, ReadPage::new(Arc::new(Vec::new()), 0, 10, 10));
    assert_eq!(cache.size(), pre - (1 << 9) + (1 << 10));
}

#[test]
fn test_cache_time_clean() {
    let mut cache = Cache::new(100000 as u64, Duration::from_millis(500));
    cache.put(10, ReadPage::new(Arc::new(Vec::new()), 0, 10, 9));
    cache.put(20, ReadPage::new(Arc::new(Vec::new()), 0, 10, 9));
    cache.put(30, ReadPage::new(Arc::new(Vec::new()), 0, 10, 9));
    std::thread::sleep(Duration::from_millis(600));
    cache.put(20, ReadPage::new(Arc::new(Vec::new()), 0, 10, 9));
    assert_eq!(cache.size(), 1 << 9);
}