use cfg_if::cfg_if;
use determinator::{
rules::{DeterminatorRules, PathMatch, RuleIndex},
Determinator, Utf8Paths0,
};
use fixtures::json::JsonFixture;
use guppy::{graph::feature::StandardFeatures, CargoMetadata};
#[test]
fn guppy_no_rules() {
let old = JsonFixture::metadata_guppy_869476c();
let new = JsonFixture::metadata_guppy_c9b4f76();
let mut determinator = Determinator::new(old.graph(), new.graph());
determinator.add_changed_paths(vec!["README.md"]);
let determinator_set = determinator.compute();
assert!(
determinator_set.path_changed_set.is_empty(),
"nothing in workspace changed"
);
assert!(
determinator_set.affected_set.is_empty(),
"nothing in workspace affected"
);
determinator.add_changed_paths(vec!["rust-toolchain"]);
let workspace_set = new.graph().resolve_workspace();
let determinator_set = determinator.compute();
assert_eq!(
determinator_set.path_changed_set, workspace_set,
"everything changed"
);
assert_eq!(
determinator_set.affected_set, workspace_set,
"everything changed"
);
}
#[test]
fn guppy_path_rules() {
let old = JsonFixture::metadata_guppy_869476c();
let new = JsonFixture::metadata_guppy_c9b4f76();
let opts = read_options(new, "path-rules.toml");
let mut determinator = Determinator::new(old.graph(), new.graph());
determinator.set_rules(&opts).expect("rules set correctly");
let determinator_set = determinator.compute();
assert!(
determinator_set.path_changed_set.is_empty(),
"nothing in workspace changed"
);
assert!(
determinator_set.affected_set.is_empty(),
"nothing in workspace affected"
);
determinator.add_changed_paths(vec!["fixtures/src/details.rs"]);
let expected_changed = new
.graph()
.resolve_workspace_names(vec!["fixtures"])
.expect("workspace names resolved");
let expected_affected = new
.graph()
.resolve_workspace_names(vec![
"fixtures",
"guppy",
"fixture-manager",
])
.expect("workspace names resolved");
{
let determinator_set = determinator.compute();
assert_eq!(determinator_set.path_changed_set, expected_changed);
assert_eq!(determinator_set.affected_set, expected_affected);
}
determinator.add_changed_paths(vec!["guppy/README.md", "cargo-guppy/README.tpl"]);
{
let determinator_set = determinator.compute();
assert_eq!(determinator_set.path_changed_set, expected_changed);
assert_eq!(determinator_set.affected_set, expected_affected);
}
determinator.add_changed_paths(vec![".gitignore", "Cargo.lock"]);
{
let determinator_set = determinator.compute();
assert_eq!(determinator_set.path_changed_set, expected_changed);
assert_eq!(determinator_set.affected_set, expected_affected);
}
determinator.add_changed_paths(vec!["foo/CODE_OF_CONDUCT.md"]);
{
let determinator_set = determinator.compute();
assert_eq!(determinator_set.path_changed_set, expected_changed);
assert_eq!(determinator_set.affected_set, expected_affected);
}
determinator.add_changed_paths(vec!["CONTRIBUTING.md"]);
{
let new_changed = new
.graph()
.resolve_workspace_names(vec!["cargo-guppy", "fixtures"])
.expect("workspace names resolved");
let new_affected = expected_affected.union(
&new.graph()
.resolve_workspace_names(vec!["cargo-guppy"])
.expect("workspace names resolved"),
);
let determinator_set = determinator.compute();
assert_eq!(determinator_set.path_changed_set, new_changed);
assert_eq!(determinator_set.affected_set, new_affected);
}
determinator.add_changed_paths(vec!["CODE_OF_CONDUCT.md"]);
{
let new_changed = new
.graph()
.resolve_workspace_names(vec!["cargo-guppy", "fixtures", "guppy"])
.expect("workspace names resolved");
let new_affected = new_changed.union(
&new.graph()
.resolve_workspace_names(
vec![
"guppy-cmdlib",
"guppy-benchmarks",
"cargo-compare",
"fixture-manager",
],
)
.expect("workspace names resolved"),
);
let determinator_set = determinator.compute();
assert_eq!(determinator_set.path_changed_set, new_changed);
assert_eq!(determinator_set.affected_set, new_affected);
}
determinator.add_changed_paths(vec!["internal-tools/benchmarks/foo"]);
{
let new_changed = new
.graph()
.resolve_workspace_names(vec![
"cargo-guppy",
"fixtures",
"guppy",
"guppy-benchmarks",
"cargo-compare",
])
.expect("workspace paths resolved");
let new_affected = new_changed.union(
&new.graph()
.resolve_workspace_names(
vec!["guppy-cmdlib", "fixture-manager"],
)
.expect("workspace names resolved"),
);
let determinator_set = determinator.compute();
assert_eq!(determinator_set.path_changed_set, new_changed);
assert_eq!(determinator_set.affected_set, new_affected);
}
}
#[test]
fn guppy_package_rules() {
let old = JsonFixture::metadata_guppy_869476c();
let new = JsonFixture::metadata_guppy_c9b4f76();
let opts = read_options(new, "package-rules.toml");
let mut determinator = Determinator::new(old.graph(), new.graph());
determinator.set_rules(&opts).expect("rules set correctly");
let determinator_set = determinator.compute();
assert!(
determinator_set.path_changed_set.is_empty(),
"no path changes"
);
assert!(
determinator_set.summary_changed_set.is_empty(),
"no summary changes"
);
assert!(determinator_set.affected_set.is_empty(), "no changes");
{
let mut determinator = determinator.clone();
determinator.add_changed_paths(vec!["Cargo.lock"]);
let determinator_set = determinator.compute();
let workspace_set = new.graph().resolve_workspace();
assert_eq!(
determinator_set.path_changed_set, workspace_set,
"everything changed"
);
assert_eq!(
determinator_set.affected_set, workspace_set,
"everything changed"
);
}
determinator.add_changed_paths(vec!["cargo-guppy/foo.rs"]);
let determinator_set = determinator.compute();
let expected_path_changed = new
.graph()
.resolve_workspace_names(vec!["cargo-guppy"])
.expect("valid workspace names");
assert_eq!(
determinator_set.path_changed_set, expected_path_changed,
"cargo-guppy in path changes"
);
assert!(
determinator_set.summary_changed_set.is_empty(),
"no summary changes"
);
assert_eq!(
determinator_set.affected_set, expected_path_changed,
"cargo-guppy in affected set"
);
determinator.add_changed_paths(vec!["fixtures/src/main.rs"]);
let determinator_set = determinator.compute();
let expected_path_changed = new
.graph()
.resolve_workspace_names(vec!["cargo-guppy", "fixtures"])
.expect("valid workspace names");
let expected_affected = expected_path_changed.union(
&new.graph()
.resolve_workspace_names(vec![
"guppy",
"guppy-cmdlib",
"cargo-compare",
"fixture-manager",
])
.expect("valid workspace names"),
);
assert_eq!(
determinator_set.path_changed_set, expected_path_changed,
"cargo-guppy + fixtures in path changes"
);
assert!(
determinator_set.summary_changed_set.is_empty(),
"no summary changes"
);
assert_eq!(
determinator_set.affected_set, expected_affected,
"most but not all packages affected"
);
}
#[test]
fn guppy_package_rules_2() {
let old = JsonFixture::metadata_guppy_869476c();
let new = JsonFixture::metadata_guppy_c9b4f76();
let opts = read_options(new, "package-rules.toml");
let mut determinator = Determinator::new(old.graph(), new.graph());
determinator.set_rules(&opts).expect("rules set correctly");
determinator.add_changed_paths(vec!["foo/fake-trigger"]);
let determinator_set = determinator.compute();
let expected_path_changed = new
.graph()
.resolve_workspace_names(vec!["proptest-ext"])
.expect("valid workspace names");
assert_eq!(
determinator_set.path_changed_set, expected_path_changed,
"cargo-guppy + fixtures in path changes"
);
assert!(
determinator_set.summary_changed_set.is_empty(),
"no summary changes"
);
assert_eq!(
determinator_set.affected_set,
new.graph().resolve_workspace(),
"all packages affected"
);
}
#[test]
fn guppy_deps() {
let old = JsonFixture::metadata_guppy_78cb7e8();
let new = JsonFixture::metadata_guppy_869476c();
let opts = read_options(new, "path-rules.toml");
let mut determinator = Determinator::new(old.graph(), new.graph());
determinator.set_rules(&opts).expect("rules set correctly");
let determinator_set = determinator.compute();
let expected = new
.graph()
.resolve_workspace_names(vec![
"cargo-guppy",
"fixture-manager",
"guppy",
"guppy-summaries",
"cargo-compare",
"target-spec",
])
.expect("workspace names resolved");
assert!(
determinator_set.path_changed_set.is_empty(),
"no path changes"
);
assert_eq!(
determinator_set.summary_changed_set, expected,
"some summary changes"
);
assert_eq!(
determinator_set.affected_set, expected,
"some packages affected"
);
determinator
.set_features_only(
["fixture-manager"].iter().copied(),
StandardFeatures::Default,
)
.expect("fixture-manager is a valid package name");
let determinator_set = determinator.compute();
let features_only_expected = expected.union(
&new.graph()
.resolve_workspace_names(vec!["fixtures", "guppy-cmdlib", "guppy-benchmarks"])
.expect("workspace names resolved"),
);
assert!(
determinator_set.path_changed_set.is_empty(),
"no path changes"
);
assert_eq!(
determinator_set.summary_changed_set, features_only_expected,
"some summary changes"
);
assert_eq!(
determinator_set.affected_set, features_only_expected,
"some packages affected"
);
}
#[test]
fn guppy_match_paths() {
let old = JsonFixture::metadata_guppy_869476c();
let new = JsonFixture::metadata_guppy_c9b4f76();
let opts = read_options(new, "path-rules.toml");
let mut determinator = Determinator::new(old.graph(), new.graph());
determinator
.set_rules(&opts)
.expect("options set correctly");
let expected = vec![
("Cargo.toml", PathMatch::RuleMatchedAll),
(
"README.md",
PathMatch::RuleMatched(RuleIndex::CustomPath(0)),
),
(
"foo/README.tpl",
PathMatch::RuleMatched(RuleIndex::CustomPath(0)),
),
(
"CONTRIBUTING.md",
PathMatch::RuleMatched(RuleIndex::DefaultPath(4)),
),
(
"CODE_OF_CONDUCT.md",
PathMatch::RuleMatched(RuleIndex::CustomPath(2)),
),
("guppy/src/foo", PathMatch::AncestorMatched),
("guppy/src/lib.rs", PathMatch::AncestorMatched),
(
"internal-tools/proptest-ext/src/lib.rs",
PathMatch::AncestorMatched,
),
(
"Cargo.lock",
PathMatch::RuleMatched(RuleIndex::DefaultPath(3)),
),
];
for (path, m) in expected {
assert_eq!(
determinator.match_path(path, |_| {}),
m,
"expected rule match for {}",
path
);
}
}
static GIT_MATCH_PATHS_DIFF: &str =
include_str!("../../../fixtures/determinator-paths/git-diff.out");
#[test]
fn git_match_paths() {
let paths = Utf8Paths0::new(GIT_MATCH_PATHS_DIFF);
git_match_paths_impl(paths)
}
#[cfg(windows)]
#[test]
fn git_match_paths_backslashes() {
let paths = Utf8Paths0::new_forward_slashes(GIT_MATCH_PATHS_DIFF);
git_match_paths_impl(paths)
}
fn git_match_paths_impl(paths: Utf8Paths0) {
cfg_if! {
if #[cfg(windows)] {
let json = include_str!("../../../fixtures/determinator-paths/guppy-win.json");
} else {
let json = include_str!("../../../fixtures/determinator-paths/guppy-linux.json");
}
};
let package_graph = CargoMetadata::parse_json(json)
.expect("metadata json parsed correct")
.build_graph()
.expect("PackageGraph built");
let mut determinator = Determinator::new(&package_graph, &package_graph);
determinator.add_changed_paths(paths.iter());
let determinator_set = determinator.compute();
let expected_path_changed = package_graph
.resolve_workspace_names(vec![
"cargo-guppy",
"determinator",
"guppy",
"target-spec",
"hakari",
])
.expect("workspace names resolved");
assert_eq!(
determinator_set.path_changed_set, expected_path_changed,
"correct path changed set"
);
let expected_affected = package_graph
.resolve_workspace_names(vec![
"cargo-guppy",
"guppy",
"fixture-manager",
"cargo-compare",
"target-spec",
"determinator",
"hakari",
"fixtures",
"guppy-cmdlib",
"guppy-benchmarks",
])
.expect("workspace names resolved");
assert_eq!(
determinator_set.affected_set, expected_affected,
"correct affected set"
);
}
fn read_options(fixture: &JsonFixture, toml_name: &str) -> DeterminatorRules {
let mut toml_path = fixture.abs_path().to_path_buf();
toml_path.pop();
toml_path.push(toml_name);
let opts =
std::fs::read_to_string(&toml_path).expect("determinator.toml was successfully read");
DeterminatorRules::parse(&opts).expect("determinator.toml parsed")
}