chore: tighten scheduling review coverage
This commit is contained in:
@@ -114,12 +114,9 @@ def _history(store: FileScheduleStore, sid: str) -> list[dict]:
|
||||
return page["occurrences"] # type: ignore[return-value]
|
||||
|
||||
|
||||
def test_overlap_skip_blocks_and_late_drops() -> None:
|
||||
import tempfile
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
root = Path(tmp)
|
||||
sched, store, runs, sources = _harness(root, capacity=4, script={"*": "hang"})
|
||||
def test_overlap_skip_blocks_and_late_drops(tmp_path: Path) -> None:
|
||||
sched, store, runs, sources = _harness(tmp_path, capacity=4, script={"*": "hang"})
|
||||
try:
|
||||
t0 = ts(2026, 9, 8, 12, 0)
|
||||
_add(
|
||||
sched,
|
||||
@@ -137,15 +134,13 @@ def test_overlap_skip_blocks_and_late_drops() -> None:
|
||||
sched.poll(t0 + timedelta(minutes=30))
|
||||
kinds = [(r["kind"], r["resolved_at"]) for r in _history(store, "a")]
|
||||
assert any(k == "skipped-misfire" for k, _ in kinds)
|
||||
finally:
|
||||
sched.ownership.release()
|
||||
|
||||
|
||||
def test_latest_coalesces_to_one_candidate_and_no_double_admit() -> None:
|
||||
import tempfile
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
root = Path(tmp)
|
||||
sched, store, runs, sources = _harness(root, capacity=0)
|
||||
def test_latest_coalesces_to_one_candidate_and_no_double_admit(tmp_path: Path) -> None:
|
||||
sched, store, runs, sources = _harness(tmp_path, capacity=0)
|
||||
try:
|
||||
_add(
|
||||
sched,
|
||||
store,
|
||||
@@ -170,6 +165,7 @@ def test_latest_coalesces_to_one_candidate_and_no_double_admit() -> None:
|
||||
2026, 9, 8, 13, 0
|
||||
)
|
||||
assert store.get_candidate("h") is None
|
||||
finally:
|
||||
sched.ownership.release()
|
||||
|
||||
|
||||
@@ -217,7 +213,6 @@ def test_schedule_edit_between_poll_snapshot_and_admission_cannot_overwrite_term
|
||||
}
|
||||
)
|
||||
super().update_schedule(edited, expected_revision=current.revision)
|
||||
return current
|
||||
return current
|
||||
|
||||
sched_store = EditOnPollRead(tmp_path / "sched")
|
||||
@@ -277,12 +272,9 @@ def test_trigger_edit_refreshes_managed_calendar_before_polling(tmp_path: Path)
|
||||
sched.ownership.release()
|
||||
|
||||
|
||||
def test_parallel_limits_and_interrupted_slots() -> None:
|
||||
import tempfile
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
root = Path(tmp)
|
||||
sched, store, runs, sources = _harness(root, capacity=4, script={"*": "hang"})
|
||||
def test_parallel_limits_and_interrupted_slots(tmp_path: Path) -> None:
|
||||
sched, store, runs, sources = _harness(tmp_path, capacity=4, script={"*": "hang"})
|
||||
try:
|
||||
t0 = ts(2026, 9, 8, 12, 0)
|
||||
_add(
|
||||
sched,
|
||||
@@ -319,17 +311,15 @@ def test_parallel_limits_and_interrupted_slots() -> None:
|
||||
r["kind"] == "skipped-overlap" and "12:15" in str(r["resolved_at"])
|
||||
for r in _history(store, "p")
|
||||
)
|
||||
finally:
|
||||
sched.ownership.release()
|
||||
|
||||
|
||||
def test_pause_is_not_downtime() -> None:
|
||||
import tempfile
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
root = Path(tmp)
|
||||
sched, store, runs, sources = _harness(
|
||||
root, capacity=4, script={"*": "complete"}
|
||||
)
|
||||
def test_pause_is_not_downtime(tmp_path: Path) -> None:
|
||||
sched, store, runs, sources = _harness(
|
||||
tmp_path, capacity=4, script={"*": "complete"}
|
||||
)
|
||||
try:
|
||||
_add(
|
||||
sched,
|
||||
store,
|
||||
@@ -352,6 +342,7 @@ def test_pause_is_not_downtime() -> None:
|
||||
]
|
||||
assert "2026-09-08T10:00:00+00:00" not in admitted
|
||||
assert "2026-09-08T11:00:00+00:00" not in admitted
|
||||
finally:
|
||||
sched.ownership.release()
|
||||
|
||||
|
||||
@@ -359,22 +350,35 @@ def test_long_downtime_is_bounded(tmp_path: Path) -> None:
|
||||
sched, store, runs, sources = _harness(
|
||||
tmp_path, capacity=4, script={"*": "complete"}
|
||||
)
|
||||
src = PeriodicSource(timedelta(minutes=1), ts(2023, 9, 8, 12, 0))
|
||||
_add(sched, store, sources, "m", src, ts(2023, 9, 8, 12, 0), misfire="latest")
|
||||
sched.poll(ts(2026, 9, 8, 12, 0, 0))
|
||||
assert src.next_calls + src.prev_calls <= SCAN_CAP + 2
|
||||
admitted = [r for r in _history(store, "m") if r["kind"] == "admitted"]
|
||||
assert len(admitted) == 1
|
||||
# Latest-eligible <= now: a poll exactly at a due instant selects that
|
||||
# instant (F3), not its exclusive predecessor.
|
||||
assert datetime.fromisoformat(admitted[0]["resolved_at"]) == ts(2026, 9, 8, 12, 0)
|
||||
assert (
|
||||
len([r for r in _history(store, "m") if r["kind"] == "interval-summary"]) == 1
|
||||
)
|
||||
# A second poll at the same instant admits nothing more.
|
||||
sched.poll(ts(2026, 9, 8, 12, 0, 0))
|
||||
assert len([r for r in _history(store, "m") if r["kind"] == "admitted"]) == 1
|
||||
sched.ownership.release()
|
||||
try:
|
||||
src = PeriodicSource(timedelta(minutes=1), ts(2023, 9, 8, 12, 0))
|
||||
_add(
|
||||
sched,
|
||||
store,
|
||||
sources,
|
||||
"m",
|
||||
src,
|
||||
ts(2023, 9, 8, 12, 0),
|
||||
misfire="latest",
|
||||
)
|
||||
sched.poll(ts(2026, 9, 8, 12, 0, 0))
|
||||
assert src.next_calls + src.prev_calls <= SCAN_CAP + 2
|
||||
admitted = [r for r in _history(store, "m") if r["kind"] == "admitted"]
|
||||
assert len(admitted) == 1
|
||||
# Latest-eligible <= now: a poll exactly at a due instant selects that
|
||||
# instant (F3), not its exclusive predecessor.
|
||||
assert datetime.fromisoformat(admitted[0]["resolved_at"]) == ts(
|
||||
2026, 9, 8, 12, 0
|
||||
)
|
||||
assert (
|
||||
len([r for r in _history(store, "m") if r["kind"] == "interval-summary"])
|
||||
== 1
|
||||
)
|
||||
# A second poll at the same instant admits nothing more.
|
||||
sched.poll(ts(2026, 9, 8, 12, 0, 0))
|
||||
assert len([r for r in _history(store, "m") if r["kind"] == "admitted"]) == 1
|
||||
finally:
|
||||
sched.ownership.release()
|
||||
|
||||
|
||||
def test_fairness_slow_schedule_not_starved(tmp_path: Path) -> None:
|
||||
|
||||
Reference in New Issue
Block a user