Skip to content

Commit 9c49536

Browse files
committed
refactor approach to start / end bounds validations, deduplicate source
1 parent 39f2eb6 commit 9c49536

File tree

1 file changed

+114
-75
lines changed

1 file changed

+114
-75
lines changed

src/main.rs

Lines changed: 114 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,52 @@ fn test_nightly_finder_iterator() {
748748
assert_eq!(start_date - chrono::Duration::days(78), iter.next().unwrap());
749749
}
750750

751+
fn install_and_test(
752+
t: &Toolchain,
753+
cfg: &Config,
754+
client: &Client,
755+
dl_spec: &DownloadParams) -> Result<Satisfies, InstallError>
756+
{
757+
match t.install(&client, &dl_spec) {
758+
Ok(()) => {
759+
eprintln!("testing...");
760+
let outcome = t.test(&cfg);
761+
// we want to fail, so a successful build doesn't satisfy us
762+
let r = match outcome {
763+
TestOutcome::Baseline => Satisfies::No,
764+
TestOutcome::Regressed => Satisfies::Yes,
765+
};
766+
eprintln!("RESULT: {}, ===> {}", t, r);
767+
if !cfg.args.preserve {
768+
let _ = t.remove(&dl_spec);
769+
}
770+
eprintln!();
771+
Ok(r)
772+
}
773+
Err(error) => {
774+
if !cfg.args.preserve {
775+
let _ = t.remove(&dl_spec);
776+
}
777+
Err(error)
778+
}
779+
}
780+
}
781+
782+
fn bisect_to_regression(
783+
toolchains: &Vec<Toolchain>,
784+
cfg: &Config,
785+
client: &Client,
786+
dl_spec: &DownloadParams) -> Result<usize, InstallError>
787+
{
788+
let found = least_satisfying(&toolchains, |t| {
789+
match install_and_test(&t, &cfg, &client, &dl_spec) {
790+
Ok(r) => r,
791+
Err(_) => Satisfies::Unknown,
792+
}
793+
});
794+
Ok(found)
795+
}
796+
751797
// nightlies branch of bisect execution
752798
fn bisect_nightlies(cfg: &Config, client: &Client) -> Result<BisectionResult, Error> {
753799
if cfg.args.alt {
@@ -781,6 +827,12 @@ fn bisect_nightlies(cfg: &Config, client: &Client) -> Result<BisectionResult, Er
781827

782828
let mut nightly_iter = NightlyFinderIter::new(nightly_date);
783829

830+
// this loop tests nightly toolchains to:
831+
// (1) validate that start date does not have regression (if start date defined on CL)
832+
// (2) identify a nightly date range for the bisection routine
833+
//
834+
// The tests here must be constrained to dates after 2015-10-20 (`end_at` date)
835+
// because -std packages were not available prior
784836
while nightly_date > end_at {
785837
let mut t = Toolchain {
786838
spec: ToolchainSpec::Nightly { date: nightly_date },
@@ -792,51 +844,61 @@ fn bisect_nightlies(cfg: &Config, client: &Client) -> Result<BisectionResult, Er
792844
if t.is_current_nightly() {
793845
eprintln!("checking {} from the currently installed default nightly \
794846
toolchain as the last failure", t);
795-
} else {
796-
eprintln!("checking {}", t);
797847
}
798-
match t.install(client, &dl_spec) {
799-
Ok(()) => {
800-
eprintln!("verifying the start of the range does not reproduce the regression");
801-
let outcome = t.test(&cfg);
802-
803-
if !cfg.args.preserve {
804-
let _ = t.remove(&dl_spec);
805-
}
806848

807-
if let TestOutcome::Baseline = outcome {
808-
eprintln!("confirmed {} does not reproduce the regression", t);
849+
match install_and_test(&t, &cfg, &client, &dl_spec) {
850+
Ok(r) => {
851+
// If Satisfies::No, then the regression was not identified in this nightly.
852+
// Break out of the loop and use this as the start date for the
853+
// bisection range
854+
if let Satisfies::No = r {
809855
first_success = Some(nightly_date);
810856
break;
811857
} else if has_start {
812-
bail!("the start of the range to test must not reproduce the regression");
858+
// If this date was explicitly defined on CL & has regression,
859+
// then this is an error in the test definition. The user must
860+
// re-define the start date and try again
861+
bail!("the start of the range ({}) must not reproduce the regression", t);
813862
} else {
814863
last_failure = nightly_date;
815864
}
816865

817866
nightly_date = nightly_iter.next().unwrap();
818-
}
867+
},
819868
Err(InstallError::NotFound { .. }) => {
820-
// go back just one day, presumably missing nightly
869+
// go back just one day, presumably missing a nightly
821870
nightly_date = nightly_date - chrono::Duration::days(1);
822-
if !cfg.args.preserve {
823-
let _ = t.remove(&dl_spec);
824-
}
871+
eprintln!("*** unable to install {}. roll back one day and try again...", t);
825872
if has_start {
826873
bail!("could not find {}", t);
827874
}
828-
}
829-
Err(e) => {
830-
if !cfg.args.preserve {
831-
let _ = t.remove(&dl_spec);
832-
}
833-
return Err(e.into());
834-
}
875+
},
876+
Err(error) => return Err(error.into()),
835877
}
836878
}
837879

838880
let first_success = first_success.ok_or(format_err!("could not find a nightly that built"))?;
839881

882+
// confirm that the end of the date range has the regression
883+
let mut t_end = Toolchain {
884+
spec: ToolchainSpec::Nightly { date: last_failure },
885+
host: cfg.args.host.clone(),
886+
std_targets: vec![cfg.args.host.clone(), cfg.target.clone()],
887+
};
888+
t_end.std_targets.sort();
889+
t_end.std_targets.dedup();
890+
891+
match install_and_test(&t_end, &cfg, &client, &dl_spec) {
892+
Ok(r) => {
893+
// If Satisfies::No, then the regression was not identified in this nightly.
894+
// this is an error, abort with error message
895+
if r == Satisfies::No {
896+
bail!("the end of the range ({}) does not reproduce the regression", t_end);
897+
}
898+
},
899+
Err(error) => return Err(error.into()),
900+
}
901+
840902
let toolchains = toolchains_between(
841903
cfg,
842904
ToolchainSpec::Nightly {
@@ -845,32 +907,7 @@ fn bisect_nightlies(cfg: &Config, client: &Client) -> Result<BisectionResult, Er
845907
ToolchainSpec::Nightly { date: last_failure },
846908
);
847909

848-
// First success check has been performed above so it is not necessary
849-
// to repeat it within the least_satisfying function in the call here.
850-
// Set `start_check` to false to prevent a repeat check on the same
851-
// nightly in `least_satisfying`
852-
let found = least_satisfying(&toolchains, false, |t| {
853-
match t.install(&client, &dl_spec) {
854-
Ok(()) => {
855-
let outcome = t.test(&cfg);
856-
// we want to fail, so a successful build doesn't satisfy us
857-
let r = match outcome {
858-
TestOutcome::Baseline => Satisfies::No,
859-
TestOutcome::Regressed => Satisfies::Yes,
860-
};
861-
if !cfg.args.preserve {
862-
let _ = t.remove(&dl_spec);
863-
}
864-
eprintln!("tested {}, got {}", t, r);
865-
r
866-
}
867-
Err(err) => {
868-
let _ = t.remove(&dl_spec);
869-
eprintln!("failed to install {}: {:?}", t, err);
870-
Satisfies::Unknown
871-
}
872-
}
873-
});
910+
let found = bisect_to_regression(&toolchains, &cfg, client, &dl_spec)?;
874911

875912
Ok(BisectionResult {
876913
dl_spec,
@@ -993,31 +1030,33 @@ fn bisect_ci_in_commits(
9931030
})
9941031
.collect::<Vec<_>>();
9951032

996-
eprintln!("testing commits");
997-
let found = least_satisfying(&toolchains, true,|t| {
998-
eprintln!("installing {}", t);
999-
match t.install(&client, &dl_spec) {
1000-
Ok(()) => {
1001-
eprintln!("testing {}", t);
1002-
let outcome = t.test(&cfg);
1003-
// we want to fail, so a successful build doesn't satisfy us
1004-
let r = match outcome {
1005-
TestOutcome::Regressed => Satisfies::Yes,
1006-
TestOutcome::Baseline => Satisfies::No,
1007-
};
1008-
eprintln!("tested {}, got {}", t, r);
1009-
if !cfg.args.preserve {
1010-
let _ = t.remove(&dl_spec);
1033+
if !toolchains.is_empty() {
1034+
// validate commit at start of range
1035+
match install_and_test(&toolchains[0], &cfg, &client, &dl_spec) {
1036+
Ok(r) => {
1037+
// If Satisfies::Yes, then the commit at the beginning of the range
1038+
// has the regression, this is an error
1039+
if r == Satisfies::Yes {
1040+
bail!("the commit at the start of the range ({}) includes the regression", &toolchains[0]);
10111041
}
1012-
r
1013-
}
1014-
Err(err) => {
1015-
let _ = t.remove(&dl_spec);
1016-
eprintln!("failed to install {}: {:?}", t, err);
1017-
Satisfies::Unknown
1018-
}
1042+
},
1043+
Err(error) => return Err(error.into()),
10191044
}
1020-
});
1045+
1046+
// validate commit at end of range
1047+
match install_and_test(&toolchains[toolchains.len()-1], &cfg, &client, &dl_spec) {
1048+
Ok(r) => {
1049+
// If Satisfies::No, then the regression was not identified at the end of the
1050+
// commit range, this is an error
1051+
if r == Satisfies::No {
1052+
bail!("the commit at the end of the range ({}) does not reproduce the regression", &toolchains[toolchains.len()-1]);
1053+
}
1054+
},
1055+
Err(error) => return Err(error.into()),
1056+
}
1057+
}
1058+
1059+
let found = bisect_to_regression(&toolchains, &cfg, client, &dl_spec)?;
10211060

10221061
Ok(BisectionResult {
10231062
searched: toolchains,
@@ -1038,7 +1077,7 @@ fn main() {
10381077
match err.downcast::<ExitError>() {
10391078
Ok(ExitError(code)) => process::exit(code),
10401079
Err(err) => {
1041-
eprintln!("{}", err);
1080+
eprintln!("ERROR: {}", err);
10421081
process::exit(1);
10431082
}
10441083
}

0 commit comments

Comments
 (0)