Open tmandry opened 2 years ago
Implementation notes: Mocking can be implemented with traits (hopefully trait objects to avoid having so many generics). But for any "reading" from the environment you must specify some mock data that can be used in tests. For example, when reading from a file you must provide mock file contents that are used in tests.
Tip: Virtualizing the filesystem itself is not actually necessary. If it's easier, for example, we could run in a sandbox build directory set up for that test. For each external command we'd specify the expected output files with mock outputs and actually create them on the filesystem, then allow directly manipulating them (move/copy/read/etc.) within bootstrap
in the test sandbox. I could see this plugging in nicely to the existing traits we have.
We already try to test some of this via --dry-run
which intends to run really quickly (it actually runs on every invocation before starting the real build, and we verify that the Steps executed are the same between both IIRC).
I'm not sure how much extra is needed beyond that -- certainly it supports configuration. I think in order to test things like passing specific flags, we'd want to be dumping/preserving more state than we do today, but that doesn't seem particularly hard (just needs some plumbing to keep vectors of commands around or something).
I'm not sure how much extra is needed beyond that -- certainly it supports configuration. I think in order to test things like passing specific flags, we'd want to be dumping/preserving more state than we do today, but that doesn't seem particularly hard (just needs some plumbing to keep vectors of commands around or something).
I don't think it's that simple - if nothing else, output
doesn't support dry_run
today, so anything using output
is special-casing dry_run
and we can't see any command it would normally try to run. and in general I think there are lots of blocks that are wholly skipped when dry_run is enabled because it was simpler.
; rg 'if .*dry_run\(' src/bootstrap | wc -l
68
🙃
@oli-obk asked me recently "why is this hard?" and I want to record those answers somewhere. A non-exhaustive things I'd like to test:
src
and out
: https://github.com/rust-lang/rust/issues/109120
out
src
is read-only?"origin
origin
src/tools/x
wrapperCan we test the NixOS support? Right now we rely on people fixing it themselves after the fact.
Also same for multiarch linux distros like Debian and Ubuntu
oh yeah I'd love to test "do external tools using rustc_private reliably find the sysroot without hacks"; and all of these things but with download-rustc
enabled.
There are lots of config knobs in bootstrap, and it is hard to understand how they interact. Consider two recent examples off the top of my head:
is_rust_llvm
llvm_from_ci
We should really catch these issues in tests, not review, and avoid relying too much on specific reviewers who know parts of the code.
Since bootstrap does I/O and interacts with external tooling, it is inherently difficult to test. The strategy I know involves mocking out the build environment (enough to make tests run in <~1s). From there you can record what the implementation does and take two approaches for the test:
-D FOO
was passed to LLVM cmake" or "foo/bar/baz was moved to foo/bar/quux".--bless
. This helps guard against unexpected behavior changes.I think both are helpful. In fact, combining the two is exactly what we do in ui tests.
cc @jyn514 @Mark-Simulacrum