Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/zyntax_lua/conformance/KNOWN_FAILURES
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ official_suite/complete_all 49075da
official_suite/main_lua 49075da

errors/library_names.lua 0903215
errors/c_stack.lua 4379825 failing-on windows
gc/finalize_after_return.lua 18b4bab failing-on windows
errors/c_stack.lua 4379825 unix
gc/finalize_after_return.lua 18b4bab linux

# C modules load where the executable exports the C API: not on Windows yet.
official/attrib.lua c17ca09 unix
Expand Down
36 changes: 31 additions & 5 deletions crates/zyntax_python/tests/conformance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,20 +89,26 @@ fn on_family(family: &str) -> bool {
struct Outcome {
stdout: String,
status: i32,
/// The last lines the program wrote to stderr, shown when a case
/// fails; never compared.
stderr_tail: String,
}

/// How many lines of a failing case's stderr are shown.
const STDERR_LINES: usize = 20;

/// Run a command with a deadline. A conformance case that hangs is a
/// failure that must be reported, not a suite that never finishes.
fn run_bounded(mut cmd: Command, limit: Duration) -> Outcome {
// Only stdout is compared. A piped stderr nobody reads would stall
// the child once it filled the pipe.
cmd.stdout(Stdio::piped()).stderr(Stdio::null());
// Only stdout is compared; stderr is kept for the report.
cmd.stdout(Stdio::piped()).stderr(Stdio::piped());
let mut child = match cmd.spawn() {
Ok(c) => c,
Err(e) => {
return Outcome {
stdout: format!("<could not start: {e}>"),
status: -1,
stderr_tail: String::new(),
};
}
};
Expand All @@ -115,6 +121,15 @@ fn run_bounded(mut cmd: Command, limit: Duration) -> Outcome {
out
})
});
let err_reader = child.stderr.take().map(|mut s| {
std::thread::spawn(move || {
let mut out = Vec::new();
let _ = s.read_to_end(&mut out);
let text = String::from_utf8_lossy(&out);
let lines: Vec<&str> = text.lines().collect();
lines[lines.len().saturating_sub(STDERR_LINES)..].join("\n")
})
});
let collect = |reader: Option<std::thread::JoinHandle<String>>| {
reader.and_then(|r| r.join().ok()).unwrap_or_default()
};
Expand All @@ -125,6 +140,7 @@ fn run_bounded(mut cmd: Command, limit: Duration) -> Outcome {
return Outcome {
stdout: collect(reader),
status: status.code().unwrap_or(-2),
stderr_tail: collect(err_reader),
};
}
Ok(None) if start.elapsed() > limit => {
Expand All @@ -134,13 +150,15 @@ fn run_bounded(mut cmd: Command, limit: Duration) -> Outcome {
return Outcome {
stdout: format!("<timed out after {:?}>", limit),
status: -3,
stderr_tail: collect(err_reader),
};
}
Ok(None) => std::thread::sleep(Duration::from_millis(20)),
Err(e) => {
return Outcome {
stdout: format!("<wait failed: {e}>"),
status: -1,
stderr_tail: String::new(),
};
}
}
Expand All @@ -163,6 +181,7 @@ fn expected_for(case: &Path) -> Option<Outcome> {
return Some(Outcome {
stdout: text,
status,
stderr_tail: String::new(),
});
}
let mut cmd = Command::new("python3");
Expand Down Expand Up @@ -266,13 +285,20 @@ fn category(name: &str, warm_up: WarmUp) {
(true, Some(issue)) => fixed.push((key, issue.clone())),
(false, Some(issue)) => known_failed.push((key, issue.clone())),
(false, None) => {
regressions.push(format!(
let mut report = format!(
"{key}\n expected (CPython, exit {}):\n{}\n got (zypy, exit {}):\n{}",
expected.status,
indent(&expected.stdout),
got.status,
indent(&got.stdout)
));
);
if !got.stderr_tail.is_empty() {
report.push_str(&format!(
"\n zypy's stderr (last {STDERR_LINES} lines):\n{}",
indent(&got.stderr_tail)
));
}
regressions.push(report);
}
}
}
Expand Down
33 changes: 29 additions & 4 deletions crates/zyntax_python/tests/memory_pressure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
//! run twice, at a small count and at one many times larger; the
//! difference in peak resident memory between the two is what the run
//! failed to release. A bounded program grows by a slab or two; a leak
//! grows by the count.
//! grows by the count. A program that grows past the allowance runs a
//! third time, longer again: the growth a warm-up leaves stops by the
//! second run, and only a program that grows past the allowance again
//! leaks.
//!
//! `pressure/KNOWN_LEAKS` lists the programs known to grow, each with
//! the git-bug issue that tracks why. A known leak that stops growing
Expand Down Expand Up @@ -38,6 +41,8 @@ const LARGE: u64 = 400_000;
/// makes has landed in both.
const SMALL_LLVM: u64 = 100_000;
const LARGE_LLVM: u64 = 1_000_000;
/// How many times the long run's steps the confirming run takes.
const CONFIRM_FACTOR: u64 = 4;
/// Growth a bounded program is allowed between the two: the slabs its
/// allocator takes, the code the long run compiles that the short one
/// interprets, and the bodies kept for later tiers, all of which stop
Expand Down Expand Up @@ -150,9 +155,29 @@ fn peak_memory_does_not_grow_with_the_step_count() {
));
continue;
}
let growth = large.saturating_sub(small);
let leaks = growth > ALLOWED_GROWTH;
let per_step = growth / (large_steps - small_steps);
let mut growth = large.saturating_sub(small);
let mut per_step = growth / (large_steps - small_steps);
let mut leaks = growth > ALLOWED_GROWTH;
if leaks {
let confirm_steps = large_steps * CONFIRM_FACTOR;
let (confirm_status, confirm) = run(program, confirm_steps);
if confirm_status != 0 {
failures.push(format!(
"{name}: exited {confirm_status} at {confirm_steps} steps"
));
continue;
}
let further = confirm.saturating_sub(large);
eprintln!(
" {name}: {} MB to {} MB, then {} MB at {confirm_steps} steps",
small >> 20,
large >> 20,
confirm >> 20
);
leaks = further > ALLOWED_GROWTH;
growth = further;
per_step = further / (confirm_steps - large_steps);
}
match (leaks, known.get(&name)) {
(true, Some(issue)) => {
known_count += 1;
Expand Down
Loading