test.rs 66.6 KB
Newer Older
1
//! Implementation of the test-related targets of the build system.
2 3 4 5
//!
//! This file implements the various regression test suites that we execute on
//! our CI.

6
use std::env;
7
use std::ffi::OsString;
U
Ulrik Sverdrup 已提交
8
use std::fmt;
9
use std::fs;
S
Santiago Pastorino 已提交
10 11 12
use std::iter;
use std::path::{Path, PathBuf};
use std::process::Command;
13

14
use build_helper::{self, output, t};
15

L
ljedrz 已提交
16 17 18 19 20 21 22 23 24 25 26
use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
use crate::cache::{Interned, INTERNER};
use crate::compile;
use crate::dist;
use crate::flags::Subcommand;
use crate::native;
use crate::tool::{self, Tool, SourceType};
use crate::toolstate::ToolState;
use crate::util::{self, dylib_path, dylib_path_var};
use crate::Crate as CargoCrate;
use crate::{DocTests, Mode, GitRepo};
27

M
Mark Simulacrum 已提交
28
const ADB_TEST_DIR: &str = "/data/tmp/work";
29

U
Ulrik Sverdrup 已提交
30
/// The two modes of the test runner; tests or benchmarks.
K
kennytm 已提交
31
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, PartialOrd, Ord)]
U
Ulrik Sverdrup 已提交
32
pub enum TestKind {
A
Alexander Regueiro 已提交
33
    /// Run `cargo test`.
U
Ulrik Sverdrup 已提交
34
    Test,
A
Alexander Regueiro 已提交
35
    /// Run `cargo bench`.
U
Ulrik Sverdrup 已提交
36 37 38
    Bench,
}

39 40 41 42 43
impl From<Kind> for TestKind {
    fn from(kind: Kind) -> Self {
        match kind {
            Kind::Test => TestKind::Test,
            Kind::Bench => TestKind::Bench,
S
Santiago Pastorino 已提交
44
            _ => panic!("unexpected kind in crate: {:?}", kind),
45 46 47 48
        }
    }
}

U
Ulrik Sverdrup 已提交
49 50 51 52 53 54 55 56 57 58 59
impl TestKind {
    // Return the cargo subcommand for this test kind
    fn subcommand(self) -> &'static str {
        match self {
            TestKind::Test => "test",
            TestKind::Bench => "bench",
        }
    }
}

impl fmt::Display for TestKind {
T
Taiki Endo 已提交
60
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
U
Ulrik Sverdrup 已提交
61 62 63 64 65 66 67
        f.write_str(match *self {
            TestKind::Test => "Testing",
            TestKind::Bench => "Benchmarking",
        })
    }
}

T
Taiki Endo 已提交
68
fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool {
69 70 71
    if !builder.fail_fast {
        if !builder.try_run(cmd) {
            let mut failures = builder.delayed_failures.borrow_mut();
72
            failures.push(format!("{:?}", cmd));
O
Oliver Schneider 已提交
73
            return false;
74 75
        }
    } else {
76
        builder.run(cmd);
77
    }
O
Oliver Schneider 已提交
78
    true
79 80
}

T
Taiki Endo 已提交
81
fn try_run_quiet(builder: &Builder<'_>, cmd: &mut Command) -> bool {
82 83 84
    if !builder.fail_fast {
        if !builder.try_run_quiet(cmd) {
            let mut failures = builder.delayed_failures.borrow_mut();
85
            failures.push(format!("{:?}", cmd));
86
            return false;
87 88
        }
    } else {
89
        builder.run_quiet(cmd);
90
    }
91
    true
92 93
}

94 95 96
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Linkcheck {
    host: Interned<String>,
97 98
}

99
impl Step for Linkcheck {
100
    type Output = ();
101 102
    const ONLY_HOSTS: bool = true;
    const DEFAULT: bool = true;
103 104 105 106 107

    /// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler.
    ///
    /// This tool in `src/tools` will verify the validity of all our links in the
    /// documentation to ensure we don't have a bunch of dead ones.
T
Taiki Endo 已提交
108
    fn run(self, builder: &Builder<'_>) {
109 110
        let host = self.host;

111
        builder.info(&format!("Linkcheck ({})", host));
112 113

        builder.default_doc(None);
114

115
        let _time = util::timeit(&builder);
S
Santiago Pastorino 已提交
116 117 118 119 120 121
        try_run(
            builder,
            builder
                .tool_cmd(Tool::Linkchecker)
                .arg(builder.out.join(host).join("doc")),
        );
122
    }
123

T
Taiki Endo 已提交
124
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
125
        let builder = run.builder;
S
Santiago Pastorino 已提交
126 127
        run.path("src/tools/linkchecker")
            .default_condition(builder.config.docs)
128 129
    }

T
Taiki Endo 已提交
130
    fn make_run(run: RunConfig<'_>) {
131
        run.builder.ensure(Linkcheck { host: run.target });
132
    }
133
}
134

135 136
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Cargotest {
137
    stage: u32,
138
    host: Interned<String>,
139
}
140

141
impl Step for Cargotest {
142
    type Output = ();
143
    const ONLY_HOSTS: bool = true;
144

T
Taiki Endo 已提交
145
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
146
        run.path("src/tools/cargotest")
147 148
    }

T
Taiki Endo 已提交
149
    fn make_run(run: RunConfig<'_>) {
150 151
        run.builder.ensure(Cargotest {
            stage: run.builder.top_stage,
152
            host: run.target,
153 154 155
        });
    }

156 157 158 159
    /// Runs the `cargotest` tool as compiled in `stage` by the `host` compiler.
    ///
    /// This tool in `src/tools` will check out a few Rust projects and run `cargo
    /// test` to ensure that we don't regress the test suites there.
T
Taiki Endo 已提交
160
    fn run(self, builder: &Builder<'_>) {
161
        let compiler = builder.compiler(self.stage, self.host);
S
Santiago Pastorino 已提交
162 163 164 165
        builder.ensure(compile::Rustc {
            compiler,
            target: compiler.host,
        });
166 167 168 169

        // Note that this is a short, cryptic, and not scoped directory name. This
        // is currently to minimize the length of path on Windows where we otherwise
        // quickly run into path name limit constraints.
170
        let out_dir = builder.out.join("ct");
171 172
        t!(fs::create_dir_all(&out_dir));

173
        let _time = util::timeit(&builder);
174
        let mut cmd = builder.tool_cmd(Tool::CargoTest);
S
Santiago Pastorino 已提交
175 176 177 178 179
        try_run(
            builder,
            cmd.arg(&builder.initial_cargo)
                .arg(&out_dir)
                .env("RUSTC", builder.rustc(compiler))
M
Mark Rousskov 已提交
180
                .env("RUSTDOC", builder.rustdoc(compiler)),
S
Santiago Pastorino 已提交
181
        );
182
    }
183 184
}

185 186
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Cargo {
187
    stage: u32,
188
    host: Interned<String>,
189 190
}

191
impl Step for Cargo {
192
    type Output = ();
193 194
    const ONLY_HOSTS: bool = true;

T
Taiki Endo 已提交
195
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
196
        run.path("src/tools/cargo")
197 198
    }

T
Taiki Endo 已提交
199
    fn make_run(run: RunConfig<'_>) {
200 201 202
        run.builder.ensure(Cargo {
            stage: run.builder.top_stage,
            host: run.target,
203 204
        });
    }
205 206

    /// Runs `cargo test` for `cargo` packaged with Rust.
T
Taiki Endo 已提交
207
    fn run(self, builder: &Builder<'_>) {
208
        let compiler = builder.compiler(self.stage, self.host);
209

S
Santiago Pastorino 已提交
210 211 212 213
        builder.ensure(tool::Cargo {
            compiler,
            target: self.host,
        });
214 215 216 217 218 219
        let mut cargo = tool::prepare_tool_cargo(builder,
                                                 compiler,
                                                 Mode::ToolRustc,
                                                 self.host,
                                                 "test",
                                                 "src/tools/cargo",
220 221
                                                 SourceType::Submodule,
                                                 &[]);
222

223
        if !builder.fail_fast {
224 225
            cargo.arg("--no-fail-fast");
        }
226

227 228 229
        // Don't run cross-compile tests, we may not have cross-compiled libstd libs
        // available.
        cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
230 231
        // Disable a test that has issues with mingw.
        cargo.env("CARGO_TEST_DISABLE_GIT_CLI", "1");
232 233 234
        // Forcibly disable tests using nightly features since any changes to
        // those features won't be able to land.
        cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
235

S
Santiago Pastorino 已提交
236 237 238 239
        try_run(
            builder,
            cargo.env("PATH", &path_for_cargo(builder, compiler)),
        );
240
    }
N
Nick Cameron 已提交
241 242
}

M
Mark Simulacrum 已提交
243 244
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Rls {
245
    stage: u32,
M
Mark Simulacrum 已提交
246
    host: Interned<String>,
247
}
N
Nick Cameron 已提交
248

M
Mark Simulacrum 已提交
249
impl Step for Rls {
250
    type Output = ();
M
Mark Simulacrum 已提交
251 252
    const ONLY_HOSTS: bool = true;

T
Taiki Endo 已提交
253
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
254
        run.path("src/tools/rls")
M
Mark Simulacrum 已提交
255 256
    }

T
Taiki Endo 已提交
257
    fn make_run(run: RunConfig<'_>) {
258 259 260
        run.builder.ensure(Rls {
            stage: run.builder.top_stage,
            host: run.target,
M
Mark Simulacrum 已提交
261 262
        });
    }
N
Nick Cameron 已提交
263

264
    /// Runs `cargo test` for the rls.
