[Test] (P11 A1/A2): LargeArenaAdoptionScenario asserts the tier its arena landed in and reads the tcp AdoptTier0 refusal; registered on Split/Spawn/Tcp for both backends (Espryt through the split-arms macro, Magma's Arena. block and Buffers lane), the monolith lanes declare adopted

This commit is contained in:
2026-09-29 07:23:41 -04:00
parent 3c72e5c637
commit 2a902cbd79
5 changed files with 250 additions and 5 deletions
+13
View File
@@ -2042,6 +2042,13 @@ jobs:
"PersistentCoherentMapScenario.TwoWritesThroughTheCoherentPointerEachReachTheirOwnDraw",
"PersistentCoherentMapScenario.AWriteAfterAFrameBoundaryReachesTheNextFramesDraw",
"StorageBufferRegrowScenario.AGrownStoreIsVisibleThroughItsExistingIndexedBinding",
# P11 A2: the >= 16 MiB arena and its tier assertion (emulated).
"LargeArenaAdoptionScenario.SubDataAfterAnInFlightDrawReachesTheNextDraw",
"LargeArenaAdoptionScenario.RespecifiedVertexArenaKeepsVaoBindings",
"LargeArenaAdoptionScenario.RespecifiedIndexArenaKeepsVaoBinding",
"LargeArenaAdoptionScenario.ReadbackSeesTheLatestCpuWrite",
"LargeArenaAdoptionScenario.GpuWriteIntoTheArenaIsReadBack",
"LargeArenaAdoptionScenario.TheArenaLandsInTheTierItsLaneDeclares",
]
slp.require_green(json.load(open(sys.argv[2])), sys.argv[3],
["DirectVulkan.Split.Buffers." + name for name in cases])
@@ -2104,6 +2111,12 @@ jobs:
"PersistentCoherentMapScenario.TwoWritesThroughTheCoherentPointerEachReachTheirOwnDraw",
"PersistentCoherentMapScenario.AWriteAfterAFrameBoundaryReachesTheNextFramesDraw",
"StorageBufferRegrowScenario.AGrownStoreIsVisibleThroughItsExistingIndexedBinding",
"LargeArenaAdoptionScenario.SubDataAfterAnInFlightDrawReachesTheNextDraw",
"LargeArenaAdoptionScenario.RespecifiedVertexArenaKeepsVaoBindings",
"LargeArenaAdoptionScenario.RespecifiedIndexArenaKeepsVaoBinding",
"LargeArenaAdoptionScenario.ReadbackSeesTheLatestCpuWrite",
"LargeArenaAdoptionScenario.GpuWriteIntoTheArenaIsReadBack",
"LargeArenaAdoptionScenario.TheArenaLandsInTheTierItsLaneDeclares",
]
required = [sys.argv[4] + name for name in cases]
if sys.argv[5] == "tcp":
+93 -3
View File
@@ -1495,14 +1495,25 @@ gtest_discover_tests(MobileGLIntegrationTest
# No log path: none of these three cases reads one, and giving them one would only add a file for
# four processes to truncate. The fourth case skips in both lanes for exactly that reason, saying
# so.
#
# P11 A2: both lanes pin monolith, so both DECLARE the adopted arm (MGITEST_PERSISTENT_MAP_ARM) and
# LargeArenaAdoptionScenario.TheArenaLandsInTheTierItsLaneDeclares asserts the 24 MiB arena really
# adopted on the handle arm (Ops_H_MapPersistentTracked) and on the legacy one. Red once with
# MOBILEGL_DISABLE_LARGE_BUFFER_ADOPTION=1 in the job environment (CONTRACT-P11 §2).
mgl_itest_join_environment(MGL_ITEST_GLES_ARENA_SUBSYSTEM_ON_ENVIRONMENT
"MOBILEGL_TRANSPORT=monolith"
"MOBILEGL_TRANSPORT=monolith" "MGITEST_PERSISTENT_MAP_ARM=adopted"
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MOBILEGL_PIPE_PUSH=0x1fff"
${MGL_ITEST_CAPABILITY_ENV} ${MGL_ITEST_COMMON_ENV})
mgl_itest_join_environment(MGL_ITEST_GLES_ARENA_SUBSYSTEM_OFF_ENVIRONMENT
"MOBILEGL_TRANSPORT=monolith"
"MOBILEGL_TRANSPORT=monolith" "MGITEST_PERSISTENT_MAP_ARM=adopted"
"MOBILEGL_BACKEND_TYPE=DirectGLES" "MOBILEGL_PIPE_PUSH=0x7f"
${MGL_ITEST_CAPABILITY_ENV} ${MGL_ITEST_COMMON_ENV})
# ... and Magma's monolith half: the legacy AcquirePersistentMap (the wire resource table is
# registered only off monolith, VkBufferManager.cpp RegisterWireResourceOps).
mgl_itest_join_environment(MGL_ITEST_VULKAN_ARENA_ARM_ENVIRONMENT
"MOBILEGL_TRANSPORT=monolith" "MGITEST_PERSISTENT_MAP_ARM=adopted"
"MOBILEGL_BACKEND_TYPE=DirectVulkan" "MOBILEGL_ITEST_REQUIRE_GPU=1"
${MGL_ITEST_CAPABILITY_ENV} ${MGL_ITEST_VULKAN_ENV})
gtest_discover_tests(MobileGLIntegrationTest
TEST_PREFIX "DirectGLES.ResourceSubsystemOn."
@@ -1522,6 +1533,15 @@ gtest_discover_tests(MobileGLIntegrationTest
TIMEOUT ${MGL_ITEST_TIMEOUT}
ENVIRONMENT "${MGL_ITEST_GLES_ARENA_SUBSYSTEM_OFF_ENVIRONMENT}"
)
gtest_discover_tests(MobileGLIntegrationTest
TEST_PREFIX "DirectVulkan.ArenaArm."
TEST_FILTER "LargeArenaAdoptionScenario.TheArenaLandsInTheTierItsLaneDeclares"
DISCOVERY_TIMEOUT 30
PROPERTIES
LABELS "integration-gpu\;integration-monolith-control"
TIMEOUT ${MGL_ITEST_TIMEOUT}
ENVIRONMENT "${MGL_ITEST_VULKAN_ARENA_ARM_ENVIRONMENT}"
)
# --- G12: the P4a subsystem A/B, and its dependency refusal ---------------------------
#
@@ -2407,6 +2427,30 @@ if (MOBILEGL_BUILD_DISAGGREGATED)
mgl_itest_register_split_arms("ClearThenReadPixelsScenario.*" "")
mgl_itest_register_split_arms("TriangleScenario.*" "")
mgl_itest_register_split_arms("PersistentCoherentMapScenario.*" "")
# P11 A2 (MG_Remote/CONTRACT-P11.md §2): the >= 16 MiB arena on all three arms. Its tier case
# is declared emulated per entry by SplitLogPaths (T2: every acquisition declines); the mpr and
# adopt-tier-refusal cases skip here for want of their lane markers. The Magma arms are the
# gated `Arena.` block beside `Pbo.` / `Fence.` below, plus the Buffers lane.
mgl_itest_register_split_arms("LargeArenaAdoptionScenario.*" "")
# P11 A1 (CONTRACT-P11 §1): the tcp arm with MOBILEGL_IPC_ADOPT_TIER=0. A stream refuses the
# tier by name at the client's handshake and runs T2, so the whole scenario is green here and
# AStreamSessionRefusesTheAdoptTierOnceByName reads exactly one refusal line. TCP ONLY by
# construction: over shared segments (split, spawn) the same knob dies at the handshake, which
# is the unit gate RemoteClientControls.AdoptTier*OverSharedSegments*. The `.AdoptTier0.` tail is
# what keeps these names out of spawn_lane_parity.py's case set (see MAGMA_TCP_ONLY there).
gtest_discover_tests(MobileGLIntegrationTest
TEST_PREFIX "DirectGLES.Tcp.AdoptTier0."
TEST_LIST "MGL_SPLIT_ARM_TESTS_${MGL_SPLIT_ARM_INDEX}"
TEST_FILTER "LargeArenaAdoptionScenario.*"
DISCOVERY_TIMEOUT 30
PROPERTIES
LABELS "integration-gpu\;integration-tcp"
TIMEOUT ${MGL_ITEST_TIMEOUT}
ENVIRONMENT "${MGL_ITEST_GLES_TCP_ENVIRONMENT}\;MOBILEGL_IPC_ADOPT_TIER=0\;MGITEST_ADOPT_TIER_REFUSAL=T0"
FIXTURES_REQUIRED mobilegl-tcp RESOURCE_LOCK mobilegl-tcp
)
list(APPEND MGL_SPLIT_ARM_TEST_LISTS "MGL_SPLIT_ARM_TESTS_${MGL_SPLIT_ARM_INDEX}")
math(EXPR MGL_SPLIT_ARM_INDEX "${MGL_SPLIT_ARM_INDEX} + 1")
# ---- P3b/P4b espryt D1 slice 1: THE ORPHANED XFB CAPTURE TARGET -------------------------
#
@@ -3697,6 +3741,16 @@ endif()
# Fatal{ReplyTooLarge, "ReadPixels 256x512 0x1908/0x1406 2097152 > 2097136"}. One entry per case
# for a private log each - two processes append to it on the spawn arm.
if (MOBILEGL_BUILD_DISAGGREGATED)
# P11: LargeArenaAdoptionScenario's cases that run on every Magma arm - the five behavioural
# cases and the tier assertion (the mpr and adopt-tier-refusal cases need lane markers of their
# own). The `Arena.` block below and the Buffers lane both walk it.
set(MGL_ITEST_ARENA_CASES
SubDataAfterAnInFlightDrawReachesTheNextDraw
RespecifiedVertexArenaKeepsVaoBindings
RespecifiedIndexArenaKeepsVaoBinding
ReadbackSeesTheLatestCpuWrite
GpuWriteIntoTheArenaIsReadBack
TheArenaLandsInTheTierItsLaneDeclares)
set(MGL_ITEST_MAGMA_BAND_FLAVOUR_ENV
"MOBILEGL_BACKEND_TYPE=DirectVulkan"
"MOBILEGL_IPC_ROLE_SPLIT_STATE=1" "MOBILEGL_IPC_STRICT_ERRORS=1" "MOBILEGL_IPC_RUN_AHEAD=1"
@@ -3753,6 +3807,34 @@ if (MOBILEGL_BUILD_DISAGGREGATED)
${mglItestArmProperties}
ENVIRONMENT "${mglItestMagmaBandEnvironment}\;MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/p10-fence${mglItestArmLogTag}-${fenceCase}.log")
endforeach()
# P11 A2 (MG_Remote/CONTRACT-P11.md §2): the >= 16 MiB arena on Magma's three arms, in the
# same flavour. Declared emulated: every split acquisition declines (the wire resource
# table's MapPersistent returns null, VkBufferManager.cpp), so the tier case asserts T2
# on every arm; DirectVulkan.ArenaArm. is its monolith (adopted) half.
foreach(arenaCase IN LISTS MGL_ITEST_ARENA_CASES)
gtest_discover_tests(MobileGLIntegrationTest
TEST_PREFIX "DirectVulkan.${mglItestArm}.Arena."
TEST_FILTER "LargeArenaAdoptionScenario.${arenaCase}"
DISCOVERY_TIMEOUT 30
PROPERTIES LABELS "${mglItestMagmaLabels}" TIMEOUT ${MGL_ITEST_TIMEOUT}
${mglItestArmProperties}
ENVIRONMENT "${mglItestMagmaBandEnvironment}\;MGITEST_PERSISTENT_MAP_ARM=emulated\;MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/p11-arena${mglItestArmLogTag}-${arenaCase}.log")
endforeach()
# P11 A1 (CONTRACT-P11 §1): the tcp arm with MOBILEGL_IPC_ADOPT_TIER=0 - refused by name at
# the client's handshake, T2, the scenario green. TCP ONLY by construction (over shared
# segments the knob dies at the handshake); spawn_lane_parity.py names the tail in
# MAGMA_TCP_ONLY.
if(mglItestArm STREQUAL "Tcp")
foreach(arenaCase IN LISTS MGL_ITEST_ARENA_CASES ITEMS AStreamSessionRefusesTheAdoptTierOnceByName)
gtest_discover_tests(MobileGLIntegrationTest
TEST_PREFIX "DirectVulkan.Tcp.AdoptTier0."
TEST_FILTER "LargeArenaAdoptionScenario.${arenaCase}"
DISCOVERY_TIMEOUT 30
PROPERTIES LABELS "${mglItestMagmaLabels}" TIMEOUT ${MGL_ITEST_TIMEOUT}
${mglItestArmProperties}
ENVIRONMENT "${mglItestMagmaBandEnvironment}\;MOBILEGL_IPC_ADOPT_TIER=0\;MGITEST_ADOPT_TIER_REFUSAL=T0\;MGITEST_PERSISTENT_MAP_ARM=emulated\;MOBILEGL_LOG_FILE_PATH=${CMAKE_CURRENT_BINARY_DIR}/p11-adopt-tier0-tcp-${arenaCase}.log")
endforeach()
endif()
endforeach()
endif()
@@ -3915,7 +3997,15 @@ if (MOBILEGL_BUILD_DISAGGREGATED)
CrossFrameBufferScenario.IndexOrphanAndReupload
PersistentCoherentMapScenario.TwoWritesThroughTheCoherentPointerEachReachTheirOwnDraw
PersistentCoherentMapScenario.AWriteAfterAFrameBoundaryReachesTheNextFramesDraw
StorageBufferRegrowScenario.AGrownStoreIsVisibleThroughItsExistingIndexedBinding)
StorageBufferRegrowScenario.AGrownStoreIsVisibleThroughItsExistingIndexedBinding
# P11 A2: the >= 16 MiB arena, the flavour's MGITEST_PERSISTENT_MAP_ARM=emulated
# asserted by its tier case (MG_Remote/CONTRACT-P11.md §2).
LargeArenaAdoptionScenario.SubDataAfterAnInFlightDrawReachesTheNextDraw
LargeArenaAdoptionScenario.RespecifiedVertexArenaKeepsVaoBindings
LargeArenaAdoptionScenario.RespecifiedIndexArenaKeepsVaoBinding
LargeArenaAdoptionScenario.ReadbackSeesTheLatestCpuWrite
LargeArenaAdoptionScenario.GpuWriteIntoTheArenaIsReadBack
LargeArenaAdoptionScenario.TheArenaLandsInTheTierItsLaneDeclares)
gtest_discover_tests(MobileGLIntegrationTest
TEST_PREFIX "DirectVulkan.${mglItestArm}.Buffers."
TEST_FILTER "${bufferCase}"
@@ -25,6 +25,9 @@ foreach(listName IN ITEMS @MGL_SPLIT_ARM_TEST_LISTS@)
elseif(entry MATCHES "PersistentCoherentMapScenario.TheMapLandsInTheArmItsLaneDeclares$")
set_tests_properties("${entry}" PROPERTIES ENVIRONMENT
"MGITEST_PMAP_LANE=1;MGITEST_PERSISTENT_MAP_ARM=emulated;MOBILEGL_PIPE_STATS=1;MOBILEGL_PIPE_STATS_PERIOD=1")
elseif(entry MATCHES "LargeArenaAdoptionScenario.TheArenaLandsInTheTierItsLaneDeclares$")
# P11 A2: every split arm runs T2, so the arena is declared emulated.
set_tests_properties("${entry}" PROPERTIES ENVIRONMENT "MGITEST_PERSISTENT_MAP_ARM=emulated")
elseif(entry MATCHES "CtWireScenario\\.")
set_tests_properties("${entry}" PROPERTIES ENVIRONMENT "MOBILEGL_TEST_SERVER_COUNTERS=1")
endif()
@@ -49,8 +49,10 @@
#include <vector>
#include "../Harness/HeadlessGL.h"
#include "../Harness/PersistentMapPeek.h"
#include "../Harness/PipeStatsWindow.h"
#include "../Harness/ScenarioFixture.h"
#include "../Harness/SplitLane.h"
#ifdef GLAPI
#undef GLAPI
@@ -94,6 +96,9 @@ void main() { word = 0xC0FFEEu; }
// Set by the MapPersistentRoundtrips. ctest entry and by nothing else; a harness marker,
// never read by the library.
constexpr const char* kLaneMarker = "MGITEST_MPR_LANE";
// P11 A1: set (to the tier the lane names, "T0") only by the `.AdoptTier0.` tcp entries,
// which also set MOBILEGL_IPC_ADOPT_TIER=0; a harness marker, never read by the library.
constexpr const char* kAdoptTierRefusalMarker = "MGITEST_ADOPT_TIER_REFUSAL";
// Draws issued against the arena inside the counted window. One definition, many draws:
// "one per definition" (1) and "one per draw" (kDrawsInTheWindow) have to be different
// numbers or the assertion cannot tell them apart.
@@ -260,6 +265,27 @@ void main() { word = 0xC0FFEEu; }
return px;
}
// P11 A2: the arena's tier as the frontend object records it, against the lane's
// declaration. Adopted = the resource owner minted a persistent coherent mapping and
// the CPU shadow was released; emulated = the owner declined (T2) and the shadow is
// the truth. Pixels cannot tell them apart - every case above is green on both.
void ExpectDeclaredArm(const std::string& declared, const char* when) {
bool adopted = false;
ASSERT_TRUE(PeekBufferIsAdoptedPersistentMap(m_arena, &adopted))
<< "no frontend BufferObject behind the arena " << when;
const std::string landed = adopted ? "adopted" : "emulated";
RecordProperty(std::string("arena_arm_") + (m_armPeeks++ == 0 ? "defined" : "used"),
landed.c_str());
EXPECT_EQ(declared, landed)
<< "the lane declared the " << declared << " arm and the " << (kArenaBytes >> 20)
<< " MiB arena is " << landed << " " << when
<< ". Monolith lanes adopt on both backends (Espryt's handle arm mints through "
"Ops_H_MapPersistentTracked, Magma's legacy AcquirePersistentMap); split lanes "
"run T2, where every acquisition declines.";
}
int m_armPeeks = 0;
unsigned int m_program = 0;
unsigned int m_compute = 0;
unsigned int m_vao = 0;
@@ -505,4 +531,92 @@ void main() { word = 0xC0FFEEu; }
<< window.line;
}
// P11 A2 (MG_Remote/CONTRACT-P11.md §2): WHICH TIER THE ARENA REALLY LANDED IN. The cases above
// are green whether the arena adopted or stayed emulated, so the lane declares the arm
// (MGITEST_PERSISTENT_MAP_ARM) and this case asserts it, the way
// PersistentCoherentMapScenario.TheMapLandsInTheArmItsLaneDeclares does for a sub-16-MiB map.
// Asked twice: after the NULL-data definition (TryAdoptLargeStorage's door) and after a frame
// of use that ends in an SSBO binding and a dispatch (the storage-binding door,
// EnsureGpuResidentStorage, which Magma's server walk opens). Lanes that declare nothing - the
// ambient entries, which run under whatever transport the job exports - skip.
TEST_F(LargeArenaAdoptionScenario, TheArenaLandsInTheTierItsLaneDeclares) {
if (!Ready() || IsSkipped()) return;
const std::string declared = SplitLane::DeclaredPersistentMapArm();
if (declared.empty()) {
GTEST_SKIP() << "this lane declares no arm: MGITEST_PERSISTENT_MAP_ARM is set only by the "
"lanes that pin their transport (monolith: adopted; the split arms: "
"emulated)";
}
if (!PersistentMapPeekAvailable()) {
GTEST_SKIP() << "this lane declares the " << declared << " arm but Harness/PersistentMapPeek "
"cannot look in this build (on Android this module links the shipping "
"library, built -fvisibility=hidden). 'Could not look' is not 'it was "
<< declared << "'.";
}
ExpectDeclaredArm(declared, "right after its NULL-data definition");
if (HasFatalFailure()) return;
UploadQuad(1.f, 0.f, 0.f);
DrawQuad();
EXPECT_GT(CenterPixel()[0], 200) << "the draw from the arena never landed";
Gl().EndFrame();
GLint maxComputeStorageBlocks = 0;
glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeStorageBlocks);
if (maxComputeStorageBlocks >= 1) {
const GLuint compute = CompileStage(GL_COMPUTE_SHADER, kMarkerComputeSource);
ASSERT_NE(compute, 0u) << m_buildLog;
m_compute = glCreateProgram();
glAttachShader(m_compute, compute);
glLinkProgram(m_compute);
glDeleteShader(compute);
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, m_arena, 0, sizeof(unsigned int));
glUseProgram(m_compute);
glDispatchCompute(1, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT);
unsigned int marker = 0;
glBindBuffer(GL_ARRAY_BUFFER, m_arena);
glGetBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(marker), &marker);
EXPECT_EQ(marker, 0xC0FFEEu) << "the dispatch through the arena's SSBO binding never landed";
} else {
RecordProperty("arena_arm_used", "not asked: no compute shader storage blocks");
}
EXPECT_EQ(FirstGLError(), 0u);
ExpectDeclaredArm(declared, "after a frame of draws, an SSBO binding and a dispatch");
}
// P11 A1 (MG_Remote/CONTRACT-P11.md §1): THE TCP LANE WITH MOBILEGL_IPC_ADOPT_TIER=0. A stream
// data plane has no memory the two sides share, so the client refuses the knob by name at its
// handshake - exactly one `Refuse{AdoptTierOnStream, "T0"}` line in its log - and the session
// runs T2: the other cases in the same `.AdoptTier0.` lane are green and the arena is emulated.
// Before A1 this lane ran T2 silently. Everywhere else it skips.
TEST_F(LargeArenaAdoptionScenario, AStreamSessionRefusesTheAdoptTierOnceByName) {
if (!Ready() || IsSkipped()) return;
const char* tier = std::getenv(kAdoptTierRefusalMarker);
if (tier == nullptr || tier[0] == '\0') {
GTEST_SKIP() << "runs only in the `.AdoptTier0.` tcp entries, which set "
"MOBILEGL_IPC_ADOPT_TIER=0 and " << kAdoptTierRefusalMarker << "=T0";
}
if (PipeStatsWindow::LibraryLogPath().empty()) {
GTEST_SKIP() << "the lane configured no MOBILEGL_LOG_FILE_PATH, and the client's log is "
"where the refusal is written";
}
// A frame of the arena's work first: a refusal is only worth reading from a session that
// then ran - and an armed split lane requires the case to move the record ordinal anyway.
UploadQuad(0.f, 1.f, 0.f);
DrawQuad();
EXPECT_GT(CenterPixel()[1], 200) << "the session that refused the tier did not render";
EXPECT_EQ(FirstGLError(), 0u);
Gl().EndFrame();
const std::string log = PipeStatsWindow::ReadWholeFile(PipeStatsWindow::LibraryLogPath());
const std::string line = std::string("Refuse{AdoptTierOnStream, \"") + tier + "\"}";
std::size_t count = 0;
for (auto at = log.find(line); at != std::string::npos; at = log.find(line, at + 1)) ++count;
RecordProperty("adopt_tier_refusals", static_cast<int>(count));
EXPECT_EQ(count, 1u) << "the client names MOBILEGL_IPC_ADOPT_TIER on a stream exactly once, at "
"its handshake (" << line << "), in " << PipeStatsWindow::LibraryLogPath();
EXPECT_EQ(log.find("Fatal{UnimplementedAdoptTier"), std::string::npos) << log;
}
} // namespace MGITest
+27 -2
View File
@@ -122,6 +122,16 @@ MAGMA_SERVER_ENV_KNOB_NO_TCP = (".ShaderMip1.", ".ShaderMip2.", ".DepthMip.",
f".PrimGenReroute.PrimitivesGeneratedNoXfbScenario.{case}" for case in PRIMGEN_REROUTE_CASES)
# P11 A1: THE MIRROR SHAPE - entries that exist on tcp ALONE, by construction. `.AdoptTier0.` runs
# LargeArenaAdoptionScenario with MOBILEGL_IPC_ADOPT_TIER=0 on the CLIENT: a stream data plane
# refuses that tier by name and runs T2 (the scenario is green there), while over shared segments -
# the split and spawn arms - the same knob dies at the handshake by design (CONTRACT-P11 §1), so a
# split or spawn copy could only ever be a death. Each tail must match at least one tcp entry, or
# the exception names nothing. (The DirectGLES `.AdoptTier0.` twins need no entry: the Espryt
# CASE pattern does not parse a middle segment, so they never enter that comparison.)
MAGMA_TCP_ONLY = (".AdoptTier0.",)
def lane_names(build_dir, label):
"""Every ctest entry name under an ANCHORED label (`ctest -L` is a regex, not a name)."""
out = subprocess.run(["ctest", "-N", "-L", "^" + label + "$"], cwd=build_dir,
@@ -169,7 +179,7 @@ def tcp_lock_check(build_dir):
return False
def compare_arms(build_dir, tier, labels, inproc_only=(), no_tcp=()):
def compare_arms(build_dir, tier, labels, inproc_only=(), no_tcp=(), tcp_only=()):
"""The three arms of one tier must name the same set after the arm segment comes off.
`inproc_only` drops a key from the comparison for EVERY non-split arm; `no_tcp` drops it for
@@ -195,6 +205,20 @@ def compare_arms(build_dir, tier, labels, inproc_only=(), no_tcp=()):
return False
failed = False
reference = "split"
if tcp_only and "tcp" in sets:
for tail in tcp_only:
hits = sorted(k for k in sets["tcp"] if tail in k)
if not hits:
print(f"::error::{tier}: the tcp-only tail {tail!r} matches no tcp entry - an exception "
f"about nothing.", file=sys.stderr)
return True
elsewhere = sorted(k for arm, keys in sets.items() if arm != "tcp" for k in keys if tail in k)
if elsewhere:
print(f"::error::{tier}: the tcp-only tail {tail!r} also names non-tcp entries "
f"{elsewhere}.", file=sys.stderr)
return True
print(f"{tier}: {len(hits)} tcp-only entrie(s) excluded from the comparison ({tail})")
sets["tcp"] = {k for k in sets["tcp"] if not any(only in k for only in tcp_only)}
comparable = {k for k in sets[reference]
if not any(only in k for only in inproc_only)}
if len(comparable) != len(sets[reference]):
@@ -294,7 +318,8 @@ def main():
"spawn": "integration-magma-spawn",
"tcp": "integration-magma-tcp"},
inproc_only=MAGMA_INPROC_ONLY,
no_tcp=MAGMA_SERVER_ENV_KNOB_NO_TCP)
no_tcp=MAGMA_SERVER_ENV_KNOB_NO_TCP,
tcp_only=MAGMA_TCP_ONLY)
failed |= compare_arms(args.build_dir, "magma informational tier",
{"split": "integration-magma-all-split",
"spawn": "integration-magma-all-spawn",