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
45 changes: 45 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,51 @@ jobs:
find target/debug/deps -maxdepth 1 -type f -perm -111 ! -name '*.so' -delete
done

# ---------------------------------------------------------------------------
# GC write-barrier stress (optional / non-blocking)
#
# `crates/perry/tests/gc_write_barrier_stress.rs` runs compiled binaries
# under the slowest GC configuration (PERRY_GC_FORCE_EVACUATE +
# PERRY_GC_VERIFY_EVACUATION) to hunt a *rare* corruption window (#5029).
# Those tests are ~200s each and nondeterministic by nature, so they are a
# poor fit for the blocking per-PR `cargo-test` gate (one flake blocked
# every unrelated PR). They are `#[ignore]`d there and run here instead.
#
# Opt-in + informational: `continue-on-error` so a flake never fails the
# workflow; triggered by the `run-extended-tests` PR label, a
# `workflow_dispatch` with `run_extended_tests=true`, or a tag push.
# ---------------------------------------------------------------------------
gc-stress:
continue-on-error: true
if: >-
github.event_name == 'push' ||
(github.event_name == 'workflow_dispatch' && inputs.run_extended_tests) ||
(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'run-extended-tests'))
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v6

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable

- uses: Swatinem/rust-cache@v2
with:
shared-key: "${{ runner.os }}-perry"
save-if: ${{ github.ref == 'refs/heads/main' }}

- name: Install clang
run: |
sudo apt-get update
sudo apt-get install -y clang

- name: Run GC write-barrier stress tests
env:
# Match the cargo-test gate's linker workaround (lld SIGBUS on the
# shared runner during large test links).
CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS: "-C linker-features=-lld"
run: cargo test -p perry --test gc_write_barrier_stress -- --ignored

# ---------------------------------------------------------------------------
# Compiler-output regression gate
#
Expand Down
13 changes: 13 additions & 0 deletions crates/perry/tests/gc_write_barrier_stress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,17 @@ fn assert_ok_output(run: &std::process::Output, expected: &str) {
/// globals) to point at freshly allocated nursery values, GC again, and
/// verify every value survived. Any missed barrier on those store paths
/// shows up as corrupt reads, an evacuation-verify panic, or a crash.
///
/// Optional / non-blocking (#5029): runs under the slowest GC config
/// (force-evacuate + verify-evacuation) and hunts a *rare* corruption
/// window, so it's nondeterministic and ~200s long — a poor fit for the
/// blocking per-PR `cargo-test` gate (one flake blocks every unrelated PR).
/// `#[ignore]`d by default; the `gc-stress` CI job runs it with `--ignored`
/// (opt-in via the `run-extended-tests` label or `workflow_dispatch`), and
/// you can run it locally with `cargo test -p perry --test
/// gc_write_barrier_stress -- --ignored`.
#[test]
#[ignore = "#5029: nondeterministic GC-corruption stress test; runs in the opt-in gc-stress CI job, not the blocking gate"]
fn tenured_mutation_stress() {
let run = compile_and_run(
r#"
Expand Down Expand Up @@ -221,7 +231,10 @@ console.log(bad === 0 ? "BARRIER_STRESS_OK" : "BARRIER_STRESS_CORRUPT " + bad);
/// deep-clone loop in `js_structured_clone` now routes through the shared
/// barriered store). Uses a 300-key literal (all fields inline) plus a deep
/// nested chain so the clone itself allocates enough to run GCs mid-clone.
///
/// Optional / non-blocking (#5029) — see `tenured_mutation_stress` above.
#[test]
#[ignore = "#5029: nondeterministic GC-corruption stress test; runs in the opt-in gc-stress CI job, not the blocking gate"]
fn structured_clone_gc_churn_stress() {
let mut fields = String::new();
for i in 0..300 {
Expand Down