forked from Crockan/MercuryToolbox
158 lines
4.6 KiB
Rust
158 lines
4.6 KiB
Rust
//! Integration tests for the `pathshadow` command.
|
|
|
|
use std::fs;
|
|
|
|
use assert_cmd::Command;
|
|
use pathshadow::{SourceKind, classify_source, find_command_matches};
|
|
use predicates::prelude::*;
|
|
use tempfile::tempdir;
|
|
|
|
fn cargo_command() -> Command {
|
|
Command::cargo_bin("pathshadow").expect("binary")
|
|
}
|
|
|
|
fn classify_path(path: &str) -> SourceKind {
|
|
classify_source(std::path::Path::new(path))
|
|
}
|
|
|
|
fn demo_path_fixture() -> (tempfile::TempDir, tempfile::TempDir, String) {
|
|
let first = tempdir().expect("first path");
|
|
let second = tempdir().expect("second path");
|
|
fs::write(first.path().join("demo.cmd"), "@echo first").expect("first command");
|
|
fs::write(second.path().join("demo.exe"), "binary").expect("second command");
|
|
let path_value = format!("{};{}", first.path().display(), second.path().display());
|
|
(first, second, path_value)
|
|
}
|
|
|
|
#[test]
|
|
fn classifies_common_install_roots() {
|
|
assert_eq!(
|
|
classify_path(r"C:\Users\example\scoop\shims\rg.exe"),
|
|
SourceKind::ScoopShim
|
|
);
|
|
assert_eq!(
|
|
classify_path(r"C:\Users\example\scoop\shims"),
|
|
SourceKind::ScoopShim
|
|
);
|
|
assert_eq!(
|
|
classify_path(r"C:\Users\example\.cargo\bin\cargo.exe"),
|
|
SourceKind::CargoBin
|
|
);
|
|
assert_eq!(
|
|
classify_path(r"C:\Users\example\.cargo\bin"),
|
|
SourceKind::CargoBin
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn finds_shadowed_matches_in_path_order() {
|
|
let (first, second, _) = demo_path_fixture();
|
|
|
|
let matches = find_command_matches(
|
|
"demo",
|
|
&[first.path().to_path_buf(), second.path().to_path_buf()],
|
|
&[".CMD".into(), ".EXE".into()],
|
|
);
|
|
|
|
assert_eq!(matches.len(), 2);
|
|
assert_eq!(matches[0].path, first.path().join("demo.cmd"));
|
|
assert!(matches[0].is_primary);
|
|
assert!(!matches[1].is_primary);
|
|
}
|
|
|
|
#[test]
|
|
fn reports_duplicates_from_cli() {
|
|
let (_first, _second, path_value) = demo_path_fixture();
|
|
let mut command = cargo_command();
|
|
command
|
|
.arg("demo")
|
|
.env("PATH", path_value)
|
|
.env("PATHEXT", ".CMD;.EXE")
|
|
.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains("demo"))
|
|
.stdout(predicate::str::contains("primary"))
|
|
.stdout(predicate::str::contains("shadowed"));
|
|
}
|
|
|
|
#[test]
|
|
fn supports_powershell_pipeline() {
|
|
let (_first, _second, path_value) = demo_path_fixture();
|
|
|
|
let binary = assert_cmd::cargo::cargo_bin("pathshadow");
|
|
let script = format!("'demo' | & '{}'", binary.display());
|
|
|
|
let mut command = Command::new("pwsh");
|
|
command
|
|
.arg("-NoProfile")
|
|
.arg("-Command")
|
|
.arg(script)
|
|
.env("PATH", path_value)
|
|
.env("PATHEXT", ".CMD;.EXE")
|
|
.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains("demo"));
|
|
}
|
|
|
|
#[test]
|
|
fn emits_rank_reason_and_winner_in_json_output() {
|
|
let (first, _second, path_value) = demo_path_fixture();
|
|
|
|
let winner = first.path().join("demo.cmd");
|
|
let winner_json = winner.display().to_string().replace('\\', "\\\\");
|
|
let mut command = cargo_command();
|
|
command
|
|
.arg("demo")
|
|
.arg("--json")
|
|
.env("PATH", path_value)
|
|
.env("PATHEXT", ".CMD;.EXE")
|
|
.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains("\"path_rank\":0"))
|
|
.stdout(predicate::str::contains("\"path_rank\":1"))
|
|
.stdout(predicate::str::contains(
|
|
"\"shadow_reason\":\"path_winner\"",
|
|
))
|
|
.stdout(predicate::str::contains(
|
|
"\"shadow_reason\":\"shadowed_by_earlier_path\"",
|
|
))
|
|
.stdout(predicate::str::contains(format!(
|
|
"\"winner_path\":\"{winner_json}\""
|
|
)));
|
|
}
|
|
|
|
#[test]
|
|
fn help_includes_path_diagnosis_examples() {
|
|
let mut command = cargo_command();
|
|
command
|
|
.arg("--help")
|
|
.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains("pathshadow rg"))
|
|
.stdout(predicate::str::contains(
|
|
"pathshadow python npm --shell powershell",
|
|
))
|
|
.stdout(predicate::str::contains(
|
|
"pathshadow --all-duplicates --high-signal --summary --json",
|
|
))
|
|
.stdout(predicate::str::contains("ConvertFrom-Json"));
|
|
}
|
|
|
|
#[test]
|
|
fn reports_alias_targets_for_powershell_resolution() {
|
|
let mut command = cargo_command();
|
|
command
|
|
.arg("where")
|
|
.arg("--shell")
|
|
.arg("powershell")
|
|
.arg("--summary")
|
|
.arg("--json")
|
|
.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains("\"shell_winner_type\":\"alias\""))
|
|
.stdout(predicate::str::contains(
|
|
"\"shell_winner_target\":\"Where-Object\"",
|
|
))
|
|
.stdout(predicate::str::contains("\"shell_disagrees\":true"));
|
|
}
|