uv/vendor/pubgrub/tests/examples.rs
Charlie Marsh 9b3405bf0e
Upgrade PubGrub to dev branch (#147)
Updates to `29c48fb9f3daa11bd02794edd55060d0b01ee705` from the
`pubgrub-rs` dev branch. This lets us reduce the number of changes we've
made to PubGrub itself (now, only changing visibility to export a few
things from the `solver.rs` module).
2023-10-20 03:23:26 +00:00

211 lines
7.4 KiB
Rust

// SPDX-License-Identifier: MPL-2.0
use pubgrub::range::Range;
use pubgrub::solver::{resolve, OfflineDependencyProvider};
use pubgrub::type_aliases::Map;
use pubgrub::version::{NumberVersion, SemanticVersion};
type NumVS = Range<NumberVersion>;
type SemVS = Range<SemanticVersion>;
use log::LevelFilter;
use std::io::Write;
fn init_log() {
let _ = env_logger::builder()
.filter_level(LevelFilter::Trace)
.format(|buf, record| writeln!(buf, "{}", record.args()))
.is_test(true)
.try_init();
}
#[test]
/// https://github.com/dart-lang/pub/blob/master/doc/solver.md#no-conflicts
fn no_conflict() {
init_log();
let mut dependency_provider = OfflineDependencyProvider::<&str, SemVS>::new();
#[rustfmt::skip]
dependency_provider.add_dependencies(
"root", (1, 0, 0),
[("foo", Range::between((1, 0, 0), (2, 0, 0)))],
);
#[rustfmt::skip]
dependency_provider.add_dependencies(
"foo", (1, 0, 0),
[("bar", Range::between((1, 0, 0), (2, 0, 0)))],
);
dependency_provider.add_dependencies("bar", (1, 0, 0), []);
dependency_provider.add_dependencies("bar", (2, 0, 0), []);
// Run the algorithm.
let computed_solution = resolve(&dependency_provider, "root", (1, 0, 0)).unwrap();
// Solution.
let mut expected_solution = Map::default();
expected_solution.insert("root", (1, 0, 0).into());
expected_solution.insert("foo", (1, 0, 0).into());
expected_solution.insert("bar", (1, 0, 0).into());
// Comparing the true solution with the one computed by the algorithm.
assert_eq!(expected_solution, computed_solution);
}
#[test]
/// https://github.com/dart-lang/pub/blob/master/doc/solver.md#avoiding-conflict-during-decision-making
fn avoiding_conflict_during_decision_making() {
init_log();
let mut dependency_provider = OfflineDependencyProvider::<&str, SemVS>::new();
#[rustfmt::skip]
dependency_provider.add_dependencies(
"root", (1, 0, 0),
[
("foo", Range::between((1, 0, 0), (2, 0, 0))),
("bar", Range::between((1, 0, 0), (2, 0, 0))),
],
);
#[rustfmt::skip]
dependency_provider.add_dependencies(
"foo", (1, 1, 0),
[("bar", Range::between((2, 0, 0), (3, 0, 0)))],
);
dependency_provider.add_dependencies("foo", (1, 0, 0), []);
dependency_provider.add_dependencies("bar", (1, 0, 0), []);
dependency_provider.add_dependencies("bar", (1, 1, 0), []);
dependency_provider.add_dependencies("bar", (2, 0, 0), []);
// Run the algorithm.
let computed_solution = resolve(&dependency_provider, "root", (1, 0, 0)).unwrap();
// Solution.
let mut expected_solution = Map::default();
expected_solution.insert("root", (1, 0, 0).into());
expected_solution.insert("foo", (1, 0, 0).into());
expected_solution.insert("bar", (1, 1, 0).into());
// Comparing the true solution with the one computed by the algorithm.
assert_eq!(expected_solution, computed_solution);
}
#[test]
/// https://github.com/dart-lang/pub/blob/master/doc/solver.md#performing-conflict-resolution
fn conflict_resolution() {
init_log();
let mut dependency_provider = OfflineDependencyProvider::<&str, SemVS>::new();
#[rustfmt::skip]
dependency_provider.add_dependencies(
"root", (1, 0, 0),
[("foo", Range::higher_than((1, 0, 0)))],
);
#[rustfmt::skip]
dependency_provider.add_dependencies(
"foo", (2, 0, 0),
[("bar", Range::between((1, 0, 0), (2, 0, 0)))],
);
dependency_provider.add_dependencies("foo", (1, 0, 0), []);
#[rustfmt::skip]
dependency_provider.add_dependencies(
"bar", (1, 0, 0),
[("foo", Range::between((1, 0, 0), (2, 0, 0)))],
);
// Run the algorithm.
let computed_solution = resolve(&dependency_provider, "root", (1, 0, 0)).unwrap();
// Solution.
let mut expected_solution = Map::default();
expected_solution.insert("root", (1, 0, 0).into());
expected_solution.insert("foo", (1, 0, 0).into());
// Comparing the true solution with the one computed by the algorithm.
assert_eq!(expected_solution, computed_solution);
}
#[test]
/// https://github.com/dart-lang/pub/blob/master/doc/solver.md#conflict-resolution-with-a-partial-satisfier
fn conflict_with_partial_satisfier() {
init_log();
let mut dependency_provider = OfflineDependencyProvider::<&str, SemVS>::new();
#[rustfmt::skip]
// root 1.0.0 depends on foo ^1.0.0 and target ^2.0.0
dependency_provider.add_dependencies(
"root", (1, 0, 0),
[
("foo", Range::between((1, 0, 0), (2, 0, 0))),
("target", Range::between((2, 0, 0), (3, 0, 0))),
],
);
#[rustfmt::skip]
// foo 1.1.0 depends on left ^1.0.0 and right ^1.0.0
dependency_provider.add_dependencies(
"foo", (1, 1, 0),
[
("left", Range::between((1, 0, 0), (2, 0, 0))),
("right", Range::between((1, 0, 0), (2, 0, 0))),
],
);
dependency_provider.add_dependencies("foo", (1, 0, 0), []);
#[rustfmt::skip]
// left 1.0.0 depends on shared >=1.0.0
dependency_provider.add_dependencies(
"left", (1, 0, 0),
[("shared", Range::higher_than((1, 0, 0)))],
);
#[rustfmt::skip]
// right 1.0.0 depends on shared <2.0.0
dependency_provider.add_dependencies(
"right", (1, 0, 0),
[("shared", Range::strictly_lower_than((2, 0, 0)))],
);
dependency_provider.add_dependencies("shared", (2, 0, 0), []);
#[rustfmt::skip]
// shared 1.0.0 depends on target ^1.0.0
dependency_provider.add_dependencies(
"shared", (1, 0, 0),
[("target", Range::between((1, 0, 0), (2, 0, 0)))],
);
dependency_provider.add_dependencies("target", (2, 0, 0), []);
dependency_provider.add_dependencies("target", (1, 0, 0), []);
// Run the algorithm.
let computed_solution = resolve(&dependency_provider, "root", (1, 0, 0)).unwrap();
// Solution.
let mut expected_solution = Map::default();
expected_solution.insert("root", (1, 0, 0).into());
expected_solution.insert("foo", (1, 0, 0).into());
expected_solution.insert("target", (2, 0, 0).into());
// Comparing the true solution with the one computed by the algorithm.
assert_eq!(expected_solution, computed_solution);
}
#[test]
/// a0 dep on b and c
/// b0 dep on d0
/// b1 dep on d1 (not existing)
/// c0 has no dep
/// c1 dep on d2 (not existing)
/// d0 has no dep
///
/// Solution: a0, b0, c0, d0
fn double_choices() {
init_log();
let mut dependency_provider = OfflineDependencyProvider::<&str, NumVS>::new();
dependency_provider.add_dependencies("a", 0, [("b", Range::full()), ("c", Range::full())]);
dependency_provider.add_dependencies("b", 0, [("d", Range::singleton(0))]);
dependency_provider.add_dependencies("b", 1, [("d", Range::singleton(1))]);
dependency_provider.add_dependencies("c", 0, []);
dependency_provider.add_dependencies("c", 1, [("d", Range::singleton(2))]);
dependency_provider.add_dependencies("d", 0, []);
// Solution.
let mut expected_solution = Map::default();
expected_solution.insert("a", 0.into());
expected_solution.insert("b", 0.into());
expected_solution.insert("c", 0.into());
expected_solution.insert("d", 0.into());
// Run the algorithm.
let computed_solution = resolve(&dependency_provider, "a", 0).unwrap();
assert_eq!(expected_solution, computed_solution);
}