T
Taiki Endo 已提交
265
    fn run(self, builder: &Builder<'_>) {
266 267
        let stage = self.stage;
        let host = self.host;
M
Mark Simulacrum 已提交
268
        let compiler = builder.compiler(stage, host);
N
Nick Cameron 已提交
269

270 271 272 273 274 275 276 277 278 279
        let build_result = builder.ensure(tool::Rls {
            compiler,
            target: self.host,
            extra_features: Vec::new(),
        });
        if build_result.is_none() {
            eprintln!("failed to test rls: could not build");
            return;
        }

C
Collins Abitekaniza 已提交
280 281
        let mut cargo = tool::prepare_tool_cargo(builder,
                                                 compiler,
282
                                                 Mode::ToolRustc,
C
Collins Abitekaniza 已提交
283 284
                                                 host,
                                                 "test",
285
                                                 "src/tools/rls",
286 287
                                                 SourceType::Submodule,
                                                 &[]);
N
Nick Cameron 已提交
288

M
Mark Simulacrum 已提交
289
        builder.add_rustc_lib_path(compiler, &mut cargo);
A
Alex Crichton 已提交
290 291
        cargo.arg("--")
            .args(builder.config.cmd.test_args());
292

293 294
        if try_run(builder, &mut cargo) {
            builder.save_toolstate("rls", ToolState::TestPass);
O
Oliver Schneider 已提交
295
        }
296
    }
N
Nick Cameron 已提交
297 298
}

N
Nick Cameron 已提交
299 300 301 302 303 304 305 306 307 308
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Rustfmt {
    stage: u32,
    host: Interned<String>,
}

impl Step for Rustfmt {
    type Output = ();
    const ONLY_HOSTS: bool = true;

T
Taiki Endo 已提交
309
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
N
Nick Cameron 已提交
310 311 312
        run.path("src/tools/rustfmt")
    }

T
Taiki Endo 已提交
313
    fn make_run(run: RunConfig<'_>) {
N
Nick Cameron 已提交
314 315 316 317 318 319 320
        run.builder.ensure(Rustfmt {
            stage: run.builder.top_stage,
            host: run.target,
        });
    }

    /// Runs `cargo test` for rustfmt.
T
Taiki Endo 已提交
321
    fn run(self, builder: &Builder<'_>) {
N
Nick Cameron 已提交
322 323 324 325
        let stage = self.stage;
        let host = self.host;
        let compiler = builder.compiler(stage, host);

326 327 328 329 330 331 332 333 334 335
        let build_result = builder.ensure(tool::Rustfmt {
            compiler,
            target: self.host,
            extra_features: Vec::new(),
        });
        if build_result.is_none() {
            eprintln!("failed to test rustfmt: could not build");
            return;
        }

C
Collins Abitekaniza 已提交
336 337
        let mut cargo = tool::prepare_tool_cargo(builder,
                                                 compiler,
338
                                                 Mode::ToolRustc,
C
Collins Abitekaniza 已提交
339 340
                                                 host,
                                                 "test",
341
                                                 "src/tools/rustfmt",
342 343
                                                 SourceType::Submodule,
                                                 &[]);
N
Nick Cameron 已提交
344

N
Nick Cameron 已提交
345 346 347
        let dir = testdir(builder, compiler.host);
        t!(fs::create_dir_all(&dir));
        cargo.env("RUSTFMT_TEST_DIR", dir);
N
Nick Cameron 已提交
348 349 350

        builder.add_rustc_lib_path(compiler, &mut cargo);

351 352
        if try_run(builder, &mut cargo) {
            builder.save_toolstate("rustfmt", ToolState::TestPass);
O
Oliver Schneider 已提交
353
        }
N
Nick Cameron 已提交
354 355
    }
}
O
Oliver Schneider 已提交
356 357

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
358
pub struct Miri {
O
Oliver Schneider 已提交
359
    stage: u32,
360 361 362 363 364 365 366
    host: Interned<String>,
}

impl Step for Miri {
    type Output = ();
    const ONLY_HOSTS: bool = true;

T
Taiki Endo 已提交
367
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
R
Ralf Jung 已提交
368
        run.path("src/tools/miri")
369 370
    }

T
Taiki Endo 已提交
371
    fn make_run(run: RunConfig<'_>) {
372
        run.builder.ensure(Miri {
O
Oliver Schneider 已提交
373
            stage: run.builder.top_stage,
374 375 376 377 378
            host: run.target,
        });
    }

    /// Runs `cargo test` for miri.
T
Taiki Endo 已提交
379
    fn run(self, builder: &Builder<'_>) {
O
Oliver Schneider 已提交
380
        let stage = self.stage;
381
        let host = self.host;
O
Oliver Schneider 已提交
382
        let compiler = builder.compiler(stage, host);
383

384 385 386 387 388 389
        let miri = builder.ensure(tool::Miri {
            compiler,
            target: self.host,
            extra_features: Vec::new(),
        });
        if let Some(miri) = miri {
390
            // # Run `cargo miri setup`.
R
Ralf Jung 已提交
391
            // As a side-effect, this will install xargo.
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
            let mut cargo = tool::prepare_tool_cargo(
                builder,
                compiler,
                Mode::ToolRustc,
                host,
                "run",
                "src/tools/miri",
                SourceType::Submodule,
                &[],
            );
            cargo
                .arg("--bin")
                .arg("cargo-miri")
                .arg("--")
                .arg("miri")
                .arg("setup");

            // Tell `cargo miri` not to worry about the sysroot mismatch (we built with
            // stage1 but run with stage2).
            cargo.env("MIRI_SKIP_SYSROOT_CHECK", "1");
            // Tell `cargo miri setup` where to find the sources.
            cargo.env("XARGO_RUST_SRC", builder.src.join("src"));
            // Make sure the libstd gets built without debug assertions.
            cargo.env("RUSTC_DEBUG_ASSERTIONS", "false");
416 417
            // Debug things.
            cargo.env("RUST_BACKTRACE", "1");
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433

            if !try_run(builder, &mut cargo) {
                return;
            }

            // # Determine where Miri put its sysroot.
            // To this end, we run `cargo miri setup --env` and capture the output.
            // (We do this separately from the above so that when the setup actually
            // happens we get some output.)
            // We re-use the `cargo` from above.
            cargo.arg("--env");

            // FIXME: Is there a way in which we can re-use the usual `run` helpers?
            let miri_sysroot = if builder.config.dry_run {
                String::new()
            } else {
434
                builder.verbose(&format!("running: {:?}", cargo));
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
                let out = cargo.output()
                    .expect("We already ran `cargo miri setup` before and that worked");
                assert!(out.status.success(), "`cargo miri setup` returned with non-0 exit code");
                // Output is "MIRI_SYSROOT=<str>\n".
                let stdout = String::from_utf8(out.stdout)
                    .expect("`cargo miri setup` stdout is not valid UTF-8");
                let stdout = stdout.trim();
                builder.verbose(&format!("`cargo miri setup --env` returned: {:?}", stdout));
                let sysroot = stdout.splitn(2, '=')
                    .nth(1).expect("`cargo miri setup` stdout did not contain '='");
                sysroot.to_owned()
            };

            // # Run `cargo test`.
            let mut cargo = tool::prepare_tool_cargo(
                builder,
                compiler,
                Mode::ToolRustc,
                host,
                "test",
                "src/tools/miri",
                SourceType::Submodule,
                &[],
            );
O
Oliver Schneider 已提交
459 460

            // miri tests need to know about the stage sysroot
461
            cargo.env("MIRI_SYSROOT", miri_sysroot);
O
Oliver Schneider 已提交
462 463 464 465 466 467
            cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler));
            cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
            cargo.env("MIRI_PATH", miri);

            builder.add_rustc_lib_path(compiler, &mut cargo);

468 469
            if !try_run(builder, &mut cargo) {
                return;
O
Oliver Schneider 已提交
470
            }
471 472 473

            // # Done!
            builder.save_toolstate("miri", ToolState::TestPass);
O
Oliver Schneider 已提交
474 475 476
        } else {
            eprintln!("failed to test miri: could not build");
        }
477 478 479
    }
}

480 481 482 483 484 485 486 487
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct CompiletestTest {
    host: Interned<String>,
}

impl Step for CompiletestTest {
    type Output = ();

T
Taiki Endo 已提交
488
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
489 490 491
        run.path("src/tools/compiletest")
    }

T
Taiki Endo 已提交
492
    fn make_run(run: RunConfig<'_>) {
493 494 495 496 497 498
        run.builder.ensure(CompiletestTest {
            host: run.target,
        });
    }

    /// Runs `cargo test` for compiletest.
T
Taiki Endo 已提交
499
    fn run(self, builder: &Builder<'_>) {
500
        let host = self.host;
501
        let compiler = builder.compiler(0, host);
502 503 504 505 506 507 508 509 510 511 512 513 514 515

        let mut cargo = tool::prepare_tool_cargo(builder,
                                                 compiler,
                                                 Mode::ToolBootstrap,
                                                 host,
                                                 "test",
                                                 "src/tools/compiletest",
                                                 SourceType::InTree,
                                                 &[]);

        try_run(builder, &mut cargo);
    }
}

516 517
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Clippy {
O
Oliver Schneider 已提交
518
    stage: u32,
519 520 521 522 523 524 525 526
    host: Interned<String>,
}

impl Step for Clippy {
    type Output = ();
    const ONLY_HOSTS: bool = true;
    const DEFAULT: bool = false;

T
Taiki Endo 已提交
527
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
528 529 530
        run.path("src/tools/clippy")
    }

T
Taiki Endo 已提交
531
    fn make_run(run: RunConfig<'_>) {
532
        run.builder.ensure(Clippy {
O
Oliver Schneider 已提交
533
            stage: run.builder.top_stage,
534 535 536 537 538
            host: run.target,
        });
    }

    /// Runs `cargo test` for clippy.
T
Taiki Endo 已提交
539
    fn run(self, builder: &Builder<'_>) {
O
Oliver Schneider 已提交
540
        let stage = self.stage;
541
        let host = self.host;
O
Oliver Schneider 已提交
542
        let compiler = builder.compiler(stage, host);
543

544 545 546 547 548 549
        let clippy = builder.ensure(tool::Clippy {
            compiler,
            target: self.host,
            extra_features: Vec::new(),
        });
        if let Some(clippy) = clippy {
550 551 552 553 554 555
            let mut cargo = tool::prepare_tool_cargo(builder,
                                                 compiler,
                                                 Mode::ToolRustc,
                                                 host,
                                                 "test",
                                                 "src/tools/clippy",
556 557
                                                 SourceType::Submodule,
                                                 &[]);
O
Oliver Schneider 已提交
558 559 560 561 562

            // clippy tests need to know about the stage sysroot
            cargo.env("SYSROOT", builder.sysroot(compiler));
            cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler));
            cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
