use std::path::PathBuf;
use std::process::Command;
fn mkit_bin() -> &'static str {
env!("CARGO_BIN_EXE_mkit")
}
fn repo_root() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("..")
.join("..")
.join("..")
}
fn read_repo_file(rel: &str) -> String {
let path = repo_root().join(rel);
std::fs::read_to_string(&path)
.unwrap_or_else(|e| panic!("read {} ({}): {e}", rel, path.display()))
}
const DOCUMENTED_SUBCOMMANDS: &[&str] = &[
"init",
"add",
"rm",
"mv",
"restore",
"reset",
"status",
"diff",
"stash",
"sparse-checkout",
"pack-shard",
"commit",
"log",
"reflog",
"blame",
"verify",
"cat",
"cat-file",
"hash",
"tree",
"ls-tree",
"ls-files",
"rev-parse",
"show",
"show-ref",
"for-each-ref",
"symbolic-ref",
"update-ref",
"branch",
"checkout",
"clean",
"tag",
"merge",
"cherry-pick",
"revert",
"rebase",
"bisect",
"gc",
"remote",
"clone",
"fetch",
"pull",
"push",
"serve",
"mcp",
"key",
"keygen",
"config",
"version",
];
#[test]
fn help_lists_every_documented_subcommand() {
let output = Command::new(mkit_bin())
.arg("help")
.output()
.expect("spawn `mkit help`");
assert!(output.status.success(), "`mkit help` must exit 0");
let text = String::from_utf8(output.stdout).expect("stdout is utf-8");
for cmd in DOCUMENTED_SUBCOMMANDS {
assert!(
text.contains(cmd),
"`mkit help` output is missing documented subcommand '{cmd}'"
);
}
}
#[test]
fn man_page_documents_every_subcommand() {
let man = read_repo_file("man/mkit.1");
for cmd in DOCUMENTED_SUBCOMMANDS {
let documented = man.lines().any(|line| {
line.match_indices(&format!("Cm {cmd}")).any(|(idx, m)| {
let after = &line[idx + m.len()..];
after.is_empty() || after.starts_with([' ', ',', '\t'])
})
});
assert!(
documented,
"man/mkit.1 is missing documented subcommand '{cmd}' (expected a `Cm {cmd}` macro)"
);
}
}
#[test]
fn completions_cover_every_subcommand() {
for (file, name) in [
("completions/mkit.bash", "bash"),
("completions/mkit.zsh", "zsh"),
("completions/mkit.fish", "fish"),
] {
let text = read_repo_file(file);
for cmd in DOCUMENTED_SUBCOMMANDS {
assert!(
text.contains(cmd),
"{name} completion ({file}) is missing documented subcommand '{cmd}'"
);
}
}
}
#[test]
fn dash_dash_help_goes_to_stdout() {
let output = Command::new(mkit_bin())
.arg("--help")
.output()
.expect("spawn `mkit --help`");
assert!(output.status.success(), "`mkit --help` must exit 0");
assert!(!output.stdout.is_empty(), "stdout empty");
assert!(output.stderr.is_empty(), "stderr should be empty on --help");
}
#[test]
fn unknown_subcommand_exits_usage() {
let output = Command::new(mkit_bin())
.arg("definitely-nonsense")
.output()
.expect("spawn");
assert_eq!(
output.status.code(),
Some(64),
"unknown command must exit 64 (sysexits EX_USAGE)"
);
}
#[test]
fn help_output_snapshot() {
let output = Command::new(mkit_bin())
.arg("--help")
.output()
.expect("spawn `mkit --help`");
let stdout = String::from_utf8(output.stdout).expect("utf-8");
insta::assert_snapshot!("mkit_dash_help", stdout);
}
#[test]
fn version_output_snapshot() {
let output = Command::new(mkit_bin())
.arg("version")
.output()
.expect("spawn `mkit version`");
let stdout = String::from_utf8(output.stdout).expect("utf-8");
insta::with_settings!({filters => vec![
(r"\d+\.\d+\.\d+(-[A-Za-z0-9._-]+)?", "[VERSION]"),
]}, {
insta::assert_snapshot!("mkit_version", stdout);
});
}