Skip to content

Commit 4e09634

Browse files
committed
Auto merge of #5921 - Eh2406:proptest, r=alexcrichton
use proptest to fuzz the resolver This has been a long time goal. This uses proptest to generate random registry indexes and throws them at the resolver. It would be simple to generate a registry by, 1. make a list of name and version number each picked at random 2. for each pick a list of dependencies by making a list of name and version requirements at random. Unfortunately, it would be extremely unlikely to generate any interesting cases, as the chance that the random name you depend on was also generated as the name of a crate is vanishingly small. So this implementation works very hard to ensure that it only generates valid dependency requirements. This is still a WIP as it has many problems: - [x] The current strategy is very convoluted. It is hard to see that it is correct, and harder to see how it can be expanded. Thanks to @Centril for working with me on IRC to get this far. Do you have advice for improving it? - [X] It is slow as molasses when run without release. I looked with a profilere and we seem to spend 2/3 of the time in `to_url`. Maybe we can special case `example.com` for test, like we do for `crates.io` or something? Edit: Done. `lazy_static` did its magic. - [x] `proptest` does not yet work with `minimal-versions`, a taste of my own medicine. - [x] I have not verified that, if I remove the fixes for other test that this regenerates them. The current strategy does not: - [x] generate interesting version numbers, it just dose 1.0.0, 2.0.0 ... - [x] guarantee that the version requirements are possible to meet by the crate named. - [ ] generate features. - [ ] generate dev-dependencies. - [x] build deep dependency trees, it seems to prefer to generate crates with 0 or 1 dependents so that on average the tree is 1 or 2 layers deep. And last but not least, there are no interesting properties being tested. Like: - [ ] If resolution was successful, then all the transitive requirements are met. - [x] If resolution was successful, then unpublishing a version of a crate that was not selected should not change that. - [x] If resolution was unsuccessful, then it should stay unsuccessful even if any version of a crate is unpublished. - [ ] @maurer suggested testing for consistency. Same registry, same cargo version, same lockfile, every time. - [ ] @maurer suggested a pareto optimality property (if all else stays the same, but new package versions are released, we don't get a new lockfile where every version is <= the old one, and at least one is < the old one)
2 parents 2e74d3f + a4da525 commit 4e09634

File tree

4 files changed

+358
-31
lines changed

4 files changed

+358
-31
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ features = [
9494

9595
[dev-dependencies]
9696
bufstream = "0.1"
97+
proptest = "0.8.7"
9798

9899
[[bin]]
99100
name = "cargo"

src/cargo/core/resolver/mod.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ fn activate_deps_loop(
200200
}
201201
}
202202

203-
let mut ticks = 0;
203+
let mut ticks = 0u16;
204204
let start = Instant::now();
205205
let time_to_print = Duration::from_millis(500);
206206
let mut printed = false;
@@ -240,6 +240,18 @@ fn activate_deps_loop(
240240
config.shell().status("Resolving", "dependency graph...")?;
241241
}
242242
}
243+
// The largest test in our sweet takes less then 5000 ticks
244+
// with all the algorithm improvements.
245+
// If any of them are removed then it takes more than I am willing to measure.
246+
// So lets fail the test fast if we have ben running for two long.
247+
debug_assert!(ticks < 50_000);
248+
// The largest test in our sweet takes less then 30 sec
249+
// with all the improvements to how fast a tick can go.
250+
// If any of them are removed then it takes more than I am willing to measure.
251+
// So lets fail the test fast if we have ben running for two long.
252+
if cfg!(debug_assertions) && (ticks % 1000 == 0) {
253+
assert!(start.elapsed() - deps_time < Duration::from_secs(90));
254+
}
243255

244256
let just_here_for_the_error_messages = deps_frame.just_for_error_messages;
245257

tests/testsuite/main.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@ extern crate flate2;
99
extern crate git2;
1010
extern crate glob;
1111
extern crate hex;
12+
#[macro_use]
13+
extern crate lazy_static;
1214
extern crate libc;
1315
#[macro_use]
16+
extern crate proptest;
17+
#[macro_use]
1418
extern crate serde_derive;
1519
#[macro_use]
1620
extern crate serde_json;

0 commit comments

Comments
 (0)