fix(calendar): bound recurrence work without hiding busy intervals
Module Package Release / publish-packages (push) Successful in 14s

Release v0.1.24. Coordinated integrity review: GovOPlaN/govoplan-core#298.
This commit is contained in:
2026-09-08 12:19:36 +02:00
parent 3e5fc05ca3
commit 8e36f8b3d2
10 changed files with 542 additions and 80 deletions
+30 -1
View File
@@ -3,11 +3,40 @@ from __future__ import annotations
import unittest
from datetime import datetime, timezone
from types import SimpleNamespace
from unittest.mock import patch
from govoplan_calendar.backend.ical import expand_event_occurrences, event_to_ics, parse_vevent
from govoplan_calendar.backend.ical import ICalendarError, _expand_event_occurrences, expand_event_occurrences, event_to_ics, parse_vevent
class ICalendarParsingTests(unittest.TestCase):
def test_recurrence_limit_rejects_without_materializing_between(self) -> None:
start = datetime(2026, 7, 1, tzinfo=timezone.utc)
event = SimpleNamespace(
uid="bounded@example.test", start_at=start, end_at=None, duration_seconds=None, all_day=False,
rrule={"FREQ": "SECONDLY", "COUNT": "121"}, rdate=[], exdate=[],
)
with patch("dateutil.rrule.rruleset.between", side_effect=AssertionError("Unbounded allocation")):
with self.assertRaisesRegex(ICalendarError, "result limit"):
_expand_event_occurrences(
event, start, datetime(2026, 7, 1, 0, 2, tzinfo=timezone.utc), limit=1,
)
def test_invalid_worker_ack_is_rejected(self) -> None:
from govoplan_core.security.worker_payload import encode_worker_payload
start = datetime(2026, 7, 1, tzinfo=timezone.utc)
event = SimpleNamespace(
uid="expected@example.test", start_at=start, end_at=None, all_day=False,
rrule={"FREQ": "DAILY", "COUNT": "1"}, rdate=[], exdate=[],
)
wrong = encode_worker_payload({"occurrences": [[{
"uid": "different@example.test", "recurrence_id": "20260701T000000Z",
"start_at": start, "end_at": None, "all_day": False,
}]]})
with patch("govoplan_core.security.bounded_process.run_bounded_operation", return_value=wrong):
with self.assertRaisesRegex(ICalendarError, "invalid result"):
expand_event_occurrences(event, start, start)
def test_parse_vevent_preserves_unknown_properties_and_params(self) -> None:
payload = """BEGIN:VCALENDAR
VERSION:2.0