]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/builder/tests.rs
Rollup merge of #106323 - starkat99:stabilize-f16c_target_feature, r=petrochenkov
[rust.git] / src / bootstrap / builder / tests.rs
1 use super::*;
2 use crate::config::{Config, DryRun, TargetSelection};
3 use std::thread;
4
5 fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config {
6     configure_with_args(&[cmd.to_owned()], host, target)
7 }
8
9 fn configure_with_args(cmd: &[String], host: &[&str], target: &[&str]) -> Config {
10     let mut config = Config::parse(cmd);
11     // don't save toolstates
12     config.save_toolstates = None;
13     config.dry_run = DryRun::SelfCheck;
14
15     // Ignore most submodules, since we don't need them for a dry run.
16     // But make sure to check out the `doc` and `rust-analyzer` submodules, since some steps need them
17     // just to know which commands to run.
18     let submodule_build = Build::new(Config {
19         // don't include LLVM, so CI doesn't require ninja/cmake to be installed
20         rust_codegen_backends: vec![],
21         ..Config::parse(&["check".to_owned()])
22     });
23     submodule_build.update_submodule(Path::new("src/doc/book"));
24     submodule_build.update_submodule(Path::new("src/tools/rust-analyzer"));
25     config.submodules = Some(false);
26
27     config.ninja_in_file = false;
28     // try to avoid spurious failures in dist where we create/delete each others file
29     // HACK: rather than pull in `tempdir`, use the one that cargo has conveniently created for us
30     let dir = Path::new(env!("OUT_DIR"))
31         .join("tmp-rustbuild-tests")
32         .join(&thread::current().name().unwrap_or("unknown").replace(":", "-"));
33     t!(fs::create_dir_all(&dir));
34     config.out = dir;
35     config.build = TargetSelection::from_user("A");
36     config.hosts = host.iter().map(|s| TargetSelection::from_user(s)).collect();
37     config.targets = target.iter().map(|s| TargetSelection::from_user(s)).collect();
38     config
39 }
40
41 fn first<A, B>(v: Vec<(A, B)>) -> Vec<A> {
42     v.into_iter().map(|(a, _)| a).collect::<Vec<_>>()
43 }
44
45 fn run_build(paths: &[PathBuf], config: Config) -> Cache {
46     let kind = config.cmd.kind();
47     let build = Build::new(config);
48     let builder = Builder::new(&build);
49     builder.run_step_descriptions(&Builder::get_step_descriptions(kind), paths);
50     builder.cache
51 }
52
53 fn check_cli<const N: usize>(paths: [&str; N]) {
54     run_build(
55         &paths.map(PathBuf::from),
56         configure_with_args(&paths.map(String::from), &["A"], &["A"]),
57     );
58 }
59
60 macro_rules! std {
61     ($host:ident => $target:ident, stage = $stage:literal) => {
62         compile::Std::new(
63             Compiler { host: TargetSelection::from_user(stringify!($host)), stage: $stage },
64             TargetSelection::from_user(stringify!($target)),
65         )
66     };
67 }
68
69 macro_rules! rustc {
70     ($host:ident => $target:ident, stage = $stage:literal) => {
71         compile::Rustc::new(
72             Compiler { host: TargetSelection::from_user(stringify!($host)), stage: $stage },
73             TargetSelection::from_user(stringify!($target)),
74         )
75     };
76 }
77
78 #[test]
79 fn test_valid() {
80     // make sure multi suite paths are accepted
81     check_cli(["test", "tests/ui/attr-start.rs", "tests/ui/attr-shebang.rs"]);
82 }
83
84 #[test]
85 #[should_panic]
86 fn test_invalid() {
87     // make sure that invalid paths are caught, even when combined with valid paths
88     check_cli(["test", "library/std", "x"]);
89 }
90
91 #[test]
92 fn test_intersection() {
93     let set = PathSet::Set(
94         ["library/core", "library/alloc", "library/std"].into_iter().map(TaskPath::parse).collect(),
95     );
96     let mut command_paths =
97         vec![Path::new("library/core"), Path::new("library/alloc"), Path::new("library/stdarch")];
98     let subset = set.intersection_removing_matches(&mut command_paths, None);
99     assert_eq!(
100         subset,
101         PathSet::Set(["library/core", "library/alloc"].into_iter().map(TaskPath::parse).collect())
102     );
103     assert_eq!(command_paths, vec![Path::new("library/stdarch")]);
104 }
105
106 #[test]
107 fn test_exclude() {
108     let mut config = configure("test", &["A"], &["A"]);
109     config.exclude = vec![TaskPath::parse("src/tools/tidy")];
110     let cache = run_build(&[], config);
111
112     // Ensure we have really excluded tidy
113     assert!(!cache.contains::<test::Tidy>());
114
115     // Ensure other tests are not affected.
116     assert!(cache.contains::<test::RustdocUi>());
117 }
118
119 #[test]
120 fn test_exclude_kind() {
121     let path = PathBuf::from("src/tools/cargotest");
122     let exclude = TaskPath::parse("test::src/tools/cargotest");
123     assert_eq!(exclude, TaskPath { kind: Some(Kind::Test), path: path.clone() });
124
125     let mut config = configure("test", &["A"], &["A"]);
126     // Ensure our test is valid, and `test::Cargotest` would be run without the exclude.
127     assert!(run_build(&[path.clone()], config.clone()).contains::<test::Cargotest>());
128     // Ensure tests for cargotest are skipped.
129     config.exclude = vec![exclude.clone()];
130     assert!(!run_build(&[path.clone()], config).contains::<test::Cargotest>());
131
132     // Ensure builds for cargotest are not skipped.
133     let mut config = configure("build", &["A"], &["A"]);
134     config.exclude = vec![exclude];
135     assert!(run_build(&[path], config).contains::<tool::CargoTest>());
136 }
137
138 /// Ensure that if someone passes both a single crate and `library`, all library crates get built.
139 #[test]
140 fn alias_and_path_for_library() {
141     let mut cache =
142         run_build(&["library".into(), "core".into()], configure("build", &["A"], &["A"]));
143     assert_eq!(
144         first(cache.all::<compile::Std>()),
145         &[std!(A => A, stage = 0), std!(A => A, stage = 1)]
146     );
147 }
148
149 mod defaults {
150     use super::{configure, first, run_build};
151     use crate::builder::*;
152     use crate::Config;
153     use pretty_assertions::assert_eq;
154
155     #[test]
156     fn build_default() {
157         let mut cache = run_build(&[], configure("build", &["A"], &["A"]));
158
159         let a = TargetSelection::from_user("A");
160         assert_eq!(
161             first(cache.all::<compile::Std>()),
162             &[std!(A => A, stage = 0), std!(A => A, stage = 1),]
163         );
164         assert!(!cache.all::<compile::Assemble>().is_empty());
165         // Make sure rustdoc is only built once.
166         assert_eq!(
167             first(cache.all::<tool::Rustdoc>()),
168             // Recall that rustdoc stages are off-by-one
169             // - this is the compiler it's _linked_ to, not built with.
170             &[tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } }],
171         );
172         assert_eq!(first(cache.all::<compile::Rustc>()), &[rustc!(A => A, stage = 0)],);
173     }
174
175     #[test]
176     fn build_stage_0() {
177         let config = Config { stage: 0, ..configure("build", &["A"], &["A"]) };
178         let mut cache = run_build(&[], config);
179
180         let a = TargetSelection::from_user("A");
181         assert_eq!(first(cache.all::<compile::Std>()), &[std!(A => A, stage = 0)]);
182         assert!(!cache.all::<compile::Assemble>().is_empty());
183         assert_eq!(
184             first(cache.all::<tool::Rustdoc>()),
185             // This is the beta rustdoc.
186             // Add an assert here to make sure this is the only rustdoc built.
187             &[tool::Rustdoc { compiler: Compiler { host: a, stage: 0 } }],
188         );
189         assert!(cache.all::<compile::Rustc>().is_empty());
190     }
191
192     #[test]
193     fn build_cross_compile() {
194         let config = Config { stage: 1, ..configure("build", &["A", "B"], &["A", "B"]) };
195         let mut cache = run_build(&[], config);
196
197         let a = TargetSelection::from_user("A");
198         let b = TargetSelection::from_user("B");
199
200         // Ideally, this build wouldn't actually have `target: a`
201         // rustdoc/rustcc/std here (the user only requested a host=B build, so
202         // there's not really a need for us to build for target A in this case
203         // (since we're producing stage 1 libraries/binaries).  But currently
204         // rustbuild is just a bit buggy here; this should be fixed though.
205         assert_eq!(
206             first(cache.all::<compile::Std>()),
207             &[
208                 std!(A => A, stage = 0),
209                 std!(A => A, stage = 1),
210                 std!(A => B, stage = 0),
211                 std!(A => B, stage = 1),
212             ]
213         );
214         assert_eq!(
215             first(cache.all::<compile::Assemble>()),
216             &[
217                 compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
218                 compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
219                 compile::Assemble { target_compiler: Compiler { host: b, stage: 1 } },
220             ]
221         );
222         assert_eq!(
223             first(cache.all::<tool::Rustdoc>()),
224             &[
225                 tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } },
226                 tool::Rustdoc { compiler: Compiler { host: b, stage: 1 } },
227             ],
228         );
229         assert_eq!(
230             first(cache.all::<compile::Rustc>()),
231             &[rustc!(A => A, stage = 0), rustc!(A => B, stage = 0),]
232         );
233     }
234
235     #[test]
236     fn doc_default() {
237         let mut config = configure("doc", &["A"], &["A"]);
238         config.compiler_docs = true;
239         config.cmd = Subcommand::Doc { paths: Vec::new(), open: false, json: false };
240         let mut cache = run_build(&[], config);
241         let a = TargetSelection::from_user("A");
242
243         // error_index_generator uses stage 0 to share rustdoc artifacts with the
244         // rustdoc tool.
245         assert_eq!(first(cache.all::<doc::ErrorIndex>()), &[doc::ErrorIndex { target: a },]);
246         assert_eq!(
247             first(cache.all::<tool::ErrorIndex>()),
248             &[tool::ErrorIndex { compiler: Compiler { host: a, stage: 0 } }]
249         );
250         // docs should be built with the beta compiler, not with the stage0 artifacts.
251         // recall that rustdoc is off-by-one: `stage` is the compiler rustdoc is _linked_ to,
252         // not the one it was built by.
253         assert_eq!(
254             first(cache.all::<tool::Rustdoc>()),
255             &[tool::Rustdoc { compiler: Compiler { host: a, stage: 0 } },]
256         );
257     }
258 }
259
260 mod dist {
261     use super::{first, run_build, Config};
262     use crate::builder::*;
263     use pretty_assertions::assert_eq;
264
265     fn configure(host: &[&str], target: &[&str]) -> Config {
266         Config { stage: 2, ..super::configure("dist", host, target) }
267     }
268
269     #[test]
270     fn dist_baseline() {
271         let mut cache = run_build(&[], configure(&["A"], &["A"]));
272
273         let a = TargetSelection::from_user("A");
274
275         assert_eq!(first(cache.all::<dist::Docs>()), &[dist::Docs { host: a },]);
276         assert_eq!(first(cache.all::<dist::Mingw>()), &[dist::Mingw { host: a },]);
277         assert_eq!(
278             first(cache.all::<dist::Rustc>()),
279             &[dist::Rustc { compiler: Compiler { host: a, stage: 2 } },]
280         );
281         assert_eq!(
282             first(cache.all::<dist::Std>()),
283             &[dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },]
284         );
285         assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
286         // Make sure rustdoc is only built once.
287         assert_eq!(
288             first(cache.all::<tool::Rustdoc>()),
289             &[tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },]
290         );
291     }
292
293     #[test]
294     fn dist_with_targets() {
295         let mut cache = run_build(&[], configure(&["A"], &["A", "B"]));
296
297         let a = TargetSelection::from_user("A");
298         let b = TargetSelection::from_user("B");
299
300         assert_eq!(
301             first(cache.all::<dist::Docs>()),
302             &[dist::Docs { host: a }, dist::Docs { host: b },]
303         );
304         assert_eq!(
305             first(cache.all::<dist::Mingw>()),
306             &[dist::Mingw { host: a }, dist::Mingw { host: b },]
307         );
308         assert_eq!(
309             first(cache.all::<dist::Rustc>()),
310             &[dist::Rustc { compiler: Compiler { host: a, stage: 2 } },]
311         );
312         assert_eq!(
313             first(cache.all::<dist::Std>()),
314             &[
315                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
316                 dist::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
317             ]
318         );
319         assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
320     }
321
322     #[test]
323     fn dist_with_hosts() {
324         let mut cache = run_build(&[], configure(&["A", "B"], &["A", "B"]));
325
326         let a = TargetSelection::from_user("A");
327         let b = TargetSelection::from_user("B");
328
329         assert_eq!(
330             first(cache.all::<dist::Docs>()),
331             &[dist::Docs { host: a }, dist::Docs { host: b },]
332         );
333         assert_eq!(
334             first(cache.all::<dist::Mingw>()),
335             &[dist::Mingw { host: a }, dist::Mingw { host: b },]
336         );
337         assert_eq!(
338             first(cache.all::<dist::Rustc>()),
339             &[
340                 dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
341                 dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
342             ]
343         );
344         assert_eq!(
345             first(cache.all::<dist::Std>()),
346             &[
347                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
348                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
349             ]
350         );
351         assert_eq!(
352             first(cache.all::<compile::Std>()),
353             &[
354                 std!(A => A, stage = 0),
355                 std!(A => A, stage = 1),
356                 std!(A => A, stage = 2),
357                 std!(A => B, stage = 1),
358                 std!(A => B, stage = 2),
359             ],
360         );
361         assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
362     }
363
364     #[test]
365     fn dist_only_cross_host() {
366         let b = TargetSelection::from_user("B");
367         let mut config = configure(&["A", "B"], &["A", "B"]);
368         config.docs = false;
369         config.extended = true;
370         config.hosts = vec![b];
371         let mut cache = run_build(&[], config);
372
373         assert_eq!(
374             first(cache.all::<dist::Rustc>()),
375             &[dist::Rustc { compiler: Compiler { host: b, stage: 2 } },]
376         );
377         assert_eq!(
378             first(cache.all::<compile::Rustc>()),
379             &[rustc!(A => A, stage = 0), rustc!(A => B, stage = 1),]
380         );
381     }
382
383     #[test]
384     fn dist_with_targets_and_hosts() {
385         let mut cache = run_build(&[], configure(&["A", "B"], &["A", "B", "C"]));
386
387         let a = TargetSelection::from_user("A");
388         let b = TargetSelection::from_user("B");
389         let c = TargetSelection::from_user("C");
390
391         assert_eq!(
392             first(cache.all::<dist::Docs>()),
393             &[dist::Docs { host: a }, dist::Docs { host: b }, dist::Docs { host: c },]
394         );
395         assert_eq!(
396             first(cache.all::<dist::Mingw>()),
397             &[dist::Mingw { host: a }, dist::Mingw { host: b }, dist::Mingw { host: c },]
398         );
399         assert_eq!(
400             first(cache.all::<dist::Rustc>()),
401             &[
402                 dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
403                 dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
404             ]
405         );
406         assert_eq!(
407             first(cache.all::<dist::Std>()),
408             &[
409                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
410                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
411                 dist::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
412             ]
413         );
414         assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
415     }
416
417     #[test]
418     fn dist_with_empty_host() {
419         let config = configure(&[], &["C"]);
420         let mut cache = run_build(&[], config);
421
422         let a = TargetSelection::from_user("A");
423         let c = TargetSelection::from_user("C");
424
425         assert_eq!(first(cache.all::<dist::Docs>()), &[dist::Docs { host: c },]);
426         assert_eq!(first(cache.all::<dist::Mingw>()), &[dist::Mingw { host: c },]);
427         assert_eq!(
428             first(cache.all::<dist::Std>()),
429             &[dist::Std { compiler: Compiler { host: a, stage: 2 }, target: c },]
430         );
431     }
432
433     #[test]
434     fn dist_with_same_targets_and_hosts() {
435         let mut cache = run_build(&[], configure(&["A", "B"], &["A", "B"]));
436
437         let a = TargetSelection::from_user("A");
438         let b = TargetSelection::from_user("B");
439
440         assert_eq!(
441             first(cache.all::<dist::Docs>()),
442             &[dist::Docs { host: a }, dist::Docs { host: b },]
443         );
444         assert_eq!(
445             first(cache.all::<dist::Mingw>()),
446             &[dist::Mingw { host: a }, dist::Mingw { host: b },]
447         );
448         assert_eq!(
449             first(cache.all::<dist::Rustc>()),
450             &[
451                 dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
452                 dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
453             ]
454         );
455         assert_eq!(
456             first(cache.all::<dist::Std>()),
457             &[
458                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
459                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
460             ]
461         );
462         assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
463         assert_eq!(
464             first(cache.all::<compile::Std>()),
465             &[
466                 std!(A => A, stage = 0),
467                 std!(A => A, stage = 1),
468                 std!(A => A, stage = 2),
469                 std!(A => B, stage = 1),
470                 std!(A => B, stage = 2),
471             ]
472         );
473         assert_eq!(
474             first(cache.all::<compile::Assemble>()),
475             &[
476                 compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
477                 compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
478                 compile::Assemble { target_compiler: Compiler { host: a, stage: 2 } },
479                 compile::Assemble { target_compiler: Compiler { host: b, stage: 2 } },
480             ]
481         );
482     }
483
484     #[test]
485     fn build_all() {
486         let build = Build::new(configure(&["A", "B"], &["A", "B", "C"]));
487         let mut builder = Builder::new(&build);
488         builder.run_step_descriptions(
489             &Builder::get_step_descriptions(Kind::Build),
490             &["compiler/rustc".into(), "library".into()],
491         );
492
493         assert_eq!(
494             first(builder.cache.all::<compile::Std>()),
495             &[
496                 std!(A => A, stage = 0),
497                 std!(A => A, stage = 1),
498                 std!(A => A, stage = 2),
499                 std!(A => B, stage = 1),
500                 std!(A => B, stage = 2),
501                 std!(A => C, stage = 2),
502             ]
503         );
504         assert_eq!(builder.cache.all::<compile::Assemble>().len(), 5);
505         assert_eq!(
506             first(builder.cache.all::<compile::Rustc>()),
507             &[
508                 rustc!(A => A, stage = 0),
509                 rustc!(A => A, stage = 1),
510                 rustc!(A => A, stage = 2),
511                 rustc!(A => B, stage = 1),
512                 rustc!(A => B, stage = 2),
513             ]
514         );
515     }
516
517     #[test]
518     fn build_with_empty_host() {
519         let config = configure(&[], &["C"]);
520         let build = Build::new(config);
521         let mut builder = Builder::new(&build);
522         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
523
524         let a = TargetSelection::from_user("A");
525
526         assert_eq!(
527             first(builder.cache.all::<compile::Std>()),
528             &[std!(A => A, stage = 0), std!(A => A, stage = 1), std!(A => C, stage = 2),]
529         );
530         assert_eq!(
531             first(builder.cache.all::<compile::Assemble>()),
532             &[
533                 compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
534                 compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
535                 compile::Assemble { target_compiler: Compiler { host: a, stage: 2 } },
536             ]
537         );
538         assert_eq!(
539             first(builder.cache.all::<compile::Rustc>()),
540             &[rustc!(A => A, stage = 0), rustc!(A => A, stage = 1),]
541         );
542     }
543
544     #[test]
545     fn test_with_no_doc_stage0() {
546         let mut config = configure(&["A"], &["A"]);
547         config.stage = 0;
548         config.cmd = Subcommand::Test {
549             paths: vec!["library/std".into()],
550             test_args: vec![],
551             rustc_args: vec![],
552             fail_fast: true,
553             doc_tests: DocTests::No,
554             bless: false,
555             force_rerun: false,
556             compare_mode: None,
557             rustfix_coverage: false,
558             pass: None,
559             run: None,
560         };
561
562         let build = Build::new(config);
563         let mut builder = Builder::new(&build);
564
565         let host = TargetSelection::from_user("A");
566
567         builder.run_step_descriptions(
568             &[StepDescription::from::<test::Crate>(Kind::Test)],
569             &["library/std".into()],
570         );
571
572         // Ensure we don't build any compiler artifacts.
573         assert!(!builder.cache.contains::<compile::Rustc>());
574         assert_eq!(
575             first(builder.cache.all::<test::Crate>()),
576             &[test::Crate {
577                 compiler: Compiler { host, stage: 0 },
578                 target: host,
579                 mode: Mode::Std,
580                 test_kind: test::TestKind::Test,
581                 crates: vec![INTERNER.intern_str("std")],
582             },]
583         );
584     }
585
586     #[test]
587     fn doc_ci() {
588         let mut config = configure(&["A"], &["A"]);
589         config.compiler_docs = true;
590         config.cmd = Subcommand::Doc { paths: Vec::new(), open: false, json: false };
591         let build = Build::new(config);
592         let mut builder = Builder::new(&build);
593         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]);
594         let a = TargetSelection::from_user("A");
595
596         // error_index_generator uses stage 1 to share rustdoc artifacts with the
597         // rustdoc tool.
598         assert_eq!(
599             first(builder.cache.all::<doc::ErrorIndex>()),
600             &[doc::ErrorIndex { target: a },]
601         );
602         assert_eq!(
603             first(builder.cache.all::<tool::ErrorIndex>()),
604             &[tool::ErrorIndex { compiler: Compiler { host: a, stage: 1 } }]
605         );
606         // This is actually stage 1, but Rustdoc::run swaps out the compiler with
607         // stage minus 1 if --stage is not 0. Very confusing!
608         assert_eq!(
609             first(builder.cache.all::<tool::Rustdoc>()),
610             &[tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },]
611         );
612     }
613
614     #[test]
615     fn test_docs() {
616         // Behavior of `x.py test` doing various documentation tests.
617         let mut config = configure(&["A"], &["A"]);
618         config.cmd = Subcommand::Test {
619             paths: vec![],
620             test_args: vec![],
621             rustc_args: vec![],
622             fail_fast: true,
623             doc_tests: DocTests::Yes,
624             bless: false,
625             force_rerun: false,
626             compare_mode: None,
627             rustfix_coverage: false,
628             pass: None,
629             run: None,
630         };
631         // Make sure rustfmt binary not being found isn't an error.
632         config.channel = "beta".to_string();
633         let build = Build::new(config);
634         let mut builder = Builder::new(&build);
635
636         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]);
637         let a = TargetSelection::from_user("A");
638
639         // error_index_generator uses stage 1 to share rustdoc artifacts with the
640         // rustdoc tool.
641         assert_eq!(
642             first(builder.cache.all::<doc::ErrorIndex>()),
643             &[doc::ErrorIndex { target: a },]
644         );
645         assert_eq!(
646             first(builder.cache.all::<tool::ErrorIndex>()),
647             &[tool::ErrorIndex { compiler: Compiler { host: a, stage: 1 } }]
648         );
649         // Unfortunately rustdoc is built twice. Once from stage1 for compiletest
650         // (and other things), and once from stage0 for std crates. Ideally it
651         // would only be built once. If someone wants to fix this, it might be
652         // worth investigating if it would be possible to test std from stage1.
653         // Note that the stages here are +1 than what they actually are because
654         // Rustdoc::run swaps out the compiler with stage minus 1 if --stage is
655         // not 0.
656         //
657         // The stage 0 copy is the one downloaded for bootstrapping. It is
658         // (currently) needed to run "cargo test" on the linkchecker, and
659         // should be relatively "free".
660         assert_eq!(
661             first(builder.cache.all::<tool::Rustdoc>()),
662             &[
663                 tool::Rustdoc { compiler: Compiler { host: a, stage: 0 } },
664                 tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } },
665                 tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },
666             ]
667         );
668     }
669 }