Тест: провал видимости перекрывается одним планом (форма Reflexio)
Воспроизводит форму с экрана Reflexio (раннее окно, большой провал видимости, далёкий кластер) и проверяет, что цепочка перекрывает провал одним длинным планом и доходит до далёкого кластера без разрыва.
This commit is contained in:
+16
-5
@@ -237,14 +237,16 @@ class PlanCalculationServiceTest {
|
|||||||
fun `calculatePlans never leaves a gap between plans across a visibility gap`() {
|
fun `calculatePlans never leaves a gap between plans across a visibility gap`() {
|
||||||
val service = createService(targetMinutes = 180L, deltaMinutes = 60L)
|
val service = createService(targetMinutes = 180L, deltaMinutes = 60L)
|
||||||
val start = LocalDateTime.of(2026, 3, 10, 10, 0)
|
val start = LocalDateTime.of(2026, 3, 10, 10, 0)
|
||||||
// Плотный кластер окон, затем большой провал видимости, затем далёкий кластер.
|
// Воспроизводит форму с экрана Reflexio: раннее окно, затем большой провал
|
||||||
// Провал допустимо перекрыть одним длинным планом, но разрыва между планами быть не должно.
|
// видимости, затем далёкий кластер. Провал допустимо перекрыть одним длинным
|
||||||
|
// планом, но разрыва между планами быть не должно.
|
||||||
|
val gap = start.plusDays(3)
|
||||||
val windows = buildList {
|
val windows = buildList {
|
||||||
for (minutes in 0..240 step 20) {
|
for (minutes in 0..240 step 20) {
|
||||||
add(window("NEAR-$minutes", start.plusMinutes(minutes.toLong())))
|
add(window("NEAR-$minutes", start.plusMinutes(minutes.toLong())))
|
||||||
}
|
}
|
||||||
for (minutes in 0..120 step 20) {
|
for (minutes in 0..240 step 20) {
|
||||||
add(window("FAR-$minutes", start.plusDays(3).plusMinutes(minutes.toLong())))
|
add(window("FAR-$minutes", gap.plusMinutes(minutes.toLong())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,7 +254,16 @@ class PlanCalculationServiceTest {
|
|||||||
|
|
||||||
// Главное требование: каждый следующий план стартует строго внутри предыдущего (без разрыва).
|
// Главное требование: каждый следующий план стартует строго внутри предыдущего (без разрыва).
|
||||||
assertChainInvariant(plans)
|
assertChainInvariant(plans)
|
||||||
assertTrue(plans.size >= 2, "expected a multi-plan chain, got ${plans.size}")
|
// Провал перекрыт одним длинным планом: есть план, начинающийся до провала и кончающийся после.
|
||||||
|
assertTrue(
|
||||||
|
plans.any { plan -> plan.startTime < gap && plan.endTime > gap },
|
||||||
|
"the visibility gap must be bridged by a single plan: $plans"
|
||||||
|
)
|
||||||
|
// И цепочка действительно доходит до далёкого кластера, а не обрывается до провала.
|
||||||
|
assertTrue(
|
||||||
|
plans.any { plan -> plan.startTime >= gap },
|
||||||
|
"the chain must reach the far cluster after the gap: $plans"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user