mod testing;
#[cfg(all(feature = "compression", feature = "chunking"))]
mod compression {
use std::io::{Read, Seek, SeekFrom, Write};
use xpct::{eq_diff, expect};
use super::testing::{Case, random_string};
use liteboxfs::{
Connection, CreateOptions,
metadata::{FileKind, Owner},
};
const BLOCK_SIZE: usize = 16 * 1024;
const CONTENT_SIZE: usize = BLOCK_SIZE * 6;
#[test]
fn compressed_blocks_readable_after_disabling_compression() -> liteboxfs::Result<()> {
let mut conn = Connection::open_in_memory(&CreateOptions::new().block_size(BLOCK_SIZE))?;
let data_a = random_string(CONTENT_SIZE, Case::Lower);
let data_b = random_string(CONTENT_SIZE, Case::Lower);
conn.exec(|fs| {
fs.set_compression(true);
let mut file_a = fs.create("a.txt", FileKind::Regular, Owner::ROOT)?;
file_a.write_all(data_a.as_bytes())?;
drop(file_a);
fs.set_compression(false);
let mut file_b = fs.create("b.txt", FileKind::Regular, Owner::ROOT)?;
file_b.write_all(data_b.as_bytes())?;
drop(file_b);
let actual_a = {
let mut actual = String::new();
let mut file = fs.open("a.txt")?;
file.read_to_string(&mut actual)?;
actual
};
expect!(actual_a).to(eq_diff(data_a));
let actual_b = {
let mut actual = String::new();
let mut file = fs.open("b.txt")?;
file.read_to_string(&mut actual)?;
actual
};
expect!(actual_b).to(eq_diff(data_b));
liteboxfs::Result::Ok(())
})?;
Ok(())
}
#[test]
fn uncompressed_blocks_readable_after_enabling_compression() -> liteboxfs::Result<()> {
let mut conn = Connection::open_in_memory(&CreateOptions::new().block_size(BLOCK_SIZE))?;
let data = random_string(CONTENT_SIZE, Case::Lower);
conn.exec(|fs| {
let mut file = fs.create("test.txt", FileKind::Regular, Owner::ROOT)?;
file.write_all(data.as_bytes())?;
drop(file);
fs.set_compression(true);
let mut actual = String::new();
let mut file = fs.open("test.txt")?;
file.read_to_string(&mut actual)?;
expect!(actual).to(eq_diff(data));
liteboxfs::Result::Ok(())
})?;
Ok(())
}
#[test]
fn write_with_compression_enabled_reads_back_correctly() -> liteboxfs::Result<()> {
let mut conn = Connection::open_in_memory(&CreateOptions::new().block_size(BLOCK_SIZE))?;
let data = random_string(CONTENT_SIZE, Case::Lower);
conn.exec(|fs| {
fs.set_compression(true);
let mut file = fs.create("test.txt", FileKind::Regular, Owner::ROOT)?;
file.write_all(data.as_bytes())?;
drop(file);
fs.set_compression(false);
let mut actual = String::new();
let mut file = fs.open("test.txt")?;
file.read_to_string(&mut actual)?;
expect!(actual).to(eq_diff(data));
liteboxfs::Result::Ok(())
})?;
Ok(())
}
#[test]
fn overwrite_with_compression_off_then_on_reads_back_correctly() -> liteboxfs::Result<()> {
let mut conn = Connection::open_in_memory(&CreateOptions::new().block_size(BLOCK_SIZE))?;
let data_v1 = random_string(CONTENT_SIZE, Case::Lower);
let data_v2 = random_string(CONTENT_SIZE, Case::Lower);
conn.exec(|fs| {
let mut file = fs.create("test.txt", FileKind::Regular, Owner::ROOT)?;
file.write_all(data_v1.as_bytes())?;
drop(file);
fs.set_compression(true);
let mut file = fs.open("test.txt")?;
file.seek(SeekFrom::Start(0))?;
file.write_all(data_v2.as_bytes())?;
drop(file);
fs.set_compression(false);
let mut actual = String::new();
let mut file = fs.open("test.txt")?;
file.read_to_string(&mut actual)?;
expect!(actual).to(eq_diff(data_v2));
liteboxfs::Result::Ok(())
})?;
Ok(())
}
#[test]
fn switching_compression_mid_write_produces_correct_data() -> liteboxfs::Result<()> {
let mut conn = Connection::open_in_memory(&CreateOptions::new().block_size(BLOCK_SIZE))?;
let first_half = random_string(CONTENT_SIZE / 2, Case::Lower);
let second_half = random_string(CONTENT_SIZE / 2, Case::Lower);
conn.exec(|fs| {
fs.set_compression(true);
let mut file = fs.create("test.txt", FileKind::Regular, Owner::ROOT)?;
file.write_all(first_half.as_bytes())?;
drop(file);
fs.set_compression(false);
let mut file = fs.open("test.txt")?;
file.seek(SeekFrom::End(0))?;
file.write_all(second_half.as_bytes())?;
drop(file);
let mut actual = String::new();
let mut file = fs.open("test.txt")?;
file.read_to_string(&mut actual)?;
let expected = format!("{first_half}{second_half}");
expect!(actual).to(eq_diff(expected));
liteboxfs::Result::Ok(())
})?;
Ok(())
}
}
#[cfg(all(feature = "compression", feature = "chunking"))]
mod chunking {
use std::io::{Read, Seek, SeekFrom, Write};
use xpct::{eq_diff, expect};
use super::testing::{Case, random_string};
use liteboxfs::{
Connection, CreateOptions,
metadata::{FileKind, Owner},
};
const BLOCK_SIZE: usize = 16 * 1024;
const CONTENT_SIZE: usize = BLOCK_SIZE * 6;
#[test]
fn cdc_blocks_readable_after_switching_to_fixed_chunking() -> liteboxfs::Result<()> {
let mut conn = Connection::open_in_memory(&CreateOptions::new().block_size(BLOCK_SIZE))?;
let data = random_string(CONTENT_SIZE, Case::Lower);
conn.exec(|fs| {
fs.set_chunking(true);
let mut file = fs.create("test.txt", FileKind::Regular, Owner::ROOT)?;
file.write_all(data.as_bytes())?;
drop(file);
fs.set_chunking(false);
let mut actual = String::new();
let mut file = fs.open("test.txt")?;
file.read_to_string(&mut actual)?;
expect!(actual).to(eq_diff(data));
liteboxfs::Result::Ok(())
})?;
Ok(())
}
#[test]
fn fixed_blocks_readable_after_switching_to_cdc() -> liteboxfs::Result<()> {
let mut conn = Connection::open_in_memory(&CreateOptions::new().block_size(BLOCK_SIZE))?;
let data = random_string(CONTENT_SIZE, Case::Lower);
conn.exec(|fs| {
let mut file = fs.create("test.txt", FileKind::Regular, Owner::ROOT)?;
file.write_all(data.as_bytes())?;
drop(file);
fs.set_chunking(true);
let mut actual = String::new();
let mut file = fs.open("test.txt")?;
file.read_to_string(&mut actual)?;
expect!(actual).to(eq_diff(data));
liteboxfs::Result::Ok(())
})?;
Ok(())
}
#[test]
fn switching_chunking_mid_write_produces_correct_data() -> liteboxfs::Result<()> {
let mut conn = Connection::open_in_memory(&CreateOptions::new().block_size(BLOCK_SIZE))?;
let first_half = random_string(CONTENT_SIZE / 2, Case::Lower);
let second_half = random_string(CONTENT_SIZE / 2, Case::Lower);
conn.exec(|fs| {
fs.set_chunking(true);
let mut file = fs.create("test.txt", FileKind::Regular, Owner::ROOT)?;
file.write_all(first_half.as_bytes())?;
drop(file);
fs.set_chunking(false);
let mut file = fs.open("test.txt")?;
file.seek(SeekFrom::End(0))?;
file.write_all(second_half.as_bytes())?;
drop(file);
let mut actual = String::new();
let mut file = fs.open("test.txt")?;
file.read_to_string(&mut actual)?;
let expected = format!("{first_half}{second_half}");
expect!(actual).to(eq_diff(expected));
liteboxfs::Result::Ok(())
})?;
Ok(())
}
}