use assert_cmd::Command;
use predicates::prelude::*;
use tempfile::tempdir;
fn avfs() -> Command {
Command::cargo_bin("avfs").unwrap()
}
#[test]
fn test_version() {
avfs()
.arg("--version")
.assert()
.success()
.stdout(predicate::str::contains("avfs"));
}
#[test]
fn test_help() {
avfs()
.arg("--help")
.assert()
.success()
.stdout(predicate::str::contains("Virtual filesystem"));
}
#[test]
fn test_vault_create_and_list() {
let home = tempdir().unwrap();
let avfs_dir = home.path().join(".avfs");
avfs()
.env("HOME", home.path())
.args(["vault", "create", "test-vault"])
.assert()
.success()
.stdout(predicate::str::contains("Created vault"));
avfs()
.env("HOME", home.path())
.args(["vault", "list"])
.assert()
.success()
.stdout(predicate::str::contains("test-vault"));
assert!(avfs_dir.join("vaults").join("test-vault.avfs").exists());
}
#[test]
fn test_vault_use() {
let home = tempdir().unwrap();
avfs()
.env("HOME", home.path())
.args(["vault", "create", "my-vault"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["vault", "use", "my-vault"])
.assert()
.success()
.stdout(predicate::str::contains("using vault"));
}
#[test]
fn test_write_and_cat() {
let home = tempdir().unwrap();
avfs()
.env("HOME", home.path())
.args(["vault", "create", "test-vault"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["write", "/hello.txt", "Hello, World!"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["cat", "/hello.txt"])
.assert()
.success()
.stdout(predicate::str::contains("Hello, World!"));
}
#[test]
fn test_mkdir_and_ls() {
let home = tempdir().unwrap();
avfs()
.env("HOME", home.path())
.args(["vault", "create", "test-vault"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["mkdir", "/mydir"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["ls", "/"])
.assert()
.success()
.stdout(predicate::str::contains("mydir"));
}
#[test]
fn test_cp_and_mv() {
let home = tempdir().unwrap();
avfs()
.env("HOME", home.path())
.args(["vault", "create", "test-vault"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["write", "/original.txt", "Test content"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["cp", "/original.txt", "/copy.txt"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["cat", "/copy.txt"])
.assert()
.success()
.stdout(predicate::str::contains("Test content"));
avfs()
.env("HOME", home.path())
.args(["mv", "/copy.txt", "/moved.txt"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["cat", "/moved.txt"])
.assert()
.success()
.stdout(predicate::str::contains("Test content"));
}
#[test]
fn test_mv_directory_into_descendant_fails_without_corrupting_vault() {
let home = tempdir().unwrap();
avfs()
.env("HOME", home.path())
.args(["vault", "create", "test-vault"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["mkdir", "/a"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["mkdir", "/a/b"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["mv", "/a", "/a/b"])
.assert()
.failure();
avfs()
.env("HOME", home.path())
.args(["ls", "/"])
.assert()
.success()
.stdout(predicate::str::contains("a"));
avfs()
.env("HOME", home.path())
.args(["ls", "/a"])
.assert()
.success()
.stdout(predicate::str::contains("b"));
}
#[test]
fn test_rm() {
let home = tempdir().unwrap();
avfs()
.env("HOME", home.path())
.args(["vault", "create", "test-vault"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["write", "/to_delete.txt", "Delete me"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["rm", "/to_delete.txt"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["cat", "/to_delete.txt"])
.assert()
.failure();
}
#[test]
fn test_tree() {
let home = tempdir().unwrap();
avfs()
.env("HOME", home.path())
.args(["vault", "create", "test-vault"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["mkdir", "/dir1"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["write", "/dir1/file.txt", "content"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["tree", "/"])
.assert()
.success()
.stdout(predicate::str::contains("dir1"));
}
#[test]
fn test_versioning() {
let home = tempdir().unwrap();
avfs()
.env("HOME", home.path())
.args(["vault", "create", "test-vault"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["write", "/versioned.txt", "Version 1"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["write", "/versioned.txt", "Version 2"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["log", "/versioned.txt"])
.assert()
.success()
.stdout(predicate::str::contains("Version"));
}
#[test]
fn test_json_output() {
let home = tempdir().unwrap();
avfs()
.env("HOME", home.path())
.args(["vault", "create", "test-vault"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["write", "/test.txt", "content"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["--json", "ls", "/"])
.assert()
.success()
.stdout(predicate::str::contains("\"name\""));
}
#[test]
fn test_search() {
let home = tempdir().unwrap();
avfs()
.env("HOME", home.path())
.args(["vault", "create", "test-vault"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args([
"write",
"/searchable.txt",
"This contains unique searchterm",
])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["search", "searchterm"])
.assert()
.success()
.stdout(predicate::str::contains("searchable.txt"));
}
#[test]
fn test_tags() {
let home = tempdir().unwrap();
avfs()
.env("HOME", home.path())
.args(["vault", "create", "test-vault"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["write", "/tagged.txt", "content"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["tag", "/tagged.txt", "important"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["tag", "--list", "/tagged.txt"])
.assert()
.success()
.stdout(predicate::str::contains("important"));
}
#[test]
fn test_metadata() {
let home = tempdir().unwrap();
avfs()
.env("HOME", home.path())
.args(["vault", "create", "test-vault"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["write", "/metafile.txt", "content"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["meta", "/metafile.txt", "author", "test"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["meta", "/metafile.txt"])
.assert()
.success()
.stdout(predicate::str::contains("author"));
}
#[test]
fn test_snapshot() {
let home = tempdir().unwrap();
avfs()
.env("HOME", home.path())
.args(["vault", "create", "test-vault"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["write", "/snap.txt", "snapshot content"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["snapshot", "save", "test-snap"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["snapshot", "list"])
.assert()
.success()
.stdout(predicate::str::contains("test-snap"));
}
#[test]
fn test_checkpoint_alias() {
let home = tempdir().unwrap();
avfs()
.env("HOME", home.path())
.args(["vault", "create", "test-vault"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["write", "/checkpoint.txt", "checkpoint content"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["checkpoint", "save", "test-checkpoint"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["checkpoint", "list"])
.assert()
.success()
.stdout(predicate::str::contains("test-checkpoint"));
}
#[test]
fn test_snapshot_restore_preserves_tags_and_metadata() {
let home = tempdir().unwrap();
avfs()
.env("HOME", home.path())
.args(["vault", "create", "test-vault"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["write", "/snap.txt", "snapshot content"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["tag", "/snap.txt", "important"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["meta", "/snap.txt", "owner", "alice"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["snapshot", "save", "full-state"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["rm", "/snap.txt"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["snapshot", "restore", "full-state"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["tag", "--list", "/snap.txt"])
.assert()
.success()
.stdout(predicate::str::contains("important"));
avfs()
.env("HOME", home.path())
.args(["meta", "/snap.txt"])
.assert()
.success()
.stdout(predicate::str::contains("owner"));
}
#[test]
fn test_vault_fork_clones_contents() {
let home = tempdir().unwrap();
avfs()
.env("HOME", home.path())
.args(["vault", "create", "source-vault"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["write", "/forked.txt", "fork me"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["vault", "fork", "source-vault", "fork-vault", "--use"])
.assert()
.success()
.stdout(predicate::str::contains("Forked vault"));
avfs()
.env("HOME", home.path())
.args(["cat", "/forked.txt"])
.assert()
.success()
.stdout(predicate::str::contains("fork me"));
avfs()
.env("HOME", home.path())
.args(["write", "/forked.txt", "fork changed"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["vault", "use", "source-vault"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["cat", "/forked.txt"])
.assert()
.success()
.stdout(predicate::str::contains("fork me"))
.stdout(predicate::str::contains("fork changed").not());
}
#[test]
fn test_stats() {
let home = tempdir().unwrap();
avfs()
.env("HOME", home.path())
.args(["vault", "create", "test-vault"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["write", "/stats.txt", "some content"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["stats"])
.assert()
.success()
.stdout(predicate::str::contains("Files"));
}
#[test]
fn test_quota_allows_deduplicated_copy() {
let home = tempdir().unwrap();
let data = vec![b'a'; 1024 * 1024];
avfs()
.env("HOME", home.path())
.args(["vault", "create", "test-vault"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["write", "/big.bin"])
.write_stdin(data)
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["quota", "set", "max_size_mb", "1"])
.assert()
.success();
avfs()
.env("HOME", home.path())
.args(["cp", "/big.bin", "/big-copy.bin"])
.assert()
.success();
}