use assert_cmd::Command;
use predicates::prelude::*;
use std::fs;
use std::path::PathBuf;
fn with_home<F: FnOnce(PathBuf)>(f: F) {
let tmp = tempfile::tempdir().unwrap();
let home = tmp.path().to_path_buf();
f(home);
}
#[test]
fn put_and_get_key() {
with_home(|home| {
let mut cmd = Command::cargo_bin("unifier").unwrap();
cmd.args(["--home", &home.display().to_string(), "put", "app/theme", "dark"])
.assert()
.success();
Command::cargo_bin("unifier")
.unwrap()
.args(["--home", &home.display().to_string(), "get", "app/theme"])
.assert()
.success()
.stdout("dark\n");
});
}
#[test]
fn send_and_poll_mailbox() {
with_home(|home| {
let home_s = home.display().to_string();
Command::cargo_bin("unifier")
.unwrap()
.args(["--home", &home_s, "send", "worker", "hello"])
.assert()
.success();
Command::cargo_bin("unifier")
.unwrap()
.args(["--home", &home_s, "poll", "worker"])
.assert()
.success()
.stdout(predicate::str::contains("hello"));
});
}
fn home_args(home: &str) -> Vec<String> {
vec!["--home".into(), home.into(), "--no-daemon".into()]
}
#[test]
fn cron_post_and_list() {
with_home(|home| {
let home_s = home.display().to_string();
let mut args = home_args(&home_s);
args.extend(["cron".into(), "0_0_*_*_*".into(), "nightly backup".into()]);
Command::cargo_bin("unifier")
.unwrap()
.args(&args)
.assert()
.success();
let mut list_args = home_args(&home_s);
list_args.extend(["list".into(), "cron/0_0_*_*_*".into()]);
Command::cargo_bin("unifier")
.unwrap()
.args(&list_args)
.assert()
.success()
.stdout(predicate::str::contains("nightly backup"));
assert!(home.join("cron/0_0_*_*_*").is_dir());
let entries: Vec<_> = fs::read_dir(home.join("cron/0_0_*_*_*"))
.unwrap()
.map(|e| e.unwrap().path())
.collect();
assert_eq!(entries.len(), 1);
assert!(entries[0].extension().unwrap() == "txt");
});
}
#[test]
fn root_prints_home() {
with_home(|home| {
Command::cargo_bin("unifier")
.unwrap()
.args(["--home", &home.display().to_string(), "root"])
.assert()
.success()
.stdout(format!("{}\n", home.display()));
});
}
#[test]
fn chroot_isolates_keys() {
with_home(|home| {
let home_s = home.display().to_string();
Command::cargo_bin("unifier")
.unwrap()
.args(["--home", &home_s, "chroot", "init", "work"])
.assert()
.success();
Command::cargo_bin("unifier")
.unwrap()
.args(["--home", &home_s, "--chroot", "work", "put", "k", "in-work"])
.assert()
.success();
Command::cargo_bin("unifier")
.unwrap()
.args(["--home", &home_s, "--chroot", "work", "get", "k"])
.assert()
.success()
.stdout("in-work\n");
Command::cargo_bin("unifier")
.unwrap()
.args(["--home", &home_s, "get", "k"])
.assert()
.failure();
Command::cargo_bin("unifier")
.unwrap()
.args(["--home", &home_s, "chroot", "init", "personal"])
.assert()
.success();
Command::cargo_bin("unifier")
.unwrap()
.args(["--home", &home_s, "--chroot", "personal", "get", "k"])
.assert()
.failure();
});
}
#[test]
fn chroot_root_shows_effective_path() {
with_home(|home| {
let home_s = home.display().to_string();
Command::cargo_bin("unifier")
.unwrap()
.args(["--home", &home_s, "chroot", "init", "work"])
.assert()
.success();
let expected = format!("{}/chroots/work\n", home.display());
Command::cargo_bin("unifier")
.unwrap()
.args(["--home", &home_s, "--chroot", "work", "root"])
.assert()
.success()
.stdout(expected);
});
}
#[test]
fn chroot_list_names() {
with_home(|home| {
let home_s = home.display().to_string();
Command::cargo_bin("unifier")
.unwrap()
.args(["--home", &home_s, "chroot", "init", "work"])
.assert()
.success();
Command::cargo_bin("unifier")
.unwrap()
.args(["--home", &home_s, "chroot", "init", "personal"])
.assert()
.success();
Command::cargo_bin("unifier")
.unwrap()
.args(["--home", &home_s, "chroot", "list"])
.assert()
.success()
.stdout("personal\nwork\n");
});
}
#[test]
fn list_rejects_path_escape() {
with_home(|home| {
let home_s = home.display().to_string();
let mut args = home_args(&home_s);
args.extend(["list".into(), "../keys".into()]);
Command::cargo_bin("unifier")
.unwrap()
.args(&args)
.assert()
.failure()
.stderr(predicate::str::contains(".."));
});
}