Skip to content

test_edge_control_flow: intermittent parity flake (state-dependent or non-deterministic codegen) #272

@proggeramlug

Description

@proggeramlug

Summary

Tracked in test-parity/known_failures.json as test_edge_control_flow (status: flake). Failed in parity run 2026-04-25 but passed on isolated re-run with the same binary. Appeared alongside test_edge_error_handling between the 2026-04-24 and 2026-04-25 runs (same flake family — see #273).

Possibly state-dependent on sibling tests or non-deterministic codegen path. Diagnose separately.

Symptoms

  • ./run_parity_tests.sh (full sweep): test FAILS with output mismatch.
  • Re-running just that one test against the same Perry binary: PASSES.

This shape almost always indicates one of:

  1. State leaks across tests in the parity-runner (a temp file, a port, a global env var).
  2. Process-level non-determinism in Perry itself (uninitialized memory, uninitialized GC roots, hash iteration order, malloc address sensitivity, signal handling).
  3. Codegen's parallel module compile via rayon producing slightly different IR depending on thread interleave.

Test contents

test-files/test_edge_control_flow.ts — exercises nested for/while/do-while, labeled break/continue, switch-with-fallthrough, nested switch, try/catch/finally, early return, ternary chains, short-circuit evaluation, for-of with break, deeply nested conditions. ~305 lines, 60 console.log assertions.

How to investigate in a clean cloud worker

git clone https://github.com/PerryTS/perry && cd perry
cargo build --release -p perry-runtime -p perry-stdlib -p perry

# Step 1: run the full parity sweep N times, look for non-determinism
for i in 1 2 3 4 5 6 7 8 9 10; do
  ./run_parity_tests.sh 2>&1 | grep test_edge_control_flow
done

# Step 2: if FAIL appears, isolate
node --experimental-strip-types test-files/test_edge_control_flow.ts > /tmp/node.out
./target/release/perry test-files/test_edge_control_flow.ts -o /tmp/perry_test

# Run the binary 100 times — does it ever produce a different output?
for i in $(seq 1 100); do
  /tmp/perry_test > /tmp/perry.\$i.out
done
md5sum /tmp/perry.*.out | sort -u   # if more than one hash, the BINARY is non-deterministic

If step 2 shows binary-level non-determinism, the bug is in the runtime (probably uninitialized memory or hash iteration order leaking). If the binary is deterministic but parity FAILs only when running alongside other tests, it's runner state leak.

Recommended approach

  1. Reproduce the flake first (may need 50-100 runs).
  2. Use git bisect from 2026-04-24 (last passing) to 2026-04-25 (first failing) — the CHANGELOG.md entry hints between those dates point to the v0.5.x range to bisect.
  3. If binary-level flake, run under ASAN/MSAN (rebuild with RUSTFLAGS=\"-Z sanitizer=address\" on a nightly toolchain) on the failing input.

Acceptance

test_edge_control_flow passes 100/100 in repeated parity sweeps; remove from known_failures.json.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions