Files
schedls/tests/unit/test_crontab.py
T
mdaleo404 aded37d491
CI / test (3.11) (push) Canceled after 0s
CI / test (3.12) (push) Canceled after 0s
CI / test (3.13) (push) Canceled after 0s
CI / test (3.14) (push) Canceled after 0s
CI / package (push) Canceled after 0s
CI / precommit-and-security (push) Canceled after 11s
CI / typecheck (push) Canceled after 11s
Initial code commit
2026-09-25 11:16:19 +01:00

96 lines
3.2 KiB
Python

from __future__ import annotations
import pytest
from schedls.backends.cron import CrontabDocument
from schedls.errors import ConflictError, SafetyRefusalError
SAMPLE = (
"MAILTO=admin@example.net\n"
"SHELL=/bin/bash\n"
"PATH=/usr/local/bin:/usr/bin\n"
"\n"
"# personal job\n"
"15 7 * * * ~/bin/foo\n"
"@daily /usr/local/bin/nightly\n"
"\n"
"# schedls:begin name=backup\n"
"0 2 * * * /usr/local/bin/backup /srv/data\n"
"# schedls:end name=backup\n"
)
def test_lossless_round_trip() -> None:
document = CrontabDocument(SAMPLE)
assert document.render() == SAMPLE
def test_managed_block_detected() -> None:
document = CrontabDocument(SAMPLE)
blocks = document.managed_blocks()
assert list(blocks) == ["backup"]
assert blocks["backup"].job_lines[0].expression == "0 2 * * *"
assert blocks["backup"].job_lines[0].command == "/usr/local/bin/backup /srv/data"
assert not document.has_malformed_markers()
def test_environment_and_nickname_parsed() -> None:
document = CrontabDocument(SAMPLE)
kinds = [entry.kind for entry in document.entries]
assert kinds.count("env") == 3
assert kinds.count("comment") == 1
assert kinds.count("managed_begin") == 1
assert kinds.count("managed_end") == 1
jobs = [entry for entry in document.entries if entry.kind == "job"]
assert jobs[0].expression == "15 7 * * *"
assert jobs[1].expression == "@daily"
def test_with_block_preserves_unrelated_content() -> None:
document = CrontabDocument(SAMPLE)
updated = document.with_block("report", ["30 6 * * * /usr/local/bin/report"])
assert "MAILTO=admin@example.net" in updated
assert "15 7 * * * ~/bin/foo" in updated
assert "0 2 * * * /usr/local/bin/backup /srv/data" in updated
assert "# schedls:begin name=report" in updated
reparsed = CrontabDocument(updated)
assert set(reparsed.managed_blocks()) == {"backup", "report"}
def test_with_block_conflict() -> None:
document = CrontabDocument(SAMPLE)
with pytest.raises(ConflictError):
document.with_block("backup", ["0 3 * * * /bin/true"])
def test_without_block_removes_only_block() -> None:
document = CrontabDocument(SAMPLE)
updated = document.without_block("backup")
assert "backup" not in updated
assert "MAILTO=admin@example.net" in updated
assert "15 7 * * * ~/bin/foo" in updated
assert "@daily /usr/local/bin/nightly" in updated
def test_without_unknown_block_refused() -> None:
document = CrontabDocument(SAMPLE)
with pytest.raises(SafetyRefusalError):
document.without_block("nope")
def test_malformed_marker_blocks_mutation() -> None:
document = CrontabDocument("# schedls:begin name=broken\n0 2 * * * /bin/true\n")
assert document.has_malformed_markers()
with pytest.raises(SafetyRefusalError):
document.with_block("new", ["0 3 * * * /bin/true"])
with pytest.raises(SafetyRefusalError):
document.without_block("broken")
def test_empty_crontab() -> None:
document = CrontabDocument("")
assert document.render() == ""
updated = document.with_block("x", ["0 0 * * * /bin/true"])
assert updated.endswith("\n")
assert "name=x" in updated