Skip to content

Commit e315056

Browse files
committed
Auto merge of #50400 - ehuss:compiletest-revisions, r=alexcrichton
compiletest: Run revisions as independent tests. Fixes #47604. - The output of each test is now in its own directory. - "auxiliary" output is now under the respective test directory. - `stage_id` removed from filenames, and instead placed in the stamp file as a hash. This helps keep path lengths down for Windows. In brief, the new layout looks like this: ``` <build_base>/<relative_dir>/<testname>.<revision>.<mode>/ stamp <testname>.err <testname>.out a (binary) auxiliary/lib<auxname>.dylib auxiliary/<auxname>/<auxname>.err auxiliary/<auxname>/<auxname>.out ``` (revision and mode are optional)
2 parents ed9a29a + b8473de commit e315056

File tree

11 files changed

+473
-390
lines changed

11 files changed

+473
-390
lines changed

src/test/ui-fulldeps/update-references.sh

+12-12
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,18 @@ MYDIR=$(dirname $0)
3131
BUILD_DIR="$1"
3232
shift
3333

34+
shopt -s nullglob
35+
3436
while [[ "$1" != "" ]]; do
35-
STDERR_NAME="${1/%.rs/.stderr}"
36-
STDOUT_NAME="${1/%.rs/.stdout}"
37+
for EXT in "stderr" "stdout"; do
38+
for OUT_NAME in $BUILD_DIR/${1%.rs}*/*$EXT; do
39+
OUT_DIR=`dirname "$1"`
40+
OUT_BASE=`basename "$OUT_NAME"`
41+
if ! (diff $OUT_NAME $MYDIR/$OUT_DIR/$OUT_BASE >& /dev/null); then
42+
echo updating $MYDIR/$OUT_DIR/$OUT_BASE
43+
cp $OUT_NAME $MYDIR/$OUT_DIR
44+
fi
45+
done
46+
done
3747
shift
38-
if [ -f $BUILD_DIR/$STDOUT_NAME ] && \
39-
! (diff $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME >& /dev/null); then
40-
echo updating $MYDIR/$STDOUT_NAME
41-
cp $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME
42-
fi
43-
if [ -f $BUILD_DIR/$STDERR_NAME ] && \
44-
! (diff $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME >& /dev/null); then
45-
echo updating $MYDIR/$STDERR_NAME
46-
cp $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME
47-
fi
4848
done

src/test/ui/update-references.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ shopt -s nullglob
3535

3636
while [[ "$1" != "" ]]; do
3737
for EXT in "stderr" "stdout" "fixed"; do
38-
for OUT_NAME in $BUILD_DIR/${1%.rs}.*$EXT; do
38+
for OUT_NAME in $BUILD_DIR/${1%.rs}*/*$EXT; do
3939
OUT_DIR=`dirname "$1"`
4040
OUT_BASE=`basename "$OUT_NAME"`
4141
if ! (diff $OUT_NAME $MYDIR/$OUT_DIR/$OUT_BASE >& /dev/null); then

src/tools/compiletest/src/common.rs

+51-11
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@
1010
pub use self::Mode::*;
1111

1212
use std::fmt;
13+
use std::path::{Path, PathBuf};
1314
use std::str::FromStr;
14-
use std::path::PathBuf;
1515

1616
use test::ColorConfig;
17+
use util::PathBufExt;
1718

