Skip to content

Commit

Permalink
Merge #289
Browse files Browse the repository at this point in the history
289: Fix regression where last release was not tested when last in search space r=foresterre a=foresterre

Fixes #288 

Co-authored-by: Martijn Gribnau <garm@ilumeo.com>
  • Loading branch information
bors[bot] and foresterre authored Feb 2, 2022
2 parents 7daf92c + 38a2888 commit 8bb2860
Show file tree
Hide file tree
Showing 4 changed files with 285 additions and 23 deletions.
6 changes: 3 additions & 3 deletions src/outcome.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl Outcome {

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SuccessOutcome {
toolchain_spec: OwnedToolchainSpec,
pub(crate) toolchain_spec: OwnedToolchainSpec,
}

impl FormatUserOutput<Human> for SuccessOutcome {
Expand Down Expand Up @@ -77,8 +77,8 @@ impl FormatUserOutput<Json> for SuccessOutcome {

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct FailureOutcome {
toolchain_spec: OwnedToolchainSpec,
error_message: String,
pub(crate) toolchain_spec: OwnedToolchainSpec,
pub(crate) error_message: String,
}

impl FormatUserOutput<Human> for FailureOutcome {
Expand Down
2 changes: 1 addition & 1 deletion src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub enum MinimalCompatibility {
}

impl MinimalCompatibility {
pub fn unwrap_version(&self) -> semver::Version {
pub fn to_version(&self) -> semver::Version {
if let Self::CapableToolchain { toolchain, .. } = self {
return toolchain.version().clone();
}
Expand Down
286 changes: 274 additions & 12 deletions src/search_methods/bisect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,9 @@ impl<R: Check> Bisect<R> {
output.set_steps(remainder + iteration);
}

fn minimum_capable(
releases: &[Release],
index_of_msrv: Option<Indices>,
config: &Config,
) -> MinimalCompatibility {
index_of_msrv.map_or(MinimalCompatibility::NoCompatibleToolchains, |i| {
let version = releases[i.middle()].version();
fn minimum_capable(msrv: Option<&Release>, config: &Config) -> MinimalCompatibility {
msrv.map_or(MinimalCompatibility::NoCompatibleToolchains, |release| {
let version = release.version();

MinimalCompatibility::CapableToolchain {
toolchain: OwnedToolchainSpec::new(version, config.target()),
Expand All @@ -68,6 +64,8 @@ impl<R: Check> FindMinimalCapableToolchain for Bisect<R> {

let mut last_compatible_index = None;

info!(?search_space);

while let Step {
indices: next_indices,
result: Some(step),
Expand All @@ -77,6 +75,8 @@ impl<R: Check> FindMinimalCapableToolchain for Bisect<R> {
)? {
iteration += 1;

info!(?indices, ?next_indices);

Self::update_progress_bar(iteration, next_indices, output);

match step {
Expand All @@ -92,10 +92,272 @@ impl<R: Check> FindMinimalCapableToolchain for Bisect<R> {
indices = next_indices;
}

Ok(Self::minimum_capable(
search_space,
last_compatible_index,
config,
))
let converged_to_release = &search_space[indices.middle()];

// Work-around for regression:
// https://github.com/foresterre/cargo-msrv/issues/288
let msrv = if indices.middle() == search_space.len() - 1 {
match Self::run_check(&self.runner, converged_to_release, config, output)? {
ConvergeTo::Left(outcome) => {
write_failed_check(&outcome, config, output);
last_compatible_index.map(|i| &search_space[i.middle()])
}
ConvergeTo::Right(outcome) => {
write_succeeded_check(&outcome, config, output);
Some(converged_to_release)
}
}
} else {
last_compatible_index.map(|i| &search_space[i.middle()])
};

Ok(Self::minimum_capable(msrv, config))
}
}

#[cfg(test)]
mod tests {
use super::Bisect;
use crate::check::Check;
use crate::outcome::{FailureOutcome, Outcome, SuccessOutcome};
use crate::reporter::no_output::NoOutput;
use crate::search_methods::FindMinimalCapableToolchain;
use crate::semver::Version;
use crate::toolchain::{OwnedToolchainSpec, ToolchainSpec};
use crate::{semver, Config, ModeIntent, TResult};
use rust_releases::Release;
use std::collections::BTreeSet;
use std::iter::FromIterator;

#[derive(Default)]
struct FakeRunner {
successes: BTreeSet<semver::Version>,
}

impl<'v> FromIterator<&'v semver::Version> for FakeRunner {
fn from_iter<T: IntoIterator<Item = &'v Version>>(iter: T) -> Self {
Self {
successes: iter.into_iter().map(ToOwned::to_owned).collect(),
}
}
}

impl Check for FakeRunner {
fn check(&self, config: &Config, toolchain: &ToolchainSpec) -> TResult<Outcome> {
if self.successes.contains(toolchain.version()) {
Ok(Outcome::Success(SuccessOutcome {
toolchain_spec: OwnedToolchainSpec::new(toolchain.version(), config.target()),
}))
} else {
Ok(Outcome::Failure(FailureOutcome {
toolchain_spec: OwnedToolchainSpec::new(toolchain.version(), config.target()),
error_message: "".to_string(),
}))
}
}
}

fn fake_config() -> Config<'static> {
Config::new(ModeIntent::Find, "".to_string())
}

#[yare::parameterized(
regression288_search_space_of_3_all_succeed = {
&[
Release::new_stable(semver::Version::new(1, 58, 1)),
Release::new_stable(semver::Version::new(1, 57, 0)),
Release::new_stable(semver::Version::new(1, 56, 1)),
], &[
semver::Version::new(1, 58, 1),
semver::Version::new(1, 57, 0),
semver::Version::new(1, 56, 1),
],
Version::new(1, 56, 1)
},
one_option = {
&[
Release::new_stable(semver::Version::new(1, 56, 1)),
],
&[
semver::Version::new(1, 56, 1)
],
semver::Version::new(1, 56, 1)
},
search_space_of_3_most_recent_two_succeed = {
&[
Release::new_stable(semver::Version::new(1, 58, 0)),
Release::new_stable(semver::Version::new(1, 57, 0)),
Release::new_stable(semver::Version::new(1, 56, 0)),
],
&[
semver::Version::new(1, 58, 0),
semver::Version::new(1, 57, 0),
],
semver::Version::new(1, 57, 0)
},
search_space_of_3_most_recent_one_succeeds = {
&[
Release::new_stable(semver::Version::new(1, 58, 0)),
Release::new_stable(semver::Version::new(1, 57, 0)),
Release::new_stable(semver::Version::new(1, 56, 0)),
],
&[
semver::Version::new(1, 58, 0),
],
semver::Version::new(1, 58, 0)
},
search_space_of_2_all_succeed = {
&[
Release::new_stable(semver::Version::new(1, 58, 0)),
Release::new_stable(semver::Version::new(1, 57, 0)),
], &[
semver::Version::new(1, 58, 0),
semver::Version::new(1, 57, 0),
],
Version::new(1, 57, 0)
},
search_space_of_2_most_recent_one_succeeds = {
&[
Release::new_stable(semver::Version::new(1, 58, 0)),
Release::new_stable(semver::Version::new(1, 57, 0)),
], &[
semver::Version::new(1, 58, 0),
],
Version::new(1, 58, 0)
},
search_space_of_4_all_succeed = {
&[
Release::new_stable(semver::Version::new(1, 58, 0)),
Release::new_stable(semver::Version::new(1, 57, 0)),
Release::new_stable(semver::Version::new(1, 56, 0)),
Release::new_stable(semver::Version::new(1, 55, 0)),
], &[
semver::Version::new(1, 58, 0),
semver::Version::new(1, 57, 0),
semver::Version::new(1, 56, 0),
semver::Version::new(1, 55, 0),
],
Version::new(1, 55, 0)
},
search_space_of_4_most_recent_three_succeed = {
&[
Release::new_stable(semver::Version::new(1, 58, 0)),
Release::new_stable(semver::Version::new(1, 57, 0)),
Release::new_stable(semver::Version::new(1, 56, 0)),
Release::new_stable(semver::Version::new(1, 55, 0)),
], &[
semver::Version::new(1, 58, 0),
semver::Version::new(1, 57, 0),
semver::Version::new(1, 56, 0),
],
Version::new(1, 56, 0)
},
search_space_of_4_most_recent_two_succeed = {
&[
Release::new_stable(semver::Version::new(1, 58, 0)),
Release::new_stable(semver::Version::new(1, 57, 0)),
Release::new_stable(semver::Version::new(1, 56, 0)),
Release::new_stable(semver::Version::new(1, 55, 0)),
], &[
semver::Version::new(1, 58, 0),
semver::Version::new(1, 57, 0),
],
Version::new(1, 57, 0)
},
search_space_of_4_most_recent_one_succeeds = {
&[
Release::new_stable(semver::Version::new(1, 58, 0)),
Release::new_stable(semver::Version::new(1, 57, 0)),
Release::new_stable(semver::Version::new(1, 56, 0)),
Release::new_stable(semver::Version::new(1, 55, 0)),
], &[
semver::Version::new(1, 58, 0),
],
Version::new(1, 58, 0)
},
search_space_of_5_all_succeed = {
&[
Release::new_stable(semver::Version::new(1, 58, 0)),
Release::new_stable(semver::Version::new(1, 57, 0)),
Release::new_stable(semver::Version::new(1, 56, 0)),
Release::new_stable(semver::Version::new(1, 55, 0)),
Release::new_stable(semver::Version::new(1, 54, 0)),
], &[
semver::Version::new(1, 58, 0),
semver::Version::new(1, 57, 0),
semver::Version::new(1, 56, 0),
semver::Version::new(1, 55, 0),
semver::Version::new(1, 54, 0),
],
Version::new(1, 54, 0)
},
search_space_of_5_most_recent_four_succeed = {
&[
Release::new_stable(semver::Version::new(1, 58, 0)),
Release::new_stable(semver::Version::new(1, 57, 0)),
Release::new_stable(semver::Version::new(1, 56, 0)),
Release::new_stable(semver::Version::new(1, 55, 0)),
Release::new_stable(semver::Version::new(1, 54, 0)),
], &[
semver::Version::new(1, 58, 0),
semver::Version::new(1, 57, 0),
semver::Version::new(1, 56, 0),
semver::Version::new(1, 55, 0),
],
Version::new(1, 55, 0)
},
search_space_of_5_most_recent_three_succeed = {
&[
Release::new_stable(semver::Version::new(1, 58, 0)),
Release::new_stable(semver::Version::new(1, 57, 0)),
Release::new_stable(semver::Version::new(1, 56, 0)),
Release::new_stable(semver::Version::new(1, 55, 0)),
Release::new_stable(semver::Version::new(1, 54, 0)),
], &[
semver::Version::new(1, 58, 0),
semver::Version::new(1, 57, 0),
semver::Version::new(1, 56, 0),
],
Version::new(1, 56, 0)
},
search_space_of_5_most_recent_two_succeed = {
&[
Release::new_stable(semver::Version::new(1, 58, 0)),
Release::new_stable(semver::Version::new(1, 57, 0)),
Release::new_stable(semver::Version::new(1, 56, 0)),
Release::new_stable(semver::Version::new(1, 55, 0)),
Release::new_stable(semver::Version::new(1, 54, 0)),
], &[
semver::Version::new(1, 58, 0),
semver::Version::new(1, 57, 0),
],
Version::new(1, 57, 0)
},
search_space_of_5_most_recent_one_succeeds = {
&[
Release::new_stable(semver::Version::new(1, 58, 0)),
Release::new_stable(semver::Version::new(1, 57, 0)),
Release::new_stable(semver::Version::new(1, 56, 0)),
Release::new_stable(semver::Version::new(1, 55, 0)),
Release::new_stable(semver::Version::new(1, 54, 0)),
], &[
semver::Version::new(1, 58, 0),
],
Version::new(1, 58, 0)
},
)]
fn find_toolchain_with_bisect(
search_space: &[Release],
accept: &[semver::Version],
expected_msrv: semver::Version,
) {
let bisect = Bisect::new(FakeRunner::from_iter(accept));

let result = bisect
.find_toolchain(search_space, &fake_config(), &NoOutput {})
.unwrap();

assert_eq!(result.to_version(), expected_msrv);
}
}
Loading

0 comments on commit 8bb2860

Please sign in to comment.