Skip to content

Commit ccb7100

Browse files
committed
Test solver behavior when using options
It is expected that the solver will make an effort to resolve packages that fit the options, even though it is not required to. Create a test where multiple builds exist with different values for a var and add an option to the solver for a specific value. A build exists with that value so the solver should pick it. Signed-off-by: J Robert Ray <[email protected]>
1 parent cd3318f commit ccb7100

File tree

2 files changed

+64
-3
lines changed

2 files changed

+64
-3
lines changed

crates/spk-solve/crates/macros/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ pub use {serde_json, spfs};
1313
/// make_repo!({"pkg": "mypkg/1.0.0"}, options = {"debug" => "off"});
1414
#[macro_export]
1515
macro_rules! make_repo {
16-
( [ $( $spec:tt ),+ $(,)? ] ) => {{
16+
( [ $( $spec:tt ),* $(,)? ] ) => {{
1717
make_repo!([ $( $spec ),* ], options={})
1818
}};
19-
( [ $( $spec:tt ),+ $(,)? ], options={ $($k:expr => $v:expr),* } ) => {{
19+
( [ $( $spec:tt ),* $(,)? ], options={ $($k:expr => $v:expr),* } ) => {{
2020
let options = spk_schema::foundation::option_map!{$($k => $v),*};
2121
make_repo!([ $( $spec ),* ], options=options)
2222
}};
23-
( [ $( $spec:tt ),+ $(,)? ], options=$options:expr ) => {{
23+
( [ $( $spec:tt ),* $(,)? ], options=$options:expr ) => {{
2424
tracing::debug!("creating in-memory repository");
2525
let repo = spk_storage::RepositoryHandle::new_mem();
2626
let _opts = $options;

crates/spk-solve/src/solvers/solver_test.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33
// https://github.com/spkenv/spk
44

5+
use std::collections::HashMap;
56
use std::sync::Arc;
67

78
use rstest::{fixture, rstest};
@@ -3083,3 +3084,63 @@ async fn request_for_all_component_picks_correct_version(
30833084
let solution = run_and_print_resolve_for_tests(&mut solver).await.unwrap();
30843085
assert_resolved!(solution, "mypkg", version = version);
30853086
}
3087+
3088+
/// Test that adding options to the solver make the solver pick the build that
3089+
/// satisfies those options, when possible.
3090+
#[rstest]
3091+
#[case::step(step_solver())]
3092+
#[case::resolvo(resolvo_solver())]
3093+
#[tokio::test]
3094+
async fn options_influence_build_choice(
3095+
#[case] mut solver: SolverImpl,
3096+
#[values(true, false)] scope_var: bool,
3097+
) {
3098+
// Create 10 builds of a package, varying the value of an option called
3099+
// "num".
3100+
let builds = (0..10)
3101+
.map(|num| {
3102+
(
3103+
num.to_string(),
3104+
make_build!({
3105+
"pkg": "mypkg/1.0.0",
3106+
"build": {"options": [{"var": format!("num/{num}")}]},
3107+
}),
3108+
)
3109+
})
3110+
.inspect(|(num, spec)| {
3111+
eprintln!("Created build with num {num}: {}", spec.ident().build());
3112+
})
3113+
.collect::<HashMap<_, _>>();
3114+
3115+
let repo = make_repo!([]);
3116+
let _options = option_map! {};
3117+
for spec in builds.values() {
3118+
let (s, cmpts) = make_package!(repo, spec, _options);
3119+
repo.publish_package(&s, &cmpts).await.unwrap();
3120+
}
3121+
3122+
let repo = Arc::new(repo);
3123+
3124+
// For each option value from above, ask the solver to resolve mypkg using
3125+
// an option with that value for "num". It is expected that it will pick the
3126+
// build that was created with that value for "num".
3127+
//
3128+
// Since there are 10 builds, the odds of this succeeding by chance are 1 in
3129+
// 10 billion.
3130+
for (num, spec) in &builds {
3131+
solver.reset();
3132+
3133+
solver.add_repository(Arc::clone(&repo));
3134+
solver.add_request(request!("mypkg"));
3135+
3136+
let options = if scope_var {
3137+
option_map! { "mypkg.num" => num.to_string() }
3138+
} else {
3139+
option_map! { "num" => num.to_string() }
3140+
};
3141+
solver.update_options(options);
3142+
3143+
let solution = run_and_print_resolve_for_tests(&mut solver).await.unwrap();
3144+
assert_resolved!(solution, "mypkg", build = *spec.ident().build());
3145+
}
3146+
}

0 commit comments

Comments
 (0)