S
Santiago Pastorino 已提交
563
            let host_libs = builder
C
Collins Abitekaniza 已提交
564
                .stage_out(compiler, Mode::ToolRustc)
S
Santiago Pastorino 已提交
565
                .join(builder.cargo_dir());
O
Oliver Schneider 已提交
566 567 568 569 570 571
            cargo.env("HOST_LIBS", host_libs);
            // clippy tests need to find the driver
            cargo.env("CLIPPY_DRIVER_PATH", clippy);

            builder.add_rustc_lib_path(compiler, &mut cargo);

572 573
            if try_run(builder, &mut cargo) {
                builder.save_toolstate("clippy-driver", ToolState::TestPass);
O
Oliver Schneider 已提交
574 575 576 577
            }
        } else {
            eprintln!("failed to test clippy: could not build");
        }
578 579
    }
}
N
Nick Cameron 已提交
580

T
Taiki Endo 已提交
581
fn path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
N
Nick Cameron 已提交
582 583 584
    // Configure PATH to find the right rustc. NB. we have to use PATH
    // and not RUSTC because the Cargo test suite has tests that will
    // fail if rustc is not spelled `rustc`.
M
Mark Simulacrum 已提交
585
    let path = builder.sysroot(compiler).join("bin");
N
Nick Cameron 已提交
586 587
    let old_path = env::var_os("PATH").unwrap_or_default();
    env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
588
}
589

G
Guillaume Gomez 已提交
590 591 592 593 594 595 596 597 598 599
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct RustdocTheme {
    pub compiler: Compiler,
}

impl Step for RustdocTheme {
    type Output = ();
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

T
Taiki Endo 已提交
600
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
G
Guillaume Gomez 已提交
601 602 603
        run.path("src/tools/rustdoc-themes")
    }

T
Taiki Endo 已提交
604
    fn make_run(run: RunConfig<'_>) {
G
Guillaume Gomez 已提交
605 606
        let compiler = run.builder.compiler(run.builder.top_stage, run.host);

607
        run.builder.ensure(RustdocTheme { compiler });
G
Guillaume Gomez 已提交
608 609
    }

T
Taiki Endo 已提交
610
    fn run(self, builder: &Builder<'_>) {
611
        let rustdoc = builder.out.join("bootstrap/debug/rustdoc");
G
Guillaume Gomez 已提交
612 613
        let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
        cmd.arg(rustdoc.to_str().unwrap())
S
Santiago Pastorino 已提交
614 615 616 617 618 619 620 621 622 623 624 625 626 627
            .arg(
                builder
                    .src
                    .join("src/librustdoc/html/static/themes")
                    .to_str()
                    .unwrap(),
            )
            .env("RUSTC_STAGE", self.compiler.stage.to_string())
            .env("RUSTC_SYSROOT", builder.sysroot(self.compiler))
            .env(
                "RUSTDOC_LIBDIR",
                builder.sysroot_libdir(self.compiler, self.compiler.host),
            )
            .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
M
Mark Rousskov 已提交
628
            .env("RUSTDOC_REAL", builder.rustdoc(self.compiler))
S
Santiago Pastorino 已提交
629 630
            .env("RUSTDOC_CRATE_VERSION", builder.rust_version())
            .env("RUSTC_BOOTSTRAP", "1");
631
        if let Some(linker) = builder.linker(self.compiler.host) {
G
Guillaume Gomez 已提交
632 633
            cmd.env("RUSTC_TARGET_LINKER", linker);
        }
634
        try_run(builder, &mut cmd);
G
Guillaume Gomez 已提交
635 636 637
    }
}

G
Guillaume Gomez 已提交
638
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
G
Guillaume Gomez 已提交
639
pub struct RustdocJSStd {
G
Guillaume Gomez 已提交
640
    pub host: Interned<String>,
641
    pub target: Interned<String>,
G
Guillaume Gomez 已提交
642 643
}

G
Guillaume Gomez 已提交
644
impl Step for RustdocJSStd {
645
    type Output = ();
G
Guillaume Gomez 已提交
646 647 648
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

T
Taiki Endo 已提交
649
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
G
Guillaume Gomez 已提交
650
        run.path("src/test/rustdoc-js-std")
G
Guillaume Gomez 已提交
651 652
    }

T
Taiki Endo 已提交
653
    fn make_run(run: RunConfig<'_>) {
G
Guillaume Gomez 已提交
654
        run.builder.ensure(RustdocJSStd {
G
Guillaume Gomez 已提交
655
            host: run.host,
656
            target: run.target,
G
Guillaume Gomez 已提交
657 658 659
        });
    }

T
Taiki Endo 已提交
660
    fn run(self, builder: &Builder<'_>) {
661 662
        if let Some(ref nodejs) = builder.config.nodejs {
            let mut command = Command::new(nodejs);
G
Guillaume Gomez 已提交
663
            command.args(&["src/tools/rustdoc-js-std/tester.js", &*self.host]);
L
ljedrz 已提交
664
            builder.ensure(crate::doc::Std {
665 666 667 668 669
                target: self.target,
                stage: builder.top_stage,
            });
            builder.run(&mut command);
        } else {
670
            builder.info(
G
Guillaume Gomez 已提交
671
                "No nodejs found, skipping \"src/test/rustdoc-js-std\" tests"
672
            );
673
        }
G
Guillaume Gomez 已提交
674 675 676
    }
}

G
Guillaume Gomez 已提交
677 678 679 680 681 682 683 684 685 686 687 688
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct RustdocJSNotStd {
    pub host: Interned<String>,
    pub target: Interned<String>,
    pub compiler: Compiler,
}

impl Step for RustdocJSNotStd {
    type Output = ();
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

G
Guillaume Gomez 已提交
689
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
G
Guillaume Gomez 已提交
690
        run.path("src/test/rustdoc-js")
G
Guillaume Gomez 已提交
691 692
    }

G
Guillaume Gomez 已提交
693
    fn make_run(run: RunConfig<'_>) {
G
Guillaume Gomez 已提交
694 695 696 697 698 699 700 701
        let compiler = run.builder.compiler(run.builder.top_stage, run.host);
        run.builder.ensure(RustdocJSNotStd {
            host: run.host,
            target: run.target,
            compiler,
        });
    }

G
Guillaume Gomez 已提交
702
    fn run(self, builder: &Builder<'_>) {
703 704 705
        if builder.config.nodejs.is_some() {
            builder.ensure(Compiletest {
                compiler: self.compiler,
G
Guillaume Gomez 已提交
706
                target: self.target,
707 708 709 710
                mode: "js-doc-test",
                suite: "rustdoc-js",
                path: None,
                compare_mode: None,
G
Guillaume Gomez 已提交
711 712 713
            });
        } else {
            builder.info(
G
Guillaume Gomez 已提交
714
                "No nodejs found, skipping \"src/test/rustdoc-js\" tests"
G
Guillaume Gomez 已提交
715 716 717 718 719
            );
        }
    }
}

720 721 722 723 724 725 726 727 728 729 730 731
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct RustdocUi {
    pub host: Interned<String>,
    pub target: Interned<String>,
    pub compiler: Compiler,
}

impl Step for RustdocUi {
    type Output = ();
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

T
Taiki Endo 已提交
732
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
733 734 735
        run.path("src/test/rustdoc-ui")
    }

T
Taiki Endo 已提交
736
    fn make_run(run: RunConfig<'_>) {
737 738 739 740 741 742 743 744
        let compiler = run.builder.compiler(run.builder.top_stage, run.host);
        run.builder.ensure(RustdocUi {
            host: run.host,
            target: run.target,
            compiler,
        });
    }

T
Taiki Endo 已提交
745
    fn run(self, builder: &Builder<'_>) {
746 747 748 749 750
        builder.ensure(Compiletest {
            compiler: self.compiler,
            target: self.target,
            mode: "ui",
            suite: "rustdoc-ui",
G
Guillaume Gomez 已提交
751
            path: Some("src/test/rustdoc-ui"),
752
            compare_mode: None,
753 754 755 756
        })
    }
}

757
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
M
Mark Simulacrum 已提交
758
pub struct Tidy;
759

760
impl Step for Tidy {
761
    type Output = ();
762 763
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;
764

M
Mark Simulacrum 已提交
765
    /// Runs the `tidy` tool.
766 767 768 769
    ///
    /// This tool in `src/tools` checks up on various bits and pieces of style and
    /// otherwise just implements a few lint-like checks that are specific to the
    /// compiler itself.
T
Taiki Endo 已提交
770
    fn run(self, builder: &Builder<'_>) {
771
        let mut cmd = builder.tool_cmd(Tool::Tidy);
772 773 774
        cmd.arg(builder.src.join("src"));
        cmd.arg(&builder.initial_cargo);
        if !builder.config.vendor {
775 776
            cmd.arg("--no-vendor");
        }
M
Mark Rousskov 已提交
777 778
        if builder.is_verbose() {
            cmd.arg("--verbose");
779
        }
780

781
        builder.info("tidy check");
782
        try_run(builder, &mut cmd);
783
    }
784

T
Taiki Endo 已提交
785
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
786
        run.path("src/tools/tidy")
787 788
    }

T
Taiki Endo 已提交
789
    fn make_run(run: RunConfig<'_>) {
M
Mark Simulacrum 已提交
790
        run.builder.ensure(Tidy);
791
    }
792
}
793

T
Taiki Endo 已提交
794
fn testdir(builder: &Builder<'_>, host: Interned<String>) -> PathBuf {
795
    builder.out.join(host).join("test")
796 797
}

798 799 800 801
macro_rules! default_test {
    ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr }) => {
        test!($name { path: $path, mode: $mode, suite: $suite, default: true, host: false });
    }
802 803
}

804 805 806 807 808 809 810 811
macro_rules! default_test_with_compare_mode {
    ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr,
                   compare_mode: $compare_mode:expr }) => {
        test_with_compare_mode!($name { path: $path, mode: $mode, suite: $suite, default: true,
                                        host: false, compare_mode: $compare_mode });
    }
}

