]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/check.rs
Utilize interning to allow Copy/Clone steps
[rust.git] / src / bootstrap / check.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::collections::HashSet;
17 use std::env;
18 use std::ffi::OsString;
19 use std::iter;
20 use std::fmt;
21 use std::fs::{self, File};
22 use std::path::{PathBuf, Path};
23 use std::process::Command;
24 use std::io::Read;
25
26 use build_helper::{self, output};
27
28 use {Build, Mode};
29 use dist;
30 use util::{self, dylib_path, dylib_path_var};
31
32 use compile;
33 use native;
34 use builder::{Kind, Builder, Compiler, Step};
35 use tool::{self, Tool};
36 use cache::{INTERNER, Interned};
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) {
69     if !build.fail_fast {
70         if !build.try_run(cmd) {
71             let failures = build.delayed_failures.get();
72             build.delayed_failures.set(failures + 1);
73         }
74     } else {
75         build.run(cmd);
76     }
77 }
78
79 fn try_run_quiet(build: &Build, cmd: &mut Command) {
80     if !build.fail_fast {
81         if !build.try_run_quiet(cmd) {
82             let failures = build.delayed_failures.get();
83             build.delayed_failures.set(failures + 1);
84         }
85     } else {
86         build.run_quiet(cmd);
87     }
88 }
89
90 // rules.test("check-linkchecker", "src/tools/linkchecker")
91 //      .dep(|s| s.name("tool-linkchecker").stage(0))
92 //      .dep(|s| s.name("default:doc"))
93 //      .default(build.config.docs)
94 //      .host(true)
95 //      .run(move |s| check::linkcheck(build, s.target));
96
97 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
98 pub struct Linkcheck {
99     host: Interned<String>,
100 }
101
102 impl Step for Linkcheck {
103     type Output = ();
104     const ONLY_HOSTS: bool = true;
105     const DEFAULT: bool = true;
106
107     /// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler.
108     ///
109     /// This tool in `src/tools` will verify the validity of all our links in the
110     /// documentation to ensure we don't have a bunch of dead ones.
111     fn run(self, builder: &Builder) {
112         let build = builder.build;
113         let host = self.host;
114
115         println!("Linkcheck ({})", host);
116
117         builder.default_doc(None);
118
119         let _time = util::timeit();
120         try_run(build, builder.tool_cmd(Tool::Linkchecker)
121                             .arg(build.out.join(host).join("doc")));
122     }
123
124     fn should_run(_builder: &Builder, path: &Path) -> bool {
125         path.ends_with("src/tools/linkchecker")
126     }
127
128     fn make_run(
129         builder: &Builder,
130         path: Option<&Path>,
131         host: Interned<String>,
132         _target: Interned<String>,
133     ) {
134         if path.is_some() {
135             builder.ensure(Linkcheck { host });
136         } else {
137             if builder.build.config.docs {
138                 builder.ensure(Linkcheck { host });
139             }
140         }
141     }
142 }
143
144 // rules.test("check-cargotest", "src/tools/cargotest")
145 //      .dep(|s| s.name("tool-cargotest").stage(0))
146 //      .dep(|s| s.name("librustc"))
147 //      .host(true)
148 //      .run(move |s| check::cargotest(build, s.stage, s.target));
149
150 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
151 pub struct Cargotest {
152     stage: u32,
153     host: Interned<String>,
154 }
155
156 impl Step for Cargotest {
157     type Output = ();
158     const ONLY_HOSTS: bool = true;
159
160     fn should_run(_builder: &Builder, path: &Path) -> bool {
161         path.ends_with("src/tools/cargotest")
162     }
163
164     fn make_run(
165         builder: &Builder,
166         _path: Option<&Path>,
167         host: Interned<String>,
168         _target: Interned<String>,
169     ) {
170         builder.ensure(Cargotest {
171             stage: builder.top_stage,
172             host: host,
173         });
174     }
175
176     /// Runs the `cargotest` tool as compiled in `stage` by the `host` compiler.
177     ///
178     /// This tool in `src/tools` will check out a few Rust projects and run `cargo
179     /// test` to ensure that we don't regress the test suites there.
180     fn run(self, builder: &Builder) {
181         let build = builder.build;
182         let compiler = builder.compiler(self.stage, self.host);
183         builder.ensure(compile::Rustc { compiler, target: compiler.host });
184
185         // Note that this is a short, cryptic, and not scoped directory name. This
186         // is currently to minimize the length of path on Windows where we otherwise
187         // quickly run into path name limit constraints.
188         let out_dir = build.out.join("ct");
189         t!(fs::create_dir_all(&out_dir));
190
191         let _time = util::timeit();
192         let mut cmd = builder.tool_cmd(Tool::CargoTest);
193         try_run(build, cmd.arg(&build.initial_cargo)
194                           .arg(&out_dir)
195                           .env("RUSTC", builder.rustc(compiler))
196                           .env("RUSTDOC", builder.rustdoc(compiler)));
197     }
198 }
199
200 //rules.test("check-cargo", "cargo")
201 //     .dep(|s| s.name("tool-cargo"))
202 //     .host(true)
203 //     .run(move |s| check::cargo(build, s.stage, s.target));
204
205 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
206 pub struct Cargo {
207     stage: u32,
208     host: Interned<String>,
209 }
210
211 impl Step for Cargo {
212     type Output = ();
213     const ONLY_HOSTS: bool = true;
214
215     fn should_run(_builder: &Builder, path: &Path) -> bool {
216         path.ends_with("src/tools/cargo")
217     }
218
219     fn make_run(
220         builder: &Builder,
221         _path: Option<&Path>,
222         _host: Interned<String>,
223         target: Interned<String>,
224     ) {
225         builder.ensure(Cargotest {
226             stage: builder.top_stage,
227             host: target,
228         });
229     }
230
231     /// Runs `cargo test` for `cargo` packaged with Rust.
232     fn run(self, builder: &Builder) {
233         let build = builder.build;
234         let compiler = builder.compiler(self.stage, self.host);
235
236         // Configure PATH to find the right rustc. NB. we have to use PATH
237         // and not RUSTC because the Cargo test suite has tests that will
238         // fail if rustc is not spelled `rustc`.
239         let path = builder.sysroot(compiler).join("bin");
240         let old_path = env::var_os("PATH").unwrap_or_default();
241         let newpath = env::join_paths(
242             iter::once(path).chain(env::split_paths(&old_path))
243         ).expect("");
244
245         let mut cargo = builder.cargo(compiler, Mode::Tool, self.host, "test");
246         cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml"));
247         if !build.fail_fast {
248             cargo.arg("--no-fail-fast");
249         }
250
251         let compiler = &Compiler::new(stage, host);
252
253         let mut cargo = build.cargo(compiler, Mode::Tool, host, "test");
254         cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml"));
255         if !build.fail_fast {
256             cargo.arg("--no-fail-fast");
257         }
258
259         // Don't build tests dynamically, just a pain to work with
260         cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
261
262         // Don't run cross-compile tests, we may not have cross-compiled libstd libs
263         // available.
264         cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
265
266         try_run(build, cargo.env("PATH", &path_for_cargo(build, compiler)));
267     }
268 }
269
270 #[derive(Serialize)]
271 pub struct Rls<'a> {
272     stage: u32,
273     host: &'a str,
274 }
275
276 impl<'a> Step<'a> for Rls<'a> {
277     type Output = ();
278
279     /// Runs `cargo test` for the rls.
280     fn run(self, builder: &Builder) {
281         let build = builder.build;
282         let stage = self.stage;
283         let host = self.host;
284         let compiler = &Compiler::new(stage, host);
285
286         let mut cargo = build.cargo(compiler, Mode::Tool, host, "test");
287         cargo.arg("--manifest-path").arg(build.src.join("src/tools/rls/Cargo.toml"));
288
289         // Don't build tests dynamically, just a pain to work with
290         cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
291
292         build.add_rustc_lib_path(compiler, &mut cargo);
293
294         try_run(build, &mut cargo);
295     }
296 }
297
298 fn path_for_cargo(build: &Build, compiler: &Compiler) -> OsString {
299     // Configure PATH to find the right rustc. NB. we have to use PATH
300     // and not RUSTC because the Cargo test suite has tests that will
301     // fail if rustc is not spelled `rustc`.
302     let path = build.sysroot(compiler).join("bin");
303     let old_path = env::var_os("PATH").unwrap_or_default();
304     env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
305 ||||||| parent of adabe3889e... Move code into Step trait implementations.
306     try_run(build, cargo.env("PATH", newpath));
307 =======
308         try_run(build, cargo.env("PATH", newpath));
309     }
310 >>>>>>> adabe3889e... Move code into Step trait implementations.
311 }
312
313 //rules.test("check-tidy", "src/tools/tidy")
314 //     .dep(|s| s.name("tool-tidy").stage(0))
315 //     .default(true)
316 //     .host(true)
317 //     .only_build(true)
318 //     .run(move |s| check::tidy(build, s.target));
319
320 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
321 pub struct Tidy {
322     host: Interned<String>,
323 }
324
325 impl Step for Tidy {
326     type Output = ();
327     const DEFAULT: bool = true;
328     const ONLY_HOSTS: bool = true;
329     const ONLY_BUILD: bool = true;
330
331     /// Runs the `tidy` tool as compiled in `stage` by the `host` compiler.
332     ///
333     /// This tool in `src/tools` checks up on various bits and pieces of style and
334     /// otherwise just implements a few lint-like checks that are specific to the
335     /// compiler itself.
336     fn run(self, builder: &Builder) {
337         let build = builder.build;
338         let host = self.host;
339
340         let _folder = build.fold_output(|| "tidy");
341         println!("tidy check ({})", host);
342         let mut cmd = builder.tool_cmd(Tool::Tidy);
343         cmd.arg(build.src.join("src"));
344         if !build.config.vendor {
345             cmd.arg("--no-vendor");
346         }
347         if build.config.quiet_tests {
348             cmd.arg("--quiet");
349         }
350         try_run(build, &mut cmd);
351     }
352
353     fn should_run(_builder: &Builder, path: &Path) -> bool {
354         path.ends_with("src/tools/tidy")
355     }
356
357     fn make_run(
358         builder: &Builder,
359         _path: Option<&Path>,
360         _host: Interned<String>,
361         _target: Interned<String>,
362     ) {
363         builder.ensure(Tidy {
364             host: builder.build.build,
365         });
366     }
367 }
368
369 fn testdir(build: &Build, host: Interned<String>) -> PathBuf {
370     build.out.join(host).join("test")
371 }
372
373 //    // ========================================================================
374 //    // Test targets
375 //    //
376 //    // Various unit tests and tests suites we can run
377 //    {
378 //        let mut suite = |name, path, mode, dir| {
379 //            rules.test(name, path)
380 //                 .dep(|s| s.name("libtest"))
381 //                 .dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
382 //                 .dep(|s| s.name("test-helpers"))
383 //                 .dep(|s| s.name("remote-copy-libs"))
384 //                 .default(mode != "pretty") // pretty tests don't run everywhere
385 //                 .run(move |s| {
386 //                     check::compiletest(build, &s.compiler(), s.target, mode, dir)
387 //                 });
388 //        };
389 //
390 //        suite("check-ui", "src/test/ui", "ui", "ui");
391 //        suite("check-rpass", "src/test/run-pass", "run-pass", "run-pass");
392 //        suite("check-cfail", "src/test/compile-fail", "compile-fail", "compile-fail");
393 //        suite("check-pfail", "src/test/parse-fail", "parse-fail", "parse-fail");
394 //        suite("check-rfail", "src/test/run-fail", "run-fail", "run-fail");
395 //        suite("check-rpass-valgrind", "src/test/run-pass-valgrind",
396 //              "run-pass-valgrind", "run-pass-valgrind");
397 //        suite("check-mir-opt", "src/test/mir-opt", "mir-opt", "mir-opt");
398 //        if build.config.codegen_tests {
399 //            suite("check-codegen", "src/test/codegen", "codegen", "codegen");
400 //        }
401 //        suite("check-codegen-units", "src/test/codegen-units", "codegen-units",
402 //              "codegen-units");
403 //        suite("check-incremental", "src/test/incremental", "incremental",
404 //              "incremental");
405 //    }
406 //
407 //    if build.build.contains("msvc") {
408 //        // nothing to do for debuginfo tests
409 //    } else {
410 //        rules.test("check-debuginfo-lldb", "src/test/debuginfo-lldb")
411 //             .dep(|s| s.name("libtest"))
412 //             .dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
413 //             .dep(|s| s.name("test-helpers"))
414 //             .dep(|s| s.name("debugger-scripts"))
415 //             .run(move |s| check::compiletest(build, &s.compiler(), s.target,
416 //                                         "debuginfo-lldb", "debuginfo"));
417 //        rules.test("check-debuginfo-gdb", "src/test/debuginfo-gdb")
418 //             .dep(|s| s.name("libtest"))
419 //             .dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
420 //             .dep(|s| s.name("test-helpers"))
421 //             .dep(|s| s.name("debugger-scripts"))
422 //             .dep(|s| s.name("remote-copy-libs"))
423 //             .run(move |s| check::compiletest(build, &s.compiler(), s.target,
424 //                                         "debuginfo-gdb", "debuginfo"));
425 //        let mut rule = rules.test("check-debuginfo", "src/test/debuginfo");
426 //        rule.default(true);
427 //        if build.build.contains("apple") {
428 //            rule.dep(|s| s.name("check-debuginfo-lldb"));
429 //        } else {
430 //            rule.dep(|s| s.name("check-debuginfo-gdb"));
431 //        }
432 //    }
433 //
434 //
435 //
436 //    {
437 //        let mut suite = |name, path, mode, dir| {
438 //            rules.test(name, path)
439 //                 .dep(|s| s.name("librustc"))
440 //                 .dep(|s| s.name("test-helpers"))
441 //                 .dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
442 //                 .default(mode != "pretty")
443 //                 .host(true)
444 //                 .run(move |s| {
445 //                     check::compiletest(build, &s.compiler(), s.target, mode, dir)
446 //                 });
447 //        };
448 //
449 //        suite("check-ui-full", "src/test/ui-fulldeps", "ui", "ui-fulldeps");
450 //        suite("check-rpass-full", "src/test/run-pass-fulldeps",
451 //              "run-pass", "run-pass-fulldeps");
452 //        suite("check-rfail-full", "src/test/run-fail-fulldeps",
453 //              "run-fail", "run-fail-fulldeps");
454 //        suite("check-cfail-full", "src/test/compile-fail-fulldeps",
455 //              "compile-fail", "compile-fail-fulldeps");
456 //        suite("check-rmake", "src/test/run-make", "run-make", "run-make");
457 //        suite("check-rustdoc", "src/test/rustdoc", "rustdoc", "rustdoc");
458 //        suite("check-pretty", "src/test/pretty", "pretty", "pretty");
459 //        suite("check-pretty-rpass", "src/test/run-pass/pretty", "pretty",
460 //              "run-pass");
461 //        suite("check-pretty-rfail", "src/test/run-fail/pretty", "pretty",
462 //              "run-fail");
463 //        suite("check-pretty-valgrind", "src/test/run-pass-valgrind/pretty", "pretty",
464 //              "run-pass-valgrind");
465 //        suite("check-pretty-rpass-full", "src/test/run-pass-fulldeps/pretty",
466 //              "pretty", "run-pass-fulldeps");
467 //        suite("check-pretty-rfail-full", "src/test/run-fail-fulldeps/pretty",
468 //              "pretty", "run-fail-fulldeps");
469 //    }
470
471 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
472 pub struct Compiletest {
473     compiler: Compiler,
474     target: Interned<String>,
475     mode: &'static str,
476     suite: &'static str,
477 }
478
479 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
480 struct Test {
481     path: &'static str,
482     mode: &'static str,
483     suite: &'static str,
484 }
485
486 static DEFAULT_COMPILETESTS: &[Test] = &[
487     Test { path: "src/test/ui", mode: "ui", suite: "ui" },
488     Test { path: "src/test/run-pass", mode: "run-pass", suite: "run-pass" },
489     Test { path: "src/test/compile-fail", mode: "compile-fail", suite: "compile-fail" },
490     Test { path: "src/test/parse-fail", mode: "parse-fail", suite: "parse-fail" },
491     Test { path: "src/test/run-fail", mode: "run-fail", suite: "run-fail" },
492     Test {
493         path: "src/test/run-pass-valgrind",
494         mode: "run-pass-valgrind",
495         suite: "run-pass-valgrind"
496     },
497     Test { path: "src/test/mir-opt", mode: "mir-opt", suite: "mir-opt" },
498     Test { path: "src/test/codegen", mode: "codegen", suite: "codegen" },
499     Test { path: "src/test/codegen-units", mode: "codegen-units", suite: "codegen-units" },
500     Test { path: "src/test/incremental", mode: "incremental", suite: "incremental" },
501
502     // What this runs varies depending on the native platform being apple
503     Test { path: "src/test/debuginfo", mode: "debuginfo-XXX", suite: "debuginfo" },
504 ];
505
506 // Also default, but host-only.
507 static HOST_COMPILETESTS: &[Test] = &[
508     Test { path: "src/test/ui-fulldeps", mode: "ui", suite: "ui-fulldeps" },
509     Test { path: "src/test/run-pass-fulldeps", mode: "run-pass", suite: "run-pass-fulldeps" },
510     Test { path: "src/test/run-fail-fulldeps", mode: "run-fail", suite: "run-fail-fulldeps" },
511     Test {
512         path: "src/test/compile-fail-fulldeps",
513         mode: "compile-fail",
514         suite: "compile-fail-fulldeps",
515     },
516     Test { path: "src/test/run-make", mode: "run-make", suite: "run-make" },
517     Test { path: "src/test/rustdoc", mode: "rustdoc", suite: "rustdoc" },
518
519     Test { path: "src/test/pretty", mode: "pretty", suite: "pretty" },
520     Test { path: "src/test/run-pass/pretty", mode: "pretty", suite: "run-pass" },
521     Test { path: "src/test/run-fail/pretty", mode: "pretty", suite: "run-fail" },
522     Test { path: "src/test/run-pass-valgrind/pretty", mode: "pretty", suite: "run-pass-valgrind" },
523     Test { path: "src/test/run-pass-fulldeps/pretty", mode: "pretty", suite: "run-pass-fulldeps" },
524     Test { path: "src/test/run-fail-fulldeps/pretty", mode: "pretty", suite: "run-fail-fulldeps" },
525 ];
526
527 static COMPILETESTS: &[Test] = &[
528     Test { path: "src/test/debuginfo-lldb", mode: "debuginfo-lldb", suite: "debuginfo" },
529     Test { path: "src/test/debuginfo-gdb", mode: "debuginfo-gdb", suite: "debuginfo" },
530 ];
531
532 impl Step for Compiletest {
533     type Output = ();
534     const DEFAULT: bool = true;
535
536     fn should_run(_builder: &Builder, path: &Path) -> bool {
537         // Note that this is general, while a few more cases are skipped inside
538         // run() itself. This is to avoid duplication across should_run and
539         // make_run.
540         COMPILETESTS.iter().chain(DEFAULT_COMPILETESTS).chain(HOST_COMPILETESTS).any(|&test| {
541             path.ends_with(test.path)
542         })
543     }
544
545     fn make_run(
546         builder: &Builder,
547         path: Option<&Path>,
548         host: Interned<String>,
549         target: Interned<String>,
550     ) {
551         let compiler = builder.compiler(builder.top_stage, host);
552
553         let test = path.map(|path| {
554             COMPILETESTS.iter().chain(DEFAULT_COMPILETESTS).chain(HOST_COMPILETESTS).find(|&&test| {
555                 path.ends_with(test.path)
556             }).unwrap_or_else(|| {
557                 panic!("make_run in compile test to receive test path, received {:?}", path);
558             })
559         });
560
561         if let Some(test) = test { // specific test
562             let target = if HOST_COMPILETESTS.contains(test) {
563                 host
564             } else {
565                 target
566             };
567             builder.ensure(Compiletest {
568                 compiler, target, mode: test.mode, suite: test.suite
569             });
570         } else { // default tests
571             for test in DEFAULT_COMPILETESTS {
572                 builder.ensure(Compiletest {
573                     compiler,
574                     target,
575                     mode: test.mode,
576                     suite: test.suite
577                 });
578             }
579             for test in HOST_COMPILETESTS {
580                 if test.mode != "pretty" {
581                     builder.ensure(Compiletest {
582                         compiler,
583                         target: host,
584                         mode: test.mode,
585                         suite: test.suite
586                     });
587                 }
588             }
589         }
590     }
591
592     /// Executes the `compiletest` tool to run a suite of tests.
593     ///
594     /// Compiles all tests with `compiler` for `target` with the specified
595     /// compiletest `mode` and `suite` arguments. For example `mode` can be
596     /// "run-pass" or `suite` can be something like `debuginfo`.
597     fn run(self, builder: &Builder) {
598         let build = builder.build;
599         let compiler = self.compiler;
600         let target = self.target;
601         let mode = self.mode;
602         let suite = self.suite;
603
604         // Skip codegen tests if they aren't enabled in configuration.
605         if !build.config.codegen_tests && suite == "codegen" {
606             return;
607         }
608
609         if suite == "debuginfo" {
610             if mode == "debuginfo-XXX" {
611                 return if build.build.contains("apple") {
612                     builder.ensure(Compiletest {
613                         mode: "debuginfo-lldb",
614                         ..self
615                     });
616                 } else {
617                     builder.ensure(Compiletest {
618                         mode: "debuginfo-gdb",
619                         ..self
620                     });
621                 };
622             }
623
624             // Skip debuginfo tests on MSVC
625             if build.build.contains("msvc") {
626                 return;
627             }
628
629             builder.ensure(dist::DebuggerScripts {
630                 sysroot: builder.sysroot(compiler),
631                 target: target
632             });
633
634             if mode == "debuginfo-gdb" {
635                 builder.ensure(RemoteCopyLibs { compiler, target });
636             }
637         }
638
639         if suite.ends_with("fulldeps") ||
640             // FIXME: Does pretty need librustc compiled? Note that there are
641             // fulldeps test suites with mode = pretty as well.
642             mode == "pretty" ||
643             mode == "rustdoc" ||
644             mode == "run-make" {
645             builder.ensure(compile::Rustc { compiler, target });
646         }
647
648         builder.ensure(compile::Test { compiler, target });
649         builder.ensure(native::TestHelpers { target });
650         builder.ensure(RemoteCopyLibs { compiler, target });
651
652         let _folder = build.fold_output(|| format!("test_{}", suite));
653         println!("Check compiletest suite={} mode={} ({} -> {})",
654                  suite, mode, &compiler.host, target);
655         let mut cmd = builder.tool_cmd(Tool::Compiletest);
656
657         // compiletest currently has... a lot of arguments, so let's just pass all
658         // of them!
659
660         cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(compiler));
661         cmd.arg("--run-lib-path").arg(builder.sysroot_libdir(compiler, target));
662         cmd.arg("--rustc-path").arg(builder.rustc(compiler));
663         cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler));
664         cmd.arg("--src-base").arg(build.src.join("src/test").join(suite));
665         cmd.arg("--build-base").arg(testdir(build, compiler.host).join(suite));
666         cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target));
667         cmd.arg("--mode").arg(mode);
668         cmd.arg("--target").arg(target);
669         cmd.arg("--host").arg(&*compiler.host);
670         cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(build.build));
671
672         if let Some(ref nodejs) = build.config.nodejs {
673             cmd.arg("--nodejs").arg(nodejs);
674         }
675
676         let mut flags = vec!["-Crpath".to_string()];
677         if build.config.rust_optimize_tests {
678             flags.push("-O".to_string());
679         }
680         if build.config.rust_debuginfo_tests {
681             flags.push("-g".to_string());
682         }
683
684         let mut hostflags = build.rustc_flags(compiler.host);
685         hostflags.extend(flags.clone());
686         cmd.arg("--host-rustcflags").arg(hostflags.join(" "));
687
688         let mut targetflags = build.rustc_flags(target);
689         targetflags.extend(flags);
690         targetflags.push(format!("-Lnative={}",
691                                  build.test_helpers_out(target).display()));
692         cmd.arg("--target-rustcflags").arg(targetflags.join(" "));
693
694         cmd.arg("--docck-python").arg(build.python());
695
696         if build.build.ends_with("apple-darwin") {
697             // Force /usr/bin/python on macOS for LLDB tests because we're loading the
698             // LLDB plugin's compiled module which only works with the system python
699             // (namely not Homebrew-installed python)
700             cmd.arg("--lldb-python").arg("/usr/bin/python");
701         } else {
702             cmd.arg("--lldb-python").arg(build.python());
703         }
704
705         if let Some(ref gdb) = build.config.gdb {
706             cmd.arg("--gdb").arg(gdb);
707         }
708         if let Some(ref vers) = build.lldb_version {
709             cmd.arg("--lldb-version").arg(vers);
710         }
711         if let Some(ref dir) = build.lldb_python_dir {
712             cmd.arg("--lldb-python-dir").arg(dir);
713         }
714         let llvm_config = build.llvm_config(target);
715         let llvm_version = output(Command::new(&llvm_config).arg("--version"));
716         cmd.arg("--llvm-version").arg(llvm_version);
717         if !build.is_rust_llvm(target) {
718             cmd.arg("--system-llvm");
719         }
720
721         cmd.args(&build.flags.cmd.test_args());
722
723         if build.is_verbose() {
724             cmd.arg("--verbose");
725         }
726
727         if build.config.quiet_tests {
728             cmd.arg("--quiet");
729         }
730
731         // Only pass correct values for these flags for the `run-make` suite as it
732         // requires that a C++ compiler was configured which isn't always the case.
733         if suite == "run-make" {
734             let llvm_components = output(Command::new(&llvm_config).arg("--components"));
735             let llvm_cxxflags = output(Command::new(&llvm_config).arg("--cxxflags"));
736             cmd.arg("--cc").arg(build.cc(target))
737                .arg("--cxx").arg(build.cxx(target).unwrap())
738                .arg("--cflags").arg(build.cflags(target).join(" "))
739                .arg("--llvm-components").arg(llvm_components.trim())
740                .arg("--llvm-cxxflags").arg(llvm_cxxflags.trim());
741         } else {
742             cmd.arg("--cc").arg("")
743                .arg("--cxx").arg("")
744                .arg("--cflags").arg("")
745                .arg("--llvm-components").arg("")
746                .arg("--llvm-cxxflags").arg("");
747         }
748
749         if build.remote_tested(target) {
750             cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
751         }
752
753         // Running a C compiler on MSVC requires a few env vars to be set, to be
754         // sure to set them here.
755         //
756         // Note that if we encounter `PATH` we make sure to append to our own `PATH`
757         // rather than stomp over it.
758         if target.contains("msvc") {
759             for &(ref k, ref v) in build.cc[&target].0.env() {
760                 if k != "PATH" {
761                     cmd.env(k, v);
762                 }
763             }
764         }
765         cmd.env("RUSTC_BOOTSTRAP", "1");
766         build.add_rust_test_threads(&mut cmd);
767
768         if build.config.sanitizers {
769             cmd.env("SANITIZER_SUPPORT", "1");
770         }
771
772         if build.config.profiler {
773             cmd.env("PROFILER_SUPPORT", "1");
774         }
775
776         cmd.arg("--adb-path").arg("adb");
777         cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
778         if target.contains("android") {
779             // Assume that cc for this target comes from the android sysroot
780             cmd.arg("--android-cross-path")
781                .arg(build.cc(target).parent().unwrap().parent().unwrap());
782         } else {
783             cmd.arg("--android-cross-path").arg("");
784         }
785
786         build.ci_env.force_coloring_in_ci(&mut cmd);
787
788         let _time = util::timeit();
789         try_run(build, &mut cmd);
790     }
791 }
792
793 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
794 pub struct Docs {
795     compiler: Compiler,
796 }
797
798 // rules.test("check-docs", "src/doc")
799 //     .dep(|s| s.name("libtest"))
800 //     .default(true)
801 //     .host(true)
802 //     .run(move |s| check::docs(build, &s.compiler()));
803 impl Step for Docs {
804     type Output = ();
805     const DEFAULT: bool = true;
806     const ONLY_HOSTS: bool = true;
807
808     fn should_run(_builder: &Builder, path: &Path) -> bool {
809         path.ends_with("src/doc")
810     }
811
812     fn make_run(
813         builder: &Builder,
814         _path: Option<&Path>,
815         host: Interned<String>,
816         _target: Interned<String>,
817     ) {
818         builder.ensure(Docs {
819             compiler: builder.compiler(builder.top_stage, host),
820         });
821     }
822
823     /// Run `rustdoc --test` for all documentation in `src/doc`.
824     ///
825     /// This will run all tests in our markdown documentation (e.g. the book)
826     /// located in `src/doc`. The `rustdoc` that's run is the one that sits next to
827     /// `compiler`.
828     fn run(self, builder: &Builder) {
829         let build = builder.build;
830         let compiler = self.compiler;
831
832         builder.ensure(compile::Test { compiler, target: compiler.host });
833
834         // Do a breadth-first traversal of the `src/doc` directory and just run
835         // tests for all files that end in `*.md`
836         let mut stack = vec![build.src.join("src/doc")];
837         let _time = util::timeit();
838         let _folder = build.fold_output(|| "test_docs");
839
840         while let Some(p) = stack.pop() {
841             if p.is_dir() {
842                 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
843                 continue
844             }
845
846             if p.extension().and_then(|s| s.to_str()) != Some("md") {
847                 continue;
848             }
849
850             // The nostarch directory in the book is for no starch, and so isn't
851             // guaranteed to build. We don't care if it doesn't build, so skip it.
852             if p.to_str().map_or(false, |p| p.contains("nostarch")) {
853                 continue;
854             }
855
856             markdown_test(builder, compiler, &p);
857         }
858     }
859 }
860
861 //rules.test("check-error-index", "src/tools/error_index_generator")
862 //     .dep(|s| s.name("libstd"))
863 //     .dep(|s| s.name("tool-error-index").host(s.host).stage(0))
864 //     .default(true)
865 //     .host(true)
866 //     .run(move |s| check::error_index(build, &s.compiler()));
867
868 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
869 pub struct ErrorIndex {
870     compiler: Compiler,
871 }
872
873 impl Step for ErrorIndex {
874     type Output = ();
875     const DEFAULT: bool = true;
876     const ONLY_HOSTS: bool = true;
877
878     fn should_run(_builder: &Builder, path: &Path) -> bool {
879         path.ends_with("src/tools/error_index_generator")
880     }
881
882     fn make_run(
883         builder: &Builder,
884         _path: Option<&Path>,
885         host: Interned<String>,
886         _target: Interned<String>,
887     ) {
888         builder.ensure(ErrorIndex {
889             compiler: builder.compiler(builder.top_stage, host),
890         });
891     }
892
893     /// Run the error index generator tool to execute the tests located in the error
894     /// index.
895     ///
896     /// The `error_index_generator` tool lives in `src/tools` and is used to
897     /// generate a markdown file from the error indexes of the code base which is
898     /// then passed to `rustdoc --test`.
899     fn run(self, builder: &Builder) {
900         let build = builder.build;
901         let compiler = self.compiler;
902
903         builder.ensure(compile::Std { compiler, target: compiler.host });
904
905         let _folder = build.fold_output(|| "test_error_index");
906         println!("Testing error-index stage{}", compiler.stage);
907
908         let dir = testdir(build, compiler.host);
909         t!(fs::create_dir_all(&dir));
910         let output = dir.join("error-index.md");
911
912         let _time = util::timeit();
913         build.run(builder.tool_cmd(Tool::ErrorIndex)
914                     .arg("markdown")
915                     .arg(&output)
916                     .env("CFG_BUILD", &build.build));
917
918         markdown_test(builder, compiler, &output);
919     }
920 }
921
922 fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) {
923     let build = builder.build;
924     let mut file = t!(File::open(markdown));
925     let mut contents = String::new();
926     t!(file.read_to_string(&mut contents));
927     if !contents.contains("```") {
928         return;
929     }
930
931     println!("doc tests for: {}", markdown.display());
932     let mut cmd = Command::new(builder.rustdoc(compiler));
933     builder.add_rustc_lib_path(compiler, &mut cmd);
934     build.add_rust_test_threads(&mut cmd);
935     cmd.arg("--test");
936     cmd.arg(markdown);
937     cmd.env("RUSTC_BOOTSTRAP", "1");
938
939     let test_args = build.flags.cmd.test_args().join(" ");
940     cmd.arg("--test-args").arg(test_args);
941
942     if build.config.quiet_tests {
943         try_run_quiet(build, &mut cmd);
944     } else {
945         try_run(build, &mut cmd);
946     }
947 }
948
949 //    for (krate, path, _default) in krates("rustc-main") {
950 //        rules.test(&krate.test_step, path)
951 //             .dep(|s| s.name("librustc"))
952 //             .dep(|s| s.name("remote-copy-libs"))
953 //             .host(true)
954 //             .run(move |s| check::krate(build, &s.compiler(), s.target,
955 //                                        Mode::Librustc, TestKind::Test,
956 //                                        Some(&krate.name)));
957 //    }
958 //    rules.test("check-rustc-all", "path/to/nowhere")
959 //         .dep(|s| s.name("librustc"))
960 //         .dep(|s| s.name("remote-copy-libs"))
961 //         .default(true)
962 //         .host(true)
963 //         .run(move |s| check::krate(build, &s.compiler(), s.target,
964 //                                    Mode::Librustc, TestKind::Test, None));
965 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
966 pub struct KrateLibrustc {
967     compiler: Compiler,
968     target: Interned<String>,
969     test_kind: TestKind,
970     krate: Option<Interned<String>>,
971 }
972
973 impl Step for KrateLibrustc {
974     type Output = ();
975     const DEFAULT: bool = true;
976     const ONLY_HOSTS: bool = true;
977
978     fn should_run(builder: &Builder, path: &Path) -> bool {
979         builder.crates("rustc-main").into_iter().any(|(_, krate_path)| {
980             path.ends_with(krate_path)
981         })
982     }
983
984     fn make_run(
985         builder: &Builder,
986         path: Option<&Path>,
987         host: Interned<String>,
988         target: Interned<String>,
989     ) {
990         let compiler = builder.compiler(builder.top_stage, host);
991
992         let run = |name: Option<Interned<String>>| {
993             let test_kind = if builder.kind == Kind::Test {
994                 TestKind::Test
995             } else if builder.kind == Kind::Bench {
996                 TestKind::Bench
997             } else {
998                 panic!("unexpected builder.kind in Krate: {:?}", builder.kind);
999             };
1000
1001             builder.ensure(KrateLibrustc {
1002                 compiler,
1003                 target,
1004                 test_kind: test_kind,
1005                 krate: name,
1006             });
1007         };
1008
1009         if let Some(path) = path {
1010             for (name, krate_path) in builder.crates("rustc-main") {
1011                 if path.ends_with(krate_path) {
1012                     run(Some(name));
1013                 }
1014             }
1015         } else {
1016             run(None);
1017         }
1018     }
1019
1020
1021     fn run(self, builder: &Builder) {
1022         builder.ensure(Krate {
1023             compiler: self.compiler,
1024             target: self.target,
1025             mode: Mode::Librustc,
1026             test_kind: self.test_kind,
1027             krate: self.krate,
1028         });
1029     }
1030 }
1031
1032
1033 //    for (krate, path, _default) in krates("std") {
1034 //        rules.test(&krate.test_step, path)
1035 //             .dep(|s| s.name("libtest"))
1036 //             .dep(|s| s.name("remote-copy-libs"))
1037 //             .run(move |s| check::krate(build, &s.compiler(), s.target,
1038 //                                        Mode::Libstd, TestKind::Test,
1039 //                                        Some(&krate.name)));
1040 //    }
1041 //    rules.test("check-std-all", "path/to/nowhere")
1042 //         .dep(|s| s.name("libtest"))
1043 //         .dep(|s| s.name("remote-copy-libs"))
1044 //         .default(true)
1045 //         .run(move |s| check::krate(build, &s.compiler(), s.target,
1046 //                                    Mode::Libstd, TestKind::Test, None));
1047 //
1048 //    // std benchmarks
1049 //    for (krate, path, _default) in krates("std") {
1050 //        rules.bench(&krate.bench_step, path)
1051 //             .dep(|s| s.name("libtest"))
1052 //             .dep(|s| s.name("remote-copy-libs"))
1053 //             .run(move |s| check::krate(build, &s.compiler(), s.target,
1054 //                                        Mode::Libstd, TestKind::Bench,
1055 //                                        Some(&krate.name)));
1056 //    }
1057 //    rules.bench("bench-std-all", "path/to/nowhere")
1058 //         .dep(|s| s.name("libtest"))
1059 //         .dep(|s| s.name("remote-copy-libs"))
1060 //         .default(true)
1061 //         .run(move |s| check::krate(build, &s.compiler(), s.target,
1062 //                                    Mode::Libstd, TestKind::Bench, None));
1063 //
1064 //    for (krate, path, _default) in krates("test") {
1065 //        rules.test(&krate.test_step, path)
1066 //             .dep(|s| s.name("libtest"))
1067 //             .dep(|s| s.name("remote-copy-libs"))
1068 //             .run(move |s| check::krate(build, &s.compiler(), s.target,
1069 //                                        Mode::Libtest, TestKind::Test,
1070 //                                        Some(&krate.name)));
1071 //    }
1072 //    rules.test("check-test-all", "path/to/nowhere")
1073 //         .dep(|s| s.name("libtest"))
1074 //         .dep(|s| s.name("remote-copy-libs"))
1075 //         .default(true)
1076 //         .run(move |s| check::krate(build, &s.compiler(), s.target,
1077 //                                    Mode::Libtest, TestKind::Test, None));
1078
1079 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1080 pub struct Krate {
1081     compiler: Compiler,
1082     target: Interned<String>,
1083     mode: Mode,
1084     test_kind: TestKind,
1085     krate: Option<Interned<String>>,
1086 }
1087
1088 impl Step for Krate {
1089     type Output = ();
1090     const DEFAULT: bool = true;
1091
1092     fn should_run(builder: &Builder, path: &Path) -> bool {
1093         builder.crates("std").into_iter().any(|(_, krate_path)| {
1094             path.ends_with(krate_path)
1095         }) ||
1096         builder.crates("test").into_iter().any(|(_, krate_path)| {
1097             path.ends_with(krate_path)
1098         })
1099     }
1100
1101     fn make_run(
1102         builder: &Builder,
1103         path: Option<&Path>,
1104         host: Interned<String>,
1105         target: Interned<String>,
1106     ) {
1107         let compiler = builder.compiler(builder.top_stage, host);
1108
1109         let run = |mode: Mode, name: Option<Interned<String>>| {
1110             let test_kind = if builder.kind == Kind::Test {
1111                 TestKind::Test
1112             } else if builder.kind == Kind::Bench {
1113                 TestKind::Bench
1114             } else {
1115                 panic!("unexpected builder.kind in Krate: {:?}", builder.kind);
1116             };
1117
1118             builder.ensure(Krate {
1119                 compiler, target,
1120                 mode: mode,
1121                 test_kind: test_kind,
1122                 krate: name,
1123             });
1124         };
1125
1126         if let Some(path) = path {
1127             for (name, krate_path) in builder.crates("std") {
1128                 if path.ends_with(krate_path) {
1129                     run(Mode::Libstd, Some(name));
1130                 }
1131             }
1132             for (name, krate_path) in builder.crates("test") {
1133                 if path.ends_with(krate_path) {
1134                     run(Mode::Libtest, Some(name));
1135                 }
1136             }
1137         } else {
1138             run(Mode::Libstd, None);
1139             run(Mode::Libtest, None);
1140         }
1141     }
1142
1143     /// Run all unit tests plus documentation tests for an entire crate DAG defined
1144     /// by a `Cargo.toml`
1145     ///
1146     /// This is what runs tests for crates like the standard library, compiler, etc.
1147     /// It essentially is the driver for running `cargo test`.
1148     ///
1149     /// Currently this runs all tests for a DAG by passing a bunch of `-p foo`
1150     /// arguments, and those arguments are discovered from `cargo metadata`.
1151     fn run(self, builder: &Builder) {
1152         let build = builder.build;
1153         let compiler = self.compiler;
1154         let target = self.target;
1155         let mode = self.mode;
1156         let test_kind = self.test_kind;
1157         let krate = self.krate;
1158
1159         builder.ensure(compile::Test { compiler, target });
1160         builder.ensure(RemoteCopyLibs { compiler, target });
1161         let (name, path, features, root) = match mode {
1162             Mode::Libstd => {
1163                 ("libstd", "src/libstd", build.std_features(), "std")
1164             }
1165             Mode::Libtest => {
1166                 ("libtest", "src/libtest", String::new(), "test")
1167             }
1168             Mode::Librustc => {
1169                 builder.ensure(compile::Rustc { compiler, target });
1170                 ("librustc", "src/rustc", build.rustc_features(), "rustc-main")
1171             }
1172             _ => panic!("can only test libraries"),
1173         };
1174         let root = INTERNER.intern_string(String::from(root));
1175         let _folder = build.fold_output(|| {
1176             format!("{}_stage{}-{}", test_kind.subcommand(), compiler.stage, name)
1177         });
1178         println!("{} {} stage{} ({} -> {})", test_kind, name, compiler.stage,
1179                 &compiler.host, target);
1180
1181         // If we're not doing a full bootstrap but we're testing a stage2 version of
1182         // libstd, then what we're actually testing is the libstd produced in
1183         // stage1. Reflect that here by updating the compiler that we're working
1184         // with automatically.
1185         let compiler = if build.force_use_stage1(compiler, target) {
1186             builder.compiler(1, compiler.host)
1187         } else {
1188             compiler.clone()
1189         };
1190
1191         // Build up the base `cargo test` command.
1192         //
1193         // Pass in some standard flags then iterate over the graph we've discovered
1194         // in `cargo metadata` with the maps above and figure out what `-p`
1195         // arguments need to get passed.
1196         let mut cargo = builder.cargo(compiler, mode, target, test_kind.subcommand());
1197         cargo.arg("--manifest-path")
1198             .arg(build.src.join(path).join("Cargo.toml"))
1199             .arg("--features").arg(features);
1200         if test_kind.subcommand() == "test" && !build.fail_fast {
1201             cargo.arg("--no-fail-fast");
1202         }
1203
1204         match krate {
1205             Some(krate) => {
1206                 cargo.arg("-p").arg(krate);
1207             }
1208             None => {
1209                 let mut visited = HashSet::new();
1210                 let mut next = vec![root];
1211                 while let Some(name) = next.pop() {
1212                     // Right now jemalloc is our only target-specific crate in the
1213                     // sense that it's not present on all platforms. Custom skip it
1214                     // here for now, but if we add more this probably wants to get
1215                     // more generalized.
1216                     //
1217                     // Also skip `build_helper` as it's not compiled normally for
1218                     // target during the bootstrap and it's just meant to be a
1219                     // helper crate, not tested. If it leaks through then it ends up
1220                     // messing with various mtime calculations and such.
1221                     if !name.contains("jemalloc") && *name != *"build_helper" {
1222                         cargo.arg("-p").arg(&format!("{}:0.0.0", name));
1223                     }
1224                     for dep in build.crates[&name].deps.iter() {
1225                         if visited.insert(dep) {
1226                             next.push(*dep);
1227                         }
1228                     }
1229                 }
1230             }
1231         }
1232
1233         // The tests are going to run with the *target* libraries, so we need to
1234         // ensure that those libraries show up in the LD_LIBRARY_PATH equivalent.
1235         //
1236         // Note that to run the compiler we need to run with the *host* libraries,
1237         // but our wrapper scripts arrange for that to be the case anyway.
1238         let mut dylib_path = dylib_path();
1239         dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target)));
1240         cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
1241
1242         if target.contains("emscripten") || build.remote_tested(target) {
1243             cargo.arg("--no-run");
1244         }
1245
1246         cargo.arg("--");
1247
1248         if build.config.quiet_tests {
1249             cargo.arg("--quiet");
1250         }
1251
1252         let _time = util::timeit();
1253
1254         if target.contains("emscripten") {
1255             build.run(&mut cargo);
1256             krate_emscripten(build, compiler, target, mode);
1257         } else if build.remote_tested(target) {
1258             build.run(&mut cargo);
1259             krate_remote(builder, compiler, target, mode);
1260         } else {
1261             cargo.args(&build.flags.cmd.test_args());
1262             try_run(build, &mut cargo);
1263         }
1264     }
1265 }
1266
1267 fn krate_emscripten(build: &Build,
1268                     compiler: Compiler,
1269                     target: Interned<String>,
1270                     mode: Mode) {
1271     let out_dir = build.cargo_out(compiler, mode, target);
1272     let tests = find_tests(&out_dir.join("deps"), target);
1273
1274     let nodejs = build.config.nodejs.as_ref().expect("nodejs not configured");
1275     for test in tests {
1276         println!("running {}", test.display());
1277         let mut cmd = Command::new(nodejs);
1278         cmd.arg(&test);
1279         if build.config.quiet_tests {
1280             cmd.arg("--quiet");
1281         }
1282         try_run(build, &mut cmd);
1283     }
1284 }
1285
1286 fn krate_remote(builder: &Builder,
1287                 compiler: Compiler,
1288                 target: Interned<String>,
1289                 mode: Mode) {
1290     let build = builder.build;
1291     let out_dir = build.cargo_out(compiler, mode, target);
1292     let tests = find_tests(&out_dir.join("deps"), target);
1293
1294     let tool = builder.tool_exe(Tool::RemoteTestClient);
1295     for test in tests {
1296         let mut cmd = Command::new(&tool);
1297         cmd.arg("run")
1298            .arg(&test);
1299         if build.config.quiet_tests {
1300             cmd.arg("--quiet");
1301         }
1302         cmd.args(&build.flags.cmd.test_args());
1303         try_run(build, &mut cmd);
1304     }
1305 }
1306
1307 fn find_tests(dir: &Path, target: Interned<String>) -> Vec<PathBuf> {
1308     let mut dst = Vec::new();
1309     for e in t!(dir.read_dir()).map(|e| t!(e)) {
1310         let file_type = t!(e.file_type());
1311         if !file_type.is_file() {
1312             continue
1313         }
1314         let filename = e.file_name().into_string().unwrap();
1315         if (target.contains("windows") && filename.ends_with(".exe")) ||
1316            (!target.contains("windows") && !filename.contains(".")) ||
1317            (target.contains("emscripten") &&
1318             filename.ends_with(".js") &&
1319             !filename.ends_with(".asm.js")) {
1320             dst.push(e.path());
1321         }
1322     }
1323     dst
1324 }
1325
1326 //    rules.test("remote-copy-libs", "path/to/nowhere")
1327 //         .dep(|s| s.name("libtest"))
1328 //         .dep(move |s| {
1329 //             if build.remote_tested(s.target) {
1330 //                s.name("tool-remote-test-client").target(s.host).stage(0)
1331 //             } else {
1332 //                 Step::noop()
1333 //             }
1334 //         })
1335 //         .dep(move |s| {
1336 //             if build.remote_tested(s.target) {
1337 //                s.name("tool-remote-test-server")
1338 //             } else {
1339 //                 Step::noop()
1340 //             }
1341 //         })
1342 //         .run(move |s| check::remote_copy_libs(build, &s.compiler(), s.target));
1343 //
1344
1345 /// Some test suites are run inside emulators or on remote devices, and most
1346 /// of our test binaries are linked dynamically which means we need to ship
1347 /// the standard library and such to the emulator ahead of time. This step
1348 /// represents this and is a dependency of all test suites.
1349 ///
1350 /// Most of the time this is a noop. For some steps such as shipping data to
1351 /// QEMU we have to build our own tools so we've got conditional dependencies
1352 /// on those programs as well. Note that the remote test client is built for
1353 /// the build target (us) and the server is built for the target.
1354 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1355 pub struct RemoteCopyLibs {
1356     compiler: Compiler,
1357     target: Interned<String>,
1358 }
1359
1360 impl Step for RemoteCopyLibs {
1361     type Output = ();
1362
1363     fn run(self, builder: &Builder) {
1364         let build = builder.build;
1365         let compiler = self.compiler;
1366         let target = self.target;
1367         if !build.remote_tested(target) {
1368             return
1369         }
1370
1371         builder.ensure(compile::Test { compiler, target });
1372
1373         println!("REMOTE copy libs to emulator ({})", target);
1374         t!(fs::create_dir_all(build.out.join("tmp")));
1375
1376         let server = builder.ensure(tool::RemoteTestServer { stage: compiler.stage, target });
1377
1378         // Spawn the emulator and wait for it to come online
1379         let tool = builder.tool_exe(Tool::RemoteTestClient);
1380         let mut cmd = Command::new(&tool);
1381         cmd.arg("spawn-emulator")
1382            .arg(target)
1383            .arg(&server)
1384            .arg(build.out.join("tmp"));
1385         if let Some(rootfs) = build.qemu_rootfs(target) {
1386             cmd.arg(rootfs);
1387         }
1388         build.run(&mut cmd);
1389
1390         // Push all our dylibs to the emulator
1391         for f in t!(builder.sysroot_libdir(compiler, target).read_dir()) {
1392             let f = t!(f);
1393             let name = f.file_name().into_string().unwrap();
1394             if util::is_dylib(&name) {
1395                 build.run(Command::new(&tool)
1396                                   .arg("push")
1397                                   .arg(f.path()));
1398             }
1399         }
1400     }
1401 }
1402
1403 //rules.test("check-distcheck", "distcheck")
1404 //     .dep(|s| s.name("dist-plain-source-tarball"))
1405 //     .dep(|s| s.name("dist-src"))
1406 //     .run(move |_| check::distcheck(build));
1407
1408 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1409 pub struct Distcheck;
1410
1411 impl Step for Distcheck {
1412     type Output = ();
1413
1414     /// Run "distcheck", a 'make check' from a tarball
1415     fn run(self, builder: &Builder) {
1416         let build = builder.build;
1417
1418         if *build.build != *"x86_64-unknown-linux-gnu" {
1419             return
1420         }
1421         if !build.config.host.iter().any(|s| s == "x86_64-unknown-linux-gnu") {
1422             return
1423         }
1424         if !build.config.target.iter().any(|s| s == "x86_64-unknown-linux-gnu") {
1425             return
1426         }
1427
1428         println!("Distcheck");
1429         let dir = build.out.join("tmp").join("distcheck");
1430         let _ = fs::remove_dir_all(&dir);
1431         t!(fs::create_dir_all(&dir));
1432
1433         let mut cmd = Command::new("tar");
1434         cmd.arg("-xzf")
1435            .arg(builder.ensure(dist::PlainSourceTarball))
1436            .arg("--strip-components=1")
1437            .current_dir(&dir);
1438         build.run(&mut cmd);
1439         build.run(Command::new("./configure")
1440                          .args(&build.config.configure_args)
1441                          .arg("--enable-vendor")
1442                          .current_dir(&dir));
1443         build.run(Command::new(build_helper::make(&build.build))
1444                          .arg("check")
1445                          .current_dir(&dir));
1446
1447         // Now make sure that rust-src has all of libstd's dependencies
1448         println!("Distcheck rust-src");
1449         let dir = build.out.join("tmp").join("distcheck-src");
1450         let _ = fs::remove_dir_all(&dir);
1451         t!(fs::create_dir_all(&dir));
1452
1453         let mut cmd = Command::new("tar");
1454         cmd.arg("-xzf")
1455            .arg(builder.ensure(dist::Src))
1456            .arg("--strip-components=1")
1457            .current_dir(&dir);
1458         build.run(&mut cmd);
1459
1460         let toml = dir.join("rust-src/lib/rustlib/src/rust/src/libstd/Cargo.toml");
1461         build.run(Command::new(&build.initial_cargo)
1462                          .arg("generate-lockfile")
1463                          .arg("--manifest-path")
1464                          .arg(&toml)
1465                          .current_dir(&dir));
1466     }
1467 }
1468
1469 //rules.test("check-bootstrap", "src/bootstrap")
1470 //     .default(true)
1471 //     .host(true)
1472 //     .only_build(true)
1473 //     .run(move |_| check::bootstrap(build));
1474
1475 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1476 pub struct Bootstrap;
1477
1478 impl Step for Bootstrap {
1479     type Output = ();
1480     const DEFAULT: bool = true;
1481     const ONLY_HOSTS: bool = true;
1482     const ONLY_BUILD: bool = true;
1483
1484     /// Test the build system itself
1485     fn run(self, builder: &Builder) {
1486         let build = builder.build;
1487         let mut cmd = Command::new(&build.initial_cargo);
1488         cmd.arg("test")
1489            .current_dir(build.src.join("src/bootstrap"))
1490            .env("CARGO_TARGET_DIR", build.out.join("bootstrap"))
1491            .env("RUSTC_BOOTSTRAP", "1")
1492            .env("RUSTC", &build.initial_rustc);
1493         if !build.fail_fast {
1494             cmd.arg("--no-fail-fast");
1495         }
1496         cmd.arg("--").args(&build.flags.cmd.test_args());
1497         try_run(build, &mut cmd);
1498     }
1499
1500     fn should_run(_builder: &Builder, path: &Path) -> bool {
1501         path.ends_with("src/bootstrap")
1502     }
1503
1504     fn make_run(
1505         builder: &Builder,
1506         _path: Option<&Path>,
1507         _host: Interned<String>,
1508         _target: Interned<String>,
1509     ) {
1510         builder.ensure(Bootstrap);
1511     }
1512 }