mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[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:
@@ -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}"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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())
|
||||
Reference in New Issue
Block a user