812 813 814 815
macro_rules! host_test {
    ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr }) => {
        test!($name { path: $path, mode: $mode, suite: $suite, default: true, host: true });
    }
816 817
}

818
macro_rules! test {
819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834
    ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr, default: $default:expr,
                   host: $host:expr }) => {
        test_definitions!($name { path: $path, mode: $mode, suite: $suite, default: $default,
                                  host: $host, compare_mode: None });
    }
}

macro_rules! test_with_compare_mode {
    ($name:ident { path: $path:expr, mode: $mode:expr, suite: $suite:expr, default: $default:expr,
                   host: $host:expr, compare_mode: $compare_mode:expr }) => {
        test_definitions!($name { path: $path, mode: $mode, suite: $suite, default: $default,
                                  host: $host, compare_mode: Some($compare_mode) });
    }
}

macro_rules! test_definitions {
835 836 837 838 839
    ($name:ident {
        path: $path:expr,
        mode: $mode:expr,
        suite: $suite:expr,
        default: $default:expr,
840 841
        host: $host:expr,
        compare_mode: $compare_mode:expr
842 843 844 845 846
    }) => {
        #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
        pub struct $name {
            pub compiler: Compiler,
            pub target: Interned<String>,
847 848
        }

849 850 851 852
        impl Step for $name {
            type Output = ();
            const DEFAULT: bool = $default;
            const ONLY_HOSTS: bool = $host;
853

T
Taiki Endo 已提交
854
            fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
855
                run.suite_path($path)
856
            }
857

T
Taiki Endo 已提交
858
            fn make_run(run: RunConfig<'_>) {
859
                let compiler = run.builder.compiler(run.builder.top_stage, run.host);
860

861
                run.builder.ensure($name {
862
                    compiler,
863
                    target: run.target,
864 865
                });
            }
866

T
Taiki Endo 已提交
867
            fn run(self, builder: &Builder<'_>) {
868 869 870 871 872
                builder.ensure(Compiletest {
                    compiler: self.compiler,
                    target: self.target,
                    mode: $mode,
                    suite: $suite,
873
                    path: Some($path),
874
                    compare_mode: $compare_mode,
875 876 877
                })
            }
        }
878 879 880
    }
}

881
default_test_with_compare_mode!(Ui {
882 883
    path: "src/test/ui",
    mode: "ui",
884 885
    suite: "ui",
    compare_mode: "nll"
886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931
});

default_test!(CompileFail {
    path: "src/test/compile-fail",
    mode: "compile-fail",
    suite: "compile-fail"
});

default_test!(RunFail {
    path: "src/test/run-fail",
    mode: "run-fail",
    suite: "run-fail"
});

default_test!(RunPassValgrind {
    path: "src/test/run-pass-valgrind",
    mode: "run-pass-valgrind",
    suite: "run-pass-valgrind"
});

default_test!(MirOpt {
    path: "src/test/mir-opt",
    mode: "mir-opt",
    suite: "mir-opt"
});

default_test!(Codegen {
    path: "src/test/codegen",
    mode: "codegen",
    suite: "codegen"
});

default_test!(CodegenUnits {
    path: "src/test/codegen-units",
    mode: "codegen-units",
    suite: "codegen-units"
});

default_test!(Incremental {
    path: "src/test/incremental",
    mode: "incremental",
    suite: "incremental"
});

default_test!(Debuginfo {
    path: "src/test/debuginfo",
T
Tom Tromey 已提交
932
    mode: "debuginfo",
933 934 935 936 937 938 939 940 941 942 943 944 945 946 947
    suite: "debuginfo"
});

host_test!(UiFullDeps {
    path: "src/test/ui-fulldeps",
    mode: "ui",
    suite: "ui-fulldeps"
});

host_test!(Rustdoc {
    path: "src/test/rustdoc",
    mode: "rustdoc",
    suite: "rustdoc"
});

948
host_test!(Pretty {
949 950
    path: "src/test/pretty",
    mode: "pretty",
951
    suite: "pretty"
952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967
});
test!(RunFailPretty {
    path: "src/test/run-fail/pretty",
    mode: "pretty",
    suite: "run-fail",
    default: false,
    host: true
});
test!(RunPassValgrindPretty {
    path: "src/test/run-pass-valgrind/pretty",
    mode: "pretty",
    suite: "run-pass-valgrind",
    default: false,
    host: true
});

E
Eric Huss 已提交
968
default_test!(RunMake {
969 970 971 972 973
    path: "src/test/run-make",
    mode: "run-make",
    suite: "run-make"
});

974 975 976 977 978 979
host_test!(RunMakeFullDeps {
    path: "src/test/run-make-fulldeps",
    mode: "run-make",
    suite: "run-make-fulldeps"
});

D
Denys Zariaiev 已提交
980 981 982 983 984 985
default_test!(Assembly {
    path: "src/test/assembly",
    mode: "assembly",
    suite: "assembly"
});

986 987 988 989 990 991
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
struct Compiletest {
    compiler: Compiler,
    target: Interned<String>,
    mode: &'static str,
    suite: &'static str,
992
    path: Option<&'static str>,
993
    compare_mode: Option<&'static str>,
994 995 996 997 998
}

impl Step for Compiletest {
    type Output = ();

T
Taiki Endo 已提交
999
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1000 1001 1002
        run.never()
    }

1003 1004 1005 1006 1007
    /// Executes the `compiletest` tool to run a suite of tests.
    ///
    /// Compiles all tests with `compiler` for `target` with the specified
    /// compiletest `mode` and `suite` arguments. For example `mode` can be
    /// "run-pass" or `suite` can be something like `debuginfo`.
T
Taiki Endo 已提交
1008
    fn run(self, builder: &Builder<'_>) {
1009 1010 1011 1012
        let compiler = self.compiler;
        let target = self.target;
        let mode = self.mode;
        let suite = self.suite;
1013

1014 1015 1016
        // Path for test suite
        let suite_path = self.path.unwrap_or("");

1017
        // Skip codegen tests if they aren't enabled in configuration.
1018
        if !builder.config.codegen_tests && suite == "codegen" {
1019 1020 1021 1022
            return;
        }

        if suite == "debuginfo" {
1023
            let msvc = builder.config.build.contains("msvc");
T
Tom Tromey 已提交
1024 1025
            if mode == "debuginfo" {
                return builder.ensure(Compiletest {
1026
                    mode: if msvc { "debuginfo-cdb" } else { "debuginfo-gdb+lldb" },
T
Tom Tromey 已提交
1027 1028
                    ..self
                });
1029 1030 1031
            }

            builder.ensure(dist::DebuggerScripts {
1032
                sysroot: builder.sysroot(compiler),
S
Santiago Pastorino 已提交
1033
                host: target,
1034 1035 1036
            });
        }

1037
        if suite.ends_with("fulldeps") {
1038 1039 1040
            builder.ensure(compile::Rustc { compiler, target });
        }

1041 1042 1043 1044
        if builder.no_std(target) == Some(true) {
            // the `test` doesn't compile for no-std targets
            builder.ensure(compile::Std { compiler, target });
        } else {
H
Hideki Sekine 已提交
1045 1046
            builder.ensure(compile::Test { compiler, target });
        }
1047 1048

        if builder.no_std(target) == Some(true) {
1049
            // for no_std run-make (e.g., thumb*),
1050 1051 1052 1053
            // we need a host compiler which is called by cargo.
            builder.ensure(compile::Std { compiler, target: compiler.host });
        }

1054 1055
        // HACK(eddyb) ensure that `libproc_macro` is available on the host.
        builder.ensure(compile::Test { compiler, target: compiler.host });
1056 1057
        // Also provide `rust_test_helpers` for the host.
        builder.ensure(native::TestHelpers { target: compiler.host });
1058

1059 1060 1061 1062
        // wasm32 can't build the test helpers
        if !target.contains("wasm32") {
            builder.ensure(native::TestHelpers { target });
        }
1063
        builder.ensure(RemoteCopyLibs { compiler, target });
1064 1065

        let mut cmd = builder.tool_cmd(Tool::Compiletest);
1066 1067 1068 1069

        // compiletest currently has... a lot of arguments, so let's just pass all
        // of them!

S
Santiago Pastorino 已提交
1070 1071 1072 1073
        cmd.arg("--compile-lib-path")
            .arg(builder.rustc_libdir(compiler));
        cmd.arg("--run-lib-path")
            .arg(builder.sysroot_libdir(compiler, target));
1074
        cmd.arg("--rustc-path").arg(builder.rustc(compiler));
1075

1076
        let is_rustdoc = suite.ends_with("rustdoc-ui") || suite.ends_with("rustdoc-js");
G
Guillaume Gomez 已提交
1077

1078
        // Avoid depending on rustdoc when we don't need it.
S
Santiago Pastorino 已提交
1079 1080
        if mode == "rustdoc"
            || (mode == "run-make" && suite.ends_with("fulldeps"))
1081 1082
            || (mode == "ui" && is_rustdoc)
            || mode == "js-doc-test"
S
Santiago Pastorino 已提交
1083 1084
        {
            cmd.arg("--rustdoc-path")
M
Mark Rousskov 已提交
1085
                .arg(builder.rustdoc(compiler));
1086 1087
        }

S
Santiago Pastorino 已提交
1088 1089 1090 1091 1092 1093
        cmd.arg("--src-base")
            .arg(builder.src.join("src/test").join(suite));
        cmd.arg("--build-base")
            .arg(testdir(builder, compiler.host).join(suite));
        cmd.arg("--stage-id")
            .arg(format!("stage{}-{}", compiler.stage, target));
1094 1095
        cmd.arg("--mode").arg(mode);
        cmd.arg("--target").arg(target);
1096
        cmd.arg("--host").arg(&*compiler.host);
S
Santiago Pastorino 已提交
1097 1098
        cmd.arg("--llvm-filecheck")
            .arg(builder.llvm_filecheck(builder.config.build));
1099

1100
        if builder.config.cmd.bless() {
1101 1102 1103
            cmd.arg("--bless");
        }

1104 1105 1106 1107 1108 1109 1110
        let compare_mode = builder.config.cmd.compare_mode().or_else(|| {
            if builder.config.test_compare_mode {
                self.compare_mode
            } else {
                None
            }
        });
S
Santiago Pastorino 已提交
1111

1112 1113 1114 1115 1116
        if let Some(ref pass) = builder.config.cmd.pass() {
            cmd.arg("--pass");
            cmd.arg(pass);
        }

1117
        if let Some(ref nodejs) = builder.config.nodejs {
1118 1119
            cmd.arg("--nodejs").arg(nodejs);
        }
1120

1121
        let mut flags = if is_rustdoc {
G
Guillaume Gomez 已提交
1122 1123 1124 1125
            Vec::new()
        } else {
            vec!["-Crpath".to_string()]
        };
1126
        if !is_rustdoc {
1127
            if builder.config.rust_optimize_tests {
G
Guillaume Gomez 已提交
1128 1129
                flags.push("-O".to_string());
            }
1130
        }
1131
        flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests));
