Skip to content

Commit bd787d5

Browse files
committed
Add tests to show the conflict graph
1 parent 7e1bd18 commit bd787d5

File tree

2 files changed

+65
-2
lines changed

2 files changed

+65
-2
lines changed

src/conflict.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ impl Conflict {
201201
for &candidate_id in requirement_candidates {
202202
let candidate_node =
203203
Self::add_node(&mut graph, &mut nodes, candidate_id.into());
204+
204205
graph.add_edge(
205206
package_node,
206207
candidate_node,
@@ -333,6 +334,8 @@ pub(crate) enum ConflictCause {
333334
ForbidMultipleInstances,
334335
/// The node was excluded
335336
Excluded,
337+
/// The condition for the dependency is not met
338+
ConditionNotMet(VersionSetId),
336339
}
337340

338341
/// Represents a node that has been merged with others
@@ -402,7 +405,7 @@ impl ConflictGraph {
402405
ConflictEdge::ConditionalRequires(_, _)
403406
if target != ConflictNode::UnresolvedDependency =>
404407
{
405-
"blue"
408+
"blue" // This indicates that the requirement has candidates, but the condition is not met
406409
}
407410
_ => "red",
408411
};
@@ -414,10 +417,16 @@ impl ConflictGraph {
414417
ConflictEdge::ConditionalRequires(condition_version_set_id, requirement) => {
415418
format!(
416419
"if {} then {}",
417-
interner.display_version_set(*condition_version_set_id),
420+
Requirement::from(*condition_version_set_id).display(interner),
418421
requirement.display(interner)
419422
)
420423
}
424+
ConflictEdge::Conflict(ConflictCause::ConditionNotMet(version_set_id)) => {
425+
format!(
426+
"condition not met: {}",
427+
interner.display_version_set(*version_set_id)
428+
)
429+
}
421430
ConflictEdge::Conflict(ConflictCause::Constrains(version_set_id)) => {
422431
interner.display_version_set(*version_set_id).to_string()
423432
}
@@ -1123,6 +1132,13 @@ impl<'i, I: Interner> fmt::Display for DisplayUnsat<'i, I> {
11231132
self.interner.display_merged_solvables(&[solvable_id]),
11241133
)?;
11251134
}
1135+
ConflictCause::ConditionNotMet(version_set_id) => {
1136+
writeln!(
1137+
f,
1138+
"{indent}condition not met: {}",
1139+
self.interner.display_version_set(*version_set_id),
1140+
)?;
1141+
}
11261142
ConflictCause::Excluded => continue,
11271143
};
11281144
}

tests/solver.rs

+47
Original file line numberDiff line numberDiff line change
@@ -1679,6 +1679,53 @@ fn test_conditional_requirements_multiple_versions_met() {
16791679
"###);
16801680
}
16811681

1682+
#[test]
1683+
fn test_conditional_requirements_conflict() {
1684+
let mut provider = BundleBoxProvider::new();
1685+
1686+
// Add multiple versions of package b
1687+
provider.add_package("b", 1.into(), &[], &[]);
1688+
provider.add_package("b", 2.into(), &[], &[]);
1689+
provider.add_package("b", 3.into(), &[], &[]);
1690+
1691+
// Package c has two versions with different dependencies
1692+
provider.add_package("c", 1.into(), &["d 1"], &[]); // c v1 requires d v1
1693+
provider.add_package("c", 2.into(), &["d 2"], &[]); // c v2 requires d v2
1694+
1695+
// Package d has incompatible versions
1696+
provider.add_package("d", 1.into(), &[], &[]);
1697+
provider.add_package("d", 2.into(), &[], &[]);
1698+
1699+
provider.add_package("a", 1.into(), &["b 1", "c 1; if b 1", "d 2", "c 2; if b 2"], &[]);
1700+
1701+
let requirements = provider.requirements(&[
1702+
"a", // Require package a
1703+
]);
1704+
1705+
let mut solver = Solver::new(provider);
1706+
let problem = Problem::new().requirements(requirements);
1707+
1708+
// This should fail to solve because:
1709+
// 1. When b=1 is chosen, it triggers the conditional requirement for c 1
1710+
// 2. c 1 requires d 1, but a requires d 2
1711+
// 3. d 1 and d 2 cannot be installed together
1712+
1713+
let solved = solver.solve(problem);
1714+
assert!(solved.is_err());
1715+
1716+
let conflict = solved.unwrap_err();
1717+
match conflict {
1718+
UnsolvableOrCancelled::Unsolvable(conflict) => {
1719+
let graph = conflict.graph(&solver);
1720+
let mut output = stderr();
1721+
graph
1722+
.graphviz(&mut output, solver.provider(), true)
1723+
.unwrap();
1724+
}
1725+
_ => panic!("Expected a conflict"),
1726+
}
1727+
}
1728+
16821729
/// In this test, the resolver installs the highest available version of b which is b 2
16831730
/// However, the conditional requirement is that if b 1..2 is installed, require c
16841731
/// Since b 2 is installed, c should not be installed

0 commit comments

Comments
 (0)