#include #include #include using namespace mbgl; namespace { RetainedUnderlayKey key(Size size = {640, 480}, int32_t boundary = 4) { RetainedUnderlayKey result{size, boundary, {}}; result.cameraMatrix[0] = 1.0; result.cameraMatrix[5] = 1.0; result.cameraMatrix[10] = 1.0; result.cameraMatrix[15] = 1.0; return result; } } // namespace TEST(RetainedDynamicBoundary, SelectsFirstCandidate) { RetainedDynamicBoundaryTracker none; none.consider(0, false); none.consider(3, false); EXPECT_FALSE(none.value()); RetainedDynamicBoundaryTracker particleOnly; particleOnly.consider(5, true); EXPECT_EQ(particleOnly.value(), 5); RetainedDynamicBoundaryTracker weatherAndParticle; weatherAndParticle.consider(7, true); weatherAndParticle.consider(2, true); EXPECT_EQ(weatherAndParticle.value(), 2); RetainedDynamicBoundaryTracker particleAndWeather; particleAndWeather.consider(2, true); particleAndWeather.consider(7, true); EXPECT_EQ(particleAndWeather.value(), 2); } TEST(RetainedLayerGroupRange, PreservesForwardReverseOriginalOrdinals) { const std::vector indices{0, 1, 3, 5, 8}; std::vector beforeForward; std::vector fromForward; std::vector beforeReverse; std::vector fromReverse; for (size_t ordinal = 0; ordinal < indices.size(); ++ordinal) { if (retainedLayerGroupInRange(indices[ordinal], 5, RetainedLayerGroupRange::Before)) beforeForward.push_back(ordinal); else fromForward.push_back(ordinal); } for (size_t ordinal = indices.size(); ordinal-- > 0;) { if (retainedLayerGroupInRange(indices[ordinal], 5, RetainedLayerGroupRange::Before)) beforeReverse.push_back(ordinal); else fromReverse.push_back(ordinal); } EXPECT_EQ(beforeForward, (std::vector{0, 1, 2})); EXPECT_EQ(fromForward, (std::vector{3, 4})); EXPECT_EQ(beforeReverse, (std::vector{2, 1, 0})); EXPECT_EQ(fromReverse, (std::vector{4, 3})); } TEST(RetainedUnderlayCache, BuildReuseAndInvalidation) { RetainedUnderlayCache cache; EXPECT_EQ(cache.evaluate(std::nullopt, false), RetainedUnderlayDecision::Disabled); EXPECT_EQ(cache.evaluate(key(), true), RetainedUnderlayDecision::Build); cache.markBuildSucceeded(); EXPECT_EQ(cache.evaluate(key(), true), RetainedUnderlayDecision::Reuse); EXPECT_EQ(cache.evaluate(key({800, 600}), true), RetainedUnderlayDecision::Build); EXPECT_EQ(cache.getLastInvalidationReason(), "viewport"); cache.markBuildSucceeded(); EXPECT_EQ(cache.evaluate(key({800, 600}, 6), true), RetainedUnderlayDecision::Build); EXPECT_EQ(cache.getLastInvalidationReason(), "camera-or-boundary"); } TEST(RetainedUnderlayCache, UnsupportedAndResourceFailureFallBackSafely) { RetainedUnderlayCache cache; EXPECT_EQ(cache.evaluate(key(), false, "3d"), RetainedUnderlayDecision::Fallback); EXPECT_EQ(cache.getLastInvalidationReason(), "3d"); EXPECT_FALSE(cache.isValid()); EXPECT_EQ(cache.evaluate(key(), true), RetainedUnderlayDecision::Build); cache.markBuildFailed("resource-or-compositor"); EXPECT_FALSE(cache.isValid()); EXPECT_EQ(cache.getFallbackCount(), 2u); } TEST(RetainedUnderlayCache, RuntimeControlDisablesAndReenablesMapScopedCache) { auto state = std::make_shared(); RetainedUnderlayCache cache; cache.synchronizeRuntimeState(state); EXPECT_EQ(cache.evaluate(key(), true), RetainedUnderlayDecision::Build); cache.markBuildSucceeded(); EXPECT_TRUE(cache.isValid()); EXPECT_TRUE(state->setEnabled(false)); cache.synchronizeRuntimeState(state); EXPECT_FALSE(cache.isValid()); EXPECT_EQ(cache.evaluate(key(), true), RetainedUnderlayDecision::Fallback); auto disabled = state->snapshot(); EXPECT_FALSE(disabled.enabled); EXPECT_EQ(disabled.build, 1u); EXPECT_EQ(disabled.fallback, 1u); EXPECT_EQ(disabled.invalidation, 2u); // first-frame plus the runtime disable. EXPECT_EQ(disabled.lastReason, "runtime-disabled"); EXPECT_TRUE(state->setEnabled(true)); cache.synchronizeRuntimeState(state); EXPECT_EQ(cache.evaluate(key(), true), RetainedUnderlayDecision::Build); EXPECT_TRUE(state->snapshot().enabled); }