G
Guillaume Gomez 已提交
1132
        flags.push("-Zunstable-options".to_string());
1133
        flags.push(builder.config.cmd.rustc_args().join(" "));
1134

1135
        if let Some(linker) = builder.linker(target) {
O
Oliver Schneider 已提交
1136 1137 1138
            cmd.arg("--linker").arg(linker);
        }

1139 1140 1141 1142 1143
        let mut hostflags = flags.clone();
        hostflags.push(format!(
            "-Lnative={}",
            builder.test_helpers_out(compiler.host).display()
        ));
1144 1145
        cmd.arg("--host-rustcflags").arg(hostflags.join(" "));

S
Shotaro Yamada 已提交
1146
        let mut targetflags = flags;
S
Santiago Pastorino 已提交
1147 1148 1149 1150
        targetflags.push(format!(
            "-Lnative={}",
            builder.test_helpers_out(target).display()
        ));
1151 1152
        cmd.arg("--target-rustcflags").arg(targetflags.join(" "));

1153
        cmd.arg("--docck-python").arg(builder.python());
1154

1155
        if builder.config.build.ends_with("apple-darwin") {
1156 1157 1158 1159 1160
            // Force /usr/bin/python on macOS for LLDB tests because we're loading the
            // LLDB plugin's compiled module which only works with the system python
            // (namely not Homebrew-installed python)
            cmd.arg("--lldb-python").arg("/usr/bin/python");
        } else {
1161
            cmd.arg("--lldb-python").arg(builder.python());
1162
        }
1163

1164
        if let Some(ref gdb) = builder.config.gdb {
1165 1166
            cmd.arg("--gdb").arg(gdb);
        }
1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177

        let run = |cmd: &mut Command| {
            cmd.output().map(|output| {
                String::from_utf8_lossy(&output.stdout)
                    .lines().next().unwrap_or_else(|| {
                        panic!("{:?} failed {:?}", cmd, output)
                    }).to_string()
            })
        };
        let lldb_exe = if builder.config.lldb_enabled && !target.contains("emscripten") {
            // Test against the lldb that was just built.
1178
            builder.llvm_out(target).join("bin").join("lldb")
1179 1180 1181 1182 1183 1184 1185 1186 1187
        } else {
            PathBuf::from("lldb")
        };
        let lldb_version = Command::new(&lldb_exe)
            .arg("--version")
            .output()
            .map(|output| { String::from_utf8_lossy(&output.stdout).to_string() })
            .ok();
        if let Some(ref vers) = lldb_version {
1188
            cmd.arg("--lldb-version").arg(vers);
1189 1190 1191 1192
            let lldb_python_dir = run(Command::new(&lldb_exe).arg("-P")).ok();
            if let Some(ref dir) = lldb_python_dir {
                cmd.arg("--lldb-python-dir").arg(dir);
            }
1193
        }
1194

1195 1196 1197
        if util::forcing_clang_based_tests() {
            let clang_exe = builder.llvm_out(target).join("bin").join("clang");
            cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
1198 1199
        }

1200 1201
        // Get paths from cmd args
        let paths = match &builder.config.cmd {
S
Santiago Pastorino 已提交
1202 1203
            Subcommand::Test { ref paths, .. } => &paths[..],
            _ => &[],
1204 1205 1206
        };

        // Get test-args by striping suite path
S
Santiago Pastorino 已提交
1207 1208
        let mut test_args: Vec<&str> = paths
            .iter()
1209 1210 1211 1212 1213 1214
            .map(|p| {
                match p.strip_prefix(".") {
                    Ok(path) => path,
                    Err(_) => p,
                }
            })
1215 1216
            .filter(|p| p.starts_with(suite_path) && (p.is_dir() || p.is_file()))
            .filter_map(|p| {
V
varkor 已提交
1217 1218 1219 1220 1221 1222
                // Since test suite paths are themselves directories, if we don't
                // specify a directory or file, we'll get an empty string here
                // (the result of the test suite directory without its suite prefix).
                // Therefore, we need to filter these out, as only the first --test-args
                // flag is respected, so providing an empty --test-args conflicts with
                // any following it.
1223 1224 1225 1226 1227
                match p.strip_prefix(suite_path).ok().and_then(|p| p.to_str()) {
                    Some(s) if s != "" => Some(s),
                    _ => None,
                }
            })
S
Santiago Pastorino 已提交
1228
            .collect();
1229 1230 1231 1232

        test_args.append(&mut builder.config.cmd.test_args());

        cmd.args(&test_args);
1233

1234
        if builder.is_verbose() {
1235 1236
            cmd.arg("--verbose");
        }
1237

O
Oliver Schneider 已提交
1238
        if !builder.config.verbose_tests {
1239 1240
            cmd.arg("--quiet");
        }
1241

B
bjorn3 已提交
1242
        if builder.config.llvm_enabled() {
1243
            let llvm_config = builder.ensure(native::Llvm {
1244
                target: builder.config.build,
1245 1246
                emscripten: false,
            });
1247
            if !builder.config.dry_run {
1248 1249 1250
                let llvm_version = output(Command::new(&llvm_config).arg("--version"));
                cmd.arg("--llvm-version").arg(llvm_version);
            }
1251
            if !builder.is_rust_llvm(target) {
B
bjorn3 已提交
1252 1253 1254 1255 1256
                cmd.arg("--system-llvm");
            }

            // Only pass correct values for these flags for the `run-make` suite as it
            // requires that a C++ compiler was configured which isn't always the case.
E
Eric Huss 已提交
1257
            if !builder.config.dry_run && suite == "run-make-fulldeps" {
B
bjorn3 已提交
1258 1259
                let llvm_components = output(Command::new(&llvm_config).arg("--components"));
                let llvm_cxxflags = output(Command::new(&llvm_config).arg("--cxxflags"));
S
Santiago Pastorino 已提交
1260 1261 1262 1263 1264
                cmd.arg("--cc")
                    .arg(builder.cc(target))
                    .arg("--cxx")
                    .arg(builder.cxx(target).unwrap())
                    .arg("--cflags")
1265
                    .arg(builder.cflags(target, GitRepo::Rustc).join(" "))
S
Santiago Pastorino 已提交
1266 1267 1268 1269
                    .arg("--llvm-components")
                    .arg(llvm_components.trim())
                    .arg("--llvm-cxxflags")
                    .arg(llvm_cxxflags.trim());
1270
                if let Some(ar) = builder.ar(target) {
O
Oliver Schneider 已提交
1271 1272
                    cmd.arg("--ar").arg(ar);
                }
1273 1274 1275 1276 1277 1278 1279

                // The llvm/bin directory contains many useful cross-platform
                // tools. Pass the path to run-make tests so they can use them.
                let llvm_bin_path = llvm_config.parent()
                    .expect("Expected llvm-config to be contained in directory");
                assert!(llvm_bin_path.is_dir());
                cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294

                // If LLD is available, add it to the PATH
                if builder.config.lld_enabled {
                    let lld_install_root = builder.ensure(native::Lld {
                        target: builder.config.build,
                    });

                    let lld_bin_path = lld_install_root.join("bin");

                    let old_path = env::var_os("PATH").unwrap_or_default();
                    let new_path = env::join_paths(std::iter::once(lld_bin_path)
                        .chain(env::split_paths(&old_path)))
                        .expect("Could not add LLD bin path to PATH");
                    cmd.env("PATH", new_path);
                }
B
bjorn3 已提交
1295 1296 1297
            }
        }

E
Eric Huss 已提交
1298
        if suite != "run-make-fulldeps" {
S
Santiago Pastorino 已提交
1299 1300 1301 1302 1303 1304 1305 1306 1307 1308
            cmd.arg("--cc")
                .arg("")
                .arg("--cxx")
                .arg("")
                .arg("--cflags")
                .arg("")
                .arg("--llvm-components")
                .arg("")
                .arg("--llvm-cxxflags")
                .arg("");
1309
        }
1310

1311
        if builder.remote_tested(target) {
S
Santiago Pastorino 已提交
1312 1313
            cmd.arg("--remote-test-client")
                .arg(builder.tool_exe(Tool::RemoteTestClient));
1314
        }
1315

1316 1317 1318 1319 1320 1321
        // Running a C compiler on MSVC requires a few env vars to be set, to be
        // sure to set them here.
        //
        // Note that if we encounter `PATH` we make sure to append to our own `PATH`
        // rather than stomp over it.
        if target.contains("msvc") {
1322
            for &(ref k, ref v) in builder.cc[&target].env() {
1323 1324 1325
                if k != "PATH" {
                    cmd.env(k, v);
                }
1326 1327
            }
        }
1328
        cmd.env("RUSTC_BOOTSTRAP", "1");
1329
        builder.add_rust_test_threads(&mut cmd);
1330

1331
        if builder.config.sanitizers {
1332
            cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
1333
        }
1334

1335
        if builder.config.profiler {
1336
            cmd.env("RUSTC_PROFILER_SUPPORT", "1");
1337
        }
1338

1339
        cmd.env("RUST_TEST_TMPDIR", builder.out.join("tmp"));
1340

1341 1342 1343 1344 1345
        cmd.arg("--adb-path").arg("adb");
        cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
        if target.contains("android") {
            // Assume that cc for this target comes from the android sysroot
            cmd.arg("--android-cross-path")
S
Santiago Pastorino 已提交
1346
                .arg(builder.cc(target).parent().unwrap().parent().unwrap());
1347 1348 1349
        } else {
            cmd.arg("--android-cross-path").arg("");
        }
