Skip to content

Commit 73497b1

Browse files
committed
ignore known paths when deciding whether to abbreviate the output
1 parent 87937d3 commit 73497b1

File tree

2 files changed

+54
-15
lines changed

2 files changed

+54
-15
lines changed

src/tools/compiletest/src/read2.rs

+29-11
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,47 @@ pub use self::imp::read2;
55
use std::io;
66
use std::process::{Child, Output};
77

8-
pub fn read2_abbreviated(mut child: Child) -> io::Result<Output> {
8+
pub fn read2_abbreviated(mut child: Child, exclude_from_len: &[String]) -> io::Result<Output> {
99
use io::Write;
1010
use std::mem::replace;
1111

1212
const HEAD_LEN: usize = 160 * 1024;
1313
const TAIL_LEN: usize = 256 * 1024;
1414

1515
enum ProcOutput {
16-
Full(Vec<u8>),
16+
Full { bytes: Vec<u8>, excluded_len: usize },
1717
Abbreviated { head: Vec<u8>, skipped: usize, tail: Box<[u8]> },
1818
}
1919

2020
impl ProcOutput {
21-
fn extend(&mut self, data: &[u8]) {
21+
fn extend(&mut self, data: &[u8], exclude_from_len: &[String]) {
2222
let new_self = match *self {
23-
ProcOutput::Full(ref mut bytes) => {
23+
ProcOutput::Full { ref mut bytes, ref mut excluded_len } => {
2424
bytes.extend_from_slice(data);
25+
26+
// We had problems in the past with tests failing only in some environments,
27+
// due to the length of the base path pushing the output size over the limit.
28+
//
29+
// To make those failures deterministic across all environments we ignore known
30+
// paths when calculating the string length, while still including the full
31+
// path in the output. This could result in some output being larger than the
32+
// threshold, but it's better than having nondeterministic failures.
33+
for pattern in exclude_from_len {
34+
let pattern_bytes = pattern.as_bytes();
35+
let matches = data
36+
.windows(pattern_bytes.len())
37+
.filter(|window| window == &pattern_bytes)
38+
.count();
39+
*excluded_len += matches * pattern_bytes.len();
40+
}
41+
2542
let new_len = bytes.len();
26-
if new_len <= HEAD_LEN + TAIL_LEN {
43+
if new_len.saturating_sub(*excluded_len) <= HEAD_LEN + TAIL_LEN {
2744
return;
2845
}
29-
let tail = bytes.split_off(new_len - TAIL_LEN).into_boxed_slice();
30-
let head = replace(bytes, Vec::new());
46+
47+
let mut head = replace(bytes, Vec::new());
48+
let tail = head.split_off(new_len - TAIL_LEN).into_boxed_slice();
3149
let skipped = new_len - HEAD_LEN - TAIL_LEN;
3250
ProcOutput::Abbreviated { head, skipped, tail }
3351
}
@@ -47,7 +65,7 @@ pub fn read2_abbreviated(mut child: Child) -> io::Result<Output> {
4765

4866
fn into_bytes(self) -> Vec<u8> {
4967
match self {
50-
ProcOutput::Full(bytes) => bytes,
68+
ProcOutput::Full { bytes, .. } => bytes,
5169
ProcOutput::Abbreviated { mut head, skipped, tail } => {
5270
write!(&mut head, "\n\n<<<<<< SKIPPED {} BYTES >>>>>>\n\n", skipped).unwrap();
5371
head.extend_from_slice(&tail);
@@ -57,15 +75,15 @@ pub fn read2_abbreviated(mut child: Child) -> io::Result<Output> {
5775
}
5876
}
5977

60-
let mut stdout = ProcOutput::Full(Vec::new());
61-
let mut stderr = ProcOutput::Full(Vec::new());
78+
let mut stdout = ProcOutput::Full { bytes: Vec::new(), excluded_len: 0 };
79+
let mut stderr = ProcOutput::Full { bytes: Vec::new(), excluded_len: 0 };
6280

6381
drop(child.stdin.take());
6482
read2(
6583
child.stdout.take().unwrap(),
6684
child.stderr.take().unwrap(),
6785
&mut |is_stdout, data, _| {
68-
if is_stdout { &mut stdout } else { &mut stderr }.extend(data);
86+
if is_stdout { &mut stdout } else { &mut stderr }.extend(data, exclude_from_len);
6987
data.clear();
7088
},
7189
)?;

src/tools/compiletest/src/runtest.rs

+25-4
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use std::hash::{Hash, Hasher};
2828
use std::io::prelude::*;
2929
use std::io::{self, BufReader};
3030
use std::path::{Path, PathBuf};
31-
use std::process::{Command, ExitStatus, Output, Stdio};
31+
use std::process::{Child, Command, ExitStatus, Output, Stdio};
3232
use std::str;
3333

3434
use glob::glob;
@@ -1735,6 +1735,28 @@ impl<'test> TestCx<'test> {
17351735
dylib
17361736
}
17371737

1738+
fn read2_abbreviated(&self, child: Child) -> Output {
1739+
let mut exclude_from_len = Vec::new();
1740+
let mut add_path = |path: &Path| {
1741+
let path = path.display().to_string();
1742+
let windows = path.replace("\\", "\\\\");
1743+
if windows != path {
1744+
exclude_from_len.push(windows);
1745+
}
1746+
exclude_from_len.push(path);
1747+
};
1748+
1749+
// List of strings that will not be measured when determining whether the output is larger
1750+
// than the output truncation threshold.
1751+
//
1752+
// Note: avoid adding a subdirectory of an already excluded directory here, otherwise the
1753+
// same slice of text will be double counted and the truncation might not happen.
1754+
add_path(&self.config.src_base);
1755+
add_path(&self.config.build_base);
1756+
1757+
read2_abbreviated(child, &exclude_from_len).expect("failed to read output")
1758+
}
1759+
17381760
fn compose_and_run(
17391761
&self,
17401762
mut command: Command,
@@ -1769,8 +1791,7 @@ impl<'test> TestCx<'test> {
17691791
child.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap();
17701792
}
17711793

1772-
let Output { status, stdout, stderr } =
1773-
read2_abbreviated(child).expect("failed to read output");
1794+
let Output { status, stdout, stderr } = self.read2_abbreviated(child);
17741795

17751796
let result = ProcRes {
17761797
status,
@@ -2959,7 +2980,7 @@ impl<'test> TestCx<'test> {
29592980
}
29602981
}
29612982

2962-
let output = cmd.spawn().and_then(read2_abbreviated).expect("failed to spawn `make`");
2983+
let output = self.read2_abbreviated(cmd.spawn().expect("failed to spawn `make`"));
29632984
if !output.status.success() {
29642985
let res = ProcRes {
29652986
status: output.status,

0 commit comments

Comments
 (0)