]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/test.rs
Auto merge of #48509 - Phlosioneer:option-doc-change, r=TimNN
[rust.git] / src / bootstrap / test.rs
1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Implementation of the test-related targets of the build system.
12 //!
13 //! This file implements the various regression test suites that we execute on
14 //! our CI.
15
16 use std::env;
17 use std::ffi::OsString;
18 use std::iter;
19 use std::fmt;
20 use std::fs::{self, File};
21 use std::path::{PathBuf, Path};
22 use std::process::Command;
23 use std::io::Read;
24
25 use build_helper::{self, output};
26
27 use builder::{Kind, RunConfig, ShouldRun, Builder, Compiler, Step};
28 use Crate as CargoCrate;
29 use cache::{INTERNER, Interned};
30 use compile;
31 use dist;
32 use native;
33 use tool::{self, Tool};
34 use util::{self, dylib_path, dylib_path_var};
35 use {Build, Mode};
36 use toolstate::ToolState;
37
38 const ADB_TEST_DIR: &str = "/data/tmp/work";
39
40 /// The two modes of the test runner; tests or benchmarks.
41 #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
42 pub enum TestKind {
43     /// Run `cargo test`
44     Test,
45     /// Run `cargo bench`
46     Bench,
47 }
48
49 impl TestKind {
50     // Return the cargo subcommand for this test kind
51     fn subcommand(self) -> &'static str {
52         match self {
53             TestKind::Test => "test",
54             TestKind::Bench => "bench",
55         }
56     }
57 }
58
59 impl fmt::Display for TestKind {
60     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61         f.write_str(match *self {
62             TestKind::Test => "Testing",
63             TestKind::Bench => "Benchmarking",
64         })
65     }
66 }
67
68 fn try_run(build: &Build, cmd: &mut Command) -> bool {
69     if !build.fail_fast {
70         if !build.try_run(cmd) {
71             let mut failures = build.delayed_failures.borrow_mut();
72             failures.push(format!("{:?}", cmd));
73             return false;
74         }
75     } else {
76         build.run(cmd);
77     }
78     true
79 }
80
81 fn try_run_quiet(build: &Build, cmd: &mut Command) -> bool {
82     if !build.fail_fast {
83         if !build.try_run_quiet(cmd) {
84             let mut failures = build.delayed_failures.borrow_mut();
85             failures.push(format!("{:?}", cmd));
86             return false;
87         }
88     } else {
89         build.run_quiet(cmd);
90     }
91     true
92 }
93
94 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
95 pub struct Linkcheck {
96     host: Interned<String>,
97 }
98
99 impl Step for Linkcheck {
100     type Output = ();
101     const ONLY_HOSTS: bool = true;
102     const DEFAULT: bool = true;
103
104     /// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler.
105     ///
106     /// This tool in `src/tools` will verify the validity of all our links in the
107     /// documentation to ensure we don't have a bunch of dead ones.
108     fn run(self, builder: &Builder) {
109         let build = builder.build;
110         let host = self.host;
111
112         println!("Linkcheck ({})", host);
113
114         builder.default_doc(None);
115
116         let _time = util::timeit();
117         try_run(build, builder.tool_cmd(Tool::Linkchecker)
118                               .arg(build.out.join(host).join("doc")));
119     }
120
121     fn should_run(run: ShouldRun) -> ShouldRun {
122         let builder = run.builder;
123         run.path("src/tools/linkchecker").default_condition(builder.build.config.docs)
124     }
125
126     fn make_run(run: RunConfig) {
127         run.builder.ensure(Linkcheck { host: run.target });
128     }
129 }
130
131 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
132 pub struct Cargotest {
133     stage: u32,
134     host: Interned<String>,
135 }
136
137 impl Step for Cargotest {
138     type Output = ();
139     const ONLY_HOSTS: bool = true;
140
141     fn should_run(run: ShouldRun) -> ShouldRun {
142         run.path("src/tools/cargotest")
143     }
144
145     fn make_run(run: RunConfig) {
146         run.builder.ensure(Cargotest {
147             stage: run.builder.top_stage,
148             host: run.target,
149         });
150     }
151
152     /// Runs the `cargotest` tool as compiled in `stage` by the `host` compiler.
153     ///
154     /// This tool in `src/tools` will check out a few Rust projects and run `cargo
155     /// test` to ensure that we don't regress the test suites there.
156     fn run(self, builder: &Builder) {
157         let build = builder.build;
158         let compiler = builder.compiler(self.stage, self.host);
159         builder.ensure(compile::Rustc { compiler, target: compiler.host });
160
161         // Note that this is a short, cryptic, and not scoped directory name. This
162         // is currently to minimize the length of path on Windows where we otherwise
163         // quickly run into path name limit constraints.
164         let out_dir = build.out.join("ct");
165         t!(fs::create_dir_all(&out_dir));
166
167         let _time = util::timeit();
168         let mut cmd = builder.tool_cmd(Tool::CargoTest);
169         try_run(build, cmd.arg(&build.initial_cargo)
170                           .arg(&out_dir)
171                           .env("RUSTC", builder.rustc(compiler))
172                           .env("RUSTDOC", builder.rustdoc(compiler.host)));
173     }
174 }
175
176 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
177 pub struct Cargo {
178     stage: u32,
179     host: Interned<String>,
180 }
181
182 impl Step for Cargo {
183     type Output = ();
184     const ONLY_HOSTS: bool = true;
185
186     fn should_run(run: ShouldRun) -> ShouldRun {
187         run.path("src/tools/cargo")
188     }
189
190     fn make_run(run: RunConfig) {
191         run.builder.ensure(Cargo {
192             stage: run.builder.top_stage,
193             host: run.target,
194         });
195     }
196
197     /// Runs `cargo test` for `cargo` packaged with Rust.
198     fn run(self, builder: &Builder) {
199         let build = builder.build;
200         let compiler = builder.compiler(self.stage, self.host);
201
202         builder.ensure(tool::Cargo { compiler, target: self.host });
203         let mut cargo = builder.cargo(compiler, Mode::Tool, self.host, "test");
204         cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml"));
205         if !build.fail_fast {
206             cargo.arg("--no-fail-fast");
207         }
208
209         // Don't build tests dynamically, just a pain to work with
210         cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
211
212         // Don't run cross-compile tests, we may not have cross-compiled libstd libs
213         // available.
214         cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
215
216         try_run(build, cargo.env("PATH", &path_for_cargo(builder, compiler)));
217     }
218 }
219
220 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
221 pub struct Rls {
222     stage: u32,
223     host: Interned<String>,
224 }
225
226 impl Step for Rls {
227     type Output = ();
228     const ONLY_HOSTS: bool = true;
229
230     fn should_run(run: ShouldRun) -> ShouldRun {
231         run.path("src/tools/rls")
232     }
233
234     fn make_run(run: RunConfig) {
235         run.builder.ensure(Rls {
236             stage: run.builder.top_stage,
237             host: run.target,
238         });
239     }
240
241     /// Runs `cargo test` for the rls.
242     fn run(self, builder: &Builder) {
243         let build = builder.build;
244         let stage = self.stage;
245         let host = self.host;
246         let compiler = builder.compiler(stage, host);
247
248         builder.ensure(tool::Rls { compiler, target: self.host });
249         let mut cargo = tool::prepare_tool_cargo(builder,
250                                                  compiler,
251                                                  host,
252                                                  "test",
253                                                  "src/tools/rls");
254
255         // Don't build tests dynamically, just a pain to work with
256         cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
257
258         builder.add_rustc_lib_path(compiler, &mut cargo);
259
260         if try_run(build, &mut cargo) {
261             build.save_toolstate("rls", ToolState::TestPass);
262         }
263     }
264 }
265
266 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
267 pub struct Rustfmt {
268     stage: u32,
269     host: Interned<String>,
270 }
271
272 impl Step for Rustfmt {
273     type Output = ();
274     const ONLY_HOSTS: bool = true;
275
276     fn should_run(run: ShouldRun) -> ShouldRun {
277         run.path("src/tools/rustfmt")
278     }
279
280     fn make_run(run: RunConfig) {
281         run.builder.ensure(Rustfmt {
282             stage: run.builder.top_stage,
283             host: run.target,
284         });
285     }
286
287     /// Runs `cargo test` for rustfmt.
288     fn run(self, builder: &Builder) {
289         let build = builder.build;
290         let stage = self.stage;
291         let host = self.host;
292         let compiler = builder.compiler(stage, host);
293
294         builder.ensure(tool::Rustfmt { compiler, target: self.host });
295         let mut cargo = tool::prepare_tool_cargo(builder,
296                                                  compiler,
297                                                  host,
298                                                  "test",
299                                                  "src/tools/rustfmt");
300
301         // Don't build tests dynamically, just a pain to work with
302         cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
303
304         builder.add_rustc_lib_path(compiler, &mut cargo);
305
306         if try_run(build, &mut cargo) {
307             build.save_toolstate("rustfmt", ToolState::TestPass);
308         }
309     }
310 }
311
312 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
313 pub struct Miri {
314     stage: u32,
315     host: Interned<String>,
316 }
317
318 impl Step for Miri {
319     type Output = ();
320     const ONLY_HOSTS: bool = true;
321     const DEFAULT: bool = true;
322
323     fn should_run(run: ShouldRun) -> ShouldRun {
324         let test_miri = run.builder.build.config.test_miri;
325         run.path("src/tools/miri").default_condition(test_miri)
326     }
327
328     fn make_run(run: RunConfig) {
329         run.builder.ensure(Miri {
330             stage: run.builder.top_stage,
331             host: run.target,
332         });
333     }
334
335     /// Runs `cargo test` for miri.
336     fn run(self, builder: &Builder) {
337         let build = builder.build;
338         let stage = self.stage;
339         let host = self.host;
340         let compiler = builder.compiler(stage, host);
341
342         if let Some(miri) = builder.ensure(tool::Miri { compiler, target: self.host }) {
343             let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test");
344             cargo.arg("--manifest-path").arg(build.src.join("src/tools/miri/Cargo.toml"));
345
346             // Don't build tests dynamically, just a pain to work with
347             cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
348             // miri tests need to know about the stage sysroot
349             cargo.env("MIRI_SYSROOT", builder.sysroot(compiler));
350             cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler));
351             cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
352             cargo.env("MIRI_PATH", miri);
353
354             builder.add_rustc_lib_path(compiler, &mut cargo);
355
356             if try_run(build, &mut cargo) {
357                 build.save_toolstate("miri", ToolState::TestPass);
358             }
359         } else {
360             eprintln!("failed to test miri: could not build");
361         }
362     }
363 }
364
365 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
366 pub struct Clippy {
367     stage: u32,
368     host: Interned<String>,
369 }
370
371 impl Step for Clippy {
372     type Output = ();
373     const ONLY_HOSTS: bool = true;
374     const DEFAULT: bool = false;
375
376     fn should_run(run: ShouldRun) -> ShouldRun {
377         run.path("src/tools/clippy")
378     }
379
380     fn make_run(run: RunConfig) {
381         run.builder.ensure(Clippy {
382             stage: run.builder.top_stage,
383             host: run.target,
384         });
385     }
386
387     /// Runs `cargo test` for clippy.
388     fn run(self, builder: &Builder) {
389         let build = builder.build;
390         let stage = self.stage;
391         let host = self.host;
392         let compiler = builder.compiler(stage, host);
393
394         if let Some(clippy) = builder.ensure(tool::Clippy { compiler, target: self.host }) {
395             let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test");
396             cargo.arg("--manifest-path").arg(build.src.join("src/tools/clippy/Cargo.toml"));
397
398             // Don't build tests dynamically, just a pain to work with
399             cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
400             // clippy tests need to know about the stage sysroot
401             cargo.env("SYSROOT", builder.sysroot(compiler));
402             cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler));
403             cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
404             let host_libs = builder.stage_out(compiler, Mode::Tool).join(builder.cargo_dir());
405             cargo.env("HOST_LIBS", host_libs);
406             // clippy tests need to find the driver
407             cargo.env("CLIPPY_DRIVER_PATH", clippy);
408
409             builder.add_rustc_lib_path(compiler, &mut cargo);
410
411             if try_run(build, &mut cargo) {
412                 build.save_toolstate("clippy-driver", ToolState::TestPass);
413             }
414         } else {
415             eprintln!("failed to test clippy: could not build");
416         }
417     }
418 }
419
420 fn path_for_cargo(builder: &Builder, compiler: Compiler) -> OsString {
421     // Configure PATH to find the right rustc. NB. we have to use PATH
422     // and not RUSTC because the Cargo test suite has tests that will
423     // fail if rustc is not spelled `rustc`.
424     let path = builder.sysroot(compiler).join("bin");
425     let old_path = env::var_os("PATH").unwrap_or_default();
426     env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
427 }
428
429 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
430 pub struct RustdocTheme {
431     pub compiler: Compiler,
432 }
433
434 impl Step for RustdocTheme {
435     type Output = ();
436     const DEFAULT: bool = true;
437     const ONLY_HOSTS: bool = true;
438
439     fn should_run(run: ShouldRun) -> ShouldRun {
440         run.path("src/tools/rustdoc-themes")
441     }
442
443     fn make_run(run: RunConfig) {
444         let compiler = run.builder.compiler(run.builder.top_stage, run.host);
445
446         run.builder.ensure(RustdocTheme {
447             compiler: compiler,
448         });
449     }
450
451     fn run(self, builder: &Builder) {
452         let rustdoc = builder.rustdoc(self.compiler.host);
453         let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
454         cmd.arg(rustdoc.to_str().unwrap())
455            .arg(builder.src.join("src/librustdoc/html/static/themes").to_str().unwrap())
456            .env("RUSTC_STAGE", self.compiler.stage.to_string())
457            .env("RUSTC_SYSROOT", builder.sysroot(self.compiler))
458            .env("RUSTDOC_LIBDIR", builder.sysroot_libdir(self.compiler, self.compiler.host))
459            .env("CFG_RELEASE_CHANNEL", &builder.build.config.channel)
460            .env("RUSTDOC_REAL", builder.rustdoc(self.compiler.host))
461            .env("RUSTDOC_CRATE_VERSION", builder.build.rust_version())
462            .env("RUSTC_BOOTSTRAP", "1");
463         if let Some(linker) = builder.build.linker(self.compiler.host) {
464             cmd.env("RUSTC_TARGET_LINKER", linker);
465         }
466         try_run(builder.build, &mut cmd);
467     }
468 }
469
470 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
471 pub struct RustdocJS {
472     pub host: Interned<String>,
473     pub target: Interned<String>,
474 }
475
476 impl Step for RustdocJS {
477     type Output = ();
478     const DEFAULT: bool = true;
479     const ONLY_HOSTS: bool = true;
480
481     fn should_run(run: ShouldRun) -> ShouldRun {
482         run.path("src/test/rustdoc-js")
483     }
484
485     fn make_run(run: RunConfig) {
486         run.builder.ensure(RustdocJS {
487             host: run.host,
488             target: run.target,
489         });
490     }
491
492     fn run(self, builder: &Builder) {
493         if let Some(ref nodejs) = builder.config.nodejs {
494             let mut command = Command::new(nodejs);
495             command.args(&["src/tools/rustdoc-js/tester.js", &*self.host]);
496             builder.ensure(::doc::Std {
497                 target: self.target,
498                 stage: builder.top_stage,
499             });
500             builder.run(&mut command);
501         } else {
502             println!("No nodejs found, skipping \"src/test/rustdoc-js\" tests");
503         }
504     }
505 }
506
507 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
508 pub struct Tidy {
509     host: Interned<String>,
510 }
511
512 impl Step for Tidy {
513     type Output = ();
514     const DEFAULT: bool = true;
515     const ONLY_HOSTS: bool = true;
516     const ONLY_BUILD: bool = true;
517
518     /// Runs the `tidy` tool as compiled in `stage` by the `host` compiler.
519     ///
520     /// This tool in `src/tools` checks up on various bits and pieces of style and
521     /// otherwise just implements a few lint-like checks that are specific to the
522     /// compiler itself.
523     fn run(self, builder: &Builder) {
524         let build = builder.build;
525         let host = self.host;
526
527         let _folder = build.fold_output(|| "tidy");
528         println!("tidy check ({})", host);
529         let mut cmd = builder.tool_cmd(Tool::Tidy);
530         cmd.arg(build.src.join("src"));
531         cmd.arg(&build.initial_cargo);
532         if !build.config.vendor {
533             cmd.arg("--no-vendor");
534         }
535         if build.config.quiet_tests {
536             cmd.arg("--quiet");
537         }
538         try_run(build, &mut cmd);
539     }
540
541     fn should_run(run: ShouldRun) -> ShouldRun {
542         run.path("src/tools/tidy")
543     }
544
545     fn make_run(run: RunConfig) {
546         run.builder.ensure(Tidy {
547             host: run.builder.build.build,
548         });
549     }
550 }
551
552 fn testdir(build: &Build, host: Interned<String>) -> PathBuf {
553     build.out.join(host).join("test")
554 }
555
556 macro_rules! default_test {
557     ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr }) => {
558         test!($name { path: $path, mode: $mode, suite: $suite, default: true, host: false });
559     }
560 }
561
562 macro_rules! host_test {
563     ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr }) => {
564         test!($name { path: $path, mode: $mode, suite: $suite, default: true, host: true });
565     }
566 }
567
568 macro_rules! test {
569     ($name:ident {
570         path: $path:expr,
571         mode: $mode:expr,
572         suite: $suite:expr,
573         default: $default:expr,
574         host: $host:expr
575     }) => {
576         #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
577         pub struct $name {
578             pub compiler: Compiler,
579             pub target: Interned<String>,
580         }
581
582         impl Step for $name {
583             type Output = ();
584             const DEFAULT: bool = $default;
585             const ONLY_HOSTS: bool = $host;
586
587             fn should_run(run: ShouldRun) -> ShouldRun {
588                 run.path($path)
589             }
590
591             fn make_run(run: RunConfig) {
592                 let compiler = run.builder.compiler(run.builder.top_stage, run.host);
593
594                 run.builder.ensure($name {
595                     compiler,
596                     target: run.target,
597                 });
598             }
599
600             fn run(self, builder: &Builder) {
601                 builder.ensure(Compiletest {
602                     compiler: self.compiler,
603                     target: self.target,
604                     mode: $mode,
605                     suite: $suite,
606                 })
607             }
608         }
609     }
610 }
611
612 default_test!(Ui {
613     path: "src/test/ui",
614     mode: "ui",
615     suite: "ui"
616 });
617
618 default_test!(RunPass {
619     path: "src/test/run-pass",
620     mode: "run-pass",
621     suite: "run-pass"
622 });
623
624 default_test!(CompileFail {
625     path: "src/test/compile-fail",
626     mode: "compile-fail",
627     suite: "compile-fail"
628 });
629
630 default_test!(ParseFail {
631     path: "src/test/parse-fail",
632     mode: "parse-fail",
633     suite: "parse-fail"
634 });
635
636 default_test!(RunFail {
637     path: "src/test/run-fail",
638     mode: "run-fail",
639     suite: "run-fail"
640 });
641
642 default_test!(RunPassValgrind {
643     path: "src/test/run-pass-valgrind",
644     mode: "run-pass-valgrind",
645     suite: "run-pass-valgrind"
646 });
647
648 default_test!(MirOpt {
649     path: "src/test/mir-opt",
650     mode: "mir-opt",
651     suite: "mir-opt"
652 });
653
654 default_test!(Codegen {
655     path: "src/test/codegen",
656     mode: "codegen",
657     suite: "codegen"
658 });
659
660 default_test!(CodegenUnits {
661     path: "src/test/codegen-units",
662     mode: "codegen-units",
663     suite: "codegen-units"
664 });
665
666 default_test!(Incremental {
667     path: "src/test/incremental",
668     mode: "incremental",
669     suite: "incremental"
670 });
671
672 default_test!(Debuginfo {
673     path: "src/test/debuginfo",
674     // What this runs varies depending on the native platform being apple
675     mode: "debuginfo-XXX",
676     suite: "debuginfo"
677 });
678
679 host_test!(UiFullDeps {
680     path: "src/test/ui-fulldeps",
681     mode: "ui",
682     suite: "ui-fulldeps"
683 });
684
685 host_test!(RunPassFullDeps {
686     path: "src/test/run-pass-fulldeps",
687     mode: "run-pass",
688     suite: "run-pass-fulldeps"
689 });
690
691 host_test!(RunFailFullDeps {
692     path: "src/test/run-fail-fulldeps",
693     mode: "run-fail",
694     suite: "run-fail-fulldeps"
695 });
696
697 host_test!(CompileFailFullDeps {
698     path: "src/test/compile-fail-fulldeps",
699     mode: "compile-fail",
700     suite: "compile-fail-fulldeps"
701 });
702
703 host_test!(IncrementalFullDeps {
704     path: "src/test/incremental-fulldeps",
705     mode: "incremental",
706     suite: "incremental-fulldeps"
707 });
708
709 host_test!(Rustdoc {
710     path: "src/test/rustdoc",
711     mode: "rustdoc",
712     suite: "rustdoc"
713 });
714
715 test!(Pretty {
716     path: "src/test/pretty",
717     mode: "pretty",
718     suite: "pretty",
719     default: false,
720     host: true
721 });
722 test!(RunPassPretty {
723     path: "src/test/run-pass/pretty",
724     mode: "pretty",
725     suite: "run-pass",
726     default: false,
727     host: true
728 });
729 test!(RunFailPretty {
730     path: "src/test/run-fail/pretty",
731     mode: "pretty",
732     suite: "run-fail",
733     default: false,
734     host: true
735 });
736 test!(RunPassValgrindPretty {
737     path: "src/test/run-pass-valgrind/pretty",
738     mode: "pretty",
739     suite: "run-pass-valgrind",
740     default: false,
741     host: true
742 });
743 test!(RunPassFullDepsPretty {
744     path: "src/test/run-pass-fulldeps/pretty",
745     mode: "pretty",
746     suite: "run-pass-fulldeps",
747     default: false,
748     host: true
749 });
750 test!(RunFailFullDepsPretty {
751     path: "src/test/run-fail-fulldeps/pretty",
752     mode: "pretty",
753     suite: "run-fail-fulldeps",
754     default: false,
755     host: true
756 });
757
758 host_test!(RunMake {
759     path: "src/test/run-make",
760     mode: "run-make",
761     suite: "run-make"
762 });
763
764 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
765 struct Compiletest {
766     compiler: Compiler,
767     target: Interned<String>,
768     mode: &'static str,
769     suite: &'static str,
770 }
771
772 impl Step for Compiletest {
773     type Output = ();
774
775     fn should_run(run: ShouldRun) -> ShouldRun {
776         run.never()
777     }
778
779     /// Executes the `compiletest` tool to run a suite of tests.
780     ///
781     /// Compiles all tests with `compiler` for `target` with the specified
782     /// compiletest `mode` and `suite` arguments. For example `mode` can be
783     /// "run-pass" or `suite` can be something like `debuginfo`.
784     fn run(self, builder: &Builder) {
785         let build = builder.build;
786         let compiler = self.compiler;
787         let target = self.target;
788         let mode = self.mode;
789         let suite = self.suite;
790
791         // Skip codegen tests if they aren't enabled in configuration.
792         if !build.config.codegen_tests && suite == "codegen" {
793             return;
794         }
795
796         if suite == "debuginfo" {
797             // Skip debuginfo tests on MSVC
798             if build.build.contains("msvc") {
799                 return;
800             }
801
802             if mode == "debuginfo-XXX" {
803                 return if build.build.contains("apple") {
804                     builder.ensure(Compiletest {
805                         mode: "debuginfo-lldb",
806                         ..self
807                     });
808                 } else {
809                     builder.ensure(Compiletest {
810                         mode: "debuginfo-gdb",
811                         ..self
812                     });
813                 };
814             }
815
816             builder.ensure(dist::DebuggerScripts {
817                 sysroot: builder.sysroot(compiler),
818                 host: target
819             });
820         }
821
822         if suite.ends_with("fulldeps") ||
823             // FIXME: Does pretty need librustc compiled? Note that there are
824             // fulldeps test suites with mode = pretty as well.
825             mode == "pretty" ||
826             mode == "rustdoc" ||
827             mode == "run-make" {
828             builder.ensure(compile::Rustc { compiler, target });
829         }
830
831         builder.ensure(compile::Test { compiler, target });
832         builder.ensure(native::TestHelpers { target });
833         builder.ensure(RemoteCopyLibs { compiler, target });
834
835         let _folder = build.fold_output(|| format!("test_{}", suite));
836         println!("Check compiletest suite={} mode={} ({} -> {})",
837                  suite, mode, &compiler.host, target);
838         let mut cmd = builder.tool_cmd(Tool::Compiletest);
839
840         // compiletest currently has... a lot of arguments, so let's just pass all
841         // of them!
842
843         cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(compiler));
844         cmd.arg("--run-lib-path").arg(builder.sysroot_libdir(compiler, target));
845         cmd.arg("--rustc-path").arg(builder.rustc(compiler));
846
847         // Avoid depending on rustdoc when we don't need it.
848         if mode == "rustdoc" || mode == "run-make" {
849             cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler.host));
850         }
851
852         cmd.arg("--src-base").arg(build.src.join("src/test").join(suite));
853         cmd.arg("--build-base").arg(testdir(build, compiler.host).join(suite));
854         cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target));
855         cmd.arg("--mode").arg(mode);
856         cmd.arg("--target").arg(target);
857         cmd.arg("--host").arg(&*compiler.host);
858         cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(build.build));
859
860         if let Some(ref nodejs) = build.config.nodejs {
861             cmd.arg("--nodejs").arg(nodejs);
862         }
863
864         let mut flags = vec!["-Crpath".to_string()];
865         if build.config.rust_optimize_tests {
866             flags.push("-O".to_string());
867         }
868         if build.config.rust_debuginfo_tests {
869             flags.push("-g".to_string());
870         }
871         flags.push("-Zmiri -Zunstable-options".to_string());
872         flags.push(build.config.cmd.rustc_args().join(" "));
873
874         if let Some(linker) = build.linker(target) {
875             cmd.arg("--linker").arg(linker);
876         }
877
878         let hostflags = flags.clone();
879         cmd.arg("--host-rustcflags").arg(hostflags.join(" "));
880
881         let mut targetflags = flags.clone();
882         targetflags.push(format!("-Lnative={}",
883                                  build.test_helpers_out(target).display()));
884         cmd.arg("--target-rustcflags").arg(targetflags.join(" "));
885
886         cmd.arg("--docck-python").arg(build.python());
887
888         if build.build.ends_with("apple-darwin") {
889             // Force /usr/bin/python on macOS for LLDB tests because we're loading the
890             // LLDB plugin's compiled module which only works with the system python
891             // (namely not Homebrew-installed python)
892             cmd.arg("--lldb-python").arg("/usr/bin/python");
893         } else {
894             cmd.arg("--lldb-python").arg(build.python());
895         }
896
897         if let Some(ref gdb) = build.config.gdb {
898             cmd.arg("--gdb").arg(gdb);
899         }
900         if let Some(ref vers) = build.lldb_version {
901             cmd.arg("--lldb-version").arg(vers);
902         }
903         if let Some(ref dir) = build.lldb_python_dir {
904             cmd.arg("--lldb-python-dir").arg(dir);
905         }
906
907         cmd.args(&build.config.cmd.test_args());
908
909         if build.is_verbose() {
910             cmd.arg("--verbose");
911         }
912
913         if build.config.quiet_tests {
914             cmd.arg("--quiet");
915         }
916
917         if build.config.llvm_enabled {
918             let llvm_config = build.llvm_config(build.config.build);
919             let llvm_version = output(Command::new(&llvm_config).arg("--version"));
920             cmd.arg("--llvm-version").arg(llvm_version);
921             if !build.is_rust_llvm(target) {
922                 cmd.arg("--system-llvm");
923             }
924
925             // Only pass correct values for these flags for the `run-make` suite as it
926             // requires that a C++ compiler was configured which isn't always the case.
927             if suite == "run-make" {
928                 let llvm_components = output(Command::new(&llvm_config).arg("--components"));
929                 let llvm_cxxflags = output(Command::new(&llvm_config).arg("--cxxflags"));
930                 cmd.arg("--cc").arg(build.cc(target))
931                 .arg("--cxx").arg(build.cxx(target).unwrap())
932                 .arg("--cflags").arg(build.cflags(target).join(" "))
933                 .arg("--llvm-components").arg(llvm_components.trim())
934                 .arg("--llvm-cxxflags").arg(llvm_cxxflags.trim());
935                 if let Some(ar) = build.ar(target) {
936                     cmd.arg("--ar").arg(ar);
937                 }
938             }
939         }
940         if suite == "run-make" && !build.config.llvm_enabled {
941             println!("Ignoring run-make test suite as they generally don't work without LLVM");
942             return;
943         }
944
945         if suite != "run-make" {
946             cmd.arg("--cc").arg("")
947                .arg("--cxx").arg("")
948                .arg("--cflags").arg("")
949                .arg("--llvm-components").arg("")
950                .arg("--llvm-cxxflags").arg("");
951         }
952
953         if build.remote_tested(target) {
954             cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
955         }
956
957         // Running a C compiler on MSVC requires a few env vars to be set, to be
958         // sure to set them here.
959         //
960         // Note that if we encounter `PATH` we make sure to append to our own `PATH`
961         // rather than stomp over it.
962         if target.contains("msvc") {
963             for &(ref k, ref v) in build.cc[&target].env() {
964                 if k != "PATH" {
965                     cmd.env(k, v);
966                 }
967             }
968         }
969         cmd.env("RUSTC_BOOTSTRAP", "1");
970         build.add_rust_test_threads(&mut cmd);
971
972         if build.config.sanitizers {
973             cmd.env("SANITIZER_SUPPORT", "1");
974         }
975
976         if build.config.profiler {
977             cmd.env("PROFILER_SUPPORT", "1");
978         }
979
980         cmd.env("RUST_TEST_TMPDIR", build.out.join("tmp"));
981
982         cmd.arg("--adb-path").arg("adb");
983         cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
984         if target.contains("android") {
985             // Assume that cc for this target comes from the android sysroot
986             cmd.arg("--android-cross-path")
987                .arg(build.cc(target).parent().unwrap().parent().unwrap());
988         } else {
989             cmd.arg("--android-cross-path").arg("");
990         }
991
992         build.ci_env.force_coloring_in_ci(&mut cmd);
993
994         let _time = util::timeit();
995         try_run(build, &mut cmd);
996     }
997 }
998
999 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1000 struct DocTest {
1001     compiler: Compiler,
1002     path: &'static str,
1003     name: &'static str,
1004     is_ext_doc: bool,
1005 }
1006
1007 impl Step for DocTest {
1008     type Output = ();
1009     const ONLY_HOSTS: bool = true;
1010
1011     fn should_run(run: ShouldRun) -> ShouldRun {
1012         run.never()
1013     }
1014
1015     /// Run `rustdoc --test` for all documentation in `src/doc`.
1016     ///
1017     /// This will run all tests in our markdown documentation (e.g. the book)
1018     /// located in `src/doc`. The `rustdoc` that's run is the one that sits next to
1019     /// `compiler`.
1020     fn run(self, builder: &Builder) {
1021         let build = builder.build;
1022         let compiler = self.compiler;
1023
1024         builder.ensure(compile::Test { compiler, target: compiler.host });
1025
1026         // Do a breadth-first traversal of the `src/doc` directory and just run
1027         // tests for all files that end in `*.md`
1028         let mut stack = vec![build.src.join(self.path)];
1029         let _time = util::timeit();
1030         let _folder = build.fold_output(|| format!("test_{}", self.name));
1031
1032         while let Some(p) = stack.pop() {
1033             if p.is_dir() {
1034                 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
1035                 continue
1036             }
1037
1038             if p.extension().and_then(|s| s.to_str()) != Some("md") {
1039                 continue;
1040             }
1041
1042             // The nostarch directory in the book is for no starch, and so isn't
1043             // guaranteed to build. We don't care if it doesn't build, so skip it.
1044             if p.to_str().map_or(false, |p| p.contains("nostarch")) {
1045                 continue;
1046             }
1047
1048             let test_result = markdown_test(builder, compiler, &p);
1049             if self.is_ext_doc {
1050                 let toolstate = if test_result {
1051                     ToolState::TestPass
1052                 } else {
1053                     ToolState::TestFail
1054                 };
1055                 build.save_toolstate(self.name, toolstate);
1056             }
1057         }
1058     }
1059 }
1060
1061 macro_rules! test_book {
1062     ($($name:ident, $path:expr, $book_name:expr, default=$default:expr;)+) => {
1063         $(
1064             #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1065             pub struct $name {
1066                 compiler: Compiler,
1067             }
1068
1069             impl Step for $name {
1070                 type Output = ();
1071                 const DEFAULT: bool = $default;
1072                 const ONLY_HOSTS: bool = true;
1073
1074                 fn should_run(run: ShouldRun) -> ShouldRun {
1075                     run.path($path)
1076                 }
1077
1078                 fn make_run(run: RunConfig) {
1079                     run.builder.ensure($name {
1080                         compiler: run.builder.compiler(run.builder.top_stage, run.host),
1081                     });
1082                 }
1083
1084                 fn run(self, builder: &Builder) {
1085                     builder.ensure(DocTest {
1086                         compiler: self.compiler,
1087                         path: $path,
1088                         name: $book_name,
1089                         is_ext_doc: !$default,
1090                     });
1091                 }
1092             }
1093         )+
1094     }
1095 }
1096
1097 test_book!(
1098     Nomicon, "src/doc/nomicon", "nomicon", default=false;
1099     Reference, "src/doc/reference", "reference", default=false;
1100     RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
1101     RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false;
1102     TheBook, "src/doc/book", "book", default=false;
1103     UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
1104 );
1105
1106 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1107 pub struct ErrorIndex {
1108     compiler: Compiler,
1109 }
1110
1111 impl Step for ErrorIndex {
1112     type Output = ();
1113     const DEFAULT: bool = true;
1114     const ONLY_HOSTS: bool = true;
1115
1116     fn should_run(run: ShouldRun) -> ShouldRun {
1117         run.path("src/tools/error_index_generator")
1118     }
1119
1120     fn make_run(run: RunConfig) {
1121         run.builder.ensure(ErrorIndex {
1122             compiler: run.builder.compiler(run.builder.top_stage, run.host),
1123         });
1124     }
1125
1126     /// Run the error index generator tool to execute the tests located in the error
1127     /// index.
1128     ///
1129     /// The `error_index_generator` tool lives in `src/tools` and is used to
1130     /// generate a markdown file from the error indexes of the code base which is
1131     /// then passed to `rustdoc --test`.
1132     fn run(self, builder: &Builder) {
1133         let build = builder.build;
1134         let compiler = self.compiler;
1135
1136         builder.ensure(compile::Std { compiler, target: compiler.host });
1137
1138         let _folder = build.fold_output(|| "test_error_index");
1139         println!("Testing error-index stage{}", compiler.stage);
1140
1141         let dir = testdir(build, compiler.host);
1142         t!(fs::create_dir_all(&dir));
1143         let output = dir.join("error-index.md");
1144
1145         let _time = util::timeit();
1146         build.run(builder.tool_cmd(Tool::ErrorIndex)
1147                     .arg("markdown")
1148                     .arg(&output)
1149                     .env("CFG_BUILD", &build.build)
1150                     .env("RUSTC_ERROR_METADATA_DST", build.extended_error_dir()));
1151
1152         markdown_test(builder, compiler, &output);
1153     }
1154 }
1155
1156 fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) -> bool {
1157     let build = builder.build;
1158     let mut file = t!(File::open(markdown));
1159     let mut contents = String::new();
1160     t!(file.read_to_string(&mut contents));
1161     if !contents.contains("```") {
1162         return true;
1163     }
1164
1165     println!("doc tests for: {}", markdown.display());
1166     let mut cmd = builder.rustdoc_cmd(compiler.host);
1167     build.add_rust_test_threads(&mut cmd);
1168     cmd.arg("--test");
1169     cmd.arg(markdown);
1170     cmd.env("RUSTC_BOOTSTRAP", "1");
1171
1172     let test_args = build.config.cmd.test_args().join(" ");
1173     cmd.arg("--test-args").arg(test_args);
1174
1175     if build.config.quiet_tests {
1176         try_run_quiet(build, &mut cmd)
1177     } else {
1178         try_run(build, &mut cmd)
1179     }
1180 }
1181
1182 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1183 pub struct CrateLibrustc {
1184     compiler: Compiler,
1185     target: Interned<String>,
1186     test_kind: TestKind,
1187     krate: Interned<String>,
1188 }
1189
1190 impl Step for CrateLibrustc {
1191     type Output = ();
1192     const DEFAULT: bool = true;
1193     const ONLY_HOSTS: bool = true;
1194
1195     fn should_run(run: ShouldRun) -> ShouldRun {
1196         run.krate("rustc-main")
1197     }
1198
1199     fn make_run(run: RunConfig) {
1200         let builder = run.builder;
1201         let compiler = builder.compiler(builder.top_stage, run.host);
1202
1203         for krate in builder.in_tree_crates("rustc-main") {
1204             if run.path.ends_with(&krate.path) {
1205                 let test_kind = if builder.kind == Kind::Test {
1206                     TestKind::Test
1207                 } else if builder.kind == Kind::Bench {
1208                     TestKind::Bench
1209                 } else {
1210                     panic!("unexpected builder.kind in crate: {:?}", builder.kind);
1211                 };
1212
1213                 builder.ensure(CrateLibrustc {
1214                     compiler,
1215                     target: run.target,
1216                     test_kind,
1217                     krate: krate.name,
1218                 });
1219             }
1220         }
1221     }
1222
1223     fn run(self, builder: &Builder) {
1224         builder.ensure(Crate {
1225             compiler: self.compiler,
1226             target: self.target,
1227             mode: Mode::Librustc,
1228             test_kind: self.test_kind,
1229             krate: self.krate,
1230         });
1231     }
1232 }
1233
1234 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1235 pub struct CrateNotDefault {
1236     compiler: Compiler,
1237     target: Interned<String>,
1238     test_kind: TestKind,
1239     krate: &'static str,
1240 }
1241
1242 impl Step for CrateNotDefault {
1243     type Output = ();
1244
1245     fn should_run(run: ShouldRun) -> ShouldRun {
1246         run.path("src/liballoc_jemalloc")
1247             .path("src/librustc_asan")
1248             .path("src/librustc_lsan")
1249             .path("src/librustc_msan")
1250             .path("src/librustc_tsan")
1251     }
1252
1253     fn make_run(run: RunConfig) {
1254         let builder = run.builder;
1255         let compiler = builder.compiler(builder.top_stage, run.host);
1256
1257         let test_kind = if builder.kind == Kind::Test {
1258             TestKind::Test
1259         } else if builder.kind == Kind::Bench {
1260             TestKind::Bench
1261         } else {
1262             panic!("unexpected builder.kind in crate: {:?}", builder.kind);
1263         };
1264
1265         builder.ensure(CrateNotDefault {
1266             compiler,
1267             target: run.target,
1268             test_kind,
1269             krate: match run.path {
1270                 _ if run.path.ends_with("src/liballoc_jemalloc") => "alloc_jemalloc",
1271                 _ if run.path.ends_with("src/librustc_asan") => "rustc_asan",
1272                 _ if run.path.ends_with("src/librustc_lsan") => "rustc_lsan",
1273                 _ if run.path.ends_with("src/librustc_msan") => "rustc_msan",
1274                 _ if run.path.ends_with("src/librustc_tsan") => "rustc_tsan",
1275                 _ => panic!("unexpected path {:?}", run.path),
1276             },
1277         });
1278     }
1279
1280     fn run(self, builder: &Builder) {
1281         builder.ensure(Crate {
1282             compiler: self.compiler,
1283             target: self.target,
1284             mode: Mode::Libstd,
1285             test_kind: self.test_kind,
1286             krate: INTERNER.intern_str(self.krate),
1287         });
1288     }
1289 }
1290
1291
1292 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1293 pub struct Crate {
1294     compiler: Compiler,
1295     target: Interned<String>,
1296     mode: Mode,
1297     test_kind: TestKind,
1298     krate: Interned<String>,
1299 }
1300
1301 impl Step for Crate {
1302     type Output = ();
1303     const DEFAULT: bool = true;
1304
1305     fn should_run(mut run: ShouldRun) -> ShouldRun {
1306         let builder = run.builder;
1307         run = run.krate("test");
1308         for krate in run.builder.in_tree_crates("std") {
1309             if krate.is_local(&run.builder) &&
1310                 !krate.name.contains("jemalloc") &&
1311                 !(krate.name.starts_with("rustc_") && krate.name.ends_with("san")) &&
1312                 krate.name != "dlmalloc" {
1313                 run = run.path(krate.local_path(&builder).to_str().unwrap());
1314             }
1315         }
1316         run
1317     }
1318
1319     fn make_run(run: RunConfig) {
1320         let builder = run.builder;
1321         let compiler = builder.compiler(builder.top_stage, run.host);
1322
1323         let make = |mode: Mode, krate: &CargoCrate| {
1324             let test_kind = if builder.kind == Kind::Test {
1325                 TestKind::Test
1326             } else if builder.kind == Kind::Bench {
1327                 TestKind::Bench
1328             } else {
1329                 panic!("unexpected builder.kind in crate: {:?}", builder.kind);
1330             };
1331
1332             builder.ensure(Crate {
1333                 compiler,
1334                 target: run.target,
1335                 mode,
1336                 test_kind,
1337                 krate: krate.name,
1338             });
1339         };
1340
1341         for krate in builder.in_tree_crates("std") {
1342             if run.path.ends_with(&krate.local_path(&builder)) {
1343                 make(Mode::Libstd, krate);
1344             }
1345         }
1346         for krate in builder.in_tree_crates("test") {
1347             if run.path.ends_with(&krate.local_path(&builder)) {
1348                 make(Mode::Libtest, krate);
1349             }
1350         }
1351     }
1352
1353     /// Run all unit tests plus documentation tests for a given crate defined
1354     /// by a `Cargo.toml` (single manifest)
1355     ///
1356     /// This is what runs tests for crates like the standard library, compiler, etc.
1357     /// It essentially is the driver for running `cargo test`.
1358     ///
1359     /// Currently this runs all tests for a DAG by passing a bunch of `-p foo`
1360     /// arguments, and those arguments are discovered from `cargo metadata`.
1361     fn run(self, builder: &Builder) {
1362         let build = builder.build;
1363         let compiler = self.compiler;
1364         let target = self.target;
1365         let mode = self.mode;
1366         let test_kind = self.test_kind;
1367         let krate = self.krate;
1368
1369         builder.ensure(compile::Test { compiler, target });
1370         builder.ensure(RemoteCopyLibs { compiler, target });
1371
1372         // If we're not doing a full bootstrap but we're testing a stage2 version of
1373         // libstd, then what we're actually testing is the libstd produced in
1374         // stage1. Reflect that here by updating the compiler that we're working
1375         // with automatically.
1376         let compiler = if build.force_use_stage1(compiler, target) {
1377             builder.compiler(1, compiler.host)
1378         } else {
1379             compiler.clone()
1380         };
1381
1382         let mut cargo = builder.cargo(compiler, mode, target, test_kind.subcommand());
1383         match mode {
1384             Mode::Libstd => {
1385                 compile::std_cargo(build, &compiler, target, &mut cargo);
1386             }
1387             Mode::Libtest => {
1388                 compile::test_cargo(build, &compiler, target, &mut cargo);
1389             }
1390             Mode::Librustc => {
1391                 builder.ensure(compile::Rustc { compiler, target });
1392                 compile::rustc_cargo(build, &mut cargo);
1393             }
1394             _ => panic!("can only test libraries"),
1395         };
1396         let _folder = build.fold_output(|| {
1397             format!("{}_stage{}-{}", test_kind.subcommand(), compiler.stage, krate)
1398         });
1399         println!("{} {} stage{} ({} -> {})", test_kind, krate, compiler.stage,
1400                 &compiler.host, target);
1401
1402         // Build up the base `cargo test` command.
1403         //
1404         // Pass in some standard flags then iterate over the graph we've discovered
1405         // in `cargo metadata` with the maps above and figure out what `-p`
1406         // arguments need to get passed.
1407         if test_kind.subcommand() == "test" && !build.fail_fast {
1408             cargo.arg("--no-fail-fast");
1409         }
1410         if build.doc_tests {
1411             cargo.arg("--doc");
1412         }
1413
1414         cargo.arg("-p").arg(krate);
1415
1416         // The tests are going to run with the *target* libraries, so we need to
1417         // ensure that those libraries show up in the LD_LIBRARY_PATH equivalent.
1418         //
1419         // Note that to run the compiler we need to run with the *host* libraries,
1420         // but our wrapper scripts arrange for that to be the case anyway.
1421         let mut dylib_path = dylib_path();
1422         dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target)));
1423         cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
1424
1425         cargo.arg("--");
1426         cargo.args(&build.config.cmd.test_args());
1427
1428         if build.config.quiet_tests {
1429             cargo.arg("--quiet");
1430         }
1431
1432         let _time = util::timeit();
1433
1434         if target.contains("emscripten") {
1435             cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target)),
1436                       build.config.nodejs.as_ref().expect("nodejs not configured"));
1437         } else if target.starts_with("wasm32") {
1438             // Warn about running tests without the `wasm_syscall` feature enabled.
1439             // The javascript shim implements the syscall interface so that test
1440             // output can be correctly reported.
1441             if !build.config.wasm_syscall {
1442                 println!("Libstd was built without `wasm_syscall` feature enabled: \
1443                           test output may not be visible.");
1444             }
1445
1446             // On the wasm32-unknown-unknown target we're using LTO which is
1447             // incompatible with `-C prefer-dynamic`, so disable that here
1448             cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
1449
1450             let node = build.config.nodejs.as_ref()
1451                 .expect("nodejs not configured");
1452             let runner = format!("{} {}/src/etc/wasm32-shim.js",
1453                                  node.display(),
1454                                  build.src.display());
1455             cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target)), &runner);
1456         } else if build.remote_tested(target) {
1457             cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target)),
1458                       format!("{} run",
1459                               builder.tool_exe(Tool::RemoteTestClient).display()));
1460         }
1461         try_run(build, &mut cargo);
1462     }
1463 }
1464
1465 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1466 pub struct CrateRustdoc {
1467     host: Interned<String>,
1468     test_kind: TestKind,
1469 }
1470
1471 impl Step for CrateRustdoc {
1472     type Output = ();
1473     const DEFAULT: bool = true;
1474     const ONLY_HOSTS: bool = true;
1475
1476     fn should_run(run: ShouldRun) -> ShouldRun {
1477         run.paths(&["src/librustdoc", "src/tools/rustdoc"])
1478     }
1479
1480     fn make_run(run: RunConfig) {
1481         let builder = run.builder;
1482
1483         let test_kind = if builder.kind == Kind::Test {
1484             TestKind::Test
1485         } else if builder.kind == Kind::Bench {
1486             TestKind::Bench
1487         } else {
1488             panic!("unexpected builder.kind in crate: {:?}", builder.kind);
1489         };
1490
1491         builder.ensure(CrateRustdoc {
1492             host: run.host,
1493             test_kind,
1494         });
1495     }
1496
1497     fn run(self, builder: &Builder) {
1498         let build = builder.build;
1499         let test_kind = self.test_kind;
1500
1501         let compiler = builder.compiler(builder.top_stage, self.host);
1502         let target = compiler.host;
1503
1504         let mut cargo = tool::prepare_tool_cargo(builder,
1505                                                  compiler,
1506                                                  target,
1507                                                  test_kind.subcommand(),
1508                                                  "src/tools/rustdoc");
1509         let _folder = build.fold_output(|| {
1510             format!("{}_stage{}-rustdoc", test_kind.subcommand(), compiler.stage)
1511         });
1512         println!("{} rustdoc stage{} ({} -> {})", test_kind, compiler.stage,
1513                 &compiler.host, target);
1514
1515         if test_kind.subcommand() == "test" && !build.fail_fast {
1516             cargo.arg("--no-fail-fast");
1517         }
1518
1519         cargo.arg("-p").arg("rustdoc:0.0.0");
1520
1521         cargo.arg("--");
1522         cargo.args(&build.config.cmd.test_args());
1523
1524         if build.config.quiet_tests {
1525             cargo.arg("--quiet");
1526         }
1527
1528         let _time = util::timeit();
1529
1530         try_run(build, &mut cargo);
1531     }
1532 }
1533
1534 fn envify(s: &str) -> String {
1535     s.chars().map(|c| {
1536         match c {
1537             '-' => '_',
1538             c => c,
1539         }
1540     }).flat_map(|c| c.to_uppercase()).collect()
1541 }
1542
1543 /// Some test suites are run inside emulators or on remote devices, and most
1544 /// of our test binaries are linked dynamically which means we need to ship
1545 /// the standard library and such to the emulator ahead of time. This step
1546 /// represents this and is a dependency of all test suites.
1547 ///
1548 /// Most of the time this is a noop. For some steps such as shipping data to
1549 /// QEMU we have to build our own tools so we've got conditional dependencies
1550 /// on those programs as well. Note that the remote test client is built for
1551 /// the build target (us) and the server is built for the target.
1552 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1553 pub struct RemoteCopyLibs {
1554     compiler: Compiler,
1555     target: Interned<String>,
1556 }
1557
1558 impl Step for RemoteCopyLibs {
1559     type Output = ();
1560
1561     fn should_run(run: ShouldRun) -> ShouldRun {
1562         run.never()
1563     }
1564
1565     fn run(self, builder: &Builder) {
1566         let build = builder.build;
1567         let compiler = self.compiler;
1568         let target = self.target;
1569         if !build.remote_tested(target) {
1570             return
1571         }
1572
1573         builder.ensure(compile::Test { compiler, target });
1574
1575         println!("REMOTE copy libs to emulator ({})", target);
1576         t!(fs::create_dir_all(build.out.join("tmp")));
1577
1578         let server = builder.ensure(tool::RemoteTestServer { compiler, target });
1579
1580         // Spawn the emulator and wait for it to come online
1581         let tool = builder.tool_exe(Tool::RemoteTestClient);
1582         let mut cmd = Command::new(&tool);
1583         cmd.arg("spawn-emulator")
1584            .arg(target)
1585            .arg(&server)
1586            .arg(build.out.join("tmp"));
1587         if let Some(rootfs) = build.qemu_rootfs(target) {
1588             cmd.arg(rootfs);
1589         }
1590         build.run(&mut cmd);
1591
1592         // Push all our dylibs to the emulator
1593         for f in t!(builder.sysroot_libdir(compiler, target).read_dir()) {
1594             let f = t!(f);
1595             let name = f.file_name().into_string().unwrap();
1596             if util::is_dylib(&name) {
1597                 build.run(Command::new(&tool)
1598                                   .arg("push")
1599                                   .arg(f.path()));
1600             }
1601         }
1602     }
1603 }
1604
1605 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1606 pub struct Distcheck;
1607
1608 impl Step for Distcheck {
1609     type Output = ();
1610     const ONLY_BUILD: bool = true;
1611
1612     fn should_run(run: ShouldRun) -> ShouldRun {
1613         run.path("distcheck")
1614     }
1615
1616     fn make_run(run: RunConfig) {
1617         run.builder.ensure(Distcheck);
1618     }
1619
1620     /// Run "distcheck", a 'make check' from a tarball
1621     fn run(self, builder: &Builder) {
1622         let build = builder.build;
1623
1624         println!("Distcheck");
1625         let dir = build.out.join("tmp").join("distcheck");
1626         let _ = fs::remove_dir_all(&dir);
1627         t!(fs::create_dir_all(&dir));
1628
1629         // Guarantee that these are built before we begin running.
1630         builder.ensure(dist::PlainSourceTarball);
1631         builder.ensure(dist::Src);
1632
1633         let mut cmd = Command::new("tar");
1634         cmd.arg("-xzf")
1635            .arg(builder.ensure(dist::PlainSourceTarball))
1636            .arg("--strip-components=1")
1637            .current_dir(&dir);
1638         build.run(&mut cmd);
1639         build.run(Command::new("./configure")
1640                          .args(&build.config.configure_args)
1641                          .arg("--enable-vendor")
1642                          .current_dir(&dir));
1643         build.run(Command::new(build_helper::make(&build.build))
1644                          .arg("check")
1645                          .current_dir(&dir));
1646
1647         // Now make sure that rust-src has all of libstd's dependencies
1648         println!("Distcheck rust-src");
1649         let dir = build.out.join("tmp").join("distcheck-src");
1650         let _ = fs::remove_dir_all(&dir);
1651         t!(fs::create_dir_all(&dir));
1652
1653         let mut cmd = Command::new("tar");
1654         cmd.arg("-xzf")
1655            .arg(builder.ensure(dist::Src))
1656            .arg("--strip-components=1")
1657            .current_dir(&dir);
1658         build.run(&mut cmd);
1659
1660         let toml = dir.join("rust-src/lib/rustlib/src/rust/src/libstd/Cargo.toml");
1661         build.run(Command::new(&build.initial_cargo)
1662                          .arg("generate-lockfile")
1663                          .arg("--manifest-path")
1664                          .arg(&toml)
1665                          .current_dir(&dir));
1666     }
1667 }
1668
1669 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1670 pub struct Bootstrap;
1671
1672 impl Step for Bootstrap {
1673     type Output = ();
1674     const DEFAULT: bool = true;
1675     const ONLY_HOSTS: bool = true;
1676     const ONLY_BUILD: bool = true;
1677
1678     /// Test the build system itself
1679     fn run(self, builder: &Builder) {
1680         let build = builder.build;
1681         let mut cmd = Command::new(&build.initial_cargo);
1682         cmd.arg("test")
1683            .current_dir(build.src.join("src/bootstrap"))
1684            .env("CARGO_TARGET_DIR", build.out.join("bootstrap"))
1685            .env("RUSTC_BOOTSTRAP", "1")
1686            .env("RUSTC", &build.initial_rustc);
1687         if !build.fail_fast {
1688             cmd.arg("--no-fail-fast");
1689         }
1690         cmd.arg("--").args(&build.config.cmd.test_args());
1691         try_run(build, &mut cmd);
1692     }
1693
1694     fn should_run(run: ShouldRun) -> ShouldRun {
1695         run.path("src/bootstrap")
1696     }
1697
1698     fn make_run(run: RunConfig) {
1699         run.builder.ensure(Bootstrap);
1700     }
1701 }