tempest-rt 0.0.1

TempestDB Deterministic Async Runtime
Documentation
use std::path::{Path, PathBuf};

use crate::{Runtime, block_on};

use super::*;
use tempest_io::{
    OpenOptions, Statx, VirtualIo,
    virtual_io::{Fault, VirtualIoConfig},
};

#[test]
fn test_open_file_create() {
    let io = VirtualIo::new(VirtualIoConfig::default().report_unclosed_fds(false));
    block_on(io, async {
        let path = PathBuf::from("/new_file.bin");
        let _fd = open_file::<VirtualIo>(path, OpenOptions::new().write(true).create(true))
            .await
            .unwrap();
    });
}

#[test]
fn test_open_file_not_found() {
    let io = VirtualIo::new(VirtualIoConfig::default().report_unclosed_fds(false));
    block_on(io, async {
        let path = PathBuf::from("/does_not_exist.bin");
        let result = open_file::<VirtualIo>(path, OpenOptions::new().read(true)).await;
        assert!(result.is_err());
    })
}

#[test]
fn test_close_file() {
    let mut io = VirtualIo::default();
    let fd = io.create_file_sync("/file_that_must_be_closed.txt");
    let mut rt = Runtime::new(io);

    rt.block_on(async {
        close_file::<VirtualIo>(fd).await.unwrap();
    });
    assert!(rt.inspect_io().all_fds_closed(), "unclosed fds");
}

#[test]
fn test_write_at_read_at() {
    let io = VirtualIo::new(VirtualIoConfig::default().report_unclosed_fds(false));
    block_on(io, async {
        let path = PathBuf::from("/file.txt");
        let fd = open_file::<VirtualIo>(path, OpenOptions::new().write(true).create(true))
            .await
            .unwrap();
        let text = b"hello world";
        let (result, _buf) = write_at::<&[u8], VirtualIo>(fd, text, 0).await;
        assert_eq!(result.unwrap(), text.len());
        let (result, buf) = read_at::<_, VirtualIo>(fd, vec![0; text.len()], 0).await;
        assert_eq!(result.unwrap(), text.len());
        assert_eq!(buf, text);
    })
}

#[test]
fn test_write_exact_read_exact() {
    let mut io = VirtualIo::new(VirtualIoConfig::default().report_unclosed_fds(false));
    io.inject(Fault::PartialRead { bytes: 4 });
    io.inject(Fault::PartialRead { bytes: 3 });
    io.inject(Fault::PartialWrite { bytes: 4 });
    io.inject(Fault::PartialWrite { bytes: 3 });
    let mut rt = Runtime::new(io);
    rt.block_on(async {
        let path = PathBuf::from("/file.txt");
        let fd = open_file::<VirtualIo>(path, OpenOptions::new().write(true).create(true))
            .await
            .unwrap();
        let text = b"hello world";
        let (result, _buf) = write_exact::<&[u8], VirtualIo>(fd, text, 0).await;
        result.unwrap();
        let (result, buf) = read_exact::<_, VirtualIo>(fd, vec![0; text.len()], 0).await;
        result.unwrap();
        assert_eq!(buf, text);
    });
}

#[test]
fn test_remove_file() {
    let mut io = VirtualIo::default();
    let path = PathBuf::from("/file.txt");
    let fd = io.create_file_sync(path.clone());
    io.close_fd_sync(fd);
    block_on(io, async {
        remove_file::<VirtualIo>(path.clone()).await.unwrap();
        assert!(
            open_file::<VirtualIo>(path, OpenOptions::new().read(true))
                .await
                .is_err()
        );
    })
}

#[test]
fn test_remove_file_nonexistent() {
    block_on(VirtualIo::default(), async {
        let result = remove_file::<VirtualIo>(PathBuf::from("/does_not_exist.txt")).await;
        assert!(result.is_err());
    });
}

#[test]
fn test_sync_file() {
    block_on(VirtualIo::default(), async {
        let fd = open_file::<VirtualIo>(
            PathBuf::from("/file.txt"),
            OpenOptions::new().write(true).create(true),
        )
        .await
        .unwrap();
        let (result, _) = write_exact::<&[u8], VirtualIo>(fd, b"hello", 0).await;
        result.unwrap();
        sync_file::<VirtualIo>(fd).await.unwrap();
        close_file::<VirtualIo>(fd).await.unwrap();
    });
}

#[test]
fn test_list_dir() {
    block_on(VirtualIo::default(), async {
        let fd_a = open_file::<VirtualIo>(
            PathBuf::from("/a.txt"),
            OpenOptions::new().write(true).create(true),
        )
        .await
        .unwrap();
        let fd_b = open_file::<VirtualIo>(
            PathBuf::from("/b.txt"),
            OpenOptions::new().write(true).create(true),
        )
        .await
        .unwrap();
        close_file::<VirtualIo>(fd_a).await.unwrap();
        close_file::<VirtualIo>(fd_b).await.unwrap();

        let entries = list_dir::<VirtualIo>(PathBuf::from("/")).unwrap();
        let paths: Vec<_> = entries.iter().map(|e| e.path.as_path()).collect();
        assert!(paths.contains(&Path::new("/a.txt")));
        assert!(paths.contains(&Path::new("/b.txt")));
    });
}

#[test]
fn test_stat_file() {
    let io = VirtualIo::default();
    block_on(io, async {
        let path = PathBuf::from("/file.txt");
        let fd = open_file::<VirtualIo>(path, OpenOptions::new().write(true).create(true))
            .await
            .unwrap();
        let buf = b"hello world";
        let (result, _buf) = write_exact::<&[u8], VirtualIo>(fd, buf, 0).await;
        result.unwrap();

        let statx = stat_file::<VirtualIo>(fd).await.unwrap();
        let size = buf.len() as u64;
        assert_eq!(statx.stx_size(), size);

        close_file::<VirtualIo>(fd).await.unwrap();
    })
}