use std::path::Path;
use liteboxfs::{
Connection, CreateOptions, Error, TransactionBehavior,
metadata::{FileKind, Owner},
};
use xpct::{be_err, be_ok, expect, match_pattern, pattern};
#[test]
fn exec_with_deferred_behavior_runs_closure() -> liteboxfs::Result<()> {
let mut conn = Connection::open_in_memory(&CreateOptions::new())?;
conn.exec_with(TransactionBehavior::Deferred, |fs| {
fs.create("a.txt", FileKind::Regular, Owner::ROOT)?;
liteboxfs::Result::Ok(())
})?;
conn.exec(|fs| {
expect!(fs.open("a.txt")).to(be_ok());
liteboxfs::Result::Ok(())
})?;
Ok(())
}
#[test]
fn exec_with_immediate_behavior_runs_closure() -> liteboxfs::Result<()> {
let mut conn = Connection::open_in_memory(&CreateOptions::new())?;
conn.exec_with(TransactionBehavior::Immediate, |fs| {
fs.create("a.txt", FileKind::Regular, Owner::ROOT)?;
liteboxfs::Result::Ok(())
})?;
conn.exec(|fs| {
expect!(fs.open("a.txt")).to(be_ok());
liteboxfs::Result::Ok(())
})?;
Ok(())
}
#[test]
fn exec_rolls_back_on_error() -> liteboxfs::Result<()> {
let mut conn = Connection::open_in_memory(&CreateOptions::new())?;
let result: liteboxfs::Result<()> = conn.exec(|fs| {
fs.create("a.txt", FileKind::Regular, Owner::ROOT)?;
Err(Error::FileNotFound {
file: liteboxfs::FileOrigin::Host {
path: Path::new("/sentinel").into(),
},
})
});
expect!(result)
.to(be_err())
.to(match_pattern(pattern!(Error::FileNotFound { .. })));
conn.exec(|fs| {
expect!(fs.open("a.txt"))
.to(be_err())
.to(match_pattern(pattern!(Error::FileNotFound { .. })));
liteboxfs::Result::Ok(())
})?;
Ok(())
}
#[test]
fn explicit_commit_persists_changes() -> liteboxfs::Result<()> {
let mut conn = Connection::open_in_memory(&CreateOptions::new())?;
let mut tx = conn.tx()?;
{
let mut fs = tx.fs()?;
fs.create("a.txt", FileKind::Regular, Owner::ROOT)?;
}
tx.commit()?;
conn.exec(|fs| {
expect!(fs.open("a.txt")).to(be_ok());
liteboxfs::Result::Ok(())
})?;
Ok(())
}
#[test]
fn explicit_commit_with_no_changes_is_ok() -> liteboxfs::Result<()> {
let mut conn = Connection::open_in_memory(&CreateOptions::new())?;
let tx = conn.tx()?;
expect!(tx.commit()).to(be_ok());
Ok(())
}
#[test]
fn explicit_rollback_discards_changes() -> liteboxfs::Result<()> {
let mut conn = Connection::open_in_memory(&CreateOptions::new())?;
let mut tx = conn.tx()?;
{
let mut fs = tx.fs()?;
fs.create("a.txt", FileKind::Regular, Owner::ROOT)?;
}
tx.rollback()?;
conn.exec(|fs| {
expect!(fs.open("a.txt"))
.to(be_err())
.to(match_pattern(pattern!(Error::FileNotFound { .. })));
liteboxfs::Result::Ok(())
})?;
Ok(())
}
#[test]
fn dropped_transaction_rolls_back() -> liteboxfs::Result<()> {
let mut conn = Connection::open_in_memory(&CreateOptions::new())?;
{
let mut tx = conn.tx()?;
let mut fs = tx.fs()?;
fs.create("a.txt", FileKind::Regular, Owner::ROOT)?;
drop(fs);
drop(tx);
}
conn.exec(|fs| {
expect!(fs.open("a.txt"))
.to(be_err())
.to(match_pattern(pattern!(Error::FileNotFound { .. })));
liteboxfs::Result::Ok(())
})?;
Ok(())
}
#[test]
fn fs_can_be_called_multiple_times() -> liteboxfs::Result<()> {
let mut conn = Connection::open_in_memory(&CreateOptions::new())?;
let mut tx = conn.tx()?;
{
let mut fs = tx.fs()?;
fs.create("a.txt", FileKind::Regular, Owner::ROOT)?;
}
{
let mut fs = tx.fs()?;
expect!(fs.open("a.txt")).to(be_ok());
fs.create("b.txt", FileKind::Regular, Owner::ROOT)?;
}
tx.commit()?;
conn.exec(|fs| {
expect!(fs.open("a.txt")).to(be_ok());
expect!(fs.open("b.txt")).to(be_ok());
liteboxfs::Result::Ok(())
})?;
Ok(())
}