[Chore] (.github/workflows, docs/ci, scripts/ci): delete dead CI control code

- Strict split lane: drop the kMGPipeP5eRunAheadReady grep and its red-by-design pre-flip arm; the constant is true, so the arm never ran
- Dual-block census lane: drop the "green with rows outstanding" rule, inert while dualblock-expected-fatals.txt is empty; the empty-census rule and expect-fatal stay
- delete scripts/ci/tcp_log_forwarding_control.py, which nothing calls
This commit is contained in:
2026-10-17 15:59:55 -04:00
parent 93c4220143
commit f87ec9ec67
3 changed files with 6 additions and 193 deletions
+4 -35
View File
@@ -1679,11 +1679,8 @@ jobs:
# ---- Strict split lane: residual pulls under MOBILEGL_IPC_STRICT_ERRORS=1 ----
#
# An unbarriered pull is always fatal, and strict also stops any barriered pull that is not
# admitted (ARCHITECTURE.md §9.2.1). The arm comes from kMGPipeP5eRunAheadReady in
# MG_Backend/Init.cpp, so the expectation changes in the commit that changes the runtime. When
# true (run-ahead), the lane must be green and its markers must match the admitted list and
# strict-expected-markers.txt; when false, every record is barriered, the lane must be red
# (strict aborts every drawing entry), and only the marker census is checked.
# admitted (ARCHITECTURE.md §9.2.1). The lane must be green, and its markers must match the
# admitted list and strict-expected-markers.txt in both directions.
- name: Strict split lane
working-directory: build-split
env:
@@ -1692,8 +1689,6 @@ jobs:
MOBILEGL_TRANSPORT: "inproc"
run: |
ulimit -c unlimited
ready=$(grep -oE 'kMGPipeP5eRunAheadReady = (true|false)' "${GITHUB_WORKSPACE}/MobileGL/MG_Backend/Init.cpp" | head -1 | awk '{print $3}')
echo "kMGPipeP5eRunAheadReady = ${ready}"
helper="${GITHUB_WORKSPACE}/MobileGL/MG_IntegrationTest/Harness/split_log_paths.py"
expected="${GITHUB_WORKSPACE}/MobileGL/MG_IntegrationTest/Harness/strict-expected-markers.txt"
@@ -1731,24 +1726,7 @@ jobs:
> "${RUNNER_TEMP}/allowed.txt"
echo "§7 allowlist (derived): $(wc -l < "${RUNNER_TEMP}/allowed.txt") admitted pair(s)"
if [ "${ready}" != "true" ]; then
# ---- the pre-flip arm ----
if [ "${rc}" -eq 0 ]; then
echo "::error::integration-split under MOBILEGL_IPC_STRICT_ERRORS=1 went GREEN while kMGPipeP5eRunAheadReady is false - the object-class residual pulls (P3b/P4b/P7) are still pinned, so strict must abort every drawing scenario. If P5e has just landed, flip that constant in the same commit."
exit 1
fi
# The census, and the ADMITTED half of the ratchet, run in this arm too: the Fatal
# half is expected here (it is what "red by design" MEANS), but a debt that appeared
# or vanished on the admitted side is news whichever arm the tree is in.
python3 "${helper}" markers "${RUNNER_TEMP}/lane.json" '.' \
"${RUNNER_TEMP}/allowed.txt" "${expected}"
echo "integration-split under strict is red by design, and its marker census above is the evidence"
exit 0
fi
# ---- the post-flip arm: HARD GREEN, two-sided ----
#
# EVERY ENTRY MUST COMPLETE, and the census is what says why when one does not: an abort
# Every entry must complete, and the census is what says why when one does not: an abort
# is either an unbarriered pull (§3.3's unconditional Fatal, a missed migration) or a
# barriered pull nothing admits, and both come out of the census by field and verb.
if [ "${rc}" -ne 0 ]; then
@@ -1806,12 +1784,7 @@ jobs:
# machine-checked list of what still depends on the two roles sharing one object, and it
# is ratcheted two-sided against Harness/dualblock-expected-fatals.txt: a new pair is a
# debt somebody now owes, a vanished pair must be removed in the commit that retired it.
#
# THE STEP ALSO FAILS WHEN THE LANE IS GREEN while the expected file still has rows -
# "green" would mean the knob stopped arming, which is exactly the decay ID-122 assigns
# to a control rather than to a lane's good mood. At P5f's exit the file is empty and the
# green arm is the correct one; delete the red expectation in the same commit.
# P5f wave 2: with the census empty, this lane is a hard green gate.
# With the census empty, this lane is a hard green gate.
- name: Dual-block census lane
working-directory: build-split
env:
@@ -1853,10 +1826,6 @@ jobs:
echo "::error::empty dual-block census requires ctest success, including infrastructure/execution status"
exit "${rc}"
fi
if [ "${rc}" -eq 0 ] && [ "${rows}" -gt 0 ]; then
echo "::error::the dual-block census lane went GREEN with ${rows} expected pair(s) outstanding - the knob stopped arming, or the fields retired and dualblock-expected-fatals.txt was not emptied in the same commit"
exit 1
fi
python3 "${helper}" expect-fatal "${RUNNER_TEMP}/dualblock-lane.json" \
"${RUNNER_TEMP}/dualblock.xml" "${expected}"
+2
View File
@@ -44,6 +44,8 @@ them wrong.
| 2026-10-17 | `Negative control B (omitted fill point)` | Test / `integration-verify` | it re-ran `PoisonOmissionScenario.WithoutOmissionCompletes` with `MOBILEGL_PIPE_POISON_OMIT=ReadPixels:GetPixelStoreParameters` and accepted any red | the in-lane `DirectGLES/DirectVulkan.PoisonOmitted.PoisonOmissionScenario.OmittedFieldAbortsOnThatVerb` entries: the same pair, and they also require SIGABRT with the named `Fatal{UnmigratedPipeInput}`; now required to pass by name |
| 2026-10-17 | `Verify lane arming check` (grep of `pipe-verify-arming-*.log`) | Test / `integration-verify` | the VerifyArming entries assert the armed line in-test; the grep only added "the entry did not skip" | `Verify lane control entries`: `junit_tally.py --require-entry-passed` on the VerifyArming, VerifyCorrupted and PoisonOmitted entries of both backends (a skip fails) |
| 2026-10-17 | `Negative control A (server-side read)` and `Negative control B (omitted stamp)` | Test / `integration-verify-split` | the first re-ran the two VerifySplitReadCorrupted entries the lane had just run and grepped what they already assert in-test (at least two where=read reports in the server half); the second re-ran with the pair the in-lane VerifySplitPoisonOmitted entries already pin, and accepted any red | `Verify-split control entries`: `--require-entry-passed` on VerifySplitArming, VerifySplitCorrupted, VerifySplitReadCorrupted and VerifySplitPoisonOmitted of both backends |
| 2026-10-17 | the pre-flip arm of `Strict split lane` (red-by-design while `kMGPipeP5eRunAheadReady` was false) and the "GREEN with rows outstanding" rule of `Dual-block census lane` | Test / `integration-split-strict` | dead: the constant is true, and `dualblock-expected-fatals.txt` has no rows, so neither branch could run | the hard-green arm and its two-sided marker census, and the empty-census rule (rows == 0 requires ctest success), both kept |
| 2026-10-17 | `scripts/ci/tcp_log_forwarding_control.py` | none | no caller outside the archived planning notes | none needed |
## Kept after investigation
-158
View File
@@ -1,158 +0,0 @@
#!/usr/bin/env python3
# MobileGL - scripts/ci/tcp_log_forwarding_control.py
# Copyright (c) 2025-2026 MobileGL-Dev
# Licensed under the GNU Lesser General Public License v3.0:
# https://www.gnu.org/licenses/gpl-3.0.txt
# https://www.gnu.org/licenses/lgpl-3.0.txt
# SPDX-License-Identifier: LGPL-3.0-only
# End of Source File Header
"""Run the four real arming scenarios with server log forwarding enabled and disabled."""
import argparse
import errno
import json
import os
from pathlib import Path
import re
import signal
import socket
import subprocess
import time
import xml.etree.ElementTree as ET
CASES = {
'unlocated': ('DirectGLES', 'UnlocatedIoBlockScenario.TheEmulationIsActuallyArmedWhenTheEnvironmentPinsItOn',
{'MOBILEGL_ESPRYT_UNLOCATED_IO_BLOCKS': '1'}, 'WITHOUT their layout(location) qualifier'),
'primitives': ('DirectVulkan', 'PrimitivesGeneratedNoXfbScenario.TheRerouteIsActuallyArmedWhenTheEnvironmentPinsItOn',
{'MOBILEGL_MAGMA_PRIMGEN_QUERY_REROUTE': '1'}, 'PRIMITIVES_GENERATED reroute engaged'),
'point-size': ('DirectGLES', 'PointSizeDemotionScenario.TheDemotionIsActuallyArmedWhenTheEnvironmentPinsItOn',
{'MOBILEGL_POINT_SIZE_DEMOTION': '1'}, 'demoted to an ordinary varying'),
'verify': ('DirectGLES', 'PipeVerifyArmingScenario.Armed',
{'MOBILEGL_PIPE_VERIFY': '1', 'MGITEST_PIPE_ARMING_LANE': '1'}, 'MGPipe: verify armed'),
}
def read(path):
return path.read_text(errors='replace') if path.exists() else ''
def run_arm(build, out, case, forward):
backend, test, knobs, marker = CASES[case]
out.mkdir(parents=True, exist_ok=True)
with socket.socket() as reserve:
reserve.bind(('127.0.0.1', 0))
port = reserve.getsockname()[1]
endpoint = f'tcp://127.0.0.1:{port}'
env = dict(os.environ, MOBILEGL_TRANSPORT='spawn', MOBILEGL_BACKEND_TYPE=backend,
MOBILEGL_IPC_REQUIRE_SAME_BUILD='1', MOBILEGL_IPC_TOKEN='', EGL_PLATFORM='surfaceless',
LIBGL_ALWAYS_SOFTWARE='1', MOBILEGL_ITEST_REQUIRE_GPU='1', **knobs)
for name in ('MOBILEGL_PIPE_VERIFY_CORRUPT', 'MOBILEGL_IPC_CONTROL', 'MOBILEGL_IPC_DIAL'):
env.pop(name, None)
if Path('/usr/share/glvnd/egl_vendor.d/50_mesa.json').exists():
env['__EGL_VENDOR_LIBRARY_FILENAMES'] = '/usr/share/glvnd/egl_vendor.d/50_mesa.json'
if Path('/usr/share/vulkan/icd.d/lvp_icd.json').exists():
env.setdefault('VK_ICD_FILENAMES', '/usr/share/vulkan/icd.d/lvp_icd.json')
peer_env = dict(env, MOBILEGL_IPC_ROLE='server', MOBILEGL_IPC_DIAL='no',
MOBILEGL_IPC_LOG_FORWARD=str(int(forward)), MOBILEGL_LOG_FILE_PATH=str(out / 'peer.log'))
for name in ('MOBILEGL_TRANSPORT', 'MOBILEGL_IPC_SERVER_PATH', 'MOBILEGL_IPC_RING_MB', 'MOBILEGL_IPC_STAGE_MB'):
peer_env.pop(name, None)
with (out / 'supervisor.log').open('wb') as output:
server = subprocess.Popen([str(build / 'libMobileGLServer.so'), endpoint, '--serve'],
env=peer_env, stdout=output, stderr=output, start_new_session=True)
try:
for _ in range(100):
if server.poll() is not None:
raise RuntimeError('supervisor exited before listening: ' + read(out / 'supervisor.log'))
with socket.socket() as probe:
probe.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
probe.bind(('127.0.0.1', port))
except OSError as error:
if error.errno == errno.EADDRINUSE:
break
raise
time.sleep(.05)
else:
raise RuntimeError('supervisor did not listen')
client_env = dict(env, MOBILEGL_IPC_CONTROL=endpoint, MOBILEGL_IPC_DATA='stream',
MOBILEGL_IPC_LOG_FORWARD='1', MOBILEGL_LOG_FILE_PATH=str(out / 'client.log'),
MGITEST_SPLIT_LANE='1', MGITEST_TCP_LANE='1')
result = subprocess.run([str(build / 'MobileGL/MG_IntegrationTest/MobileGLIntegrationTest'),
'--gtest_filter=' + test, '--gtest_output=xml:' + str(out / 'result.xml')],
env=client_env, capture_output=True, text=True, timeout=120)
(out / 'stdout.log').write_text(result.stdout + result.stderr)
finally:
try:
os.killpg(server.pid, signal.SIGTERM)
except ProcessLookupError:
pass
server.wait(timeout=10)
passed = failed = skipped = 0
marker_assertion_failed = False
if (out / 'result.xml').exists():
for entry in ET.parse(out / 'result.xml').getroot().iter('testcase'):
if entry.find('skipped') is not None or entry.get('status') == 'notrun':
skipped += 1
elif entry.find('failure') is not None:
failed += 1
marker_assertion_failed = any(marker in (failure.get('message', '') + (failure.text or ''))
for failure in entry.findall('failure'))
else:
passed += 1
client_log = read(out / 'client.client.log')
return {'case': test, 'returncode': result.returncode, 'passed': passed, 'failed': failed, 'skipped': skipped,
'tcp_armed': bool(re.search(r'control=tcp data=stream server=\S+ pid=[1-9][0-9]*', client_log)),
'marker_in_client': marker in client_log,
'marker_in_server': marker in read(out / 'peer.server.log'),
'marker_forwarded': marker in read(out / 'client.server.log'),
'marker_assertion_failed': marker_assertion_failed,
'output': str(out)}
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--build-dir', type=Path, required=True)
parser.add_argument('--verify-build-dir', type=Path)
parser.add_argument('--out', type=Path, required=True)
parser.add_argument('--case', action='append', choices=CASES,
help='Explicit subset; the default runs all four and requires a verify build')
args = parser.parse_args()
selected = args.case or list(CASES)
if 'verify' in selected and not args.verify_build_dir:
parser.error('the verify scenario requires --verify-build-dir configured with MOBILEGL_PIPE_VERIFY=ON')
args.out.mkdir(parents=True, exist_ok=True)
results = {}
for case in selected:
build = args.verify_build_dir if case == 'verify' else args.build_dir
arms = {}
for forward in (True, False):
name = 'forward-on' if forward else 'forward-off'
try:
arms[name] = run_arm(build, args.out / case / name, case, forward)
except Exception as error:
arms[name] = {'error': str(error)}
on, off = arms['forward-on'], arms['forward-off']
if case == 'verify':
# PipeFill owns this marker in the client. Disabling peer forwarding
# must leave it visible; requiring red here would test a false design.
arms['expectation'] = 'client-owned marker remains green with peer forwarding disabled'
arms['proved'] = all(arm.get('passed') == 1 and arm.get('returncode') == 0
and arm.get('tcp_armed') and arm.get('marker_in_client')
for arm in (on, off))
else:
arms['expectation'] = 'server-owned marker passes with forwarding and fails without it'
arms['proved'] = bool(on.get('passed') == 1 and on.get('returncode') == 0
and on.get('tcp_armed') and on.get('marker_in_server') and on.get('marker_forwarded')
and off.get('failed') == 1 and not off.get('skipped') and off.get('tcp_armed')
and off.get('marker_in_server') and not off.get('marker_forwarded')
and off.get('marker_assertion_failed')
and not off.get('marker_in_client'))
results[case] = arms
print(case + ': ' + ('PASS' if arms['proved'] else 'NOT PROVEN'), flush=True)
(args.out / 'summary.json').write_text(json.dumps(results, indent=2))
return 0 if all(result['proved'] for result in results.values()) else 1
if __name__ == '__main__':
raise SystemExit(main())