mod roster;
use std::os::unix::fs::PermissionsExt as _;
use super::*;
use tempfile::tempdir;
fn host(program: &str) -> Cli {
Cli::new(program)
}
#[test]
fn shim_script_reexecs_the_clis_own_words_and_forwards_argv() {
let cli = Cli::resolve_with(
crate::cli_outbound::Binary::Bl,
|_| None,
Some(PathBuf::from("/opt/yog/bin/yog")),
);
let script = shim_script(BL, &cli.exec_words());
assert!(script.starts_with("#!/bin/sh\n"), "{script}");
assert!(
script.ends_with("exec '/opt/yog/bin/yog' 'bl' \"$@\"\n"),
"{script}"
);
let script = shim_script(BL, &host("/usr/bin/bl").exec_words());
assert!(script.ends_with("exec '/usr/bin/bl' \"$@\"\n"), "{script}");
}
#[test]
fn shim_script_quotes_a_path_with_spaces_and_quotes() {
let script = shim_script(BL, &host("/we ird/yo'g").exec_words());
assert!(
script.ends_with("exec '/we ird/yo'\\''g' \"$@\"\n"),
"{script}"
);
}
#[test]
fn ensure_shim_creates_the_tree_and_marks_it_executable() {
let dir = tempdir().unwrap();
let tools = dir.path().join("world").join("tools");
let path = ensure_shim(&tools, BL, &host("/usr/bin/bl")).unwrap();
assert_eq!(path, tools.join(BL));
assert_eq!(
fs::read_to_string(&path).unwrap(),
shim_script(BL, &host("/usr/bin/bl").exec_words())
);
let mode = fs::metadata(&path).unwrap().permissions().mode();
assert_eq!(mode & 0o777, 0o755);
}
#[test]
fn ensure_shim_leaves_an_identical_file_untouched_but_rewrites_drift() {
let dir = tempdir().unwrap();
let tools = dir.path().to_path_buf();
let path = ensure_shim(&tools, BL, &host("/usr/bin/bl")).unwrap();
let first = fs::metadata(&path).unwrap().modified().unwrap();
ensure_shim(&tools, BL, &host("/usr/bin/bl")).unwrap();
assert_eq!(fs::metadata(&path).unwrap().modified().unwrap(), first);
ensure_shim(&tools, BL, &host("/opt/bl")).unwrap();
assert_eq!(
fs::read_to_string(&path).unwrap(),
shim_script(BL, &host("/opt/bl").exec_words())
);
fs::write(&path, "#!/bin/sh\nexit 7\n").unwrap();
ensure_shim(&tools, BL, &host("/opt/bl")).unwrap();
assert_eq!(
fs::read_to_string(&path).unwrap(),
shim_script(BL, &host("/opt/bl").exec_words())
);
}
#[test]
fn ensure_shim_refuses_a_target_that_is_not_an_absolute_path() {
let dir = tempdir().unwrap();
let tools = dir.path().join("tools");
let good = ensure_shim(&tools, BL, &host("/opt/yog/bin/yog")).unwrap();
let before = fs::read_to_string(&good).unwrap();
let err = ensure_shim(&tools, BL, &host("bl")).unwrap_err();
assert_eq!(err.kind(), io::ErrorKind::NotFound);
assert!(err.to_string().contains("absolute path"), "{err}");
assert_eq!(fs::read_to_string(&good).unwrap(), before);
let empty = dir.path().join("empty");
ensure_shim(&empty, BL, &Cli::new("")).unwrap_err();
assert!(!empty.join(BL).exists());
}
#[test]
fn the_seeded_shim_runs_and_passes_argv_through_verbatim() {
let dir = tempdir().unwrap();
let target = dir.path().join("fake yog");
let log = dir.path().join("argv");
crate::test_support::write_exec(
&target,
&format!(
"#!/bin/sh\nprintf '%s\\n' \"$@\" > '{}'\nexit 3\n",
log.display()
),
);
let tools = dir.path().join("tools");
let shim = ensure_shim(&tools, BL, &host(target.to_string_lossy().as_ref())).unwrap();
let out = crate::git_env::output(crate::git_env::command(&shim).args([
"close",
"bl-1a2b",
"-m",
"two words",
]))
.unwrap();
assert_eq!(out.status.code(), Some(3));
assert_eq!(
fs::read_to_string(&log).unwrap(),
"close\nbl-1a2b\n-m\ntwo words\n"
);
}