1350

1351 1352 1353 1354
        if builder.config.cmd.rustfix_coverage() {
            cmd.arg("--rustfix-coverage");
        }

1355
        builder.ci_env.force_coloring_in_ci(&mut cmd);
1356

S
Santiago Pastorino 已提交
1357 1358 1359 1360
        builder.info(&format!(
            "Check compiletest suite={} mode={} ({} -> {})",
            suite, mode, &compiler.host, target
        ));
1361 1362
        let _time = util::timeit(&builder);
        try_run(builder, &mut cmd);
1363 1364 1365

        if let Some(compare_mode) = compare_mode {
            cmd.arg("--compare-mode").arg(compare_mode);
S
Santiago Pastorino 已提交
1366 1367 1368 1369
            builder.info(&format!(
                "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
                suite, mode, compare_mode, &compiler.host, target
            ));
1370 1371 1372
            let _time = util::timeit(&builder);
            try_run(builder, &mut cmd);
        }
1373
    }
1374
}
1375

1376
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1377
struct DocTest {
1378
    compiler: Compiler,
1379 1380 1381
    path: &'static str,
    name: &'static str,
    is_ext_doc: bool,
1382 1383
}

1384
impl Step for DocTest {
1385 1386
    type Output = ();
    const ONLY_HOSTS: bool = true;
1387

T
Taiki Endo 已提交
1388
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1389
        run.never()
1390
    }
M
Mark Simulacrum 已提交
1391

A
Alexander Regueiro 已提交
1392
    /// Runs `rustdoc --test` for all documentation in `src/doc`.
1393
    ///
1394
    /// This will run all tests in our markdown documentation (e.g., the book)
1395 1396
    /// located in `src/doc`. The `rustdoc` that's run is the one that sits next to
    /// `compiler`.
T
Taiki Endo 已提交
1397
    fn run(self, builder: &Builder<'_>) {
1398
        let compiler = self.compiler;
1399

S
Santiago Pastorino 已提交
1400 1401 1402 1403
        builder.ensure(compile::Test {
            compiler,
            target: compiler.host,
        });
1404

1405 1406
        // Do a breadth-first traversal of the `src/doc` directory and just run
        // tests for all files that end in `*.md`
1407 1408
        let mut stack = vec![builder.src.join(self.path)];
        let _time = util::timeit(&builder);
1409

1410
        let mut files = Vec::new();
1411 1412 1413
        while let Some(p) = stack.pop() {
            if p.is_dir() {
                stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
S
Santiago Pastorino 已提交
1414
                continue;
1415 1416 1417 1418 1419 1420 1421
            }

            if p.extension().and_then(|s| s.to_str()) != Some("md") {
                continue;
            }

            // The nostarch directory in the book is for no starch, and so isn't
1422
            // guaranteed to builder. We don't care if it doesn't build, so skip it.
1423 1424 1425 1426
            if p.to_str().map_or(false, |p| p.contains("nostarch")) {
                continue;
            }

1427 1428 1429 1430 1431
            files.push(p);
        }

        files.sort();

1432
        let mut toolstate = ToolState::TestPass;
1433
        for file in files {
1434 1435
            if !markdown_test(builder, compiler, &file) {
                toolstate = ToolState::TestFail;
1436
            }
1437
        }
1438 1439 1440
        if self.is_ext_doc {
            builder.save_toolstate(self.name, toolstate);
        }
1441 1442 1443
    }
}

1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456
macro_rules! test_book {
    ($($name:ident, $path:expr, $book_name:expr, default=$default:expr;)+) => {
        $(
            #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
            pub struct $name {
                compiler: Compiler,
            }

            impl Step for $name {
                type Output = ();
                const DEFAULT: bool = $default;
                const ONLY_HOSTS: bool = true;

T
Taiki Endo 已提交
1457
                fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1458 1459 1460
                    run.path($path)
                }

T
Taiki Endo 已提交
1461
                fn make_run(run: RunConfig<'_>) {
1462 1463 1464 1465 1466
                    run.builder.ensure($name {
                        compiler: run.builder.compiler(run.builder.top_stage, run.host),
                    });
                }

T
Taiki Endo 已提交
1467
                fn run(self, builder: &Builder<'_>) {
1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483
                    builder.ensure(DocTest {
                        compiler: self.compiler,
                        path: $path,
                        name: $book_name,
                        is_ext_doc: !$default,
                    });
                }
            }
        )+
    }
}

test_book!(
    Nomicon, "src/doc/nomicon", "nomicon", default=false;
    Reference, "src/doc/reference", "reference", default=false;
    RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
1484
    RustcBook, "src/doc/rustc", "rustc", default=true;
1485
    RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false;
1486
    EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false;
1487 1488
    TheBook, "src/doc/book", "book", default=false;
    UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
E
Eric Huss 已提交
1489
    EditionGuide, "src/doc/edition-guide", "edition-guide", default=false;
1490 1491
);

1492 1493 1494
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct ErrorIndex {
    compiler: Compiler,
1495
}
1496

1497
impl Step for ErrorIndex {
1498
    type Output = ();
1499 1500 1501
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

T
Taiki Endo 已提交
1502
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1503
        run.path("src/tools/error_index_generator")
1504 1505
    }

T
Taiki Endo 已提交
1506
    fn make_run(run: RunConfig<'_>) {
1507 1508
        run.builder.ensure(ErrorIndex {
            compiler: run.builder.compiler(run.builder.top_stage, run.host),
1509 1510
        });
    }
1511

A
Alexander Regueiro 已提交
1512
    /// Runs the error index generator tool to execute the tests located in the error
1513 1514 1515 1516 1517
    /// index.
    ///
    /// The `error_index_generator` tool lives in `src/tools` and is used to
    /// generate a markdown file from the error indexes of the code base which is
    /// then passed to `rustdoc --test`.
T
Taiki Endo 已提交
1518
    fn run(self, builder: &Builder<'_>) {
1519 1520
        let compiler = self.compiler;

S
Santiago Pastorino 已提交
1521 1522 1523 1524
        builder.ensure(compile::Std {
            compiler,
            target: compiler.host,
        });
1525

1526
        let dir = testdir(builder, compiler.host);
1527 1528 1529
        t!(fs::create_dir_all(&dir));
        let output = dir.join("error-index.md");

1530 1531 1532 1533
        let mut tool = tool::ErrorIndex::command(
            builder,
            builder.compiler(compiler.stage, builder.config.build),
        );
1534 1535
        tool.arg("markdown")
            .arg(&output)
1536 1537
            .env("CFG_BUILD", &builder.config.build)
            .env("RUSTC_ERROR_METADATA_DST", builder.extended_error_dir());
1538

1539 1540
        builder.info(&format!("Testing error-index stage{}", compiler.stage));
        let _time = util::timeit(&builder);
1541
        builder.run_quiet(&mut tool);
1542
        markdown_test(builder, compiler, &output);
1543
    }
1544 1545
}

T
Taiki Endo 已提交
1546
fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
1547 1548
    match fs::read_to_string(markdown) {
        Ok(contents) => {
1549 1550 1551 1552
            if !contents.contains("```") {
                return true;
            }
        }
S
Santiago Pastorino 已提交
1553
        Err(_) => {}
1554 1555
    }

1556
    builder.info(&format!("doc tests for: {}", markdown.display()));
M
Mark Rousskov 已提交
1557
    let mut cmd = builder.rustdoc_cmd(compiler);
1558
    builder.add_rust_test_threads(&mut cmd);
1559 1560
    cmd.arg("--test");
    cmd.arg(markdown);
1561
    cmd.env("RUSTC_BOOTSTRAP", "1");
1562

1563
    let test_args = builder.config.cmd.test_args().join(" ");
1564 1565
    cmd.arg("--test-args").arg(test_args);

O
Oliver Schneider 已提交
1566
    if builder.config.verbose_tests {
1567
        try_run(builder, &mut cmd)
O
Oliver Schneider 已提交
1568 1569
    } else {
        try_run_quiet(builder, &mut cmd)
1570
    }
1571
}
1572

1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct RustcGuide;

impl Step for RustcGuide {
    type Output = ();
    const DEFAULT: bool = false;
    const ONLY_HOSTS: bool = true;

    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
        run.path("src/doc/rustc-guide")
    }

    fn make_run(run: RunConfig<'_>) {
        run.builder.ensure(RustcGuide);
    }

    fn run(self, builder: &Builder<'_>) {
        let src = builder.src.join("src/doc/rustc-guide");
        let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
E
Eric Huss 已提交
1592 1593 1594 1595 1596 1597
        let toolstate = if try_run(builder, rustbook_cmd.arg("linkcheck").arg(&src)) {
            ToolState::TestPass
        } else {
            ToolState::TestFail
        };
        builder.save_toolstate("rustc-guide", toolstate);
1598 1599 1600
    }
}

1601
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
M
Mark Simulacrum 已提交
1602
pub struct CrateLibrustc {
1603 1604
    compiler: Compiler,
    target: Interned<String>,
1605
    test_kind: TestKind,
1606
    krate: Interned<String>,
1607 1608
}

M
Mark Simulacrum 已提交
1609
impl Step for CrateLibrustc {
1610 1611 1612 1613
    type Output = ();
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

T
Taiki Endo 已提交
1614
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1615
        run.krate("rustc-main")
1616 1617
    }

T
Taiki Endo 已提交
1618
    fn make_run(run: RunConfig<'_>) {
1619 1620
        let builder = run.builder;
        let compiler = builder.compiler(builder.top_stage, run.host);
1621

1622 1623
        for krate in builder.in_tree_crates("rustc-main") {
            if run.path.ends_with(&krate.path) {
1624
                let test_kind = builder.kind.into();
1625

1626 1627 1628 1629 1630 1631
                builder.ensure(CrateLibrustc {
                    compiler,
                    target: run.target,
                    test_kind,
                    krate: krate.name,
                });
1632 1633 1634 1635
            }
        }
    }

