mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-17 08:38:30 +09:00
[Fix] (IntegrationTest): gate private split logs and repair control red-checks
This commit is contained in:
@@ -1043,9 +1043,9 @@ jobs:
|
|||||||
# THE RUNTIME HALF OF "THIS IS REALLY A SPLIT BUILD". The build-level nm check in
|
# THE RUNTIME HALF OF "THIS IS REALLY A SPLIT BUILD". The build-level nm check in
|
||||||
# build-linux-split proves the library CARRIES MG_Remote; this proves the transport
|
# build-linux-split proves the library CARRIES MG_Remote; this proves the transport
|
||||||
# RESOLVED in a process of this lane. ConfigLoader::InitTransport logs one INFO line when it
|
# RESOLVED in a process of this lane. ConfigLoader::InitTransport logs one INFO line when it
|
||||||
# selects InProcess, and the DirectGLES.Split.PersistentMapArm. entry is the one Split entry
|
# selects InProcess, and the DirectGLES.Split.PersistentMapArm. entry retains its private
|
||||||
# with a MOBILEGL_LOG_FILE_PATH of its own (nothing else writes it, so the grep means what it
|
# counting log (all Split entries now have private paths; nothing else writes this file).
|
||||||
# says). The line is written during bring-up, before any scenario decides to skip, so this
|
# The line is written during bring-up, before any scenario decides to skip, so this
|
||||||
# check is live from the day the lanes land rather than from the day they stop skipping.
|
# check is live from the day the lanes land rather than from the day they stop skipping.
|
||||||
- name: The split lane really resolved the transport
|
- name: The split lane really resolved the transport
|
||||||
working-directory: build-split
|
working-directory: build-split
|
||||||
@@ -1106,7 +1106,9 @@ jobs:
|
|||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: integration-split-logs
|
name: integration-split-logs
|
||||||
path: build-split/MobileGL/MG_IntegrationTest/*.log*
|
path: |
|
||||||
|
build-split/MobileGL/MG_IntegrationTest/*.log*
|
||||||
|
build-split/MobileGL/MG_IntegrationTest/split-logs/*.log
|
||||||
if-no-files-found: warn
|
if-no-files-found: warn
|
||||||
|
|
||||||
- name: Upload core dumps
|
- name: Upload core dumps
|
||||||
|
|||||||
@@ -1950,7 +1950,6 @@ if (MOBILEGL_BUILD_DISAGGREGATED)
|
|||||||
|
|
||||||
gtest_discover_tests(MobileGLIntegrationTest
|
gtest_discover_tests(MobileGLIntegrationTest
|
||||||
TEST_PREFIX "DirectGLES.Split.PersistentMapArm."
|
TEST_PREFIX "DirectGLES.Split.PersistentMapArm."
|
||||||
TEST_LIST MGL_SPLIT_ARM_TESTS
|
|
||||||
TEST_FILTER "PersistentCoherentMapScenario.TheMapLandsInTheArmItsLaneDeclares"
|
TEST_FILTER "PersistentCoherentMapScenario.TheMapLandsInTheArmItsLaneDeclares"
|
||||||
DISCOVERY_TIMEOUT 30
|
DISCOVERY_TIMEOUT 30
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
@@ -1984,8 +1983,9 @@ if (MOBILEGL_BUILD_DISAGGREGATED)
|
|||||||
"MGITEST_SMALL_RING_LANE=1" "MOBILEGL_IPC_RING_MB=1" "MOBILEGL_IPC_STAGE_MB=1"
|
"MGITEST_SMALL_RING_LANE=1" "MOBILEGL_IPC_RING_MB=1" "MOBILEGL_IPC_STAGE_MB=1"
|
||||||
${MGL_ITEST_CAPABILITY_ENV} ${MGL_ITEST_COMMON_ENV})
|
${MGL_ITEST_CAPABILITY_ENV} ${MGL_ITEST_COMMON_ENV})
|
||||||
|
|
||||||
foreach(mglItestSmallRingScenario ClearThenReadPixelsScenario TriangleScenario
|
set(MGL_SPLIT_SMALL_RING_SCENARIOS ClearThenReadPixelsScenario TriangleScenario
|
||||||
PersistentCoherentMapScenario)
|
PersistentCoherentMapScenario)
|
||||||
|
foreach(mglItestSmallRingScenario IN LISTS MGL_SPLIT_SMALL_RING_SCENARIOS)
|
||||||
gtest_discover_tests(MobileGLIntegrationTest
|
gtest_discover_tests(MobileGLIntegrationTest
|
||||||
TEST_PREFIX "DirectGLES.Split.SmallRing."
|
TEST_PREFIX "DirectGLES.Split.SmallRing."
|
||||||
TEST_LIST "MGL_SPLIT_SMALL_${mglItestSmallRingScenario}_TESTS"
|
TEST_LIST "MGL_SPLIT_SMALL_${mglItestSmallRingScenario}_TESTS"
|
||||||
@@ -2001,9 +2001,12 @@ if (MOBILEGL_BUILD_DISAGGREGATED)
|
|||||||
configure_file(Harness/SplitLogPaths.cmake.in SplitLogPaths.cmake @ONLY)
|
configure_file(Harness/SplitLogPaths.cmake.in SplitLogPaths.cmake @ONLY)
|
||||||
set_property(DIRECTORY APPEND PROPERTY TEST_INCLUDE_FILES
|
set_property(DIRECTORY APPEND PROPERTY TEST_INCLUDE_FILES
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/SplitLogPaths.cmake")
|
"${CMAKE_CURRENT_BINARY_DIR}/SplitLogPaths.cmake")
|
||||||
|
# Python is mandatory for this split integration gate (also used by the CI controls).
|
||||||
|
# Do not silently omit the ownership check when the interpreter is unavailable.
|
||||||
find_package(Python3 REQUIRED COMPONENTS Interpreter)
|
find_package(Python3 REQUIRED COMPONENTS Interpreter)
|
||||||
add_test(NAME SplitLogPaths.PrivateAndDistinct
|
add_test(NAME SplitLogPaths.PrivateAndDistinct
|
||||||
COMMAND "${Python3_EXECUTABLE}"
|
COMMAND "${Python3_EXECUTABLE}"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Harness/split_log_paths.py"
|
"${CMAKE_CURRENT_SOURCE_DIR}/Harness/split_log_paths.py"
|
||||||
check "${CMAKE_CTEST_COMMAND}" "${CMAKE_BINARY_DIR}")
|
check "${CMAKE_CTEST_COMMAND}" "${CMAKE_BINARY_DIR}")
|
||||||
|
set_tests_properties(SplitLogPaths.PrivateAndDistinct PROPERTIES LABELS "integration-split")
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ foreach(entry IN LISTS MGL_SPLIT_CLEAR_TESTS MGL_SPLIT_TRIANGLE_TESTS MGL_SPLIT_
|
|||||||
set_tests_properties("${entry}" PROPERTIES ENVIRONMENT
|
set_tests_properties("${entry}" PROPERTIES ENVIRONMENT
|
||||||
"MOBILEGL_LOG_FILE_PATH=@CMAKE_CURRENT_BINARY_DIR@/split-logs/${entry}.log")
|
"MOBILEGL_LOG_FILE_PATH=@CMAKE_CURRENT_BINARY_DIR@/split-logs/${entry}.log")
|
||||||
endforeach()
|
endforeach()
|
||||||
foreach(scenario ClearThenReadPixelsScenario TriangleScenario PersistentCoherentMapScenario)
|
foreach(scenario @MGL_SPLIT_SMALL_RING_SCENARIOS@)
|
||||||
foreach(entry IN LISTS MGL_SPLIT_SMALL_${scenario}_TESTS)
|
foreach(entry IN LISTS MGL_SPLIT_SMALL_${scenario}_TESTS)
|
||||||
set_tests_properties("${entry}" PROPERTIES ENVIRONMENT
|
set_tests_properties("${entry}" PROPERTIES ENVIRONMENT
|
||||||
"MOBILEGL_LOG_FILE_PATH=@CMAKE_CURRENT_BINARY_DIR@/split-logs/${entry}.log")
|
"MOBILEGL_LOG_FILE_PATH=@CMAKE_CURRENT_BINARY_DIR@/split-logs/${entry}.log")
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ def paths(document):
|
|||||||
props = {p["name"]: p["value"] for p in test.get("properties", [])}
|
props = {p["name"]: p["value"] for p in test.get("properties", [])}
|
||||||
values = [v.split("=", 1)[1] for v in props.get("ENVIRONMENT", [])
|
values = [v.split("=", 1)[1] for v in props.get("ENVIRONMENT", [])
|
||||||
if v.startswith("MOBILEGL_LOG_FILE_PATH=")]
|
if v.startswith("MOBILEGL_LOG_FILE_PATH=")]
|
||||||
is_split = "integration-split" in props.get("LABELS", [])
|
is_split = test["name"].startswith("DirectGLES.Split.")
|
||||||
if is_split and (len(values) != 1 or not values[0]):
|
if is_split and (len(values) != 1 or not values[0]):
|
||||||
raise ValueError(f"{test['name']}: requires exactly one nonempty MOBILEGL_LOG_FILE_PATH")
|
raise ValueError(f"{test['name']}: requires exactly one nonempty MOBILEGL_LOG_FILE_PATH")
|
||||||
for value in values:
|
for value in values:
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
set -u
|
set -u
|
||||||
|
|
||||||
HERE="$(cd "$(dirname "$0")" && pwd)"
|
HERE="$(cd "$(dirname "$0")" && pwd)"
|
||||||
WORK="$(mktemp -d)"
|
WORK="$(mktemp -d)" || exit 1
|
||||||
trap 'rm -rf "${WORK}"' EXIT
|
trap 'rm -rf "${WORK}"' EXIT
|
||||||
|
|
||||||
STUB_DIR="${WORK}/stub"
|
STUB_DIR="${WORK}/stub"
|
||||||
@@ -99,6 +99,10 @@ expect FAILED "a pull library passed the split retrace" -- run_retrace retr
|
|||||||
|
|
||||||
echo
|
echo
|
||||||
echo "smoke test: ${passes} passed, ${failures} failed"
|
echo "smoke test: ${passes} passed, ${failures} failed"
|
||||||
|
# Keep the private-file cases on the entry point used by CI and the local gate.
|
||||||
|
if ! bash "${HERE}/testdata/split_private_log_smoke.sh"; then
|
||||||
|
failures=$((failures + 1))
|
||||||
|
fi
|
||||||
if [ "${failures}" -gt 0 ]; then
|
if [ "${failures}" -gt 0 ]; then
|
||||||
echo "CONTROL_SMOKE_TEST_FAILED"
|
echo "CONTROL_SMOKE_TEST_FAILED"
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
@@ -5,13 +5,13 @@
|
|||||||
# X = revert the message check in each control, i.e. put the controls back in the state ID-46
|
# X = revert the message check in each control, i.e. put the controls back in the state ID-46
|
||||||
# finding 8 found them in: a non-zero ctest exit is accepted whatever the failure was.
|
# finding 8 found them in: a non-zero ctest exit is accepted whatever the failure was.
|
||||||
#
|
#
|
||||||
# The smoke test must then FAIL, and it must fail on the two cases that exist for this defect -
|
# The smoke test must then FAIL on the cases that exist for this defect -
|
||||||
# "unrelated failure with a non-empty selection" and "red without the transport-resolution
|
# "unrelated failure with a non-empty selection" and "red without the transport-resolution
|
||||||
# message" - and not merely somewhere. A smoke test that goes red for any other reason when the
|
# message", plus the missing private-file Fatal - and not merely somewhere. A smoke test that goes
|
||||||
# evidence check is removed would not be pinning the evidence check.
|
# red for any other reason when the evidence check is removed would not be pinning the evidence check.
|
||||||
set -u
|
set -u
|
||||||
HERE="$(cd "$(dirname "$0")" && pwd)"
|
HERE="$(cd "$(dirname "$0")" && pwd)"
|
||||||
WORK="$(mktemp -d)"
|
WORK="$(mktemp -d)" || exit 1
|
||||||
trap 'cp "${WORK}/split.orig" "${HERE}/split_negative_controls.sh"; cp "${WORK}/retrace.orig" "${HERE}/retrace_pull_library_control.sh"; rm -rf "${WORK}"' EXIT
|
trap 'cp "${WORK}/split.orig" "${HERE}/split_negative_controls.sh"; cp "${WORK}/retrace.orig" "${HERE}/retrace_pull_library_control.sh"; rm -rf "${WORK}"' EXIT
|
||||||
|
|
||||||
cp "${HERE}/split_negative_controls.sh" "${WORK}/split.orig"
|
cp "${HERE}/split_negative_controls.sh" "${WORK}/split.orig"
|
||||||
@@ -27,27 +27,35 @@ tail -1 "${WORK}/before.log"
|
|||||||
|
|
||||||
echo
|
echo
|
||||||
echo "=== perturbation: remove the evidence check from both controls"
|
echo "=== perturbation: remove the evidence check from both controls"
|
||||||
python3 - "${HERE}/split_negative_controls.sh" "${HERE}/retrace_pull_library_control.sh" <<'PY'
|
python3 - "${HERE}/split_negative_controls.sh" "${HERE}/retrace_pull_library_control.sh" <<'PY' || exit 1
|
||||||
import sys
|
import sys
|
||||||
|
import re
|
||||||
split, retrace = sys.argv[1], sys.argv[2]
|
split, retrace = sys.argv[1], sys.argv[2]
|
||||||
for path, needle in ((split, 'grep -qE "${evidence}"'), (retrace, 'grep -qF "${EVIDENCE}"')):
|
for path, needle in ((split, 'grep -qE "${evidence}"'), (retrace, 'grep -qF "${EVIDENCE}"')):
|
||||||
text = open(path).read()
|
text = open(path).read()
|
||||||
|
if path == split:
|
||||||
|
text, count = re.subn(
|
||||||
|
r'(?m)^ python3 "\$\{log_helper\}" evidence[^\n]*\n[^\n]*\|\| exit 1\n',
|
||||||
|
' : "private-file evidence check removed by red-check"\n', text)
|
||||||
|
if count != 1:
|
||||||
|
raise SystemExit(f"expected exactly one private-file evidence check in {path}, found {count}")
|
||||||
out, hit = [], 0
|
out, hit = [], 0
|
||||||
for line in text.splitlines(keepends=True):
|
for line in text.splitlines(keepends=True):
|
||||||
if needle in line and line.lstrip().startswith('if ! '):
|
if needle in line and line.lstrip().startswith(('if ! ', 'elif ! ')):
|
||||||
indent = line[:len(line) - len(line.lstrip())]
|
indent = line[:len(line) - len(line.lstrip())]
|
||||||
out.append(f"{indent}if false; then\n")
|
keyword = 'elif' if line.lstrip().startswith('elif ') else 'if'
|
||||||
|
out.append(f"{indent}{keyword} false; then\n")
|
||||||
hit += 1
|
hit += 1
|
||||||
else:
|
else:
|
||||||
out.append(line)
|
out.append(line)
|
||||||
if hit != 1:
|
if hit != 1:
|
||||||
raise SystemExit(f"expected exactly one evidence check in {path}, found {hit}")
|
raise SystemExit(f"expected exactly one evidence check in {path}, found {hit}")
|
||||||
open(path, 'w').write(''.join(out))
|
open(path, 'w').write(''.join(out))
|
||||||
print("both evidence checks reverted to 'any non-zero ctest exit is accepted'")
|
print("E1 private-file, E3(a) and retrace evidence checks reverted to 'any non-zero ctest exit is accepted'")
|
||||||
PY
|
PY
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "=== the smoke test on the reverted controls (it MUST be red, on those two cases)"
|
echo "=== the smoke test on the reverted controls (it MUST be red on the pinned cases)"
|
||||||
bash "${HERE}/control_smoke_test.sh" > "${WORK}/after.log" 2>&1
|
bash "${HERE}/control_smoke_test.sh" > "${WORK}/after.log" 2>&1
|
||||||
rc=$?
|
rc=$?
|
||||||
cat "${WORK}/after.log"
|
cat "${WORK}/after.log"
|
||||||
@@ -61,11 +69,12 @@ fi
|
|||||||
missed=0
|
missed=0
|
||||||
grep -q "NOT OK unrelated failure with a non-empty selection" "${WORK}/after.log" || missed=1
|
grep -q "NOT OK unrelated failure with a non-empty selection" "${WORK}/after.log" || missed=1
|
||||||
grep -q "NOT OK red without the transport-resolution message" "${WORK}/after.log" || missed=1
|
grep -q "NOT OK red without the transport-resolution message" "${WORK}/after.log" || missed=1
|
||||||
|
grep -qF "NOT OK missing-fatal: control must report FAILED for its own reason" "${WORK}/after.log" || missed=1
|
||||||
if [ "${missed}" -ne 0 ]; then
|
if [ "${missed}" -ne 0 ]; then
|
||||||
echo
|
echo
|
||||||
echo "RED-CHECK FAILED: the smoke test went red, but not on the two cases the evidence check exists for."
|
echo "RED-CHECK FAILED: the smoke test went red, but not on the unrelated split, unrelated retrace and missing private-Fatal cases."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "P5_T1_CONTROL_SMOKE_REDCHECK_OK - removing the evidence check reds exactly the two cases that pin it"
|
echo "P5_T1_CONTROL_SMOKE_REDCHECK_OK - removing the evidence checks reds the unrelated split, unrelated retrace and missing private-Fatal cases"
|
||||||
|
|||||||
@@ -42,8 +42,7 @@
|
|||||||
set -u
|
set -u
|
||||||
|
|
||||||
if [ "${1:-}" = "--self-test" ]; then
|
if [ "${1:-}" = "--self-test" ]; then
|
||||||
bash "$(dirname "$0")/control_smoke_test.sh" &&
|
bash "$(dirname "$0")/control_smoke_test.sh"
|
||||||
bash "$(dirname "$0")/testdata/split_private_log_smoke.sh"
|
|
||||||
exit $?
|
exit $?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -65,7 +64,8 @@ python3 "${log_helper}" check "${CTEST}" "$PWD" || exit 1
|
|||||||
# runtime fact inside each test process (MG_Config::Transport, ClientSession::Active(),
|
# runtime fact inside each test process (MG_Config::Transport, ClientSession::Active(),
|
||||||
# ImplementedVerbCount(), read by Harness/SplitRuntimePeek), so the only honest way to ask it from a
|
# ImplementedVerbCount(), read by Harness/SplitRuntimePeek), so the only honest way to ask it from a
|
||||||
# shell is to look at what the entries DID.
|
# shell is to look at what the entries DID.
|
||||||
"${CTEST}" -L integration-split -j 4 --no-tests=error --output-junit "${junit}"
|
# The metadata ownership test shares the label but cannot arm runtime controls.
|
||||||
|
"${CTEST}" -L integration-split -R '^DirectGLES\.Split\.' -j 4 --no-tests=error --output-junit "${junit}"
|
||||||
baseline_rc=$?
|
baseline_rc=$?
|
||||||
|
|
||||||
if [ ! -f "${junit}" ]; then
|
if [ ! -f "${junit}" ]; then
|
||||||
@@ -136,7 +136,9 @@ run_control() {
|
|||||||
echo "${name} turned ${matched} selected entries red, and the red carries the scenario's own diagnostic, as it must"
|
echo "${name} turned ${matched} selected entries red, and the red carries the scenario's own diagnostic, as it must"
|
||||||
}
|
}
|
||||||
|
|
||||||
# E1: c1 ClientSession::Post emits MGLOG_F Fatal{BarrierViolation, "<slot>"}.
|
# E1: c1 ClientSession::EmitAndWait emits MGLOG_F Fatal{BarrierViolation, "<slot>"}.
|
||||||
|
# This asserts an observed overlap with the applier, which is timing-dependent.
|
||||||
|
# Without that Fatal in a fresh selected file E1 fails; pixel/status fallbacks do not count.
|
||||||
# Keep the ID-53-approved SmallRing selection as well as the default lane.
|
# Keep the ID-53-approved SmallRing selection as well as the default lane.
|
||||||
run_control "negative control E1 (MOBILEGL_IPC_VERB_BARRIER=0)" \
|
run_control "negative control E1 (MOBILEGL_IPC_VERB_BARRIER=0)" \
|
||||||
'DirectGLES\.Split\.(SmallRing\.)?(Triangle|ClearThenReadPixels)' \
|
'DirectGLES\.Split\.(SmallRing\.)?(Triangle|ClearThenReadPixels)' \
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ for mode in missing-fatal stdout-fatal stale-fatal evidence e3-unrelated; do
|
|||||||
[ "${rc}" = 0 ] && grep -q "negative control E3(a).*scenario's own diagnostic" "${WORK}/${mode}.out" || {
|
[ "${rc}" = 0 ] && grep -q "negative control E3(a).*scenario's own diagnostic" "${WORK}/${mode}.out" || {
|
||||||
cat "${WORK}/${mode}.out"; echo "NOT OK private-file Fatal must PASS"; exit 1;
|
cat "${WORK}/${mode}.out"; echo "NOT OK private-file Fatal must PASS"; exit 1;
|
||||||
}
|
}
|
||||||
|
grep -qFx "private-log evidence: DirectGLES.Split.ClearThenReadPixelsScenario.ClearWithNoDrawIsVisibleToDefaultFramebufferReadPixels: ${WORK}/${mode}/entry.log" "${WORK}/${mode}.out" || {
|
||||||
|
cat "${WORK}/${mode}.out"; echo "NOT OK private-file evidence line must name the selected entry and path"; exit 1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
message='E1 FAILED: selected private logs lack expected Fatal'
|
message='E1 FAILED: selected private logs lack expected Fatal'
|
||||||
[ "${mode}" != e3-unrelated ] || message='FAILED: red lacks its persistent-map push diagnostic'
|
[ "${mode}" != e3-unrelated ] || message='FAILED: red lacks its persistent-map push diagnostic'
|
||||||
|
|||||||
Reference in New Issue
Block a user