diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-05-03 15:26:10 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-03 15:26:10 +0200 |
| commit | c27d3d5d2a8e65d91f32f5b30510655863238e2d (patch) | |
| tree | 992ed04e1d5183207b59326b70c24c7612754b0d | |
| parent | 08d99928121f4a22b1e6e5aea8e84efc025f9484 (diff) | |
| parent | 2c4214e0a00287be39c2b8d5331b4fa4f88b1390 (diff) | |
| download | rust-c27d3d5d2a8e65d91f32f5b30510655863238e2d.tar.gz rust-c27d3d5d2a8e65d91f32f5b30510655863238e2d.zip | |
Rollup merge of #124612 - Urgau:run-make-stdin, r=jieyouxu
Add support for inputing via stdin with run-make-support This PR adds the facility to set a input bytes that will be passed via the standard input. This is useful for testing `rustc -` (and soon `rustdoc -`). In #124611 took the approach of having a dedicated `run` method but it is not very convenient to use and would necessitate many functions, one for success, one for fail, ... Instead this PR takes a different approach and allows setting the input bytes as if it were a parameter and when calling the (now custom) `output` function, we write the input bytes into stdin. I think this gives us maximum flexibility in the implementation and a simple interface for users. To test this new logic I ported `tests/run-make/stdin-non-utf8/` to an `rmake.rs` one. r? `@jieyouxu`
| -rw-r--r-- | src/tools/run-make-support/src/cc.rs | 5 | ||||
| -rw-r--r-- | src/tools/run-make-support/src/clang.rs | 5 | ||||
| -rw-r--r-- | src/tools/run-make-support/src/lib.rs | 18 | ||||
| -rw-r--r-- | src/tools/run-make-support/src/llvm_readobj.rs | 6 | ||||
| -rw-r--r-- | src/tools/run-make-support/src/rustc.rs | 38 | ||||
| -rw-r--r-- | src/tools/run-make-support/src/rustdoc.rs | 39 | ||||
| -rw-r--r-- | src/tools/tidy/src/allowed_run_make_makefiles.txt | 1 | ||||
| -rw-r--r-- | tests/run-make/stdin-non-utf8/Makefile | 6 | ||||
| -rw-r--r-- | tests/run-make/stdin-non-utf8/non-utf8 | 1 | ||||
| -rw-r--r-- | tests/run-make/stdin-rustc/rmake.rs | 26 |
10 files changed, 120 insertions, 25 deletions
diff --git a/src/tools/run-make-support/src/cc.rs b/src/tools/run-make-support/src/cc.rs index 146123793be..4082639f618 100644 --- a/src/tools/run-make-support/src/cc.rs +++ b/src/tools/run-make-support/src/cc.rs @@ -71,6 +71,11 @@ impl Cc { self } + + /// Get the [`Output`][::std::process::Output] of the finished process. + pub fn output(&mut self) -> ::std::process::Output { + self.cmd.output().expect("failed to get output of finished process") + } } /// `EXTRACFLAGS` diff --git a/src/tools/run-make-support/src/clang.rs b/src/tools/run-make-support/src/clang.rs index ed9f8383dc3..c30ba29ed76 100644 --- a/src/tools/run-make-support/src/clang.rs +++ b/src/tools/run-make-support/src/clang.rs @@ -70,4 +70,9 @@ impl Clang { self.cmd.arg(format!("-fuse-ld={ld}")); self } + + /// Get the [`Output`][::std::process::Output] of the finished process. + pub fn output(&mut self) -> ::std::process::Output { + self.cmd.output().expect("failed to get output of finished process") + } } diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index a874c1313b5..239f90b23c9 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -144,7 +144,7 @@ pub fn set_host_rpath(cmd: &mut Command) { } /// Implement common helpers for command wrappers. This assumes that the command wrapper is a struct -/// containing a `cmd: Command` field. The provided helpers are: +/// containing a `cmd: Command` field and a `output` function. The provided helpers are: /// /// 1. Generic argument acceptors: `arg` and `args` (delegated to [`Command`]). These are intended /// to be *fallback* argument acceptors, when specific helpers don't make sense. Prefer to add @@ -160,7 +160,12 @@ pub fn set_host_rpath(cmd: &mut Command) { /// Example usage: /// /// ```ignore (illustrative) -/// struct CommandWrapper { cmd: Command } +/// struct CommandWrapper { cmd: Command } // <- required `cmd` field +/// +/// impl CommandWrapper { +/// /// Get the [`Output`][::std::process::Output] of the finished process. +/// pub fn output(&mut self) -> Output { /* ... */ } // <- required `output()` method +/// } /// /// crate::impl_common_helpers!(CommandWrapper); /// @@ -231,18 +236,13 @@ macro_rules! impl_common_helpers { self } - /// Get the [`Output`][::std::process::Output] of the finished process. - pub fn output(&mut self) -> ::std::process::Output { - self.cmd.output().expect("failed to get output of finished process") - } - /// Run the constructed command and assert that it is successfully run. #[track_caller] pub fn run(&mut self) -> ::std::process::Output { let caller_location = ::std::panic::Location::caller(); let caller_line_number = caller_location.line(); - let output = self.cmd.output().unwrap(); + let output = self.output(); if !output.status.success() { handle_failed_output(&self.cmd, output, caller_line_number); } @@ -255,7 +255,7 @@ macro_rules! impl_common_helpers { let caller_location = ::std::panic::Location::caller(); let caller_line_number = caller_location.line(); - let output = self.cmd.output().unwrap(); + let output = self.output(); if output.status.success() { handle_failed_output(&self.cmd, output, caller_line_number); } diff --git a/src/tools/run-make-support/src/llvm_readobj.rs b/src/tools/run-make-support/src/llvm_readobj.rs index 32ea07e932e..4e1f2b002f3 100644 --- a/src/tools/run-make-support/src/llvm_readobj.rs +++ b/src/tools/run-make-support/src/llvm_readobj.rs @@ -41,4 +41,10 @@ impl LlvmReadobj { self.cmd.arg("--file-header"); self } + + /// Get the [`Output`][::std::process::Output] of the finished process. + #[track_caller] + pub fn output(&mut self) -> ::std::process::Output { + self.cmd.output().expect("failed to get output of finished process") + } } diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs index ddaae3236c2..37539528ab3 100644 --- a/src/tools/run-make-support/src/rustc.rs +++ b/src/tools/run-make-support/src/rustc.rs @@ -1,7 +1,8 @@ use std::env; use std::ffi::OsString; +use std::io::Write; use std::path::Path; -use std::process::{Command, Output}; +use std::process::{Command, Output, Stdio}; use crate::{handle_failed_output, set_host_rpath, tmp_dir}; @@ -19,6 +20,7 @@ pub fn aux_build() -> Rustc { #[derive(Debug)] pub struct Rustc { cmd: Command, + stdin: Option<Box<[u8]>>, } crate::impl_common_helpers!(Rustc); @@ -37,14 +39,14 @@ impl Rustc { /// Construct a new `rustc` invocation. pub fn new() -> Self { let cmd = setup_common(); - Self { cmd } + Self { cmd, stdin: None } } /// Construct a new `rustc` invocation with `aux_build` preset (setting `--crate-type=lib`). pub fn new_aux_build() -> Self { let mut cmd = setup_common(); cmd.arg("--crate-type=lib"); - Self { cmd } + Self { cmd, stdin: None } } // Argument provider methods @@ -161,12 +163,40 @@ impl Rustc { self } + /// Specify a stdin input + pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self { + self.stdin = Some(input.as_ref().to_vec().into_boxed_slice()); + self + } + + /// Get the [`Output`][::std::process::Output] of the finished process. + #[track_caller] + pub fn output(&mut self) -> ::std::process::Output { + // let's make sure we piped all the input and outputs + self.cmd.stdin(Stdio::piped()); + self.cmd.stdout(Stdio::piped()); + self.cmd.stderr(Stdio::piped()); + + if let Some(input) = &self.stdin { + let mut child = self.cmd.spawn().unwrap(); + + { + let mut stdin = child.stdin.take().unwrap(); + stdin.write_all(input.as_ref()).unwrap(); + } + + child.wait_with_output().expect("failed to get output of finished process") + } else { + self.cmd.output().expect("failed to get output of finished process") + } + } + #[track_caller] pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output { let caller_location = std::panic::Location::caller(); let caller_line_number = caller_location.line(); - let output = self.cmd.output().unwrap(); + let output = self.output(); if output.status.code().unwrap() != code { handle_failed_output(&self.cmd, output, caller_line_number); } diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs index 1054ac83c10..c2c4f2e68e2 100644 --- a/src/tools/run-make-support/src/rustdoc.rs +++ b/src/tools/run-make-support/src/rustdoc.rs @@ -1,6 +1,7 @@ use std::env; +use std::io::Write; use std::path::Path; -use std::process::{Command, Output}; +use std::process::{Command, Output, Stdio}; use crate::{handle_failed_output, set_host_rpath}; @@ -17,6 +18,7 @@ pub fn rustdoc() -> Rustdoc { #[derive(Debug)] pub struct Rustdoc { cmd: Command, + stdin: Option<Box<[u8]>>, } crate::impl_common_helpers!(Rustdoc); @@ -32,7 +34,7 @@ impl Rustdoc { /// Construct a bare `rustdoc` invocation. pub fn bare() -> Self { let cmd = setup_common(); - Self { cmd } + Self { cmd, stdin: None } } /// Construct a `rustdoc` invocation with `-L $(TARGET_RPATH_DIR)` set. @@ -40,7 +42,7 @@ impl Rustdoc { let mut cmd = setup_common(); let target_rpath_dir = env::var_os("TARGET_RPATH_DIR").unwrap(); cmd.arg(format!("-L{}", target_rpath_dir.to_string_lossy())); - Self { cmd } + Self { cmd, stdin: None } } /// Specify path to the input file. @@ -62,12 +64,41 @@ impl Rustdoc { self } + /// Specify a stdin input + pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self { + self.cmd.stdin(Stdio::piped()); + self.stdin = Some(input.as_ref().to_vec().into_boxed_slice()); + self + } + + /// Get the [`Output`][::std::process::Output] of the finished process. + #[track_caller] + pub fn output(&mut self) -> ::std::process::Output { + // let's make sure we piped all the input and outputs + self.cmd.stdin(Stdio::piped()); + self.cmd.stdout(Stdio::piped()); + self.cmd.stderr(Stdio::piped()); + + if let Some(input) = &self.stdin { + let mut child = self.cmd.spawn().unwrap(); + + { + let mut stdin = child.stdin.take().unwrap(); + stdin.write_all(input.as_ref()).unwrap(); + } + + child.wait_with_output().expect("failed to get output of finished process") + } else { + self.cmd.output().expect("failed to get output of finished process") + } + } + #[track_caller] pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output { let caller_location = std::panic::Location::caller(); let caller_line_number = caller_location.line(); - let output = self.cmd.output().unwrap(); + let output = self.output(); if output.status.code().unwrap() != code { handle_failed_output(&self.cmd, output, caller_line_number); } diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 69c6dda4b19..4b79b910ec3 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -288,7 +288,6 @@ run-make/static-unwinding/Makefile run-make/staticlib-blank-lib/Makefile run-make/staticlib-dylib-linkage/Makefile run-make/std-core-cycle/Makefile -run-make/stdin-non-utf8/Makefile run-make/suspicious-library/Makefile run-make/symbol-mangling-hashed/Makefile run-make/symbol-visibility/Makefile diff --git a/tests/run-make/stdin-non-utf8/Makefile b/tests/run-make/stdin-non-utf8/Makefile deleted file mode 100644 index 709d4cf1408..00000000000 --- a/tests/run-make/stdin-non-utf8/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -include ../tools.mk - -all: - cp non-utf8 $(TMPDIR)/non-utf.rs - cat $(TMPDIR)/non-utf.rs | $(RUSTC) - 2>&1 \ - | $(CGREP) "error: couldn't read from stdin, as it did not contain valid UTF-8" diff --git a/tests/run-make/stdin-non-utf8/non-utf8 b/tests/run-make/stdin-non-utf8/non-utf8 deleted file mode 100644 index bc87051a852..00000000000 --- a/tests/run-make/stdin-non-utf8/non-utf8 +++ /dev/null @@ -1 +0,0 @@ -Ò diff --git a/tests/run-make/stdin-rustc/rmake.rs b/tests/run-make/stdin-rustc/rmake.rs new file mode 100644 index 00000000000..c07a6df4d84 --- /dev/null +++ b/tests/run-make/stdin-rustc/rmake.rs @@ -0,0 +1,26 @@ +//! This test checks rustc `-` (stdin) support + +use run_make_support::{is_windows, rustc, tmp_dir}; + +const HELLO_WORLD: &str = r#" +fn main() { + println!("Hello world!"); +} +"#; + +const NOT_UTF8: &[u8] = &[0xff, 0xff, 0xff]; + +fn main() { + let out_dir = tmp_dir(); + + // echo $HELLO_WORLD | rustc - + rustc().arg("-").stdin(HELLO_WORLD).run(); + assert!( + out_dir.join(if !is_windows() { "rust_out" } else { "rust_out.exe" }).try_exists().unwrap() + ); + + // echo $NOT_UTF8 | rustc - + let output = rustc().arg("-").stdin(NOT_UTF8).run_fail(); + let stderr = String::from_utf8(output.stderr).unwrap(); + assert!(stderr.contains("error: couldn't read from stdin, as it did not contain valid UTF-8")); +} |
