-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #14614 - x-hgg-x:more-sat-resolver-tests, r=Eh2406
Add more SAT resolver tests ### What does this PR try to resolve? This is a follow-up of #14583. ### How should we test and review this PR? * Commit 1 splits tests into smaller modules. * Commit 2 adds more helper trait methods. * Commit 3 refactors computation of the SAT clauses, by introducing intermediate boolean variables for each dependency and each dependency feature declared in a package. The old behavior was incorrect: package features specified in an optional dependency were activated if the package was activated, even if the dependency wasn't activated. * Commit 4 add tests from https://github.com/Eh2406/pubgrub-crates-benchmark/tree/main/out/index_ron. r? Eh2406
- Loading branch information
Showing
9 changed files
with
2,242 additions
and
1,220 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,260 @@ | ||
use std::collections::BTreeMap; | ||
use std::fmt::Debug; | ||
use std::sync::OnceLock; | ||
|
||
use cargo::core::dependency::DepKind; | ||
use cargo::core::{Dependency, GitReference, PackageId, SourceId, Summary}; | ||
use cargo::util::IntoUrl; | ||
|
||
pub trait ToDep { | ||
fn to_dep(self) -> Dependency; | ||
fn opt(self) -> Dependency; | ||
fn with(self, features: &[&'static str]) -> Dependency; | ||
fn with_default(self) -> Dependency; | ||
fn rename(self, name: &str) -> Dependency; | ||
} | ||
|
||
impl ToDep for &'static str { | ||
fn to_dep(self) -> Dependency { | ||
Dependency::parse(self, Some("1.0.0"), registry_loc()).unwrap() | ||
} | ||
fn opt(self) -> Dependency { | ||
let mut dep = self.to_dep(); | ||
dep.set_optional(true); | ||
dep | ||
} | ||
fn with(self, features: &[&'static str]) -> Dependency { | ||
let mut dep = self.to_dep(); | ||
dep.set_default_features(false); | ||
dep.set_features(features.into_iter().copied()); | ||
dep | ||
} | ||
fn with_default(self) -> Dependency { | ||
let mut dep = self.to_dep(); | ||
dep.set_default_features(true); | ||
dep | ||
} | ||
fn rename(self, name: &str) -> Dependency { | ||
let mut dep = self.to_dep(); | ||
dep.set_explicit_name_in_toml(name); | ||
dep | ||
} | ||
} | ||
|
||
impl ToDep for Dependency { | ||
fn to_dep(self) -> Dependency { | ||
self | ||
} | ||
fn opt(mut self) -> Dependency { | ||
self.set_optional(true); | ||
self | ||
} | ||
fn with(mut self, features: &[&'static str]) -> Dependency { | ||
self.set_default_features(false); | ||
self.set_features(features.into_iter().copied()); | ||
self | ||
} | ||
fn with_default(mut self) -> Dependency { | ||
self.set_default_features(true); | ||
self | ||
} | ||
fn rename(mut self, name: &str) -> Dependency { | ||
self.set_explicit_name_in_toml(name); | ||
self | ||
} | ||
} | ||
|
||
pub trait ToPkgId { | ||
fn to_pkgid(&self) -> PackageId; | ||
} | ||
|
||
impl ToPkgId for PackageId { | ||
fn to_pkgid(&self) -> PackageId { | ||
*self | ||
} | ||
} | ||
|
||
impl<'a> ToPkgId for &'a str { | ||
fn to_pkgid(&self) -> PackageId { | ||
PackageId::try_new(*self, "1.0.0", registry_loc()).unwrap() | ||
} | ||
} | ||
|
||
impl<T: AsRef<str>, U: AsRef<str>> ToPkgId for (T, U) { | ||
fn to_pkgid(&self) -> PackageId { | ||
let (name, vers) = self; | ||
PackageId::try_new(name.as_ref(), vers.as_ref(), registry_loc()).unwrap() | ||
} | ||
} | ||
|
||
#[macro_export] | ||
macro_rules! pkg { | ||
($pkgid:expr => [$($deps:expr),* $(,)? ]) => ({ | ||
use $crate::helpers::ToDep; | ||
let d: Vec<Dependency> = vec![$($deps.to_dep()),*]; | ||
$crate::helpers::pkg_dep($pkgid, d) | ||
}); | ||
|
||
($pkgid:expr) => ({ | ||
$crate::helpers::pkg($pkgid) | ||
}) | ||
} | ||
|
||
fn registry_loc() -> SourceId { | ||
static EXAMPLE_DOT_COM: OnceLock<SourceId> = OnceLock::new(); | ||
let example_dot = EXAMPLE_DOT_COM.get_or_init(|| { | ||
SourceId::for_registry(&"https://example.com".into_url().unwrap()).unwrap() | ||
}); | ||
*example_dot | ||
} | ||
|
||
pub fn pkg<T: ToPkgId>(name: T) -> Summary { | ||
pkg_dep(name, Vec::new()) | ||
} | ||
|
||
pub fn pkg_dep<T: ToPkgId>(name: T, dep: Vec<Dependency>) -> Summary { | ||
let pkgid = name.to_pkgid(); | ||
let link = if pkgid.name().ends_with("-sys") { | ||
Some(pkgid.name()) | ||
} else { | ||
None | ||
}; | ||
Summary::new(name.to_pkgid(), dep, &BTreeMap::new(), link, None).unwrap() | ||
} | ||
|
||
pub fn pkg_dep_with<T: ToPkgId>( | ||
name: T, | ||
dep: Vec<Dependency>, | ||
features: &[(&'static str, &[&'static str])], | ||
) -> Summary { | ||
let pkgid = name.to_pkgid(); | ||
let link = if pkgid.name().ends_with("-sys") { | ||
Some(pkgid.name()) | ||
} else { | ||
None | ||
}; | ||
let features = features | ||
.into_iter() | ||
.map(|&(name, values)| (name.into(), values.into_iter().map(|&v| v.into()).collect())) | ||
.collect(); | ||
Summary::new(name.to_pkgid(), dep, &features, link, None).unwrap() | ||
} | ||
|
||
pub fn pkg_dep_link<T: ToPkgId>(name: T, link: &str, dep: Vec<Dependency>) -> Summary { | ||
Summary::new(name.to_pkgid(), dep, &BTreeMap::new(), Some(link), None).unwrap() | ||
} | ||
|
||
pub fn pkg_id(name: &str) -> PackageId { | ||
PackageId::try_new(name, "1.0.0", registry_loc()).unwrap() | ||
} | ||
|
||
pub fn pkg_id_source(name: &str, source: &str) -> PackageId { | ||
PackageId::try_new( | ||
name, | ||
"1.0.0", | ||
SourceId::for_registry(&source.into_url().unwrap()).unwrap(), | ||
) | ||
.unwrap() | ||
} | ||
|
||
fn pkg_id_loc(name: &str, loc: &str) -> PackageId { | ||
let remote = loc.into_url(); | ||
let master = GitReference::Branch("master".to_string()); | ||
let source_id = SourceId::for_git(&remote.unwrap(), master).unwrap(); | ||
|
||
PackageId::try_new(name, "1.0.0", source_id).unwrap() | ||
} | ||
|
||
pub fn pkg_loc(name: &str, loc: &str) -> Summary { | ||
let link = if name.ends_with("-sys") { | ||
Some(name) | ||
} else { | ||
None | ||
}; | ||
Summary::new( | ||
pkg_id_loc(name, loc), | ||
Vec::new(), | ||
&BTreeMap::new(), | ||
link, | ||
None, | ||
) | ||
.unwrap() | ||
} | ||
|
||
pub fn remove_dep(sum: &Summary, ind: usize) -> Summary { | ||
let mut deps = sum.dependencies().to_vec(); | ||
deps.remove(ind); | ||
// note: more things will need to be copied over in the future, but it works for now. | ||
Summary::new(sum.package_id(), deps, &BTreeMap::new(), sum.links(), None).unwrap() | ||
} | ||
|
||
pub fn dep(name: &str) -> Dependency { | ||
dep_req(name, "*") | ||
} | ||
|
||
pub fn dep_req(name: &str, req: &str) -> Dependency { | ||
Dependency::parse(name, Some(req), registry_loc()).unwrap() | ||
} | ||
|
||
pub fn dep_req_kind(name: &str, req: &str, kind: DepKind) -> Dependency { | ||
let mut dep = dep_req(name, req); | ||
dep.set_kind(kind); | ||
dep | ||
} | ||
|
||
pub fn dep_req_platform(name: &str, req: &str, platform: &str) -> Dependency { | ||
let mut dep = dep_req(name, req); | ||
dep.set_platform(Some(platform.parse().unwrap())); | ||
dep | ||
} | ||
|
||
pub fn dep_loc(name: &str, location: &str) -> Dependency { | ||
let url = location.into_url().unwrap(); | ||
let master = GitReference::Branch("master".to_string()); | ||
let source_id = SourceId::for_git(&url, master).unwrap(); | ||
Dependency::parse(name, Some("1.0.0"), source_id).unwrap() | ||
} | ||
|
||
pub fn dep_kind(name: &str, kind: DepKind) -> Dependency { | ||
let mut dep = dep(name); | ||
dep.set_kind(kind); | ||
dep | ||
} | ||
|
||
pub fn dep_platform(name: &str, platform: &str) -> Dependency { | ||
let mut dep = dep(name); | ||
dep.set_platform(Some(platform.parse().unwrap())); | ||
dep | ||
} | ||
|
||
pub fn registry(pkgs: Vec<Summary>) -> Vec<Summary> { | ||
pkgs | ||
} | ||
|
||
pub fn names<P: ToPkgId>(names: &[P]) -> Vec<PackageId> { | ||
names.iter().map(|name| name.to_pkgid()).collect() | ||
} | ||
|
||
pub fn loc_names(names: &[(&'static str, &'static str)]) -> Vec<PackageId> { | ||
names | ||
.iter() | ||
.map(|&(name, loc)| pkg_id_loc(name, loc)) | ||
.collect() | ||
} | ||
|
||
/// Assert `xs` contains `elems` | ||
#[track_caller] | ||
pub fn assert_contains<A: PartialEq + Debug>(xs: &[A], elems: &[A]) { | ||
for elem in elems { | ||
assert!( | ||
xs.contains(elem), | ||
"missing element\nset: {xs:?}\nmissing: {elem:?}" | ||
); | ||
} | ||
} | ||
|
||
#[track_caller] | ||
pub fn assert_same<A: PartialEq + Debug>(a: &[A], b: &[A]) { | ||
assert_eq!(a.len(), b.len(), "not equal\n{a:?}\n{b:?}"); | ||
assert_contains(b, a); | ||
} |
Oops, something went wrong.