T
Taiki Endo 已提交
1636
    fn run(self, builder: &Builder<'_>) {
M
Mark Simulacrum 已提交
1637
        builder.ensure(Crate {
1638 1639
            compiler: self.compiler,
            target: self.target,
C
Collins Abitekaniza 已提交
1640
            mode: Mode::Rustc,
1641 1642 1643 1644 1645 1646
            test_kind: self.test_kind,
            krate: self.krate,
        });
    }
}

1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct CrateNotDefault {
    compiler: Compiler,
    target: Interned<String>,
    test_kind: TestKind,
    krate: &'static str,
}

impl Step for CrateNotDefault {
    type Output = ();

T
Taiki Endo 已提交
1658
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1659
        run.path("src/librustc_asan")
1660 1661 1662 1663 1664
            .path("src/librustc_lsan")
            .path("src/librustc_msan")
            .path("src/librustc_tsan")
    }

T
Taiki Endo 已提交
1665
    fn make_run(run: RunConfig<'_>) {
1666 1667 1668
        let builder = run.builder;
        let compiler = builder.compiler(builder.top_stage, run.host);

1669
        let test_kind = builder.kind.into();
1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684

        builder.ensure(CrateNotDefault {
            compiler,
            target: run.target,
            test_kind,
            krate: match run.path {
                _ if run.path.ends_with("src/librustc_asan") => "rustc_asan",
                _ if run.path.ends_with("src/librustc_lsan") => "rustc_lsan",
                _ if run.path.ends_with("src/librustc_msan") => "rustc_msan",
                _ if run.path.ends_with("src/librustc_tsan") => "rustc_tsan",
                _ => panic!("unexpected path {:?}", run.path),
            },
        });
    }

T
Taiki Endo 已提交
1685
    fn run(self, builder: &Builder<'_>) {
1686 1687 1688
        builder.ensure(Crate {
            compiler: self.compiler,
            target: self.target,
C
Collins Abitekaniza 已提交
1689
            mode: Mode::Std,
1690 1691 1692 1693 1694 1695
            test_kind: self.test_kind,
            krate: INTERNER.intern_str(self.krate),
        });
    }
}

K
kennytm 已提交
1696
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
M
Mark Simulacrum 已提交
1697
pub struct Crate {
K
kennytm 已提交
1698 1699 1700 1701 1702
    pub compiler: Compiler,
    pub target: Interned<String>,
    pub mode: Mode,
    pub test_kind: TestKind,
    pub krate: Interned<String>,
1703
}
1704

M
Mark Simulacrum 已提交
1705
impl Step for Crate {
1706
    type Output = ();
1707 1708
    const DEFAULT: bool = true;

T
Taiki Endo 已提交
1709
    fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
1710 1711 1712
        let builder = run.builder;
        run = run.krate("test");
        for krate in run.builder.in_tree_crates("std") {
1713
            if !(krate.name.starts_with("rustc_") && krate.name.ends_with("san")) {
1714 1715 1716 1717
                run = run.path(krate.local_path(&builder).to_str().unwrap());
            }
        }
        run
1718 1719
    }

T
Taiki Endo 已提交
1720
    fn make_run(run: RunConfig<'_>) {
1721 1722
        let builder = run.builder;
        let compiler = builder.compiler(builder.top_stage, run.host);
1723

1724
        let make = |mode: Mode, krate: &CargoCrate| {
1725
            let test_kind = builder.kind.into();
1726

M
Mark Simulacrum 已提交
1727
            builder.ensure(Crate {
1728 1729
                compiler,
                target: run.target,
1730 1731
                mode,
                test_kind,
1732
                krate: krate.name,
1733 1734 1735
            });
        };

1736 1737
        for krate in builder.in_tree_crates("std") {
            if run.path.ends_with(&krate.local_path(&builder)) {
C
Collins Abitekaniza 已提交
1738
                make(Mode::Std, krate);
1739
            }
1740 1741 1742
        }
        for krate in builder.in_tree_crates("test") {
            if run.path.ends_with(&krate.local_path(&builder)) {
C
Collins Abitekaniza 已提交
1743
                make(Mode::Test, krate);
1744 1745 1746
            }
        }
    }
1747

A
Alexander Regueiro 已提交
1748
    /// Runs all unit tests plus documentation tests for a given crate defined
1749
    /// by a `Cargo.toml` (single manifest)
1750 1751 1752 1753 1754 1755
    ///
    /// This is what runs tests for crates like the standard library, compiler, etc.
    /// It essentially is the driver for running `cargo test`.
    ///
    /// Currently this runs all tests for a DAG by passing a bunch of `-p foo`
    /// arguments, and those arguments are discovered from `cargo metadata`.
T
Taiki Endo 已提交
1756
    fn run(self, builder: &Builder<'_>) {
1757 1758 1759 1760 1761 1762
        let compiler = self.compiler;
        let target = self.target;
        let mode = self.mode;
        let test_kind = self.test_kind;
        let krate = self.krate;

1763 1764
        builder.ensure(compile::Test { compiler, target });
        builder.ensure(RemoteCopyLibs { compiler, target });
A
Alex Crichton 已提交
1765

1766 1767 1768 1769 1770
        // If we're not doing a full bootstrap but we're testing a stage2
        // version of libstd, then what we're actually testing is the libstd
        // produced in stage1. Reflect that here by updating the compiler that
        // we're working with automatically.
        let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
A
Alex Crichton 已提交
1771 1772

        let mut cargo = builder.cargo(compiler, mode, target, test_kind.subcommand());
1773
        match mode {
C
Collins Abitekaniza 已提交
1774
            Mode::Std => {
1775
                compile::std_cargo(builder, &compiler, target, &mut cargo);
1776
            }
C
Collins Abitekaniza 已提交
1777
            Mode::Test => {
1778
                compile::test_cargo(builder, &compiler, target, &mut cargo);
1779
            }
C
Collins Abitekaniza 已提交
1780
            Mode::Rustc => {
1781
                builder.ensure(compile::Rustc { compiler, target });
1782
                compile::rustc_cargo(builder, &mut cargo);
1783 1784 1785 1786 1787 1788 1789 1790 1791
            }
            _ => panic!("can only test libraries"),
        };

        // Build up the base `cargo test` command.
        //
        // Pass in some standard flags then iterate over the graph we've discovered
        // in `cargo metadata` with the maps above and figure out what `-p`
        // arguments need to get passed.
1792
        if test_kind.subcommand() == "test" && !builder.fail_fast {
1793 1794
            cargo.arg("--no-fail-fast");
        }
K
kennytm 已提交
1795
        match builder.doc_tests {
K
kennytm 已提交
1796
            DocTests::Only => {
K
kennytm 已提交
1797 1798
                cargo.arg("--doc");
            }
K
kennytm 已提交
1799
            DocTests::No => {
K
kennytm 已提交
1800 1801
                cargo.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]);
            }
K
kennytm 已提交
1802
            DocTests::Yes => {}
1803
        }
1804

1805
        cargo.arg("-p").arg(krate);
1806

1807 1808 1809 1810 1811 1812
        // The tests are going to run with the *target* libraries, so we need to
        // ensure that those libraries show up in the LD_LIBRARY_PATH equivalent.
        //
        // Note that to run the compiler we need to run with the *host* libraries,
        // but our wrapper scripts arrange for that to be the case anyway.
        let mut dylib_path = dylib_path();
1813
        dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target)));
1814 1815 1816
        cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());

        cargo.arg("--");
1817
        cargo.args(&builder.config.cmd.test_args());
1818

O
Oliver Schneider 已提交
1819
        if !builder.config.verbose_tests {
1820 1821
            cargo.arg("--quiet");
        }
1822

1823
        if target.contains("emscripten") {
S
Santiago Pastorino 已提交
1824 1825 1826 1827 1828 1829 1830 1831
            cargo.env(
                format!("CARGO_TARGET_{}_RUNNER", envify(&target)),
                builder
                    .config
                    .nodejs
                    .as_ref()
                    .expect("nodejs not configured"),
            );
O
Oliver Schneider 已提交
1832
        } else if target.starts_with("wasm32") {
1833 1834 1835
            // Warn about running tests without the `wasm_syscall` feature enabled.
            // The javascript shim implements the syscall interface so that test
            // output can be correctly reported.
1836
            if !builder.config.wasm_syscall {
1837
                builder.info(
S
Santiago Pastorino 已提交
1838 1839
                    "Libstd was built without `wasm_syscall` feature enabled: \
                     test output may not be visible."
1840
                );
1841 1842
            }

O
Oliver Schneider 已提交
1843 1844 1845 1846
            // On the wasm32-unknown-unknown target we're using LTO which is
            // incompatible with `-C prefer-dynamic`, so disable that here
            cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");

S
Santiago Pastorino 已提交
1847 1848 1849 1850
            let node = builder
                .config
                .nodejs
                .as_ref()
O
Oliver Schneider 已提交
1851
                .expect("nodejs not configured");
S
Santiago Pastorino 已提交
1852 1853 1854 1855 1856
            let runner = format!(
                "{} {}/src/etc/wasm32-shim.js",
                node.display(),
                builder.src.display()
            );
O
Oliver Schneider 已提交
1857
            cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target)), &runner);
1858
        } else if builder.remote_tested(target) {
S
Santiago Pastorino 已提交
1859 1860 1861 1862
            cargo.env(
                format!("CARGO_TARGET_{}_RUNNER", envify(&target)),
                format!("{} run", builder.tool_exe(Tool::RemoteTestClient).display()),
            );
1863
        }
1864

S
Santiago Pastorino 已提交
1865 1866 1867 1868
        builder.info(&format!(
            "{} {} stage{} ({} -> {})",
            test_kind, krate, compiler.stage, &compiler.host, target
        ));
1869 1870
        let _time = util::timeit(&builder);
        try_run(builder, &mut cargo);
1871 1872
    }
}
1873

M
Mark Simulacrum 已提交
1874
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1875
pub struct CrateRustdoc {
M
Mark Simulacrum 已提交
1876 1877 1878 1879
    host: Interned<String>,
    test_kind: TestKind,
}

1880
impl Step for CrateRustdoc {
M
Mark Simulacrum 已提交
1881 1882 1883 1884
    type Output = ();
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

T
Taiki Endo 已提交
1885
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1886
        run.paths(&["src/librustdoc", "src/tools/rustdoc"])
M
Mark Simulacrum 已提交
1887 1888
    }

