diagnostics: add STEP-099 render source readiness audit
This commit is contained in:
@@ -934,6 +934,115 @@ TEST(RenderSegmentDiagnostics, SnapshotCoversStyleExactlyAndSerializesContinuous
|
||||
EXPECT_NE(json.find("\"cache\":null"), std::string::npos);
|
||||
}
|
||||
|
||||
|
||||
TEST(RenderSegmentDiagnostics, ReadinessSnapshotMapsSourcesToSegmentsWithoutSideEffects) {
|
||||
RetainedUnderlayRuntimeState state;
|
||||
RenderSegmentPlan configured;
|
||||
configured.segments = {{RenderSegmentStrategy::Retained, std::nullopt},
|
||||
{RenderSegmentStrategy::Continuous, "weather"},
|
||||
{RenderSegmentStrategy::Retained, "land"}};
|
||||
ASSERT_TRUE(state.setRenderSegmentPlan(configured));
|
||||
const auto resolved = resolveRenderSegmentPlan(state.renderSegmentPlanConfig(), segmentLayerIds(), true);
|
||||
|
||||
std::vector<StyleLayerDiagnostics> layers;
|
||||
for (std::size_t i = 0; i < segmentLayerIds().size(); ++i) {
|
||||
layers.push_back({static_cast<int32_t>(i), segmentLayerIds()[i], "fill", true, std::nullopt, std::nullopt});
|
||||
}
|
||||
layers[1].sourceId = "chart";
|
||||
layers[2].sourceId = "dynamic";
|
||||
layers[3].sourceId = "dynamic";
|
||||
layers[4].sourceId = "chart";
|
||||
layers[5].layerType = "symbol";
|
||||
layers[5].sourceId = "ais";
|
||||
state.recordRenderSegmentResolution(resolved, layers);
|
||||
state.recordSegmentBuild(0);
|
||||
state.recordSegmentCacheState(0, RetainedRangeCacheState::Ready, 41);
|
||||
|
||||
RendererReadinessDiagnostics readiness;
|
||||
readiness.styleLoaded = true;
|
||||
readiness.imageManagerLoaded = true;
|
||||
readiness.renderOrchestratorLoaded = false;
|
||||
readiness.spriteLoaded = true;
|
||||
readiness.hasFadingTiles = false;
|
||||
readiness.contentRevision = 42;
|
||||
readiness.sources = {
|
||||
{.sourceId = "chart",
|
||||
.sourceType = "vector",
|
||||
.enabled = true,
|
||||
.isLoaded = true,
|
||||
.tileBacked = true,
|
||||
.tileCount = 4,
|
||||
.incompleteTileCount = 0,
|
||||
.loadedTileCount = 4},
|
||||
{.sourceId = "dynamic",
|
||||
.sourceType = "raster",
|
||||
.enabled = true,
|
||||
.isLoaded = false,
|
||||
.tileBacked = true,
|
||||
.tileCount = 1,
|
||||
.incompleteTileCount = 1,
|
||||
.loadedTileCount = 0,
|
||||
.lastSourceMutationSequence = 11,
|
||||
.lastTileChangedSequence = 12,
|
||||
.lastTileActionSequence = 13,
|
||||
.lastTileAction = "StartParse",
|
||||
.lastMutationReason = "tile-mutation"}};
|
||||
readiness.lastMutation = {.sequence = 12,
|
||||
.contentRevision = 42,
|
||||
.eventType = "TileMutation",
|
||||
.reason = "tile-mutation",
|
||||
.sourceId = "dynamic"};
|
||||
state.recordRendererReadiness(readiness);
|
||||
|
||||
const auto first = state.renderSegmentSnapshot();
|
||||
ASSERT_EQ(first.sources.size(), 2u);
|
||||
EXPECT_TRUE(first.styleLoaded);
|
||||
EXPECT_TRUE(first.imageManagerLoaded);
|
||||
EXPECT_FALSE(first.renderOrchestratorLoaded);
|
||||
EXPECT_EQ(first.contentRevision, 42u);
|
||||
EXPECT_EQ(first.sources[0].sourceId, "chart");
|
||||
EXPECT_TRUE(first.sources[0].isLoaded);
|
||||
EXPECT_EQ(first.sources[0].tileCount, std::optional<uint32_t>{4});
|
||||
EXPECT_EQ(first.sources[1].sourceId, "dynamic");
|
||||
EXPECT_FALSE(first.sources[1].isLoaded);
|
||||
EXPECT_EQ(first.sources[1].incompleteTileCount, std::optional<uint32_t>{1});
|
||||
ASSERT_EQ(first.segments.size(), 3u);
|
||||
EXPECT_EQ(first.segments[0].dependentSourceIds, std::vector<std::string>({"chart"}));
|
||||
EXPECT_EQ(first.segments[1].dependentSourceIds, std::vector<std::string>({"dynamic"}));
|
||||
EXPECT_EQ(first.segments[2].dependentSourceIds, std::vector<std::string>({"ais", "chart"}));
|
||||
EXPECT_TRUE(first.segments[0].unknownDependencies.empty());
|
||||
EXPECT_EQ(first.segments[2].unknownDependencies,
|
||||
std::vector<std::string>({"symbol/glyph/image/placement"}));
|
||||
EXPECT_EQ(first.segments[0].dependentSourceIds.size(), 1u);
|
||||
const auto backgroundLayer = std::find_if(first.segments[0].layers.begin(), first.segments[0].layers.end(),
|
||||
[](const auto& layer) { return layer.layerId == "background"; });
|
||||
ASSERT_NE(backgroundLayer, first.segments[0].layers.end());
|
||||
EXPECT_FALSE(backgroundLayer->sourceId.has_value());
|
||||
EXPECT_EQ(first.lastMutation.affectedSegmentIndices, std::vector<uint32_t>({1}));
|
||||
EXPECT_EQ(first.lastMutation.dependencyScope, "source-local-diagnostic");
|
||||
|
||||
const auto topologyRevision = first.topologyRevision;
|
||||
const auto cacheBuild = first.segments[0].cache->build;
|
||||
state.recordRendererReadiness(readiness);
|
||||
const auto second = state.renderSegmentSnapshot();
|
||||
EXPECT_EQ(second.topologyRevision, topologyRevision);
|
||||
ASSERT_TRUE(second.segments[0].cache);
|
||||
EXPECT_EQ(second.segments[0].cache->build, cacheBuild);
|
||||
EXPECT_EQ(second.segments[0].cache->contentRevision, 41u);
|
||||
const auto third = state.renderSegmentSnapshot();
|
||||
EXPECT_EQ(third.topologyRevision, second.topologyRevision);
|
||||
EXPECT_EQ(third.contentRevision, second.contentRevision);
|
||||
EXPECT_EQ(third.sources, second.sources);
|
||||
EXPECT_EQ(third.lastMutation, second.lastMutation);
|
||||
|
||||
const auto json = renderSegmentDiagnosticsToJSON(second);
|
||||
EXPECT_EQ(renderSegmentDiagnosticsToJSON(state.renderSegmentSnapshot()), json);
|
||||
EXPECT_NE(json.find("\"renderOrchestratorLoaded\":false"), std::string::npos);
|
||||
EXPECT_NE(json.find("\"incompleteTileCount\":1"), std::string::npos);
|
||||
EXPECT_NE(json.find("\"dependentSourceIds\":[\"dynamic\"]"), std::string::npos);
|
||||
EXPECT_NE(json.find("\"affectedSegmentIndices\":[1]"), std::string::npos);
|
||||
}
|
||||
|
||||
TEST(RenderSegmentPlan, StrictJSONRejectsUnknownFieldsStrategyAndInvalidFirstBoundary) {
|
||||
EXPECT_FALSE(parseRenderSegmentPlanJSON(
|
||||
R"({"schemaVersion":1,"segments":[{"strategy":"RETAINED","unexpected":true}]})"));
|
||||
|
||||
Reference in New Issue
Block a user