]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/builder/tests.rs
Rollup merge of #97249 - GuillaumeGomez:details-summary-fixes, r=notriddle
[rust.git] / src / bootstrap / builder / tests.rs
1 use super::*;
2 use crate::config::{Config, 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 = true;
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 #[test]
61 fn test_valid() {
62     // make sure multi suite paths are accepted
63     check_cli(["test", "src/test/ui/attr-start.rs", "src/test/ui/attr-shebang.rs"]);
64 }
65
66 #[test]
67 #[should_panic]
68 fn test_invalid() {
69     // make sure that invalid paths are caught, even when combined with valid paths
70     check_cli(["test", "library/std", "x"]);
71 }
72
73 #[test]
74 fn test_intersection() {
75     let set = PathSet::Set(
76         ["library/core", "library/alloc", "library/std"].into_iter().map(TaskPath::parse).collect(),
77     );
78     let mut command_paths =
79         vec![Path::new("library/core"), Path::new("library/alloc"), Path::new("library/stdarch")];
80     let subset = set.intersection_removing_matches(&mut command_paths, None);
81     assert_eq!(
82         subset,
83         PathSet::Set(["library/core", "library/alloc"].into_iter().map(TaskPath::parse).collect())
84     );
85     assert_eq!(command_paths, vec![Path::new("library/stdarch")]);
86 }
87
88 #[test]
89 fn test_exclude() {
90     let mut config = configure("test", &["A"], &["A"]);
91     config.exclude = vec![TaskPath::parse("src/tools/tidy")];
92     let cache = run_build(&[], config);
93
94     // Ensure we have really excluded tidy
95     assert!(!cache.contains::<test::Tidy>());
96
97     // Ensure other tests are not affected.
98     assert!(cache.contains::<test::RustdocUi>());
99 }
100
101 #[test]
102 fn test_exclude_kind() {
103     let path = PathBuf::from("src/tools/cargotest");
104     let exclude = TaskPath::parse("test::src/tools/cargotest");
105     assert_eq!(exclude, TaskPath { kind: Some(Kind::Test), path: path.clone() });
106
107     let mut config = configure("test", &["A"], &["A"]);
108     // Ensure our test is valid, and `test::Cargotest` would be run without the exclude.
109     assert!(run_build(&[path.clone()], config.clone()).contains::<test::Cargotest>());
110     // Ensure tests for cargotest are skipped.
111     config.exclude = vec![exclude.clone()];
112     assert!(!run_build(&[path.clone()], config).contains::<test::Cargotest>());
113
114     // Ensure builds for cargotest are not skipped.
115     let mut config = configure("build", &["A"], &["A"]);
116     config.exclude = vec![exclude];
117     assert!(run_build(&[path], config).contains::<tool::CargoTest>());
118 }
119
120 mod defaults {
121     use super::{configure, first, run_build};
122     use crate::builder::*;
123     use crate::Config;
124     use pretty_assertions::assert_eq;
125
126     #[test]
127     fn build_default() {
128         let mut cache = run_build(&[], configure("build", &["A"], &["A"]));
129
130         let a = TargetSelection::from_user("A");
131         assert_eq!(
132             first(cache.all::<compile::Std>()),
133             &[
134                 compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
135                 compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
136             ]
137         );
138         assert!(!cache.all::<compile::Assemble>().is_empty());
139         // Make sure rustdoc is only built once.
140         assert_eq!(
141             first(cache.all::<tool::Rustdoc>()),
142             // Recall that rustdoc stages are off-by-one
143             // - this is the compiler it's _linked_ to, not built with.
144             &[tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } }],
145         );
146         assert_eq!(
147             first(cache.all::<compile::Rustc>()),
148             &[compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },]
149         );
150     }
151
152     #[test]
153     fn build_stage_0() {
154         let config = Config { stage: 0, ..configure("build", &["A"], &["A"]) };
155         let mut cache = run_build(&[], config);
156
157         let a = TargetSelection::from_user("A");
158         assert_eq!(
159             first(cache.all::<compile::Std>()),
160             &[compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },]
161         );
162         assert!(!cache.all::<compile::Assemble>().is_empty());
163         assert_eq!(
164             first(cache.all::<tool::Rustdoc>()),
165             // This is the beta rustdoc.
166             // Add an assert here to make sure this is the only rustdoc built.
167             &[tool::Rustdoc { compiler: Compiler { host: a, stage: 0 } }],
168         );
169         assert!(cache.all::<compile::Rustc>().is_empty());
170     }
171
172     #[test]
173     fn build_cross_compile() {
174         let config = Config { stage: 1, ..configure("build", &["A", "B"], &["A", "B"]) };
175         let mut cache = run_build(&[], config);
176
177         let a = TargetSelection::from_user("A");
178         let b = TargetSelection::from_user("B");
179
180         // Ideally, this build wouldn't actually have `target: a`
181         // rustdoc/rustcc/std here (the user only requested a host=B build, so
182         // there's not really a need for us to build for target A in this case
183         // (since we're producing stage 1 libraries/binaries).  But currently
184         // rustbuild is just a bit buggy here; this should be fixed though.
185         assert_eq!(
186             first(cache.all::<compile::Std>()),
187             &[
188                 compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
189                 compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
190                 compile::Std { compiler: Compiler { host: a, stage: 0 }, target: b },
191                 compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
192             ]
193         );
194         assert_eq!(
195             first(cache.all::<compile::Assemble>()),
196             &[
197                 compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
198                 compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
199                 compile::Assemble { target_compiler: Compiler { host: b, stage: 1 } },
200             ]
201         );
202         assert_eq!(
203             first(cache.all::<tool::Rustdoc>()),
204             &[
205                 tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } },
206                 tool::Rustdoc { compiler: Compiler { host: b, stage: 1 } },
207             ],
208         );
209         assert_eq!(
210             first(cache.all::<compile::Rustc>()),
211             &[
212                 compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
213                 compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: b },
214             ]
215         );
216     }
217
218     #[test]
219     fn doc_default() {
220         let mut config = configure("doc", &["A"], &["A"]);
221         config.compiler_docs = true;
222         config.cmd = Subcommand::Doc { paths: Vec::new(), open: false };
223         let mut cache = run_build(&[], config);
224         let a = TargetSelection::from_user("A");
225
226         // error_index_generator uses stage 0 to share rustdoc artifacts with the
227         // rustdoc tool.
228         assert_eq!(first(cache.all::<doc::ErrorIndex>()), &[doc::ErrorIndex { target: a },]);
229         assert_eq!(
230             first(cache.all::<tool::ErrorIndex>()),
231             &[tool::ErrorIndex { compiler: Compiler { host: a, stage: 0 } }]
232         );
233         // docs should be built with the beta compiler, not with the stage0 artifacts.
234         // recall that rustdoc is off-by-one: `stage` is the compiler rustdoc is _linked_ to,
235         // not the one it was built by.
236         assert_eq!(
237             first(cache.all::<tool::Rustdoc>()),
238             &[tool::Rustdoc { compiler: Compiler { host: a, stage: 0 } },]
239         );
240     }
241 }
242
243 mod dist {
244     use super::{first, run_build, Config};
245     use crate::builder::*;
246     use pretty_assertions::assert_eq;
247
248     fn configure(host: &[&str], target: &[&str]) -> Config {
249         Config { stage: 2, ..super::configure("dist", host, target) }
250     }
251
252     #[test]
253     fn dist_baseline() {
254         let mut cache = run_build(&[], configure(&["A"], &["A"]));
255
256         let a = TargetSelection::from_user("A");
257
258         assert_eq!(first(cache.all::<dist::Docs>()), &[dist::Docs { host: a },]);
259         assert_eq!(first(cache.all::<dist::Mingw>()), &[dist::Mingw { host: a },]);
260         assert_eq!(
261             first(cache.all::<dist::Rustc>()),
262             &[dist::Rustc { compiler: Compiler { host: a, stage: 2 } },]
263         );
264         assert_eq!(
265             first(cache.all::<dist::Std>()),
266             &[dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },]
267         );
268         assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
269         // Make sure rustdoc is only built once.
270         assert_eq!(
271             first(cache.all::<tool::Rustdoc>()),
272             &[tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },]
273         );
274     }
275
276     #[test]
277     fn dist_with_targets() {
278         let mut cache = run_build(&[], configure(&["A"], &["A", "B"]));
279
280         let a = TargetSelection::from_user("A");
281         let b = TargetSelection::from_user("B");
282
283         assert_eq!(
284             first(cache.all::<dist::Docs>()),
285             &[dist::Docs { host: a }, dist::Docs { host: b },]
286         );
287         assert_eq!(
288             first(cache.all::<dist::Mingw>()),
289             &[dist::Mingw { host: a }, dist::Mingw { host: b },]
290         );
291         assert_eq!(
292             first(cache.all::<dist::Rustc>()),
293             &[dist::Rustc { compiler: Compiler { host: a, stage: 2 } },]
294         );
295         assert_eq!(
296             first(cache.all::<dist::Std>()),
297             &[
298                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
299                 dist::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
300             ]
301         );
302         assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
303     }
304
305     #[test]
306     fn dist_with_hosts() {
307         let mut cache = run_build(&[], configure(&["A", "B"], &["A", "B"]));
308
309         let a = TargetSelection::from_user("A");
310         let b = TargetSelection::from_user("B");
311
312         assert_eq!(
313             first(cache.all::<dist::Docs>()),
314             &[dist::Docs { host: a }, dist::Docs { host: b },]
315         );
316         assert_eq!(
317             first(cache.all::<dist::Mingw>()),
318             &[dist::Mingw { host: a }, dist::Mingw { host: b },]
319         );
320         assert_eq!(
321             first(cache.all::<dist::Rustc>()),
322             &[
323                 dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
324                 dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
325             ]
326         );
327         assert_eq!(
328             first(cache.all::<dist::Std>()),
329             &[
330                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
331                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
332             ]
333         );
334         assert_eq!(
335             first(cache.all::<compile::Std>()),
336             &[
337                 compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
338                 compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
339                 compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
340                 compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
341                 compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
342             ],
343         );
344         assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
345     }
346
347     #[test]
348     fn dist_only_cross_host() {
349         let a = TargetSelection::from_user("A");
350         let b = TargetSelection::from_user("B");
351         let mut config = configure(&["A", "B"], &["A", "B"]);
352         config.docs = false;
353         config.extended = true;
354         config.hosts = vec![b];
355         let mut cache = run_build(&[], config);
356
357         assert_eq!(
358             first(cache.all::<dist::Rustc>()),
359             &[dist::Rustc { compiler: Compiler { host: b, stage: 2 } },]
360         );
361         assert_eq!(
362             first(cache.all::<compile::Rustc>()),
363             &[
364                 compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
365                 compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
366             ]
367         );
368     }
369
370     #[test]
371     fn dist_with_targets_and_hosts() {
372         let mut cache = run_build(&[], configure(&["A", "B"], &["A", "B", "C"]));
373
374         let a = TargetSelection::from_user("A");
375         let b = TargetSelection::from_user("B");
376         let c = TargetSelection::from_user("C");
377
378         assert_eq!(
379             first(cache.all::<dist::Docs>()),
380             &[dist::Docs { host: a }, dist::Docs { host: b }, dist::Docs { host: c },]
381         );
382         assert_eq!(
383             first(cache.all::<dist::Mingw>()),
384             &[dist::Mingw { host: a }, dist::Mingw { host: b }, dist::Mingw { host: c },]
385         );
386         assert_eq!(
387             first(cache.all::<dist::Rustc>()),
388             &[
389                 dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
390                 dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
391             ]
392         );
393         assert_eq!(
394             first(cache.all::<dist::Std>()),
395             &[
396                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
397                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
398                 dist::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
399             ]
400         );
401         assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
402     }
403
404     #[test]
405     fn dist_with_empty_host() {
406         let config = configure(&[], &["C"]);
407         let mut cache = run_build(&[], config);
408
409         let a = TargetSelection::from_user("A");
410         let c = TargetSelection::from_user("C");
411
412         assert_eq!(first(cache.all::<dist::Docs>()), &[dist::Docs { host: c },]);
413         assert_eq!(first(cache.all::<dist::Mingw>()), &[dist::Mingw { host: c },]);
414         assert_eq!(
415             first(cache.all::<dist::Std>()),
416             &[dist::Std { compiler: Compiler { host: a, stage: 2 }, target: c },]
417         );
418     }
419
420     #[test]
421     fn dist_with_same_targets_and_hosts() {
422         let mut cache = run_build(&[], configure(&["A", "B"], &["A", "B"]));
423
424         let a = TargetSelection::from_user("A");
425         let b = TargetSelection::from_user("B");
426
427         assert_eq!(
428             first(cache.all::<dist::Docs>()),
429             &[dist::Docs { host: a }, dist::Docs { host: b },]
430         );
431         assert_eq!(
432             first(cache.all::<dist::Mingw>()),
433             &[dist::Mingw { host: a }, dist::Mingw { host: b },]
434         );
435         assert_eq!(
436             first(cache.all::<dist::Rustc>()),
437             &[
438                 dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
439                 dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
440             ]
441         );
442         assert_eq!(
443             first(cache.all::<dist::Std>()),
444             &[
445                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
446                 dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
447             ]
448         );
449         assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
450         assert_eq!(
451             first(cache.all::<compile::Std>()),
452             &[
453                 compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
454                 compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
455                 compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
456                 compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
457                 compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
458             ]
459         );
460         assert_eq!(
461             first(cache.all::<compile::Assemble>()),
462             &[
463                 compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
464                 compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
465                 compile::Assemble { target_compiler: Compiler { host: a, stage: 2 } },
466                 compile::Assemble { target_compiler: Compiler { host: b, stage: 2 } },
467             ]
468         );
469     }
470
471     #[test]
472     fn build_all() {
473         let build = Build::new(configure(&["A", "B"], &["A", "B", "C"]));
474         let mut builder = Builder::new(&build);
475         builder.run_step_descriptions(
476             &Builder::get_step_descriptions(Kind::Build),
477             &["compiler/rustc".into(), "library/std".into()],
478         );
479
480         let a = TargetSelection::from_user("A");
481         let b = TargetSelection::from_user("B");
482         let c = TargetSelection::from_user("C");
483
484         assert_eq!(
485             first(builder.cache.all::<compile::Std>()),
486             &[
487                 compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
488                 compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
489                 compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
490                 compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
491                 compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
492                 compile::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
493             ]
494         );
495         assert!(!builder.cache.all::<compile::Assemble>().is_empty());
496         assert_eq!(
497             first(builder.cache.all::<compile::Rustc>()),
498             &[
499                 compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
500                 compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: a },
501                 compile::Rustc { compiler: Compiler { host: a, stage: 2 }, target: a },
502                 compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
503                 compile::Rustc { compiler: Compiler { host: a, stage: 2 }, target: b },
504             ]
505         );
506     }
507
508     #[test]
509     fn build_with_empty_host() {
510         let config = configure(&[], &["C"]);
511         let build = Build::new(config);
512         let mut builder = Builder::new(&build);
513         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
514
515         let a = TargetSelection::from_user("A");
516         let c = TargetSelection::from_user("C");
517
518         assert_eq!(
519             first(builder.cache.all::<compile::Std>()),
520             &[
521                 compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
522                 compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
523                 compile::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
524             ]
525         );
526         assert_eq!(
527             first(builder.cache.all::<compile::Assemble>()),
528             &[
529                 compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
530                 compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
531                 compile::Assemble { target_compiler: Compiler { host: a, stage: 2 } },
532             ]
533         );
534         assert_eq!(
535             first(builder.cache.all::<compile::Rustc>()),
536             &[
537                 compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
538                 compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: a },
539             ]
540         );
541     }
542
543     #[test]
544     fn test_with_no_doc_stage0() {
545         let mut config = configure(&["A"], &["A"]);
546         config.stage = 0;
547         config.cmd = Subcommand::Test {
548             paths: vec!["library/std".into()],
549             skip: vec![],
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 };
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             skip: vec![],
621             test_args: vec![],
622             rustc_args: vec![],
623             fail_fast: true,
624             doc_tests: DocTests::Yes,
625             bless: false,
626             force_rerun: false,
627             compare_mode: None,
628             rustfix_coverage: false,
629             pass: None,
630             run: None,
631         };
632         // Make sure rustfmt binary not being found isn't an error.
633         config.channel = "beta".to_string();
634         let build = Build::new(config);
635         let mut builder = Builder::new(&build);
636
637         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]);
638         let a = TargetSelection::from_user("A");
639
640         // error_index_generator uses stage 1 to share rustdoc artifacts with the
641         // rustdoc tool.
642         assert_eq!(
643             first(builder.cache.all::<doc::ErrorIndex>()),
644             &[doc::ErrorIndex { target: a },]
645         );
646         assert_eq!(
647             first(builder.cache.all::<tool::ErrorIndex>()),
648             &[tool::ErrorIndex { compiler: Compiler { host: a, stage: 1 } }]
649         );
650         // Unfortunately rustdoc is built twice. Once from stage1 for compiletest
651         // (and other things), and once from stage0 for std crates. Ideally it
652         // would only be built once. If someone wants to fix this, it might be
653         // worth investigating if it would be possible to test std from stage1.
654         // Note that the stages here are +1 than what they actually are because
655         // Rustdoc::run swaps out the compiler with stage minus 1 if --stage is
656         // not 0.
657         //
658         // The stage 0 copy is the one downloaded for bootstrapping. It is
659         // (currently) needed to run "cargo test" on the linkchecker, and
660         // should be relatively "free".
661         assert_eq!(
662             first(builder.cache.all::<tool::Rustdoc>()),
663             &[
664                 tool::Rustdoc { compiler: Compiler { host: a, stage: 0 } },
665                 tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } },
666                 tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },
667             ]
668         );
669     }
670 }