Section 04: Matrix Testing — Regression Guard
Status: Complete Goal: Build a combinatorial test matrix that covers the cross-product of (value type × operation × context). When any ARC pipeline change breaks leak-free behavior for a specific combination, the matrix test catches it immediately. The goal is to narrow the band of acceptable behavior so regressions become harder as the compiler grows.
Context: The FatValue PrimOp bug existed because no test exercised “string in loop” — there were string tests and loop tests but not the combination. Matrix testing prevents this class of gap by systematically covering the cross-product.
Depends on: Section 01 (leak detection), Section 02 (existing leaks fixed).
Warning: Test timing risk. This section adds 66+ AOT tests, each compiling and running an Ori program via
compile_and_run_capture. AOT tests currently run sequentially due to LLVMContext::create()contention. Adding 66 tests that each invokeori build+ execute could add 2-5 minutes to the AOT test suite. Verify thattimeout 150 ./test-all.shstill passes after adding all matrix tests. If timing becomes an issue, consider batching multiple assertions into fewer test functions (e.g., one test function per matrix row instead of per cell).
04.1 Matrix Design — Dimensions & Cross-Product
Define the test matrix dimensions:
Dimension 1: Value Types (RC-managed)
str(FatValue) — SSO and heap variants[int](RcPointer) — empty and non-empty[str](RcPointer with RC elements) — nested RC{str: int}(RcPointer with RC keys) — map with heap keystype S = { items: [int], name: str }(Aggregate with RC fields)
Dimension 2: Operations
- Construct (literal creation)
- Reassign in loop (
s = s + "x") - Pass to function (owned, borrowed)
- Return from function
- Store in struct field
- Extract from struct field (Project)
- Compare (equality, ordering)
- Drop at end of scope
Dimension 3: Context
-
Top-level local (simple scope)
-
For-loop body
-
While-loop body
-
Loop-with-break body
-
If-else branches (value live in one, dead in other)
-
Match arms (value live in one arm, dead in others)
-
Function call argument
-
Function return value
-
Closure capture (RC variable captured by closure, closure dropped)
-
Document the full matrix dimensions in this section
-
Identify which combinations are already covered by existing tests — extensive coverage in
iter_rc_matrix.rs(iteration patterns),fat_matrix/(20 categories),fat_ptr_iter.rs; gaps in reassignment-in-loop and scope-context patterns -
Identify which combinations are gaps (the cross-product minus existing coverage) — gaps: no
whilekeyword in Ori (foreign keyword, useloop+if/break), no AOT while-loop tests existed -
Prioritize: high-risk combinations (loops + heap types, branches + struct drops) first
04.2 Value Type × Loop Pattern Matrix
File(s): compiler/ori_llvm/tests/aot/arc.rs (or new file compiler/ori_llvm/tests/aot/rc_matrix.rs)
Test every value type being reassigned inside every loop pattern. Each test uses assert_aot_success (which enables ORI_CHECK_LEAKS=1).
Note: while is a foreign keyword in Ori — use loop { if !cond then break; body } equivalent.
for range | loop+if/break (≈while) | for+early break | |
|---|---|---|---|
str (SSO→heap) | test_matrix_str_for_loop | test_matrix_str_while_loop | test_matrix_str_loop_break |
[int] push | test_matrix_list_int_for_loop | test_matrix_list_int_while_loop | test_matrix_list_int_loop_break |
[str] push | test_matrix_list_str_for_loop | test_matrix_list_str_while_loop | test_matrix_list_str_loop_break |
{str: int} insert | test_matrix_map_for_loop | test_matrix_map_while_loop | test_matrix_map_loop_break |
| Struct w/ heap | test_matrix_struct_for_loop | test_matrix_struct_while_loop | test_matrix_struct_loop_break |
- Create
compiler/ori_llvm/tests/aot/rc_matrix.rs - Add
pub mod rc_matrix;tocompiler/ori_llvm/tests/aot/main.rs - Implement all 15 loop matrix tests (5 types × 3 loop patterns)
- Each test: 30 iterations, verify correct result AND zero leaks
- All 15 tests pass
04.3 Value Type × Scope Pattern Matrix
Test every value type in different scope contexts — ensures drops fire at the right points.
| Simple scope | If-else | Match arms | Function arg | Function return | |
|---|---|---|---|---|---|
str (heap) | test_matrix_str_scope | test_matrix_str_if_else | test_matrix_str_match | test_matrix_str_arg | test_matrix_str_return |
[int] | test_matrix_list_scope | test_matrix_list_if_else | test_matrix_list_match | test_matrix_list_arg | test_matrix_list_return |
[str] | test_matrix_list_str_scope | test_matrix_list_str_if_else | test_matrix_list_str_match | test_matrix_list_str_arg | test_matrix_list_str_return |
{str: int} | test_matrix_map_scope | test_matrix_map_if_else | test_matrix_map_match | test_matrix_map_arg | test_matrix_map_return |
| Struct w/ heap | test_matrix_struct_scope | test_matrix_struct_if_else | test_matrix_struct_match | test_matrix_struct_arg | test_matrix_struct_return |
- Implement all 25 scope matrix tests (5 types × 5 contexts)
- Each test verifies correct result AND zero leaks
- All 25 tests pass
- FIXED:
test_matrix_str_if_elseleak — select-fold optimization eagerly materialized both if-else branches for heap types. Fix:detect_select_diamondnow rejects diamonds with non-scalar merge params (Criterion 7). Semantic pin:select_not_folded_non_scalar_merge_paraminori_arc/src/block_merge/tests.rs.
04.4 Nested & Composed Pattern Matrix
Test combinations that compose multiple dimensions — the highest-risk patterns.
-
test_matrix_struct_with_list_in_loop— Struct containing[int]reassigned in loop -
test_matrix_list_of_strings_in_loop—[str]with push in loop (nested RC: list + string elements) -
test_matrix_string_in_if_else_in_loop— String conditionally updated in loop -
test_matrix_slice_in_scope— Create slice, use, let both slice and original drop — FIXED: double-free —emit_auto_iterandemit_rc_inc_clonecalledori_rc_inc(data)directly instead of slice-awareori_list_rc_inc(data, cap). Fixed viaemit_slice_aware_rc_inchelper. -
test_matrix_slice_in_loop— Create slices in a loop -
test_matrix_multiple_heap_locals— Multiple independent heap variables in one scope -
test_matrix_heap_var_shadowing— Shadow a heap variable with a new heap value -
test_matrix_closure_captures_string— Lambda capturing a heap string, called, then dropped -
test_matrix_closure_captures_list— Lambda capturing a[int], called, then dropped -
test_matrix_closure_in_loop— Lambda created inside loop body capturing loop variable, used and dropped each iteration
04.5 Journey Score Regression Guard
Ensure the 10/10 code journey scores cannot regress.
- Create
compiler/ori_llvm/tests/aot/journey_guard.rs - Add
pub mod journey_guard;tocompiler/ori_llvm/tests/aot/main.rs - For each of the 20 journeys (13 original + 7 new):
- Compile the journey
.orifile fromplans/code-journeys/NN-name.ori - Run with
ORI_CHECK_LEAKS=1 - Verify exit code matches expected value (each journey’s
@mainreturns anintexit code; stored as named constants injourney_guard.rs) - Verify zero leaks (exit code != 2)
- Compile the journey
- Each test must hard-fail (not skip) if the journey
.orifile is missing - These tests run as part of
cargo test -p ori_llvm --test aot - Verify these tests are included in
./test-all.shvia the existingcargo test -p ori_llvm --test aotinvocation — confirmed: 1797 AOT tests pass
Cleanup (Applies to rc_matrix.rs and journey_guard.rs creation)
- [BLOAT]
compiler/ori_llvm/tests/aot/util.rs— No new helpers added toutil.rs. Journey guard uses its ownrun_journey/assert_journeyhelpers inline. Matrix tests use onlyassert_aot_successfrom util.
04.R Third Party Review Findings
-
[TPR-04-001][medium]plans/rc-integrity/index.md:1— RC Integrity status metadata drifted into contradictory states before review. Resolved: Validated on 2026-03-20. The drift was corrected in a prior session — index.md now readsstatus: active, 00-overview.md readsstatus: in-progress, and section-04 frontmatter readsstatus: in-progress. All three are consistent and correctly reflect the plan’s incomplete state. -
[TPR-04-002][medium]plans/rc-integrity/section-04-matrix-testing.md:4— RC Integrity status metadata is contradictory again in the current tree. Resolved: Fixed on 2026-03-20. Synced all files in one pass: section-04 body/frontmatter/subsections allcomplete,third_party_review.status: resolved. Overviewstatus: complete, indexstatus: resolved. All 41/41 items checked, all TPR findings resolved. Section-05 also synced (36/36 items, 8 TPR findings resolved).
04.N Completion Checklist
- Matrix test file created (
rc_matrix.rs) and registered inmain.rs - Journey guard file created (
journey_guard.rs) and registered inmain.rs - 15 loop matrix tests pass (5 types × 3 loop patterns)
- 25 scope matrix tests pass (5 types × 5 contexts) — all 25 pass after select-fold fix
- 10 nested/composed matrix tests pass (7 original + 3 closure) — all 10 pass after slice RC fix
- 20 journey guard tests pass (all 20 journeys)
- Total: 70 new tests, all 70 passing with zero leaks
-
timeout 150 ./test-all.shgreen — 13,456 passed, 0 failed -
./clippy-all.shgreen - No regressions in existing tests — 1799 AOT tests pass (was 1797 before, +2 new passing)
Exit Criteria: 66+ matrix tests covering the cross-product of value types, operations, and contexts. Every combination that could regress has an explicit test. Journey scores are guarded by automated tests that fail on any regression.