refactor tests
Publish container image / Build and push (push) Successful in 32s

This commit is contained in:
2026-07-26 23:49:40 +02:00
parent 5ef10d28fe
commit ce9f1e3d20
32 changed files with 1546 additions and 1923 deletions
+39 -54
View File
@@ -1,24 +1,14 @@
import sqlite3
from contextlib import closing
from datetime import UTC, datetime, timedelta
from pathlib import Path
import pytest
from agentci.engine import _sqlite
from agentci.engine import repository as repository_module
from agentci.engine.events import JobStarted, PermissionGranted
from agentci.engine.model import IncomingCommand, QueueName, Task, TaskKind
from agentci.engine.repository import Repository
MIGRATIONS = Path(__file__).parents[1] / "src" / "agentci" / "migrations"
@pytest.fixture
async def repository(tmp_path: Path) -> Repository:
value = Repository(tmp_path / "state.sqlite3", MIGRATIONS)
await value.initialize()
return value
from tests.conftest import SQLiteClock
def command(delivery: str, *, issue: int = 3) -> IncomingCommand:
@@ -34,8 +24,8 @@ def command(delivery: str, *, issue: int = 3) -> IncomingCommand:
)
def task_storage(repository: Repository, task_id: int) -> tuple[object, ...]:
with closing(sqlite3.connect(repository.database_path)) as connection, connection:
def task_storage(engine_repository: Repository, task_id: int) -> tuple[object, ...]:
with closing(sqlite3.connect(engine_repository.database_path)) as connection, connection:
row = connection.execute(
"""SELECT status, attempts, available_at, error, created_at, started_at, finished_at
FROM listener_tasks WHERE id=?""",
@@ -46,20 +36,18 @@ def task_storage(repository: Repository, task_id: int) -> tuple[object, ...]:
async def test_claim_and_complete_record_attempt_and_lifecycle_timestamps(
repository: Repository,
monkeypatch: pytest.MonkeyPatch,
engine_repository: Repository,
sqlite_clock: SQLiteClock,
) -> None:
clock = {"now": "2026-02-01T00:00:00+00:00"}
monkeypatch.setattr(_sqlite, "now", lambda: clock["now"])
job = (await repository.accept(command("delivery-1"))).job
clock["now"] = "2026-02-01T00:01:00+00:00"
job = (await engine_repository.accept(command("delivery-1"))).job
sqlite_clock.now = "2026-02-01T00:01:00+00:00"
task = await repository.claim_task(QueueName.CONTROL)
task = await engine_repository.claim_task(QueueName.CONTROL)
assert task is not None
clock["now"] = "2026-02-01T00:02:00+00:00"
await repository.complete_task(task.id)
sqlite_clock.now = "2026-02-01T00:02:00+00:00"
await engine_repository.complete_task(task.id)
assert (task, task_storage(repository, task.id)) == (
assert (task, task_storage(engine_repository, task.id)) == (
Task(
id=task.id,
job_id=job.id,
@@ -82,17 +70,16 @@ async def test_claim_and_complete_record_attempt_and_lifecycle_timestamps(
@pytest.mark.parametrize(("attempts", "delay_seconds"), [(1, 2), (9, 256)])
async def test_retry_uses_bounded_backoff_and_preserves_attempt_history_until_due(
repository: Repository,
engine_repository: Repository,
sqlite_clock: SQLiteClock,
monkeypatch: pytest.MonkeyPatch,
attempts: int,
delay_seconds: int,
) -> None:
clock = {"now": "2026-02-01T00:00:00+00:00"}
monkeypatch.setattr(_sqlite, "now", lambda: clock["now"])
await repository.accept(command("delivery-1"))
task = await repository.claim_task(QueueName.CONTROL)
await engine_repository.accept(command("delivery-1"))
task = await engine_repository.claim_task(QueueName.CONTROL)
assert task is not None
with closing(sqlite3.connect(repository.database_path)) as connection, connection:
with closing(sqlite3.connect(engine_repository.database_path)) as connection, connection:
connection.execute("UPDATE listener_tasks SET attempts=? WHERE id=?", (attempts, task.id))
retry_time = datetime(2026, 2, 1, 1, tzinfo=UTC)
@@ -105,12 +92,12 @@ async def test_retry_uses_bounded_backoff_and_preserves_attempt_history_until_du
monkeypatch.setattr(repository_module, "datetime", FixedDateTime)
error = "failure: " + "x" * 1100
await repository.retry_task(task.id, attempts, error)
pending_storage = task_storage(repository, task.id)
clock["now"] = (available_at - timedelta(microseconds=1)).isoformat()
early_claim = await repository.claim_task(QueueName.CONTROL)
clock["now"] = available_at.isoformat()
due_claim = await repository.claim_task(QueueName.CONTROL)
await engine_repository.retry_task(task.id, attempts, error)
pending_storage = task_storage(engine_repository, task.id)
sqlite_clock.now = (available_at - timedelta(microseconds=1)).isoformat()
early_claim = await engine_repository.claim_task(QueueName.CONTROL)
sqlite_clock.now = available_at.isoformat()
due_claim = await engine_repository.claim_task(QueueName.CONTROL)
assert (
pending_storage,
@@ -132,35 +119,33 @@ async def test_retry_uses_bounded_backoff_and_preserves_attempt_history_until_du
async def test_recovery_requeues_control_and_unstarted_execution_but_fails_started_execution(
repository: Repository,
monkeypatch: pytest.MonkeyPatch,
engine_repository: Repository,
sqlite_clock: SQLiteClock,
) -> None:
clock = {"now": "2026-02-01T00:00:00+00:00"}
monkeypatch.setattr(_sqlite, "now", lambda: clock["now"])
await repository.accept(command("delivery-1", issue=1))
control_task = await repository.claim_task(QueueName.CONTROL)
await engine_repository.accept(command("delivery-1", issue=1))
control_task = await engine_repository.claim_task(QueueName.CONTROL)
assert control_task is not None
queued_job = (await repository.accept(command("delivery-2", issue=2))).job
await repository.apply("queued:grant", PermissionGranted(job_id=queued_job.id))
queued_execute = await repository.claim_task(QueueName.JOBS)
queued_job = (await engine_repository.accept(command("delivery-2", issue=2))).job
await engine_repository.apply("queued:grant", PermissionGranted(job_id=queued_job.id))
queued_execute = await engine_repository.claim_task(QueueName.JOBS)
assert queued_execute is not None
running_job = (await repository.accept(command("delivery-3", issue=3))).job
await repository.apply("running:grant", PermissionGranted(job_id=running_job.id))
running_execute = await repository.claim_task(QueueName.JOBS)
running_job = (await engine_repository.accept(command("delivery-3", issue=3))).job
await engine_repository.apply("running:grant", PermissionGranted(job_id=running_job.id))
running_execute = await engine_repository.claim_task(QueueName.JOBS)
assert running_execute is not None
await repository.apply("running:start", JobStarted(job_id=running_job.id))
await engine_repository.apply("running:start", JobStarted(job_id=running_job.id))
clock["now"] = "2026-02-01T01:00:00+00:00"
await repository.recover_tasks()
sqlite_clock.now = "2026-02-01T01:00:00+00:00"
await engine_repository.recover_tasks()
assert (
task_storage(repository, control_task.id),
task_storage(repository, queued_execute.id),
task_storage(repository, running_execute.id),
[job.id for job in await repository.running_jobs()],
task_storage(engine_repository, control_task.id),
task_storage(engine_repository, queued_execute.id),
task_storage(engine_repository, running_execute.id),
[job.id for job in await engine_repository.running_jobs()],
) == (
(
"pending",