use super::*;
use crate::operation::Operation;
use crate::state::fsflags::FsFlags;
use crate::test_helpers::StateBuilder;
fn immutable_flags() -> FsFlags {
FsFlags {
immutable: true,
append_only: false,
}
}
fn append_only_flags() -> FsFlags {
FsFlags {
immutable: false,
append_only: true,
}
}
fn no_flags() -> FsFlags {
FsFlags {
immutable: false,
append_only: false,
}
}
#[test]
fn write_to_immutable_file_fails() {
let state = StateBuilder::new()
.operation(Operation::Write)
.mount("/", "ext4", "rw")
.component("/", 0, 0, 0o755)
.component_file_with_flags("/data.txt", 0, 0, 0o644, immutable_flags())
.build();
let result = check_fs_flags(&state);
assert!(result.is_fail());
if let LayerResult::Fail { detail, .. } = &result {
assert!(detail.contains("immutable"));
}
}
#[test]
fn write_to_append_only_file_fails() {
let state = StateBuilder::new()
.operation(Operation::Write)
.mount("/", "ext4", "rw")
.component("/", 0, 0, 0o755)
.component_file_with_flags("/log.txt", 0, 0, 0o644, append_only_flags())
.build();
let result = check_fs_flags(&state);
assert!(result.is_fail());
if let LayerResult::Fail { detail, .. } = &result {
assert!(detail.contains("append-only"));
}
}
#[test]
fn read_from_immutable_file_passes() {
let state = StateBuilder::new()
.operation(Operation::Read)
.mount("/", "ext4", "rw")
.component("/", 0, 0, 0o755)
.component_file_with_flags("/data.txt", 0, 0, 0o644, immutable_flags())
.build();
let result = check_fs_flags(&state);
assert!(result.is_pass());
}
#[test]
fn execute_on_immutable_file_passes() {
let state = StateBuilder::new()
.operation(Operation::Execute)
.mount("/", "ext4", "rw")
.component("/", 0, 0, 0o755)
.component_file_with_flags("/bin/tool", 0, 0, 0o755, immutable_flags())
.build();
let result = check_fs_flags(&state);
assert!(result.is_pass());
}
#[test]
fn delete_targets_parent_so_unknown_flags_degrades() {
let state = StateBuilder::new()
.operation(Operation::Delete)
.mount("/", "ext4", "rw")
.component("/", 0, 0, 0o755)
.component_file_with_flags("/locked.txt", 0, 0, 0o644, immutable_flags())
.build();
let result = check_fs_flags(&state);
assert!(result.is_degraded());
}
#[test]
fn delete_with_immutable_parent_fails() {
let state = StateBuilder::new()
.operation(Operation::Delete)
.mount("/", "ext4", "rw")
.component_with_flags("/", 0, 0, 0o755, immutable_flags())
.component_file("/locked.txt", 0, 0, 0o644)
.build();
let result = check_fs_flags(&state);
assert!(result.is_fail());
if let LayerResult::Fail { detail, .. } = &result {
assert!(detail.contains("immutable"));
}
}
#[test]
fn unknown_flags_returns_degraded() {
let state = StateBuilder::new()
.operation(Operation::Write)
.mount("/", "ext4", "rw")
.component("/", 0, 0, 0o755)
.component_file("/data.txt", 0, 0, 0o644)
.build();
let result = check_fs_flags(&state);
assert!(result.is_degraded());
}
#[test]
fn no_flags_set_passes() {
let state = StateBuilder::new()
.operation(Operation::Write)
.mount("/", "ext4", "rw")
.component("/", 0, 0, 0o755)
.component_file_with_flags("/data.txt", 0, 0, 0o644, no_flags())
.build();
let result = check_fs_flags(&state);
assert!(result.is_pass());
}
#[test]
fn stat_on_immutable_file_passes() {
let state = StateBuilder::new()
.operation(Operation::Stat)
.mount("/", "ext4", "rw")
.component("/", 0, 0, 0o755)
.component_file_with_flags("/data.txt", 0, 0, 0o644, immutable_flags())
.build();
let result = check_fs_flags(&state);
assert!(result.is_pass());
}
#[test]
fn delete_with_append_only_parent_fails() {
let state = StateBuilder::new()
.operation(Operation::Delete)
.mount("/", "ext4", "rw")
.component_with_flags("/dir", 0, 0, 0o755, append_only_flags())
.component_file("/dir/file.txt", 0, 0, 0o644)
.build();
let result = check_fs_flags(&state);
assert!(result.is_fail());
if let LayerResult::Fail { detail, .. } = &result {
assert!(
detail.contains("append-only"),
"expected append-only: {detail}"
);
assert!(
detail.contains("cannot delete"),
"expected delete context: {detail}"
);
}
}
#[test]
fn create_with_append_only_parent_passes() {
let state = StateBuilder::new()
.operation(Operation::Create)
.mount("/", "ext4", "rw")
.component_with_flags("/dir", 0, 0, 0o755, append_only_flags())
.component_file("/dir/newfile.txt", 0, 0, 0o644)
.build();
let result = check_fs_flags(&state);
assert!(result.is_pass());
}