T
Taiki Endo 已提交
1889
    fn make_run(run: RunConfig<'_>) {
M
Mark Simulacrum 已提交
1890 1891
        let builder = run.builder;

1892
        let test_kind = builder.kind.into();
M
Mark Simulacrum 已提交
1893

1894
        builder.ensure(CrateRustdoc {
M
Mark Simulacrum 已提交
1895 1896 1897 1898 1899
            host: run.host,
            test_kind,
        });
    }

T
Taiki Endo 已提交
1900
    fn run(self, builder: &Builder<'_>) {
M
Mark Simulacrum 已提交
1901 1902 1903 1904
        let test_kind = self.test_kind;

        let compiler = builder.compiler(builder.top_stage, self.host);
        let target = compiler.host;
1905
        builder.ensure(compile::Rustc { compiler, target });
M
Mark Simulacrum 已提交
1906

C
Collins Abitekaniza 已提交
1907 1908
        let mut cargo = tool::prepare_tool_cargo(builder,
                                                 compiler,
C
Collins Abitekaniza 已提交
1909
                                                 Mode::ToolRustc,
C
Collins Abitekaniza 已提交
1910 1911
                                                 target,
                                                 test_kind.subcommand(),
1912
                                                 "src/tools/rustdoc",
1913 1914
                                                 SourceType::InTree,
                                                 &[]);
1915
        if test_kind.subcommand() == "test" && !builder.fail_fast {
M
Mark Simulacrum 已提交
1916 1917 1918 1919 1920 1921
            cargo.arg("--no-fail-fast");
        }

        cargo.arg("-p").arg("rustdoc:0.0.0");

        cargo.arg("--");
1922
        cargo.args(&builder.config.cmd.test_args());
M
Mark Simulacrum 已提交
1923

1924 1925 1926 1927
        if self.host.contains("musl") {
            cargo.arg("'-Ctarget-feature=-crt-static'");
        }

O
Oliver Schneider 已提交
1928
        if !builder.config.verbose_tests {
M
Mark Simulacrum 已提交
1929 1930 1931
            cargo.arg("--quiet");
        }

S
Santiago Pastorino 已提交
1932 1933 1934 1935
        builder.info(&format!(
            "{} rustdoc stage{} ({} -> {})",
            test_kind, compiler.stage, &compiler.host, target
        ));
1936
        let _time = util::timeit(&builder);
M
Mark Simulacrum 已提交
1937

1938
        try_run(builder, &mut cargo);
M
Mark Simulacrum 已提交
1939 1940 1941
    }
}

1942
fn envify(s: &str) -> String {
S
Santiago Pastorino 已提交
1943 1944
    s.chars()
        .map(|c| match c {
1945 1946
            '-' => '_',
            c => c,
S
Santiago Pastorino 已提交
1947 1948 1949
        })
        .flat_map(|c| c.to_uppercase())
        .collect()
1950 1951
}

1952 1953 1954 1955 1956
/// Some test suites are run inside emulators or on remote devices, and most
/// of our test binaries are linked dynamically which means we need to ship
/// the standard library and such to the emulator ahead of time. This step
/// represents this and is a dependency of all test suites.
///
A
Alexander Regueiro 已提交
1957
/// Most of the time this is a no-op. For some steps such as shipping data to
1958 1959 1960
/// QEMU we have to build our own tools so we've got conditional dependencies
/// on those programs as well. Note that the remote test client is built for
/// the build target (us) and the server is built for the target.
1961 1962 1963 1964
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct RemoteCopyLibs {
    compiler: Compiler,
    target: Interned<String>,
1965
}
1966

1967
impl Step for RemoteCopyLibs {
1968
    type Output = ();
1969

T
Taiki Endo 已提交
1970
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1971
        run.never()
1972 1973
    }

T
Taiki Endo 已提交
1974
    fn run(self, builder: &Builder<'_>) {
1975 1976
        let compiler = self.compiler;
        let target = self.target;
1977
        if !builder.remote_tested(target) {
S
Santiago Pastorino 已提交
1978
            return;
1979 1980
        }

1981 1982
        builder.ensure(compile::Test { compiler, target });

1983 1984
        builder.info(&format!("REMOTE copy libs to emulator ({})", target));
        t!(fs::create_dir_all(builder.out.join("tmp")));
1985

1986 1987 1988 1989
        let server = builder.ensure(tool::RemoteTestServer {
            compiler: compiler.with_stage(0),
            target,
        });
1990 1991

        // Spawn the emulator and wait for it to come online
1992
        let tool = builder.tool_exe(Tool::RemoteTestClient);
1993 1994
        let mut cmd = Command::new(&tool);
        cmd.arg("spawn-emulator")
S
Santiago Pastorino 已提交
1995 1996 1997
            .arg(target)
            .arg(&server)
            .arg(builder.out.join("tmp"));
1998
        if let Some(rootfs) = builder.qemu_rootfs(target) {
1999 2000
            cmd.arg(rootfs);
        }
2001
        builder.run(&mut cmd);
2002 2003

        // Push all our dylibs to the emulator
2004
        for f in t!(builder.sysroot_libdir(compiler, target).read_dir()) {
2005 2006 2007
            let f = t!(f);
            let name = f.file_name().into_string().unwrap();
            if util::is_dylib(&name) {
S
Santiago Pastorino 已提交
2008
                builder.run(Command::new(&tool).arg("push").arg(f.path()));
2009
            }
2010 2011 2012 2013
        }
    }
}

2014
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2015
pub struct Distcheck;
A
Alex Crichton 已提交
2016

2017
impl Step for Distcheck {
2018 2019
    type Output = ();

T
Taiki Endo 已提交
2020
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2021
        run.path("distcheck")
2022 2023
    }

T
Taiki Endo 已提交
2024
    fn make_run(run: RunConfig<'_>) {
M
Mark Simulacrum 已提交
2025 2026 2027
        run.builder.ensure(Distcheck);
    }

A
Alexander Regueiro 已提交
2028
    /// Runs "distcheck", a 'make check' from a tarball
T
Taiki Endo 已提交
2029
    fn run(self, builder: &Builder<'_>) {
2030
        builder.info("Distcheck");
2031
        let dir = builder.out.join("tmp").join("distcheck");
2032 2033 2034
        let _ = fs::remove_dir_all(&dir);
        t!(fs::create_dir_all(&dir));

M
Mark Simulacrum 已提交
2035 2036 2037 2038
        // Guarantee that these are built before we begin running.
        builder.ensure(dist::PlainSourceTarball);
        builder.ensure(dist::Src);

2039 2040
        let mut cmd = Command::new("tar");
        cmd.arg("-xzf")
S
Santiago Pastorino 已提交
2041 2042 2043
            .arg(builder.ensure(dist::PlainSourceTarball))
            .arg("--strip-components=1")
            .current_dir(&dir);
2044
        builder.run(&mut cmd);
S
Santiago Pastorino 已提交
2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055
        builder.run(
            Command::new("./configure")
                .args(&builder.config.configure_args)
                .arg("--enable-vendor")
                .current_dir(&dir),
        );
        builder.run(
            Command::new(build_helper::make(&builder.config.build))
                .arg("check")
                .current_dir(&dir),
        );
2056 2057

        // Now make sure that rust-src has all of libstd's dependencies
2058
        builder.info("Distcheck rust-src");
2059
        let dir = builder.out.join("tmp").join("distcheck-src");
2060 2061 2062 2063 2064
        let _ = fs::remove_dir_all(&dir);
        t!(fs::create_dir_all(&dir));

        let mut cmd = Command::new("tar");
        cmd.arg("-xzf")
S
Santiago Pastorino 已提交
2065 2066 2067
            .arg(builder.ensure(dist::Src))
            .arg("--strip-components=1")
            .current_dir(&dir);
2068
        builder.run(&mut cmd);
2069 2070

        let toml = dir.join("rust-src/lib/rustlib/src/rust/src/libstd/Cargo.toml");
S
Santiago Pastorino 已提交
2071 2072 2073 2074 2075 2076 2077
        builder.run(
            Command::new(&builder.initial_cargo)
                .arg("generate-lockfile")
                .arg("--manifest-path")
                .arg(&toml)
                .current_dir(&dir),
        );
2078
    }
A
Alex Crichton 已提交
2079
}
2080

2081
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2082 2083
pub struct Bootstrap;

2084
impl Step for Bootstrap {
2085
    type Output = ();
2086 2087
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;
2088

A
Alexander Regueiro 已提交
2089
    /// Tests the build system itself.
T
Taiki Endo 已提交
2090
    fn run(self, builder: &Builder<'_>) {
2091
        let mut cmd = Command::new(&builder.initial_cargo);
2092
        cmd.arg("test")
S
Santiago Pastorino 已提交
2093 2094 2095 2096 2097
            .current_dir(builder.src.join("src/bootstrap"))
            .env("RUSTFLAGS", "-Cdebuginfo=2")
            .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
            .env("RUSTC_BOOTSTRAP", "1")
            .env("RUSTC", &builder.initial_rustc);
2098 2099 2100 2101 2102 2103
        if let Some(flags) = option_env!("RUSTFLAGS") {
            // Use the same rustc flags for testing as for "normal" compilation,
            // so that Cargo doesn’t recompile the entire dependency graph every time:
            // https://github.com/rust-lang/rust/issues/49215
            cmd.env("RUSTFLAGS", flags);
        }
2104
        if !builder.fail_fast {
2105 2106
            cmd.arg("--no-fail-fast");
        }
2107
        cmd.arg("--").args(&builder.config.cmd.test_args());
2108 2109 2110
        // rustbuild tests are racy on directory creation so just run them one at a time.
        // Since there's not many this shouldn't be a problem.
        cmd.arg("--test-threads=1");
2111
        try_run(builder, &mut cmd);
2112
    }
2113

T
Taiki Endo 已提交
2114
    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2115
        run.path("src/bootstrap")
2116 2117
    }

T
Taiki Endo 已提交
2118
    fn make_run(run: RunConfig<'_>) {
2119
        run.builder.ensure(Bootstrap);
2120
    }
2121
}