#![cfg(feature = "oom_inject")]
use fsys::builder;
use fsys::test_support::OomThreshold;
#[cfg(target_os = "linux")]
use fsys::{Error, JournalOptions};
use std::path::PathBuf;
use std::sync::atomic::{AtomicU64, Ordering};
static C: AtomicU64 = AtomicU64::new(0);
fn tmp_path(tag: &str) -> PathBuf {
let n = C.fetch_add(1, Ordering::Relaxed);
std::env::temp_dir().join(format!(
"fsys_oom_inject_{}_{}_{tag}",
std::process::id(),
n
))
}
struct Cleanup(PathBuf);
impl Drop for Cleanup {
fn drop(&mut self) {
let _ = std::fs::remove_file(&self.0);
}
}
#[test]
fn allocator_passes_through_when_threshold_is_unlimited() {
let path = tmp_path("smoke");
let _g = Cleanup(path.clone());
let h = builder().build().expect("handle");
h.write(&path, b"smoke").expect("write");
let data = h.read(&path).expect("read");
assert_eq!(data, b"smoke");
}
#[cfg(target_os = "linux")]
#[test]
fn direct_mode_journal_open_handles_oom_gracefully() {
let path = tmp_path("direct_oom");
let _g = Cleanup(path.clone());
let h = builder().build().expect("handle");
std::fs::write(&path, b"").expect("create file");
let result = {
let _guard = OomThreshold::set(2048);
h.journal_with(&path, JournalOptions::new().direct(true))
};
match result {
Ok(_) => panic!("direct journal open under OOM must error, got Ok"),
Err(Error::Io(io_err)) => {
assert_eq!(
io_err.kind(),
std::io::ErrorKind::OutOfMemory,
"expected ErrorKind::OutOfMemory, got {:?}",
io_err.kind()
);
}
Err(other) => panic!("expected Error::Io(OutOfMemory), got {:?}", other),
}
let log = h
.journal_with(&path, JournalOptions::new().direct(true))
.expect("direct journal open succeeds without threshold");
drop(log);
}
#[test]
fn threshold_guard_restores_on_drop() {
use fsys::test_support::OOM_THRESHOLD;
let baseline = OOM_THRESHOLD.with(|c| c.get());
assert_eq!(baseline, usize::MAX);
{
let _guard = OomThreshold::set(1024);
let during = OOM_THRESHOLD.with(|c| c.get());
assert_eq!(during, 1024, "threshold set inside guard scope");
}
let after = OOM_THRESHOLD.with(|c| c.get());
assert_eq!(after, baseline, "threshold restored after guard drop");
}
#[test]
fn buffered_mode_journal_open_unaffected_by_targeted_threshold() {
let path = tmp_path("buffered_oom");
let _g = Cleanup(path.clone());
let h = builder().build().expect("handle");
std::fs::write(&path, b"").expect("create file");
let _guard = OomThreshold::set(2048);
let log = h
.journal(&path)
.expect("buffered journal open under threshold must succeed");
drop(log);
}