[MG_IntegrationTest, CI] (P6/t6): integration-spawn, and the set identity made structural instead of maintained

Exit gates 9.2 and 9.3. Until now nothing ran the integration suite across a
process boundary at all - the spawn shape was proven only by the retrace lane,
which exercises one trace per case and no scenario assertions.

integration-spawn: 102 cases, 102 green.

THE SET IDENTITY IS THE POINT, AND IT IS NOT MAINTAINED BY HAND. 9.2 asks that
the spawn lane's case-name set equal the split lane's. Registering the spawn
arm as a second copy of each block would satisfy that today and drift the first
time somebody adds a scenario to one of them - and a spawn lane covering LESS
goes green while proving less, with nothing about a smaller green lane looking
wrong. The eleven split-environment blocks become eleven calls to one macro
that emits BOTH arms from one filter, so a case added to either is added to
both or to neither.

scripts/ci/spawn_lane_parity.py asserts it anyway, because a macro is one edit
from a hand-written block. It compares SETS rather than counts - a count can
agree while the membership does not - and carries exactly one sanctioned
asymmetry, named in the file: integration-split also labels the PUSH-MONOLITH
arm, whose scenario is monolith-only by construction. R-16: introduce a
split-only block and it reds naming the case and the macro to use.

THREE CASES SKIP UNDER SPAWN, BY NAME. CtWireScenario reads PipeApplier's
in-process tallies through ServerVerbs(); under spawn those live in the SERVER's
process and this one's copy is 0 forever, so the assertions were failing about
somebody else's memory. That is a harness limit, not a product defect - the
records themselves cross, which the retrace lane proves. They are SKIPPED and
not deregistered: a case dropped from the registration would make the two sets
differ silently, which is the drift the macro exists to prevent. What retires
the skip is cross-process telemetry, which is also what S8's SessionFaultCount
needs.

TWO REAL REGRESSIONS THE EXISTING GATES CAUGHT, both from this refactor:

  * the macro dropped the per-block TEST_LIST variables, which were what
    SplitLogPaths fed to give every entry a PRIVATE MOBILEGL_LOG_FILE_PATH.
    SplitLogPaths.PrivateAndDistinct went red naming the first orphan. The
    macro accumulates list NAMES now, so a block added later is covered without
    anyone remembering to extend a list - and the names have to be unique,
    because gtest_discover_tests' TEST_LIST is populated when CTEST runs, not
    at configure time, so one shared variable held only the last block's
    entries. That matters more on the spawn arm: there TWO PROCESSES append to
    the path, so a shared file interleaves two sessions rather than merely
    being ambiguous.

  * the configure_file that substitutes those names ran BEFORE the F1 and Ct
    blocks registered, so it captured neither. Same gate, naming
    F1WireScenario.ClearBufferfiPixels. It now runs last.

junit_tally gains --require-spawn-ran beside --require-split-ran: the prefix IS
the arm, and a shared flag would let one lane tally the other's entries and call
itself run. Verified to discriminate - the spawn junit reads 96/0/5 under its
own flag and 0/0/0 under the split flag, which correctly fails.

Two death tests follow the ADOPT_TIER message the census commit retagged with
Fatal{UnimplementedAdoptTier}; their regexes asserted the old wording.

Unit 2353 (one pre-existing environmental failure), integration-split 186/186,
integration-spawn 102/102, retrace 6/6, fatal census 0 unmarked, G1 0 symbols
and .text unchanged at 0xa52203.
This commit is contained in:
2026-09-21 20:20:24 -04:00
parent 3399b8791c
commit 15f5b54bbd
7 changed files with 246 additions and 132 deletions
+12
View File
@@ -1076,6 +1076,13 @@ jobs:
# ProtocolSmoke and FdPassing - are registered only under MOBILEGL_BUILD_DISAGGREGATED
# (MG_Test/CMakeLists.txt), and before this job existed NO cmake invocation anywhere in this
# workflow passed that option. They had never been compiled by CI, let alone run.
# Exit gate 9.2. BEFORE the lanes run, because it costs a `ctest -N` and answers the one
# question a green lane cannot: did the spawn arm cover the same cases the split arm did?
# A spawn lane registered with fewer cases goes green while proving less, and nothing about
# a smaller green lane looks wrong.
- name: integration-spawn covers integration-split (9.2)
run: python3 scripts/ci/spawn_lane_parity.py build-split
- name: Unit tests on the split runtime
working-directory: build-split
env:
@@ -1099,6 +1106,11 @@ jobs:
sudo sysctl -w kernel.core_pattern='/tmp/core.%e.%p'
ctest --output-on-failure -L integration-split --no-tests=error -j 4 --output-junit "${RUNNER_TEMP}/split-baseline.xml"
python3 ../scripts/ci/junit_tally.py "${RUNNER_TEMP}/split-baseline.xml" --require-split-ran
# Exit gate 9.3: the spawn arm green at the same count. It runs the same cases through a
# SECOND PROCESS, so a failure here that the line above did not see is a transport fact
# and not a phase one - which is the whole reason both lanes exist.
ctest --output-on-failure -L integration-spawn --no-tests=error -j 4 --output-junit "${RUNNER_TEMP}/spawn-baseline.xml"
python3 ../scripts/ci/junit_tally.py "${RUNNER_TEMP}/spawn-baseline.xml" --require-spawn-ran
# Both full transport runs are hard gates. The per-case comparison below
# remains diagnostic because explicit mechanism controls retain their own mode.