96 lines
2.8 KiB
Python
96 lines
2.8 KiB
Python
|
|
# retoor <retoor@molodetz.nl>
|
||
|
|
|
||
|
|
from datetime import timedelta
|
||
|
|
|
||
|
|
from devplacepy.database import invalidate_admins_cache
|
||
|
|
from devplacepy.services.devii.tasks.guards import (
|
||
|
|
REASON_BUDGET,
|
||
|
|
REASON_EXPIRED,
|
||
|
|
REASON_FAILURES,
|
||
|
|
REASON_MAX_RUNS,
|
||
|
|
REASON_NOT_ADMIN,
|
||
|
|
automation_allowed,
|
||
|
|
refusal,
|
||
|
|
)
|
||
|
|
from devplacepy.services.devii.tasks.schedule import now_utc, to_iso
|
||
|
|
from devplacepy.utils import generate_uid
|
||
|
|
|
||
|
|
|
||
|
|
def _account(local_db, role):
|
||
|
|
uid = generate_uid()
|
||
|
|
local_db["users"].insert(
|
||
|
|
{
|
||
|
|
"uid": uid,
|
||
|
|
"username": f"guard-{uid[-10:]}",
|
||
|
|
"role": role,
|
||
|
|
"deleted_at": None,
|
||
|
|
}
|
||
|
|
)
|
||
|
|
invalidate_admins_cache()
|
||
|
|
return uid
|
||
|
|
|
||
|
|
|
||
|
|
def _row(owner_uid, **overrides):
|
||
|
|
row = {
|
||
|
|
"uid": generate_uid(),
|
||
|
|
"owner_kind": "user",
|
||
|
|
"owner_id": owner_uid,
|
||
|
|
"run_count": 0,
|
||
|
|
"created_at": to_iso(now_utc()),
|
||
|
|
}
|
||
|
|
row.update(overrides)
|
||
|
|
return row
|
||
|
|
|
||
|
|
|
||
|
|
def test_only_administrators_may_automate(local_db):
|
||
|
|
admin = _account(local_db, "Admin")
|
||
|
|
member = _account(local_db, "Member")
|
||
|
|
assert automation_allowed("user", admin) is True
|
||
|
|
assert automation_allowed("user", member) is False
|
||
|
|
assert automation_allowed("guest", "guest-cookie") is False
|
||
|
|
assert automation_allowed("user", "") is False
|
||
|
|
|
||
|
|
|
||
|
|
def test_member_owned_task_is_refused(local_db):
|
||
|
|
member = _account(local_db, "Member")
|
||
|
|
assert refusal(_row(member), now_utc()) == REASON_NOT_ADMIN
|
||
|
|
|
||
|
|
|
||
|
|
def test_clean_admin_task_is_allowed(local_db):
|
||
|
|
admin = _account(local_db, "Admin")
|
||
|
|
assert refusal(_row(admin), now_utc()) is None
|
||
|
|
|
||
|
|
|
||
|
|
def test_exhausted_task_is_refused(local_db):
|
||
|
|
admin = _account(local_db, "Admin")
|
||
|
|
row = _row(admin, max_runs=5, run_count=5)
|
||
|
|
assert refusal(row, now_utc()) == REASON_MAX_RUNS
|
||
|
|
|
||
|
|
|
||
|
|
def test_expired_task_is_refused(local_db):
|
||
|
|
admin = _account(local_db, "Admin")
|
||
|
|
now = now_utc()
|
||
|
|
row = _row(admin, expires_at=to_iso(now - timedelta(minutes=1)))
|
||
|
|
assert refusal(row, now) == REASON_EXPIRED
|
||
|
|
|
||
|
|
|
||
|
|
def test_task_without_an_expiry_stops_at_the_fallback_ceiling(local_db):
|
||
|
|
admin = _account(local_db, "Admin")
|
||
|
|
now = now_utc()
|
||
|
|
row = _row(admin, created_at=to_iso(now - timedelta(days=40)))
|
||
|
|
assert refusal(row, now) == REASON_EXPIRED
|
||
|
|
|
||
|
|
|
||
|
|
def test_repeated_failures_refuse_the_task(local_db):
|
||
|
|
admin = _account(local_db, "Admin")
|
||
|
|
row = _row(admin, failure_count=3)
|
||
|
|
assert refusal(row, now_utc(), max_failures=3) == REASON_FAILURES
|
||
|
|
assert refusal(row, now_utc(), max_failures=0) is None
|
||
|
|
|
||
|
|
|
||
|
|
def test_budget_probe_refuses_the_task(local_db):
|
||
|
|
admin = _account(local_db, "Admin")
|
||
|
|
row = _row(admin)
|
||
|
|
assert refusal(row, now_utc(), budget_exceeded=lambda k, i: True) == REASON_BUDGET
|
||
|
|
assert refusal(row, now_utc(), budget_exceeded=lambda k, i: False) is None
|