1819
#[derive(Clone, Copy, PartialEq, Debug)]
1920
pub enum Mode {
@@ -103,7 +104,7 @@ pub enum CompareMode {
103104
impl CompareMode {
104105
pub(crate) fn to_str(&self) -> &'static str {
105106
match *self {
106-
CompareMode::Nll => "nll"
107+
CompareMode::Nll => "nll",
107108
}
108109
}
109110

@@ -245,24 +246,28 @@ pub struct Config {
245246
pub nodejs: Option<String>,
246247
}
247248

248-
#[derive(Clone)]
249+
#[derive(Debug, Clone)]
249250
pub struct TestPaths {
250251
pub file: PathBuf, // e.g., compile-test/foo/bar/baz.rs
251-
pub base: PathBuf, // e.g., compile-test, auxiliary
252252
pub relative_dir: PathBuf, // e.g., foo/bar
253253
}
254254

255255
/// Used by `ui` tests to generate things like `foo.stderr` from `foo.rs`.
256-
pub fn expected_output_path(testpaths: &TestPaths,
257-
revision: Option<&str>,
258-
compare_mode: &Option<CompareMode>,
259-
kind: &str) -> PathBuf {
260-
256+
pub fn expected_output_path(
257+
testpaths: &TestPaths,
258+
revision: Option<&str>,
259+
compare_mode: &Option<CompareMode>,
260+
kind: &str,
261+
) -> PathBuf {
261262
assert!(UI_EXTENSIONS.contains(&kind));
262263
let mut parts = Vec::new();
263264

264-
if let Some(x) = revision { parts.push(x); }
265-
if let Some(ref x) = *compare_mode { parts.push(x.to_str()); }
265+
if let Some(x) = revision {
266+
parts.push(x);
267+
}
268+
if let Some(ref x) = *compare_mode {
269+
parts.push(x.to_str());
270+
}
266271
parts.push(kind);
267272

268273
let extension = parts.join(".");
@@ -273,3 +278,38 @@ pub const UI_EXTENSIONS: &[&str] = &[UI_STDERR, UI_STDOUT, UI_FIXED];
273278
pub const UI_STDERR: &str = "stderr";
274279
pub const UI_STDOUT: &str = "stdout";
275280
pub const UI_FIXED: &str = "fixed";
281+
282+
/// Absolute path to the directory where all output for all tests in the given
283+
/// `relative_dir` group should reside. Example:
284+
/// /path/to/build/host-triple/test/ui/relative/
285+
/// This is created early when tests are collected to avoid race conditions.
286+
pub fn output_relative_path(config: &Config, relative_dir: &Path) -> PathBuf {
287+
config.build_base.join(relative_dir)
288+
}
289+
290+
/// Generates a unique name for the test, such as `testname.revision.mode`.
291+
pub fn output_testname_unique(
292+
config: &Config,
293+
testpaths: &TestPaths,
294+
revision: Option<&str>,
295+
) -> PathBuf {
296+
let mode = config.compare_mode.as_ref().map_or("", |m| m.to_str());
297+
PathBuf::from(&testpaths.file.file_stem().unwrap())
298+
.with_extra_extension(revision.unwrap_or(""))
299+
.with_extra_extension(mode)
300+
}
301+
302+
/// Absolute path to the directory where all output for the given
303+
/// test/revision should reside. Example:
304+
/// /path/to/build/host-triple/test/ui/relative/testname.revision.mode/
305+
pub fn output_base_dir(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
306+
output_relative_path(config, &testpaths.relative_dir)
307+
.join(output_testname_unique(config, testpaths, revision))
308+
}
309+
310+
/// Absolute path to the base filename used as output for the given
311+
/// test/revision. Example:
312+
/// /path/to/build/host-triple/test/ui/relative/testname.revision.mode/testname
313+
pub fn output_base_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
314+
output_base_dir(config, testpaths, revision).join(testpaths.file.file_stem().unwrap())
315+
}

src/tools/compiletest/src/errors.rs

+41-29
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ use self::WhichLine::*;
1111

1212
use std::fmt;
1313
use std::fs::File;
14-
use std::io::BufReader;
1514
use std::io::prelude::*;
15+
use std::io::BufReader;
1616
use std::path::Path;
1717
use std::str::FromStr;
1818

@@ -35,8 +35,7 @@ impl FromStr for ErrorKind {
3535
"ERROR" => Ok(ErrorKind::Error),
3636
"NOTE" => Ok(ErrorKind::Note),
3737
"SUGGESTION" => Ok(ErrorKind::Suggestion),
38-
"WARN" |
39-
"WARNING" => Ok(ErrorKind::Warning),
38+
"WARN" | "WARNING" => Ok(ErrorKind::Warning),
4039
_ => Err(()),
4140
}
4241
}
@@ -101,61 +100,74 @@ pub fn load_errors(testfile: &Path, cfg: Option<&str>) -> Vec<Error> {
101100
rdr.lines()
102101
.enumerate()
103102
.filter_map(|(line_num, line)| {
104-
parse_expected(last_nonfollow_error, line_num + 1, &line.unwrap(), &tag)
105-
.map(|(which, error)| {
103+
parse_expected(last_nonfollow_error, line_num + 1, &line.unwrap(), &tag).map(
104+
|(which, error)| {
106105
match which {
107106
FollowPrevious(_) => {}
108107
_ => last_nonfollow_error = Some(error.line_num),
109108
}
110109
error
111-
})
110+
},
111+
)
112112
})
113113
.collect()
114114
}
115115

116-
fn parse_expected(last_nonfollow_error: Option<usize>,
117-
line_num: usize,
118-
line: &str,
119-
tag: &str)
120-
-> Option<(WhichLine, Error)> {
116+
fn parse_expected(
117+
last_nonfollow_error: Option<usize>,
118+
line_num: usize,
119+
line: &str,
120+
tag: &str,
121+
) -> Option<(WhichLine, Error)> {
121122
let start = match line.find(tag) {
122123
Some(i) => i,
123124
None => return None,
124125
};
125126
let (follow, adjusts) = if line[start + tag.len()..].chars().next().unwrap() == '|' {
126127
(true, 0)
127128
} else {
128-
(false, line[start + tag.len()..].chars().take_while(|c| *c == '^').count())
129+
(
130+
false,
131+
line[start + tag.len()..]
132+
.chars()
133+
.take_while(|c| *c == '^')
134+
.count(),
135+
)
129136
};
130137
let kind_start = start + tag.len() + adjusts + (follow as usize);
131138
let (kind, msg);
132139
match line[kind_start..]
133140
.split_whitespace()
134141
.next()
135142
.expect("Encountered unexpected empty comment")
136-
.parse::<ErrorKind>() {
143+
.parse::<ErrorKind>()
144+
{
137145
Ok(k) => {
138146
// If we find `//~ ERROR foo` or something like that:
139147
kind = Some(k);
140148
let letters = line[kind_start..].chars();
141-
msg = letters.skip_while(|c| c.is_whitespace())
149+
msg = letters
150+
.skip_while(|c| c.is_whitespace())
142151
.skip_while(|c| !c.is_whitespace())
143152
.collect::<String>();
144153
}
145154
Err(_) => {
146155
// Otherwise we found `//~ foo`:
147156
kind = None;
148157
let letters = line[kind_start..].chars();
149-
msg = letters.skip_while(|c| c.is_whitespace())
158+
msg = letters
159+
.skip_while(|c| c.is_whitespace())
150160
.collect::<String>();
151161
}
152162
}
153163
let msg = msg.trim().to_owned();
154164

155165
let (which, line_num) = if follow {
156166
assert_eq!(adjusts, 0, "use either //~| or //~^, not both.");
157-
let line_num = last_nonfollow_error.expect("encountered //~| without \
158-
preceding //~^ line.");
167+
let line_num = last_nonfollow_error.expect(
168+
"encountered //~| without \
169+
preceding //~^ line.",
170+
);
159171
(FollowPrevious(line_num), line_num)
160172
} else {
161173
let which = if adjusts > 0 {
@@ -167,16 +179,16 @@ fn parse_expected(last_nonfollow_error: Option<usize>,
167179
(which, line_num)
168180
};
169181

170-
debug!("line={} tag={:?} which={:?} kind={:?} msg={:?}",
171-
line_num,
172-
tag,
173-
which,
174-
kind,
175-
msg);
176-
Some((which,
177-
Error {
178-
line_num,
179-
kind,
180-
msg,
181-
}))
182+
debug!(
183+
"line={} tag={:?} which={:?} kind={:?} msg={:?}",
184+
line_num, tag, which, kind, msg
185+
);
186+
Some((
187+
which,
188+
Error {
189+
line_num,
190+
kind,
191+
msg,
192+
},
193+
))
182194
}

0 commit comments

Comments
 (0)