Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix multiple version ordering #424

Merged
merged 2 commits into from
May 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions src/bans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,15 @@ pub fn check(
let mut all_start = std::usize::MAX;
let mut all_end = 0;

let mut kids = smallvec::SmallVec::<[Kid; 2]>::new();
struct Dupe {
/// Unique id, used for printing the actual diagnostic graphs
id: Kid,
/// Version, for deterministically ordering the duplicates
version: semver::Version,
}

let mut kids = smallvec::SmallVec::<[Dupe; 2]>::new();

#[allow(clippy::needless_range_loop)]
for dup in multi_detector.dupes.iter().cloned() {
let span = &ctx.krate_spans[dup];

Expand All @@ -247,7 +253,18 @@ pub fn check(

let krate = &ctx.krates[dup];

kids.push(krate.id.clone());
if let Err(i) = kids.binary_search_by(|other| match other.version.cmp(&krate.version) {
std::cmp::Ordering::Equal => other.id.cmp(&krate.id),
ord => ord,
}) {
kids.insert(
i,
Dupe {
id: krate.id.clone(),
version: krate.version.clone(),
},
);
}
}

{
Expand All @@ -262,7 +279,7 @@ pub fn check(
}
.into();

diag.kids = kids;
diag.kids = kids.into_iter().map(|dupe| dupe.id).collect();

let mut pack = Pack::new(Check::Bans);
pack.push(diag);
Expand Down
46 changes: 46 additions & 0 deletions tests/bans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,49 @@ fn deny_wildcards() {
);
}
}

#[test]
fn deterministic_duplicate_ordering() {
let diags = utils::gather_diagnostics::<cfg::Config, _, _>(
utils::get_test_data_krates("duplicates").unwrap(),
"deterministic_duplicate_ordering",
Some("multiple-versions = 'deny'"),
Some(std::time::Duration::from_millis(10000)),
|ctx, cs, tx| {
bans::check(ctx, None, cs, tx);
},
)
.unwrap();

let duplicates = [
("block-buffer", &["0.7.3", "0.10.2"]),
("digest", &["0.8.1", "0.10.3"]),
("generic-array", &["0.12.4", "0.14.5"]),
];

for dup in &duplicates {
assert!(
diags.iter().any(|v| {
if !field_eq!(v, "/fields/severity", "error")
|| !field_eq!(
v,
"/fields/message",
format!("found 2 duplicate entries for crate '{}'", dup.0)
)
{
return false;
}

for (i, version) in dup.1.iter().enumerate() {
if !field_eq!(v, &format!("/fields/graphs/{}/version", i), version) {
return false;
}
}

true
}),
"unable to find error diagnostic for duplicate '{}'",
dup.0
);
}
}
Loading