mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Test] (.github/workflows, docs/ci, MG_IntegrationTest, MG_IntegrationTest/Scenarios, MG_Test/Pipe): restore the fatal-arm, per-verb capability and verb-scope checks
- Armed requires fatal=1; the monolith control envs share the ambient lane's base list - the capability field is corrupted through the knob at Clear, DrawArrays and ReadPixels - the library's poison omission is checked to match its verb, not its class
This commit is contained in:
@@ -905,8 +905,10 @@ jobs:
|
||||
|
||||
# The lane's own control entries, by name: each must have run and passed, and a skip is a
|
||||
# failure here although ctest reports it green. VerifyArming asserts in-test that the
|
||||
# comparator printed its armed line, VerifyCorrupted that a corrupted field is reported by
|
||||
# name, and PoisonOmitted that an omitted stamp kills a forked child with its own Fatal.
|
||||
# comparator printed its armed line with fatal=1, under the ambient entries' own environment
|
||||
# (MG_IntegrationTest/CMakeLists.txt builds both from one list), VerifyCorrupted that a
|
||||
# corrupted field is reported by name, and PoisonOmitted that an omitted stamp kills a
|
||||
# forked child with its own Fatal.
|
||||
- name: Verify lane control entries
|
||||
run: |
|
||||
python3 scripts/ci/junit_tally.py "${RUNNER_TEMP}/verify.xml" \
|
||||
@@ -917,7 +919,6 @@ jobs:
|
||||
--require-entry-passed DirectGLES.PoisonOmitted.PoisonOmissionScenario.OmittedFieldAbortsOnThatVerb \
|
||||
--require-entry-passed DirectVulkan.PoisonOmitted.PoisonOmissionScenario.OmittedFieldAbortsOnThatVerb
|
||||
|
||||
|
||||
- name: Upload verify lane logs
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@v7
|
||||
|
||||
@@ -1260,17 +1260,22 @@ if (MOBILEGL_PIPE_VERIFY)
|
||||
# boundary and again at every accessor read, which the design budgets at 5-10x.
|
||||
set(MGL_ITEST_VERIFY_TIMEOUT 900)
|
||||
|
||||
mgl_itest_join_environment(MGL_ITEST_GLES_VERIFY_ENVIRONMENT
|
||||
"MOBILEGL_TRANSPORT=monolith"
|
||||
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MOBILEGL_PIPE_VERIFY=1"
|
||||
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-verify-DirectGLES.log"
|
||||
# What "the monolith verify lane" means, per backend, in one place: the ambient Verify. entries
|
||||
# and every control entry below are this list plus their own log path and markers. So the
|
||||
# controls run the configuration the ambient entries run, and an edit that leaves that lane
|
||||
# unarmed or non-fatal turns PipeVerifyArmingScenario.Armed red, which asserts both.
|
||||
set(MGL_ITEST_GLES_VERIFY_BASE_ENV
|
||||
"MOBILEGL_TRANSPORT=monolith" "MOBILEGL_BACKEND_TYPE=DirectGLES" "MOBILEGL_PIPE_VERIFY=1"
|
||||
${MGL_ITEST_COMMON_ENV})
|
||||
mgl_itest_join_environment(MGL_ITEST_VULKAN_VERIFY_ENVIRONMENT
|
||||
"MOBILEGL_TRANSPORT=monolith"
|
||||
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MOBILEGL_PIPE_VERIFY=1"
|
||||
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-verify-DirectVulkan.log"
|
||||
set(MGL_ITEST_VULKAN_VERIFY_BASE_ENV
|
||||
"MOBILEGL_TRANSPORT=monolith" "MOBILEGL_BACKEND_TYPE=DirectVulkan" "MOBILEGL_PIPE_VERIFY=1"
|
||||
${MGL_ITEST_VULKAN_ENV})
|
||||
|
||||
mgl_itest_join_environment(MGL_ITEST_GLES_VERIFY_ENVIRONMENT ${MGL_ITEST_GLES_VERIFY_BASE_ENV}
|
||||
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-verify-DirectGLES.log")
|
||||
mgl_itest_join_environment(MGL_ITEST_VULKAN_VERIFY_ENVIRONMENT ${MGL_ITEST_VULKAN_VERIFY_BASE_ENV}
|
||||
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-verify-DirectVulkan.log")
|
||||
|
||||
# The arming assertion's own lane, one case per backend, with a log path nothing else writes to.
|
||||
#
|
||||
# PipeVerifyArmingScenario.Armed reads the library's log, and the log is a per-LANE resource: it
|
||||
@@ -1280,33 +1285,23 @@ if (MOBILEGL_PIPE_VERIFY)
|
||||
# the primgen reroute, the point-size demotion) is registered exactly like this for the same
|
||||
# reason. MGITEST_PIPE_ARMING_LANE is a harness marker - the library never reads it - and it is
|
||||
# what makes the case skip in the ambient lane instead of racing there.
|
||||
mgl_itest_join_environment(MGL_ITEST_GLES_VERIFY_ARMING_ENVIRONMENT
|
||||
"MOBILEGL_TRANSPORT=monolith"
|
||||
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MOBILEGL_PIPE_VERIFY=1" "MGITEST_PIPE_ARMING_LANE=1"
|
||||
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-verify-arming-DirectGLES.log"
|
||||
${MGL_ITEST_COMMON_ENV})
|
||||
mgl_itest_join_environment(MGL_ITEST_VULKAN_VERIFY_ARMING_ENVIRONMENT
|
||||
"MOBILEGL_TRANSPORT=monolith"
|
||||
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MOBILEGL_PIPE_VERIFY=1" "MGITEST_PIPE_ARMING_LANE=1"
|
||||
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-verify-arming-DirectVulkan.log"
|
||||
${MGL_ITEST_VULKAN_ENV})
|
||||
mgl_itest_join_environment(MGL_ITEST_GLES_VERIFY_ARMING_ENVIRONMENT ${MGL_ITEST_GLES_VERIFY_BASE_ENV}
|
||||
"MGITEST_PIPE_ARMING_LANE=1"
|
||||
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-verify-arming-DirectGLES.log")
|
||||
mgl_itest_join_environment(MGL_ITEST_VULKAN_VERIFY_ARMING_ENVIRONMENT ${MGL_ITEST_VULKAN_VERIFY_BASE_ENV}
|
||||
"MGITEST_PIPE_ARMING_LANE=1"
|
||||
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-verify-arming-DirectVulkan.log")
|
||||
|
||||
# Negative control A (G4). MOBILEGL_PIPE_VERIFY_FATAL=0 so the process SURVIVES its own
|
||||
# divergence and the case can read the report back out of the log; the other half, that with
|
||||
# FATAL at its default of 1 a divergence aborts, is PipeInputsTest's
|
||||
# VerifyCorruptKnobNamesTheFieldAtEntry.
|
||||
mgl_itest_join_environment(MGL_ITEST_GLES_VERIFY_CORRUPT_ENVIRONMENT
|
||||
"MOBILEGL_TRANSPORT=monolith"
|
||||
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MOBILEGL_PIPE_VERIFY=1"
|
||||
mgl_itest_join_environment(MGL_ITEST_GLES_VERIFY_CORRUPT_ENVIRONMENT ${MGL_ITEST_GLES_VERIFY_BASE_ENV}
|
||||
"MOBILEGL_PIPE_VERIFY_CORRUPT=GetRenderStateParameters" "MOBILEGL_PIPE_VERIFY_FATAL=0"
|
||||
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-verify-corrupt-DirectGLES.log"
|
||||
${MGL_ITEST_COMMON_ENV})
|
||||
mgl_itest_join_environment(MGL_ITEST_VULKAN_VERIFY_CORRUPT_ENVIRONMENT
|
||||
"MOBILEGL_TRANSPORT=monolith"
|
||||
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MOBILEGL_PIPE_VERIFY=1"
|
||||
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-verify-corrupt-DirectGLES.log")
|
||||
mgl_itest_join_environment(MGL_ITEST_VULKAN_VERIFY_CORRUPT_ENVIRONMENT ${MGL_ITEST_VULKAN_VERIFY_BASE_ENV}
|
||||
"MOBILEGL_PIPE_VERIFY_CORRUPT=GetRenderStateParameters" "MOBILEGL_PIPE_VERIFY_FATAL=0"
|
||||
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-verify-corrupt-DirectVulkan.log"
|
||||
${MGL_ITEST_VULKAN_ENV})
|
||||
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-verify-corrupt-DirectVulkan.log")
|
||||
|
||||
# Negative control B (G5). The omission skips the STAMP of one field for one verb while still
|
||||
# copying its value, which is indistinguishable from a fill row nobody wrote; the scenario
|
||||
@@ -1317,18 +1312,12 @@ if (MOBILEGL_PIPE_VERIFY)
|
||||
# the fill (around its neutral-pack readback). GetActiveTextureUnit at GenerateMipmap was the
|
||||
# frontend arm's read; the record arm resolves the texture from the verb's own handle and never
|
||||
# reads it, so that pair could no longer go red for its own reason.
|
||||
mgl_itest_join_environment(MGL_ITEST_GLES_POISON_OMIT_ENVIRONMENT
|
||||
"MOBILEGL_TRANSPORT=monolith"
|
||||
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MOBILEGL_PIPE_VERIFY=1"
|
||||
mgl_itest_join_environment(MGL_ITEST_GLES_POISON_OMIT_ENVIRONMENT ${MGL_ITEST_GLES_VERIFY_BASE_ENV}
|
||||
"MGITEST_POISON_OMIT=ReadPixels:GetPixelStoreParameters"
|
||||
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-poison-omit-DirectGLES.log"
|
||||
${MGL_ITEST_COMMON_ENV})
|
||||
mgl_itest_join_environment(MGL_ITEST_VULKAN_POISON_OMIT_ENVIRONMENT
|
||||
"MOBILEGL_TRANSPORT=monolith"
|
||||
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MOBILEGL_PIPE_VERIFY=1"
|
||||
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-poison-omit-DirectGLES.log")
|
||||
mgl_itest_join_environment(MGL_ITEST_VULKAN_POISON_OMIT_ENVIRONMENT ${MGL_ITEST_VULKAN_VERIFY_BASE_ENV}
|
||||
"MGITEST_POISON_OMIT=ReadPixels:GetPixelStoreParameters"
|
||||
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-poison-omit-DirectVulkan.log"
|
||||
${MGL_ITEST_VULKAN_ENV})
|
||||
"MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/pipe-poison-omit-DirectVulkan.log")
|
||||
|
||||
# The whole suite again, per backend, with the comparator armed. Same scenarios, same
|
||||
# assertions, but every backend read of frontend state is now checked against a snapshot taken
|
||||
@@ -1350,9 +1339,9 @@ if (MOBILEGL_PIPE_VERIFY)
|
||||
)
|
||||
|
||||
# The arming assertion, one entry per backend. This is the entry that fails a lane whose library
|
||||
# never armed: it runs the same library and the same MOBILEGL_PIPE_VERIFY=1 as the ambient
|
||||
# entries above, but unlike them it cannot be green against a library with no comparator
|
||||
# compiled in. Its log is its own, so `-j 4` cannot make it flake.
|
||||
# never armed: it runs the same library and the same base list as the ambient entries above,
|
||||
# but unlike them it cannot be green against a library with no comparator compiled in, or with
|
||||
# one that only logs a divergence. Its log is its own, so `-j 4` cannot make it flake.
|
||||
mgl_itest_lane("DirectGLES.VerifyArming." "PipeVerifyArmingScenario.Armed"
|
||||
LABELS "integration-gpu\;integration-verify\;integration-monolith-control" TIMEOUT ${MGL_ITEST_VERIFY_TIMEOUT} ENV "${MGL_ITEST_GLES_VERIFY_ARMING_ENVIRONMENT}")
|
||||
mgl_itest_lane("DirectVulkan.VerifyArming." "PipeVerifyArmingScenario.Armed"
|
||||
|
||||
@@ -16,10 +16,11 @@
|
||||
// clean pass. That is the failure mode this scenario exists to make impossible:
|
||||
//
|
||||
// Armed - the environment says the comparator is on for this process, so the
|
||||
// library must SAY it armed. It asserts a library observable against
|
||||
// the environment, the same shape UnlocatedIoBlockScenario's arming
|
||||
// case and AsyncCompileScenario::ExtensionStringMatchesTheConfiguration
|
||||
// use. A lane whose library never armed FAILS here; it never passes.
|
||||
// library must SAY it armed, with fatal=1. It asserts a library
|
||||
// observable against the environment, the same shape
|
||||
// UnlocatedIoBlockScenario's arming case and
|
||||
// AsyncCompileScenario::ExtensionStringMatchesTheConfiguration use. A
|
||||
// lane whose library never armed FAILS here; it never passes.
|
||||
// CorruptedFieldIsReported - the negative control for the comparator itself (gate G4). With
|
||||
// MOBILEGL_PIPE_VERIFY_CORRUPT naming a field, the snapshot arm is
|
||||
// perturbed before the entry compare, so a comparator that works must
|
||||
@@ -230,13 +231,28 @@ void main() { o_color = vec4(0.25, 0.5, 0.75, 1.0); }
|
||||
// of the process, which may already have happened during the harness bring-up. The file
|
||||
// is truncated at this process's first log write, so it still carries nothing else.
|
||||
const std::string whole = LibraryLog();
|
||||
EXPECT_NE(whole.find(kArmedLine), std::string::npos)
|
||||
const std::size_t armedAt = whole.find(kArmedLine);
|
||||
EXPECT_NE(armedAt, std::string::npos)
|
||||
<< "MOBILEGL_PIPE_VERIFY=1 is set for this process and a frame was cleared, drawn and "
|
||||
"read back, and the library never reported arming the comparator. Either this "
|
||||
"library was not built with -DMOBILEGL_PIPE_VERIFY=ON (in which case the whole lane "
|
||||
"is verifying nothing), or the arming MGLOG_I is gone. Log:\n"
|
||||
<< whole;
|
||||
|
||||
// Fatal as well as armed: an ambient entry fails on a divergence only through the abort,
|
||||
// so a lane armed non-fatal logs every divergence and stays green. This entry is the
|
||||
// ambient entries' environment plus its marker and log (CMakeLists.txt builds both from
|
||||
// one list), so its arming line answers for theirs.
|
||||
if (armedAt != std::string::npos) {
|
||||
const std::size_t eol = whole.find('\n', armedAt);
|
||||
const std::string line =
|
||||
whole.substr(armedAt, eol == std::string::npos ? std::string::npos : eol - armedAt);
|
||||
EXPECT_NE(line.find("fatal=1"), std::string::npos)
|
||||
<< "the comparator armed, but not fatal, so a divergence in any entry of this lane "
|
||||
"is logged and the entry stays green. Arming line:\n"
|
||||
<< line;
|
||||
}
|
||||
|
||||
const std::string appended = LibraryLogSince(before);
|
||||
EXPECT_EQ(appended.find(kDifferPrefix), std::string::npos)
|
||||
<< "the comparator reported a push/pull divergence on an ordinary frame:\n"
|
||||
|
||||
@@ -146,7 +146,8 @@ namespace {
|
||||
// Negative control B, layer 1 (P1 brief D6 / G5): the omitted (verb, field) pair is the
|
||||
// ONLY thing that goes stale - every other bit of the verb class's mask is fresh, every
|
||||
// field outside it is not, and the verb after it neither heals the field (not in kDraw's
|
||||
// mask) nor loses one of its own. The omission is the test's own (FillWithholdingTheStamp).
|
||||
// mask) nor loses one of its own. The omission is the test's own (FillWithholdingTheStamp); a
|
||||
// verify build also checks the scope of the library's (MGPipeSetPoisonOmission).
|
||||
TEST_F(PipeInputsTest, OmittingOneFieldForOneVerbLeavesExactlyThatFieldStale) {
|
||||
#if !MOBILEGL_PIPE_POISON
|
||||
GTEST_SKIP() << "poison not compiled in (MOBILEGL_PIPE_POISON=0)";
|
||||
@@ -182,6 +183,24 @@ TEST_F(PipeInputsTest, OmittingOneFieldForOneVerbLeavesExactlyThatFieldStale) {
|
||||
// And the omission is scoped to its fill: the next verb of the same class stamps it again.
|
||||
MGPipeValidateForVerb(MGPipeVerb::BindImageTexture);
|
||||
EXPECT_TRUE(Fresh(MGPipeInputField::GetActiveTextureUnit));
|
||||
|
||||
#if MOBILEGL_PIPE_VERIFY && MGTEST_HAVE_FORK
|
||||
// The library's own omission, the one the PoisonOmitted entries arm, stays armed across fills
|
||||
// and is scoped to its VERB: a different verb of the same class keeps the stamp. In a child,
|
||||
// because nothing disarms it.
|
||||
const ChildResult r = RunInChild([] {
|
||||
if (!MGPipeSetPoisonOmission("GenerateMipmap", "GetActiveTextureUnit")) ::_exit(3);
|
||||
MGPipeValidateForVerb(MGPipeVerb::GenerateMipmap);
|
||||
if (Fresh(MGPipeInputField::GetActiveTextureUnit)) ::_exit(4);
|
||||
MGPipeValidateForVerb(MGPipeVerb::BindImageTexture);
|
||||
if (!Fresh(MGPipeInputField::GetActiveTextureUnit)) ::_exit(5);
|
||||
});
|
||||
EXPECT_TRUE(ExitedWith(r, 0)) << DescribeStatus(r)
|
||||
<< " (3: the setter refused the names; 4: GenerateMipmap stamped the omitted "
|
||||
"field; 5: BindImageTexture did not stamp it, so the omission matched the "
|
||||
"class rather than the verb)\n"
|
||||
<< r.Log;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -335,6 +354,34 @@ TEST_F(PipeInputsTest, EveryCorruptedFieldIsNamedByTheComparator) {
|
||||
EXPECT_EQ(named, field) << "a corrupted " << name(field) << " was reported as " << name(named);
|
||||
}
|
||||
EXPECT_EQ(corruptedFields, kMGPipeInputFieldCount - kMGPipeForwardedFieldCount);
|
||||
|
||||
#if MGTEST_HAVE_FORK
|
||||
// And the capability field through the knob and each verb's own mask, at the verbs a clear,
|
||||
// draw and readback frame crosses: every one whose class fills the field must report it at
|
||||
// entry, and at least one must fill it.
|
||||
ASSERT_FALSE(g_logPath.empty()) << "main() did not set MOBILEGL_LOG_FILE_PATH";
|
||||
static constexpr MGPipeVerb kFrameVerbs[] = {MGPipeVerb::Clear, MGPipeVerb::DrawArrays, MGPipeVerb::ReadPixels};
|
||||
const ChildResult r = RunInChild([] {
|
||||
MG_Config::Features.PipeVerify = true;
|
||||
MG_Config::Features.PipeVerifyFatal = false;
|
||||
::setenv("MOBILEGL_PIPE_VERIFY_CORRUPT", "IsCapabilityEnabled", 1);
|
||||
for (const MGPipeVerb verb : kFrameVerbs)
|
||||
MGPipeValidateForVerb(verb);
|
||||
});
|
||||
ASSERT_TRUE(ExitedWith(r, 0)) << DescribeStatus(r) << "\n" << r.Log;
|
||||
SizeT filling = 0;
|
||||
for (const MGPipeVerb verb : kFrameVerbs) {
|
||||
const auto cls = static_cast<SizeT>(kMGPipeVerbClass[static_cast<SizeT>(verb)]);
|
||||
const Bool fills = MGPipeFieldMaskHas(kMGPipeClassFieldMask[cls], MGPipeInputField::IsCapabilityEnabled);
|
||||
filling += fills ? 1 : 0;
|
||||
const std::string report = std::string("Fatal{PipeVerifyDiffer, \"IsCapabilityEnabled@") +
|
||||
kMGPipeVerbNames[static_cast<SizeT>(verb)] + "\"";
|
||||
EXPECT_EQ(r.Log.find(report) != std::string::npos, fills)
|
||||
<< report << (fills ? " missing" : " unexpected") << " in\n"
|
||||
<< r.Log;
|
||||
}
|
||||
EXPECT_GT(filling, 0u) << "no verb of a clear, draw and readback frame fills IsCapabilityEnabled";
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -59,10 +59,10 @@ them wrong.
|
||||
| 2026-10-18 | `scripts/ci/control_smoke_test.sh`, `scripts/ci/testdata/stub_ctest.sh`, `scripts/ci/testdata/split_private_log_smoke.sh`, and the `reset` / `results` / `assertion` / `evidence` modes of `split_log_paths.py` | Test / pipe-gates (R-16) | smoke cases and helpers of the step above only | none needed |
|
||||
| 2026-10-18 | unit `RemoteRunAhead.ClearingTheVerbBarrierDisarmsRunAheadEvenWithTheCapBit`, and the `MOBILEGL_IPC_VERB_BARRIER` knob with its arm in the shipped client (`ClientSession`: the free-running `EmitAndWaitTails` return, the run-ahead latch term, the `gPipeInputs` guard's early return, the `verb-barrier=` field of the `Config: IPC` line) | Test / unit (split); product code | `0` was never a product mode, only E1's negative control, retired above; the unit case pinned that the control also disarmed run-ahead | `RemoteWaitBoundaryControl.AnUnwaitedPublishIsSeenAsNoWait`; `MOBILEGL_IPC_RUN_AHEAD=0` stays the lockstep A/B arm |
|
||||
| 2026-10-18 | unit `SplitBufferSet.AZeroBlockSizeTurnsThePushOffRatherThanMakingItUnlimited` (and its skip stub in the non-disaggregated half), and the `MOBILEGL_IPC_PERSISTENT_BLOCK_KB` knob with its `0` arm in the shipped tracker (`PersistentMapTracker::PushBlocksForChecked`'s early return and once-per-process warning, `BufferObject::NotePersistentMapStateChanged`'s, the `persistent-block=` field of the `Config: IPC` line) | Test / unit; product code | `0` was never a product mode, only E3(a)'s negative control, retired above; the unit case pinned that `0` shipped nothing; the block size is now the constant 64 KiB (`PersistentMapTracker::BlockBytes()`) | `PersistentCoherentMapScenario.ThePushIsTheOnlyRouteAWriteTakesToTheServer` |
|
||||
| 2026-10-18 | `Negative control A (corrupted snapshot)` | Test / `integration-verify` | it re-ran the five `DirectGLES.Verify.ClearThenReadPixelsScenario` entries with `MOBILEGL_PIPE_VERIFY_CORRUPT=GetRenderStateParameters` exported job-wide and accepted any red | the in-lane `DirectGLES/DirectVulkan.VerifyCorrupted.PipeVerifyArmingScenario.CorruptedFieldIsReported` entries, required by name (`Verify lane control entries`), which require `Fatal{PipeVerifyDiffer, "GetRenderStateParameters@...` in the log; the abort with `MOBILEGL_PIPE_VERIFY_FATAL` at its default is unit `PipeInputsTest.VerifyCorruptKnobNamesTheFieldAtEntry` on the verify runtime |
|
||||
| 2026-10-18 | `Negative control A2 (corrupted capability)` | Test / `integration-verify` | the same five-entry rerun with `MOBILEGL_PIPE_VERIFY_CORRUPT=IsCapabilityEnabled`, accepting any red; it proved that the comparator compares the capability field (P13 W3c moved the residual block's cross-check there) | unit `PipeInputsTest.EveryCorruptedFieldIsNamedByTheComparator` (`Unit tests on the verify runtime`): every field with storage, the capability field among them, corrupted in turn must be the field the comparator names |
|
||||
| 2026-10-18 | `Negative control A (corrupted snapshot)` and `Keep lane logs before controls` | Test / `integration-verify-split` | the first re-ran the ten `VerifySplit.ClearThenReadPixelsScenario` entries of both backends with the same knob and accepted any red; the second only kept the lane's logs from being overwritten by that rerun | the in-lane `VerifySplitCorrupted` and `VerifySplitReadCorrupted` entries of both backends, required by name (`Verify-split control entries`) |
|
||||
| 2026-10-18 | unit `PipeInputsTest.{PoisonOmitKnobArmsTheOmission, BadPoisonOmitKnobIsFatalNamingTheKnob}`, and the `MOBILEGL_PIPE_POISON_OMIT` knob: `Features.PipePoisonOmit`, its parser on every verb (`MGPipeValidateForVerb`'s `ParsePoisonOmissionKnob`, compiled into every build) and the server stamp's own parse of it | Test / unit (every poison lane); product code | the knob existed only for negative control B, and the two cases pinned its parser and its `Fatal{PipeVerifyBadKnob}` | the PoisonOmitted and VerifySplitPoisonOmitted entries set the harness marker `MGITEST_POISON_OMIT` to the same pair, and the re-executed child arms it through `MGPipeSetPoisonOmission`, compiled only with `-DMOBILEGL_PIPE_VERIFY=ON` (`Harness/PoisonOmissionArm.h`); `OmittingOneFieldForOneVerbLeavesExactlyThatFieldStale`, `ReadingAnOmittedFieldAbortsNamingTheVerb` and `TheMutationNoticeRefreshesTheValueButNotTheStamp` withhold the stamp test-side and still run in every poison lane |
|
||||
| 2026-10-18 | `Negative control A (corrupted snapshot)` | Test / `integration-verify` | it re-ran the five `DirectGLES.Verify.ClearThenReadPixelsScenario` entries with `MOBILEGL_PIPE_VERIFY_CORRUPT=GetRenderStateParameters` exported job-wide and accepted any red | the in-lane `DirectGLES/DirectVulkan.VerifyCorrupted.PipeVerifyArmingScenario.CorruptedFieldIsReported` entries, required by name (`Verify lane control entries`), which require `Fatal{PipeVerifyDiffer, "GetRenderStateParameters@...` in the log; the abort with `MOBILEGL_PIPE_VERIFY_FATAL` at its default is unit `PipeInputsTest.VerifyCorruptKnobNamesTheFieldAtEntry` on the verify runtime; that the ambient entries run the comparator armed and fatal is `VerifyArming.PipeVerifyArmingScenario.Armed`, whose environment is now the ambient entries' list plus its marker and log, and which requires `fatal=1` on the arming line |
|
||||
| 2026-10-18 | `Negative control A2 (corrupted capability)` | Test / `integration-verify` | the same five-entry rerun with `MOBILEGL_PIPE_VERIFY_CORRUPT=IsCapabilityEnabled`, accepting any red; it proved that the comparator compares the capability field (P13 W3c moved the residual block's cross-check there) | unit `PipeInputsTest.EveryCorruptedFieldIsNamedByTheComparator` (`Unit tests on the verify runtime`): every field with storage, the capability field among them, corrupted in turn must be the field the comparator names; then, in a forked child with the knob set to `IsCapabilityEnabled`, each of Clear, DrawArrays and ReadPixels whose class fills the field must report it at entry, and one must |
|
||||
| 2026-10-18 | `Negative control A (corrupted snapshot)` and `Keep lane logs before controls` | Test / `integration-verify-split` | the first re-ran the ten `VerifySplit.ClearThenReadPixelsScenario` entries of both backends with the same knob and accepted any red; the second only kept the lane's logs from being overwritten by that rerun | the in-lane `VerifySplitCorrupted` and `VerifySplitReadCorrupted` entries of both backends, required by name (`Verify-split control entries`); that the ambient entries arm is the per-entry arm proof, and that they run fatal is `VerifySplitArming.PipeVerifyArmingScenario.Armed` (the ambient environment plus its marker and log), which requires `fatal=1` on the arming line |
|
||||
| 2026-10-18 | unit `PipeInputsTest.{PoisonOmitKnobArmsTheOmission, BadPoisonOmitKnobIsFatalNamingTheKnob}`, and the `MOBILEGL_PIPE_POISON_OMIT` knob: `Features.PipePoisonOmit`, its parser on every verb (`MGPipeValidateForVerb`'s `ParsePoisonOmissionKnob`, compiled into every build) and the server stamp's own parse of it | Test / unit (every poison lane); product code | the knob existed only for negative control B, and the two cases pinned its parser and its `Fatal{PipeVerifyBadKnob}` | the PoisonOmitted and VerifySplitPoisonOmitted entries set the harness marker `MGITEST_POISON_OMIT` to the same pair, and the re-executed child arms it through `MGPipeSetPoisonOmission`, compiled only with `-DMOBILEGL_PIPE_VERIFY=ON` (`Harness/PoisonOmissionArm.h`); `OmittingOneFieldForOneVerbLeavesExactlyThatFieldStale`, `ReadingAnOmittedFieldAbortsNamingTheVerb` and `TheMutationNoticeRefreshesTheValueButNotTheStamp` withhold the stamp test-side and still run in every poison lane; the setter's scope to its verb, not its class, is checked by `OmittingOneFieldForOneVerbLeavesExactlyThatFieldStale` in a forked child, on the verify runtime only |
|
||||
|
||||
## Kept after investigation
|
||||
|
||||
|
||||
Reference in New Issue
Block a user