#![allow(dead_code)]
use std::env;
use std::fs;
use std::path::Path;
pub mod conf;
pub mod files;
pub mod run;
const FIXTURES_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixtures/");
const MOCK_BIN_DIR: &str = concat!(env!("CARGO_TARGET_TMPDIR"), "/mock_bin/");
pub fn mock_bin(bin_name: &str, file: &str) {
let fixtures_dir = Path::new(FIXTURES_DIR);
let bin_dir = Path::new(MOCK_BIN_DIR);
let fixture = fixtures_dir.join(file).with_extension("sh");
let test_mock = bin_dir.join(bin_name);
assert!(
fs::create_dir_all(bin_dir).is_ok(),
"Error creating mock bin directory: '{}'.",
bin_dir.display()
);
assert!(
fs::copy(&fixture, test_mock).is_ok(),
"Error setting up mock executable: '{}'.",
fixture.display()
);
unsafe {
env::set_var("PATH", format!("{}:/bin:/usr/bin/", bin_dir.display()));
}
}
pub fn read_output_file(file: &str) -> String {
let bin_dir = Path::new(MOCK_BIN_DIR);
fs::read_to_string(bin_dir.join(file).with_extension("txt"))
.expect("if file doesn't exist, the test failed")
}
pub fn output_file_exists(file: &str) -> bool {
let bin_dir = Path::new(MOCK_BIN_DIR);
bin_dir.join(file).with_extension("txt").exists()
}
pub fn remove_output_file(file: &str) {
let bin_dir = Path::new(MOCK_BIN_DIR);
let output = bin_dir.join(file).with_extension("txt");
if output.exists() {
fs::remove_file(output).unwrap();
}
}
pub const HOOK_COMMANDS: &[&str] = &["sync", "rsync", "link", "status", "diff", "clean"];
pub fn create_all_command_hooks(content: Option<&str>) {
for c in HOOK_COMMANDS {
conf::create_executable_file_in_configs(&format!("pre-{c}.sh"), content);
conf::create_executable_file_in_configs(&format!("post-{c}.sh"), content);
}
}
pub fn create_all_command_hooks_in_home(content: Option<&str>) {
for c in HOOK_COMMANDS {
conf::create_file_in_home(&format!("pre-{c}.sh"), content);
conf::create_file_in_home(&format!("post-{c}.sh"), content);
}
}
pub fn assert_only_own_hooks_ran(output: &run::Output, cmd: &str) {
for c in HOOK_COMMANDS {
let pre = format!("hook: pre-{c}.sh");
let post = format!("hook: post-{c}.sh");
if *c == cmd {
assert!(output.stdout.contains(&pre), "expected '{pre}' to run");
assert!(output.stdout.contains(&post), "expected '{post}' to run");
} else {
assert!(
!output.stdout.contains(&pre),
"'{pre}' must not run for '{cmd}'"
);
assert!(
!output.stdout.contains(&post),
"'{post}' must not run for '{cmd}'"
);
}
}
}
pub fn assert_no_command_hooks_in_home() {
for c in HOOK_COMMANDS {
assert!(!files::file_exists_in_home(&format!("pre-{c}.sh")));
assert!(!files::file_exists_in_home(&format!("post-{c}.sh")));
}
}
pub fn assert_all_command_hooks_survive_in_home() {
for c in HOOK_COMMANDS {
assert!(files::file_exists_in_home(&format!("pre-{c}.sh")));
assert!(files::file_exists_in_home(&format!("post-{c}.sh")));
}
}
pub fn assert_config_hooks_unchanged(expected: &str) {
for c in HOOK_COMMANDS {
assert_eq!(files::read_in_configs(&format!("pre-{c}.sh")), expected);
assert_eq!(files::read_in_configs(&format!("post-{c}.sh")), expected);
}
}
pub fn assert_hooks_section_listed(output: &run::Output) {
let mut expected = String::from("Hooks\n");
for c in HOOK_COMMANDS {
expected.push_str(" pre-");
expected.push_str(c);
expected.push_str(".sh\n");
expected.push_str(" post-");
expected.push_str(c);
expected.push_str(".sh\n");
}
assert!(
output.stdout.contains(&expected),
"expected hooks section:\n{expected}\n--- got stdout: ---\n{}",
output.stdout
);
}
pub fn assert_aborted_by(output: &run::Output, hook: &str) {
assert_eq!(output.exit_code, 1);
assert!(
output
.stderr
.contains(&format!("abort: Execution aborted by '{hook}'.")),
"expected abort message for '{hook}', got stderr:\n{}",
output.stderr
);
}