Skip to content

Commit

Permalink
Migrate runmake tests away from custom commands and command_output
Browse files Browse the repository at this point in the history
  • Loading branch information
Kobzol committed Jun 8, 2024
1 parent 18ae9af commit 0a190e8
Show file tree
Hide file tree
Showing 30 changed files with 176 additions and 141 deletions.
2 changes: 1 addition & 1 deletion src/tools/run-make-support/src/cc.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::path::Path;

use crate::{bin_name, cygpath_windows, env_var, handle_failed_output, is_msvc, is_windows, uname};
use crate::command::Command;
use crate::{bin_name, cygpath_windows, env_var, is_msvc, is_windows, uname};

/// Construct a new platform-specific C compiler invocation.
///
Expand Down
2 changes: 1 addition & 1 deletion src/tools/run-make-support/src/clang.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::path::Path;

use crate::{bin_name, env_var, handle_failed_output};
use crate::command::Command;
use crate::{bin_name, env_var};

/// Construct a new `clang` invocation. `clang` is not always available for all targets.
pub fn clang() -> Clang {
Expand Down
76 changes: 68 additions & 8 deletions src/tools/run-make-support/src/command.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use crate::{assert_not_contains, handle_failed_output};
use std::ffi::OsStr;
use std::io::Write;
use std::ops::{Deref, DerefMut};
use std::process::{Command as StdCommand, ExitStatus, Output, Stdio};

/// This is a custom command wrapper that simplifies working with commands
/// and makes it easier to ensure that we check the exit status of executed
/// processes.
#[derive(Debug)]
pub struct Command {
cmd: StdCommand,
Expand All @@ -11,16 +15,39 @@ pub struct Command {

impl Command {
pub fn new<S: AsRef<OsStr>>(program: S) -> Self {
Self {
cmd: StdCommand::new(program),
stdin: None,
}
Self { cmd: StdCommand::new(program), stdin: None }
}

pub fn set_stdin(&mut self, stdin: Box<[u8]>) {
self.stdin = Some(stdin);
}

/// Run the constructed command and assert that it is successfully run.
#[track_caller]
pub fn run(&mut self) -> CompletedProcess {
let caller_location = std::panic::Location::caller();
let caller_line_number = caller_location.line();

let output = self.command_output();
if !output.status().success() {
handle_failed_output(&self, output, caller_line_number);
}
output
}

/// Run the constructed command and assert that it does not successfully run.
#[track_caller]
pub fn run_fail(&mut self) -> CompletedProcess {
let caller_location = std::panic::Location::caller();
let caller_line_number = caller_location.line();

let output = self.command_output();
if output.status().success() {
handle_failed_output(&self, output, caller_line_number);
}
output
}

#[track_caller]
pub(crate) fn command_output(&mut self) -> CompletedProcess {
// let's make sure we piped all the input and outputs
Expand Down Expand Up @@ -59,6 +86,8 @@ impl DerefMut for Command {
}

/// Represents the result of an executed process.
/// The various `assert_` helper methods should preferably be used for
/// checking the contents of stdout/stderr.
pub struct CompletedProcess {
output: Output,
}
Expand All @@ -76,16 +105,47 @@ impl CompletedProcess {
self.output.status
}

/// Checks that trimmed `stdout` matches trimmed `content`.
#[track_caller]
pub fn assert_stdout_equals<S: AsRef<str>>(self, content: S) -> Self {
assert_eq!(self.stdout_utf8().trim(), content.as_ref().trim());
self
}

#[track_caller]
pub fn assert_exit_code(&self, code: i32) {
pub fn assert_stdout_not_contains<S: AsRef<str>>(self, needle: S) -> Self {
assert_not_contains(&self.stdout_utf8(), needle.as_ref());
self
}

/// Checks that trimmed `stderr` matches trimmed `content`.
#[track_caller]
pub fn assert_stderr_equals<S: AsRef<str>>(self, content: S) -> Self {
assert_eq!(self.stderr_utf8().trim(), content.as_ref().trim());
self
}

#[track_caller]
pub fn assert_stderr_contains<S: AsRef<str>>(self, needle: S) -> Self {
assert!(self.stderr_utf8().contains(needle.as_ref()));
self
}

#[track_caller]
pub fn assert_stderr_not_contains<S: AsRef<str>>(self, needle: S) -> Self {
assert_not_contains(&self.stdout_utf8(), needle.as_ref());
self
}

#[track_caller]
pub fn assert_exit_code(self, code: i32) -> Self {
assert!(self.output.status.code() == Some(code));
self
}
}

impl From<Output> for CompletedProcess {
fn from(output: Output) -> Self {
Self {
output
}
Self { output }
}
}
25 changes: 6 additions & 19 deletions src/tools/run-make-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@

pub mod cc;
pub mod clang;
mod command;
pub mod diff;
pub mod llvm_readobj;
pub mod run;
pub mod rustc;
pub mod rustdoc;
mod command;

use std::env;
use std::ffi::OsString;
Expand All @@ -27,7 +27,7 @@ pub use cc::{cc, extra_c_flags, extra_cxx_flags, Cc};
pub use clang::{clang, Clang};
pub use diff::{diff, Diff};
pub use llvm_readobj::{llvm_readobj, LlvmReadobj};
pub use run::{run, run_fail};
pub use run::{cmd, run, run_fail};
pub use rustc::{aux_build, rustc, Rustc};
pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc};

Expand Down Expand Up @@ -285,6 +285,7 @@ pub fn read_dir<F: Fn(&Path)>(dir: impl AsRef<Path>, callback: F) {
}

/// Check that `haystack` does not contain `needle`. Panic otherwise.
#[track_caller]
pub fn assert_not_contains(haystack: &str, needle: &str) {
if haystack.contains(needle) {
eprintln!("=== HAYSTACK ===");
Expand Down Expand Up @@ -412,27 +413,13 @@ macro_rules! impl_common_helpers {
/// Run the constructed command and assert that it is successfully run.
#[track_caller]
pub fn run(&mut self) -> crate::command::CompletedProcess {
let caller_location = ::std::panic::Location::caller();
let caller_line_number = caller_location.line();

let output = self.cmd.command_output();
if !output.status().success() {
handle_failed_output(&self.cmd, output, caller_line_number);
}
output
self.cmd.run()
}

/// Run the constructed command and assert that it does not successfully run.
#[track_caller]
pub fn run_fail(&mut self) -> crate::command::CompletedProcess {
let caller_location = ::std::panic::Location::caller();
let caller_line_number = caller_location.line();

let output = self.cmd.command_output();
if output.status().success() {
handle_failed_output(&self.cmd, output, caller_line_number);
}
output
self.cmd.run_fail()
}

/// Set the path where the command will be run.
Expand All @@ -444,5 +431,5 @@ macro_rules! impl_common_helpers {
};
}

pub(crate) use impl_common_helpers;
use crate::command::{Command, CompletedProcess};
pub(crate) use impl_common_helpers;
2 changes: 1 addition & 1 deletion src/tools/run-make-support/src/llvm_readobj.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::path::{Path, PathBuf};

use crate::{env_var, handle_failed_output};
use crate::command::Command;
use crate::env_var;

/// Construct a new `llvm-readobj` invocation. This assumes that `llvm-readobj` is available
/// at `$LLVM_BIN_DIR/llvm-readobj`.
Expand Down
11 changes: 10 additions & 1 deletion src/tools/run-make-support/src/run.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use std::env;
use std::ffi::OsStr;
use std::path::{Path, PathBuf};

use crate::{cwd, env_var, is_windows};
use crate::command::{Command, CompletedProcess};
use crate::{cwd, env_var, is_windows, set_host_rpath};

use super::handle_failed_output;

Expand Down Expand Up @@ -62,3 +63,11 @@ pub fn run_fail(name: &str) -> CompletedProcess {
}
output
}

/// Create a new custom Command.
/// This should be preferred to creating `std::process::Command` directly.
pub fn cmd<S: AsRef<OsStr>>(program: S) -> Command {
let mut command = Command::new(program);
set_host_rpath(&mut command);
command
}
4 changes: 2 additions & 2 deletions src/tools/run-make-support/src/rustc.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use command::Command;
use std::ffi::{OsStr, OsString};
use std::path::Path;
use command::Command;

use crate::{command, cwd, env_var, handle_failed_output, set_host_rpath};
use crate::{command, cwd, env_var, set_host_rpath};

/// Construct a new `rustc` invocation.
pub fn rustc() -> Rustc {
Expand Down
2 changes: 1 addition & 1 deletion src/tools/run-make-support/src/rustdoc.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::ffi::OsStr;
use std::path::Path;

use crate::{env_var, env_var_os, handle_failed_output, set_host_rpath};
use crate::command::Command;
use crate::{env_var, env_var_os, set_host_rpath};

/// Construct a plain `rustdoc` invocation with no flags set.
pub fn bare_rustdoc() -> Rustdoc {
Expand Down
10 changes: 3 additions & 7 deletions tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,10 @@ use run_make_support::{aux_build, rustc, source_root};
fn main() {
aux_build().input("stable.rs").emit("metadata").run();

let output = rustc()
.input("main.rs")
.emit("metadata")
.extern_("stable", "libstable.rmeta")
.command_output();
let output =
rustc().input("main.rs").emit("metadata").extern_("stable", "libstable.rmeta").run();

let stderr = String::from_utf8_lossy(&output.stderr);
let version = std::fs::read_to_string(source_root().join("src/version")).unwrap();
let expected_string = format!("stable since {}", version.trim());
assert!(stderr.contains(&expected_string));
output.assert_stderr_contains(expected_string);
}
12 changes: 7 additions & 5 deletions tests/run-make/allow-warnings-cmdline-stability/rmake.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// Test that `-Awarnings` suppresses warnings for unstable APIs.

use run_make_support::{assert_not_contains, rustc};
use run_make_support::rustc;

fn main() {
rustc().input("bar.rs").run();
let output = rustc().input("foo.rs").arg("-Awarnings").run();

assert_not_contains(&String::from_utf8(output.stdout).unwrap(), "warning");
assert_not_contains(&String::from_utf8(output.stderr).unwrap(), "warning");
rustc()
.input("foo.rs")
.arg("-Awarnings")
.run()
.assert_stdout_not_contains("warning")
.assert_stderr_not_contains("warning");
}
9 changes: 3 additions & 6 deletions tests/run-make/compiler-builtins/rmake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ use run_make_support::object::read::Object;
use run_make_support::object::ObjectSection;
use run_make_support::object::ObjectSymbol;
use run_make_support::object::RelocationTarget;
use run_make_support::set_host_rpath;
use run_make_support::{env_var, object};
use run_make_support::{cmd, env_var, object};
use std::collections::HashSet;
use std::path::PathBuf;

Expand All @@ -35,7 +34,7 @@ fn main() {
let path = env_var("PATH");
let rustc = env_var("RUSTC");
let bootstrap_cargo = env_var("BOOTSTRAP_CARGO");
let mut cmd = std::process::Command::new(bootstrap_cargo);
let mut cmd = cmd(bootstrap_cargo);
cmd.args([
"build",
"--manifest-path",
Expand All @@ -52,10 +51,8 @@ fn main() {
// Visual Studio 2022 requires that the LIB env var be set so it can
// find the Windows SDK.
.env("LIB", std::env::var("LIB").unwrap_or_default());
set_host_rpath(&mut cmd);

let status = cmd.status().unwrap();
assert!(status.success());
cmd.run();

let rlibs_path = target_dir.join(target).join("debug").join("deps");
let compiler_builtins_rlib = std::fs::read_dir(rlibs_path)
Expand Down
2 changes: 1 addition & 1 deletion tests/run-make/const-prop-lint/rmake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::fs;
use run_make_support::{cwd, rustc};

fn main() {
rustc().input("input.rs").run_fail_assert_exit_code(1);
rustc().input("input.rs").run_fail().assert_exit_code(1);

for entry in fs::read_dir(cwd()).unwrap() {
let entry = entry.unwrap();
Expand Down
35 changes: 17 additions & 18 deletions tests/run-make/crate-data-smoke/rmake.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
use std::process::Output;

use run_make_support::{bin_name, rust_lib_name, rustc};

fn compare_stdout<S: AsRef<str>>(output: Output, expected: S) {
assert_eq!(String::from_utf8(output.stdout).unwrap().trim(), expected.as_ref());
}

fn main() {
compare_stdout(rustc().print("crate-name").input("crate.rs").run(), "foo");
compare_stdout(rustc().print("file-names").input("crate.rs").run(), bin_name("foo"));
compare_stdout(
rustc().print("file-names").crate_type("lib").arg("--test").input("crate.rs").run(),
bin_name("foo"),
);
compare_stdout(
rustc().print("file-names").arg("--test").input("lib.rs").run(),
bin_name("mylib"),
);
compare_stdout(rustc().print("file-names").input("lib.rs").run(), rust_lib_name("mylib"));
compare_stdout(rustc().print("file-names").input("rlib.rs").run(), rust_lib_name("mylib"));
rustc().print("crate-name").input("crate.rs").run().assert_stdout_equals("foo");
rustc().print("file-names").input("crate.rs").run().assert_stdout_equals(bin_name("foo"));
rustc()
.print("file-names")
.crate_type("lib")
.arg("--test")
.input("crate.rs")
.run()
.assert_stdout_equals(bin_name("foo"));
rustc()
.print("file-names")
.arg("--test")
.input("lib.rs")
.run()
.assert_stdout_equals(bin_name("mylib"));
rustc().print("file-names").input("lib.rs").run().assert_stdout_equals(rust_lib_name("mylib"));
rustc().print("file-names").input("rlib.rs").run().assert_stdout_equals(rust_lib_name("mylib"));
}
Loading

0 comments on commit 0a190e8

Please sign in to comment.