Skip to content

Commit 458e4c8

Browse files
authored
Unrolled build for rust-lang#129973
Rollup merge of rust-lang#129973 - jieyouxu:rework-rmake-stdio, r=Kobzol run_make_support: rename `Command::stdin` to `stdin_buf` and add `std{in,out,err}` config helpers Previously `Command::stdin` was actually just a stdin buffer helper, but this is different from `std::process::Command::stdin`. This is needlessly confusing, and blocks support to add `std{in,out,err}` config helpers that tests may want to use to e.g. redirect to `/dev/ptmx`.
2 parents eb33b43 + 8871ce0 commit 458e4c8

File tree

22 files changed

+116
-46
lines changed

22 files changed

+116
-46
lines changed

src/tools/run-make-support/src/command.rs

+71-14
Original file line numberDiff line numberDiff line change
@@ -15,34 +15,81 @@ use crate::{
1515
/// This is a custom command wrapper that simplifies working with commands and makes it easier to
1616
/// ensure that we check the exit status of executed processes.
1717
///
18-
/// # A [`Command`] must be executed
18+
/// # A [`Command`] must be executed exactly once
1919
///
2020
/// A [`Command`] is armed by a [`DropBomb`] on construction to enforce that it will be executed. If
2121
/// a [`Command`] is constructed but never executed, the drop bomb will explode and cause the test
2222
/// to panic. Execution methods [`run`] and [`run_fail`] will defuse the drop bomb. A test
2323
/// containing constructed but never executed commands is dangerous because it can give a false
2424
/// sense of confidence.
2525
///
26+
/// Each [`Command`] invocation can also only be executed once, because we want to enforce
27+
/// `std{in,out,err}` config via [`std::process::Stdio`] but [`std::process::Stdio`] is not
28+
/// cloneable.
29+
///
30+
/// In this sense, [`Command`] exhibits linear type semantics but enforced at run-time.
31+
///
2632
/// [`run`]: Self::run
2733
/// [`run_fail`]: Self::run_fail
2834
/// [`run_unchecked`]: Self::run_unchecked
2935
#[derive(Debug)]
3036
pub struct Command {
3137
cmd: StdCommand,
32-
stdin: Option<Box<[u8]>>,
38+
// Convience for providing a quick stdin buffer.
39+
stdin_buf: Option<Box<[u8]>>,
40+
41+
// Configurations for child process's std{in,out,err} handles.
42+
stdin: Option<Stdio>,
43+
stdout: Option<Stdio>,
44+
stderr: Option<Stdio>,
45+
46+
// Emulate linear type semantics.
3347
drop_bomb: DropBomb,
48+
already_executed: bool,
3449
}
3550

3651
impl Command {
3752
#[track_caller]
3853
pub fn new<P: AsRef<OsStr>>(program: P) -> Self {
3954
let program = program.as_ref();
40-
Self { cmd: StdCommand::new(program), stdin: None, drop_bomb: DropBomb::arm(program) }
55+
Self {
56+
cmd: StdCommand::new(program),
57+
stdin_buf: None,
58+
drop_bomb: DropBomb::arm(program),
59+
stdin: None,
60+
stdout: None,
61+
stderr: None,
62+
already_executed: false,
63+
}
4164
}
4265

43-
/// Specify a stdin input
44-
pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
45-
self.stdin = Some(input.as_ref().to_vec().into_boxed_slice());
66+
/// Specify a stdin input buffer. This is a convenience helper,
67+
pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
68+
self.stdin_buf = Some(input.as_ref().to_vec().into_boxed_slice());
69+
self
70+
}
71+
72+
/// Configuration for the child process’s standard input (stdin) handle.
73+
///
74+
/// See [`std::process::Command::stdin`].
75+
pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self {
76+
self.stdin = Some(cfg.into());
77+
self
78+
}
79+
80+
/// Configuration for the child process’s standard output (stdout) handle.
81+
///
82+
/// See [`std::process::Command::stdout`].
83+
pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self {
84+
self.stdout = Some(cfg.into());
85+
self
86+
}
87+
88+
/// Configuration for the child process’s standard error (stderr) handle.
89+
///
90+
/// See [`std::process::Command::stderr`].
91+
pub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self {
92+
self.stderr = Some(cfg.into());
4693
self
4794
}
4895

@@ -105,6 +152,8 @@ impl Command {
105152
}
106153

107154
/// Run the constructed command and assert that it is successfully run.
155+
///
156+
/// By default, std{in,out,err} are [`Stdio::piped()`].
108157
#[track_caller]
109158
pub fn run(&mut self) -> CompletedProcess {
110159
let output = self.command_output();
@@ -115,6 +164,8 @@ impl Command {
115164
}
116165

117166
/// Run the constructed command and assert that it does not successfully run.
167+
///
168+
/// By default, std{in,out,err} are [`Stdio::piped()`].
118169
#[track_caller]
119170
pub fn run_fail(&mut self) -> CompletedProcess {
120171
let output = self.command_output();
@@ -124,24 +175,30 @@ impl Command {
124175
output
125176
}
126177

127-
/// Run the command but do not check its exit status.
128-
/// Only use if you explicitly don't care about the exit status.
129-
/// Prefer to use [`Self::run`] and [`Self::run_fail`]
130-
/// whenever possible.
178+
/// Run the command but do not check its exit status. Only use if you explicitly don't care
179+
/// about the exit status.
180+
///
181+
/// Prefer to use [`Self::run`] and [`Self::run_fail`] whenever possible.
131182
#[track_caller]
132183
pub fn run_unchecked(&mut self) -> CompletedProcess {
133184
self.command_output()
134185
}
135186

136187
#[track_caller]
137188
fn command_output(&mut self) -> CompletedProcess {
189+
if self.already_executed {
190+
panic!("command was already executed");
191+
} else {
192+
self.already_executed = true;
193+
}
194+
138195
self.drop_bomb.defuse();
139196
// let's make sure we piped all the input and outputs
140-
self.cmd.stdin(Stdio::piped());
141-
self.cmd.stdout(Stdio::piped());
142-
self.cmd.stderr(Stdio::piped());
197+
self.cmd.stdin(self.stdin.take().unwrap_or(Stdio::piped()));
198+
self.cmd.stdout(self.stdout.take().unwrap_or(Stdio::piped()));
199+
self.cmd.stderr(self.stderr.take().unwrap_or(Stdio::piped()));
143200

144-
let output = if let Some(input) = &self.stdin {
201+
let output = if let Some(input) = &self.stdin_buf {
145202
let mut child = self.cmd.spawn().unwrap();
146203

147204
{

src/tools/run-make-support/src/external_deps/llvm.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -227,9 +227,10 @@ impl LlvmFilecheck {
227227
Self { cmd }
228228
}
229229

230-
/// Pipe a read file into standard input containing patterns that will be matched against the .patterns(path) call.
231-
pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
232-
self.cmd.stdin(input);
230+
/// Provide a buffer representing standard input containing patterns that will be matched
231+
/// against the `.patterns(path)` call.
232+
pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
233+
self.cmd.stdin_buf(input);
233234
self
234235
}
235236

src/tools/run-make-support/src/external_deps/rustc.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -291,9 +291,9 @@ impl Rustc {
291291
self
292292
}
293293

294-
/// Specify a stdin input
295-
pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
296-
self.cmd.stdin(input);
294+
/// Specify a stdin input buffer.
295+
pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
296+
self.cmd.stdin_buf(input);
297297
self
298298
}
299299

src/tools/run-make-support/src/external_deps/rustdoc.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,9 @@ impl Rustdoc {
8585
self
8686
}
8787

88-
/// Specify a stdin input
89-
pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
90-
self.cmd.stdin(input);
88+
/// Specify a stdin input buffer.
89+
pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
90+
self.cmd.stdin_buf(input);
9191
self
9292
}
9393

src/tools/run-make-support/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,15 @@ pub mod rfs {
3434
}
3535

3636
// Re-exports of third-party library crates.
37+
// tidy-alphabetical-start
3738
pub use bstr;
3839
pub use gimli;
3940
pub use libc;
4041
pub use object;
4142
pub use regex;
4243
pub use serde_json;
4344
pub use wasmparser;
45+
// tidy-alphabetical-end
4446

4547
// Re-exports of external dependencies.
4648
pub use external_deps::{c_build, cc, clang, htmldocck, llvm, python, rustc, rustdoc};

tests/run-make/clear-error-blank-output/rmake.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88
use run_make_support::rustc;
99

1010
fn main() {
11-
let output = rustc().output("").stdin(b"fn main() {}").run_fail();
11+
let output = rustc().output("").stdin_buf(b"fn main() {}").run_fail();
1212
output.assert_stderr_not_contains("panic");
1313
}

tests/run-make/comment-section/rmake.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ fn main() {
1414

1515
rustc()
1616
.arg("-")
17-
.stdin("fn main() {}")
17+
.stdin_buf("fn main() {}")
1818
.emit("link,obj")
1919
.arg("-Csave-temps")
2020
.target(target)

tests/run-make/compile-stdin/rmake.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88
use run_make_support::{run, rustc};
99

1010
fn main() {
11-
rustc().arg("-").stdin("fn main() {}").run();
11+
rustc().arg("-").stdin_buf("fn main() {}").run();
1212
run("rust_out");
1313
}

tests/run-make/libtest-junit/rmake.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ fn run_tests(extra_args: &[&str], expected_file: &str) {
2121
.run_fail();
2222
let test_stdout = &cmd_out.stdout_utf8();
2323

24-
python_command().arg("validate_junit.py").stdin(test_stdout).run();
24+
python_command().arg("validate_junit.py").stdin_buf(test_stdout).run();
2525

2626
diff()
2727
.expected_file(expected_file)

tests/run-make/llvm-ident/rmake.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fn main() {
1717
.codegen_units(16)
1818
.opt_level("2")
1919
.target(&env_var("TARGET"))
20-
.stdin("fn main(){}")
20+
.stdin_buf("fn main(){}")
2121
.run();
2222

2323
// `llvm-dis` is used here since `--emit=llvm-ir` does not emit LLVM IR

tests/run-make/llvm-outputs/rmake.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ fn main() {
1111
let p = cwd();
1212
path_bc = p.join("nonexistant_dir_bc");
1313
path_ir = p.join("nonexistant_dir_ir");
14-
rustc().input("-").stdin("fn main() {}").out_dir(&path_bc).emit("llvm-bc").run();
15-
rustc().input("-").stdin("fn main() {}").out_dir(&path_ir).emit("llvm-ir").run();
14+
rustc().input("-").stdin_buf("fn main() {}").out_dir(&path_bc).emit("llvm-bc").run();
15+
rustc().input("-").stdin_buf("fn main() {}").out_dir(&path_ir).emit("llvm-ir").run();
1616
assert!(path_bc.exists());
1717
assert!(path_ir.exists());
1818
});

tests/run-make/no-builtins-attribute/rmake.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ use run_make_support::{llvm_filecheck, rfs, rustc};
99
fn main() {
1010
rustc().input("no_builtins.rs").emit("link").run();
1111
rustc().input("main.rs").emit("llvm-ir").run();
12-
llvm_filecheck().patterns("filecheck.main.txt").stdin(rfs::read("main.ll")).run();
12+
llvm_filecheck().patterns("filecheck.main.txt").stdin_buf(rfs::read("main.ll")).run();
1313
}

tests/run-make/pgo-branch-weights/rmake.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,8 @@ fn main() {
3535
.codegen_units(1)
3636
.emit("llvm-ir")
3737
.run();
38-
llvm_filecheck().patterns("filecheck-patterns.txt").stdin(rfs::read("interesting.ll")).run();
38+
llvm_filecheck()
39+
.patterns("filecheck-patterns.txt")
40+
.stdin_buf(rfs::read("interesting.ll"))
41+
.run();
3942
}

tests/run-make/pgo-indirect-call-promotion/rmake.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,8 @@ fn main() {
2929
.codegen_units(1)
3030
.emit("llvm-ir")
3131
.run();
32-
llvm_filecheck().patterns("filecheck-patterns.txt").stdin(rfs::read("interesting.ll")).run();
32+
llvm_filecheck()
33+
.patterns("filecheck-patterns.txt")
34+
.stdin_buf(rfs::read("interesting.ll"))
35+
.run();
3336
}

tests/run-make/pgo-use/rmake.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,5 @@ fn main() {
5151
let lines: Vec<_> = ir.lines().rev().collect();
5252
let mut reversed_ir = lines.join("\n");
5353
reversed_ir.push('\n');
54-
llvm_filecheck().patterns("filecheck-patterns.txt").stdin(reversed_ir.as_bytes()).run();
54+
llvm_filecheck().patterns("filecheck-patterns.txt").stdin_buf(reversed_ir.as_bytes()).run();
5555
}

tests/run-make/separate-link/rmake.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use run_make_support::{run, rustc};
99

1010
fn main() {
11-
rustc().stdin(b"fn main(){}").arg("-Zno-link").arg("-").run();
11+
rustc().stdin_buf(b"fn main(){}").arg("-Zno-link").arg("-").run();
1212
rustc().arg("-Zlink-only").input("rust_out.rlink").run();
1313
run("rust_out");
1414
}

tests/run-make/static-pie/rmake.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ fn ok_compiler_version(compiler: &str) -> bool {
2828
}
2929

3030
let compiler_output =
31-
cmd(compiler).stdin(trigger).arg("-").arg("-E").arg("-x").arg("c").run().stdout_utf8();
31+
cmd(compiler).stdin_buf(trigger).arg("-").arg("-E").arg("-x").arg("c").run().stdout_utf8();
3232
let re = Regex::new(r"(?m)^(\d+)").unwrap();
3333
let version: u32 =
3434
re.captures(&compiler_output).unwrap().get(1).unwrap().as_str().parse().unwrap();

tests/run-make/stdin-rustc/rmake.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ const NOT_UTF8: &[u8] = &[0xff, 0xff, 0xff];
1414

1515
fn main() {
1616
// echo $HELLO_WORLD | rustc -
17-
rustc().arg("-").stdin(HELLO_WORLD).run();
17+
rustc().arg("-").stdin_buf(HELLO_WORLD).run();
1818
assert!(
1919
PathBuf::from(if !is_windows() { "rust_out" } else { "rust_out.exe" })
2020
.try_exists()
2121
.unwrap()
2222
);
2323

2424
// echo $NOT_UTF8 | rustc -
25-
rustc().arg("-").stdin(NOT_UTF8).run_fail().assert_stderr_contains(
25+
rustc().arg("-").stdin_buf(NOT_UTF8).run_fail().assert_stderr_contains(
2626
"error: couldn't read from stdin, as it did not contain valid UTF-8",
2727
);
2828
}

tests/run-make/stdin-rustdoc/rmake.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ fn main() {
1515
let out_dir = PathBuf::from("doc");
1616

1717
// rustdoc -
18-
rustdoc().arg("-").out_dir(&out_dir).stdin(INPUT).run();
18+
rustdoc().arg("-").out_dir(&out_dir).stdin_buf(INPUT).run();
1919
assert!(out_dir.join("rust_out/struct.F.html").try_exists().unwrap());
2020

2121
// rustdoc --test -
22-
rustdoc().arg("--test").arg("-").stdin(INPUT).run();
22+
rustdoc().arg("--test").arg("-").stdin_buf(INPUT).run();
2323

2424
// rustdoc file.rs -
2525
rustdoc().arg("file.rs").arg("-").run_fail();

tests/run-make/sysroot-crates-are-unstable/rmake.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ fn check_crate_is_unstable(cr: &Crate) {
3434
.target(target())
3535
.extern_(name, path)
3636
.input("-")
37-
.stdin(format!("extern crate {name};"))
37+
.stdin_buf(format!("extern crate {name};"))
3838
.run_fail();
3939

4040
// Make sure it failed for the intended reason, not some other reason.

tests/run-make/unknown-mod-stdin/rmake.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
use run_make_support::{diff, rustc};
1313

1414
fn main() {
15-
let out = rustc().crate_type("rlib").stdin(b"mod unknown;").arg("-").run_fail();
15+
let out = rustc().crate_type("rlib").stdin_buf(b"mod unknown;").arg("-").run_fail();
1616
diff()
1717
.actual_text("actual-stdout", out.stdout_utf8())
1818
.expected_file("unknown-mod.stdout")

tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -78,19 +78,23 @@ fn check(func_re: &str, mut checks: &str) {
7878
// This is because frame pointers are optional, and them being enabled requires
7979
// an additional `popq` in the pattern checking file.
8080
if func_re == "std::io::stdio::_print::[[:alnum:]]+" {
81-
let output = llvm_filecheck().stdin(&dump).patterns(checks).run_unchecked();
81+
let output = llvm_filecheck().stdin_buf(&dump).patterns(checks).run_unchecked();
8282
if !output.status().success() {
8383
checks = "print.without_frame_pointers.checks";
84-
llvm_filecheck().stdin(&dump).patterns(checks).run();
84+
llvm_filecheck().stdin_buf(&dump).patterns(checks).run();
8585
}
8686
} else {
87-
llvm_filecheck().stdin(&dump).patterns(checks).run();
87+
llvm_filecheck().stdin_buf(&dump).patterns(checks).run();
8888
}
8989
if !["rust_plus_one_global_asm", "cmake_plus_one_c_global_asm", "cmake_plus_one_cxx_global_asm"]
9090
.contains(&func_re)
9191
{
9292
// The assembler cannot avoid explicit `ret` instructions. Sequences
9393
// of `shlq $0x0, (%rsp); lfence; retq` are used instead.
94-
llvm_filecheck().args(&["--implicit-check-not", "ret"]).stdin(dump).patterns(checks).run();
94+
llvm_filecheck()
95+
.args(&["--implicit-check-not", "ret"])
96+
.stdin_buf(dump)
97+
.patterns(checks)
98+
.run();
9599
}
96100
}

0 commit comments

Comments
 (0)