Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c2ae2e0

Browse files
committed
Implement compiletest --new-output-capture, in stable Rust
1 parent 5d71a8a commit c2ae2e0

File tree

4 files changed

+76
-2
lines changed

4 files changed

+76
-2
lines changed

‎src/tools/compiletest/src/common.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,10 @@ pub struct Config {
667667
/// to avoid `!nocapture` double-negatives.
668668
pub nocapture: bool,
669669

670+
/// True if the experimental new output-capture implementation should be
671+
/// used, avoiding the need for `#![feature(internal_output_capture)]`.
672+
pub new_output_capture: bool,
673+
670674
/// Needed both to construct [`build_helper::git::GitConfig`].
671675
pub nightly_branch: String,
672676
pub git_merge_commit_email: String,
@@ -784,6 +788,7 @@ impl Config {
784788
builtin_cfg_names: Default::default(),
785789
supported_crate_types: Default::default(),
786790
nocapture: Default::default(),
791+
new_output_capture: Default::default(),
787792
nightly_branch: Default::default(),
788793
git_merge_commit_email: Default::default(),
789794
profiler_runtime: Default::default(),

‎src/tools/compiletest/src/executor.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,12 +168,17 @@ enum CaptureKind {
168168
/// Use the old output-capture implementation, which relies on the unstable
169169
/// library feature `#![feature(internal_output_capture)]`.
170170
Old { buf: Arc<Mutex<Vec<u8>>> },
171+
172+
/// Use the new output-capture implementation, which only uses stable Rust.
173+
New { buf: output_capture::CaptureBuf },
171174
}
172175

173176
impl CaptureKind {
174177
fn for_config(config: &Config) -> Self {
175178
if config.nocapture {
176179
Self::None
180+
} else if config.new_output_capture {
181+
Self::New { buf: output_capture::CaptureBuf::new() }
177182
} else {
178183
// Create a capure buffer for `io::set_output_capture`.
179184
Self::Old { buf: Default::default() }
@@ -184,21 +189,30 @@ impl CaptureKind {
184189
match self {
185190
Self::None => false,
186191
Self::Old { .. } => true,
192+
Self::New { .. } => true,
187193
}
188194
}
189195

190196
fn stdout(&self) -> &dyn ConsoleOut {
191-
&output_capture::Stdout
197+
self.capture_buf_or(&output_capture::Stdout)
192198
}
193199

194200
fn stderr(&self) -> &dyn ConsoleOut {
195-
&output_capture::Stderr
201+
self.capture_buf_or(&output_capture::Stderr)
202+
}
203+
204+
fn capture_buf_or<'a>(&'a self, fallback: &'a dyn ConsoleOut) -> &'a dyn ConsoleOut {
205+
match self {
206+
Self::None | Self::Old { .. } => fallback,
207+
Self::New { buf } => buf,
208+
}
196209
}
197210

198211
fn into_inner(self) -> Option<Vec<u8>> {
199212
match self {
200213
Self::None => None,
201214
Self::Old { buf } => Some(buf.lock().unwrap_or_else(|e| e.into_inner()).to_vec()),
215+
Self::New { buf } => Some(buf.into_inner().into()),
202216
}
203217
}
204218
}

‎src/tools/compiletest/src/lib.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
178178
// FIXME: Temporarily retained so we can point users to `--no-capture`
179179
.optflag("", "nocapture", "")
180180
.optflag("", "no-capture", "don't capture stdout/stderr of tests")
181+
.optopt(
182+
"N",
183+
"new-output-capture",
184+
"enables or disables the new output-capture implementation",
185+
"off|on",
186+
)
181187
.optflag("", "profiler-runtime", "is the profiler runtime enabled for this target")
182188
.optflag("h", "help", "show this message")
183189
.reqopt("", "channel", "current Rust channel", "CHANNEL")
@@ -462,6 +468,14 @@ pub fn parse_config(args: Vec<String>) -> Config {
462468
supported_crate_types: OnceLock::new(),
463469

464470
nocapture: matches.opt_present("no-capture"),
471+
new_output_capture: {
472+
let value = matches
473+
.opt_str("new-output-capture")
474+
.or_else(|| env::var("COMPILETEST_NEW_OUTPUT_CAPTURE").ok())
475+
.unwrap_or_else(|| "off".to_owned());
476+
parse_bool_option(&value)
477+
.unwrap_or_else(|| panic!("unknown `--new-output-capture` value `{value}` given"))
478+
},
465479

466480
nightly_branch: matches.opt_str("nightly-branch").unwrap(),
467481
git_merge_commit_email: matches.opt_str("git-merge-commit-email").unwrap(),
@@ -477,6 +491,19 @@ pub fn parse_config(args: Vec<String>) -> Config {
477491
}
478492
}
479493

494+
/// Parses the same set of boolean values accepted by rustc command-line arguments.
495+
///
496+
/// Accepting all of these values is more complicated than just picking one
497+
/// pair, but has the advantage that contributors who are used to rustc
498+
/// shouldn't have to think about which values are legal.
499+
fn parse_bool_option(value: &str) -> Option<bool> {
500+
match value {
501+
"off" | "no" | "n" | "false" => Some(false),
502+
"on" | "yes" | "y" | "true" => Some(true),
503+
_ => None,
504+
}
505+
}
506+
480507
pub fn opt_str(maybestr: &Option<String>) -> &str {
481508
match *maybestr {
482509
None => "(none)",

‎src/tools/compiletest/src/output_capture.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::fmt;
22
use std::panic::RefUnwindSafe;
3+
use std::sync::Mutex;
34

45
pub trait ConsoleOut: fmt::Debug + RefUnwindSafe {
56
fn write_fmt(&self, args: fmt::Arguments<'_>);
@@ -22,3 +23,30 @@ impl ConsoleOut for Stderr {
2223
eprint!("{args}");
2324
}
2425
}
26+
27+
pub(crate) struct CaptureBuf {
28+
inner: Mutex<String>,
29+
}
30+
31+
impl CaptureBuf {
32+
pub(crate) fn new() -> Self {
33+
Self { inner: Mutex::new(String::new()) }
34+
}
35+
36+
pub(crate) fn into_inner(self) -> String {
37+
self.inner.into_inner().unwrap_or_else(|e| e.into_inner())
38+
}
39+
}
40+
41+
impl fmt::Debug for CaptureBuf {
42+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43+
f.debug_struct("CaptureBuf").finish_non_exhaustive()
44+
}
45+
}
46+
47+
impl ConsoleOut for CaptureBuf {
48+
fn write_fmt(&self, args: fmt::Arguments<'_>) {
49+
let mut s = self.inner.lock().unwrap_or_else(|e| e.into_inner());
50+
<String as fmt::Write>::write_fmt(&mut s, args).unwrap();
51+
}
52+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /