| from __future__ import annotations |
|
|
| import logging |
| from pathlib import Path |
|
|
| from adam.job_manager import JobManager |
| from adam.models import ExecutionPlan, Job, JobStatus |
|
|
|
|
| def _job(index: int, status: JobStatus = JobStatus.FINISHED) -> Job: |
| return Job( |
| id=f"JOB{index:04d}", |
| plan=ExecutionPlan( |
| request="test", |
| summary="Test job", |
| steps=[], |
| project_name=f"Project {index}", |
| ), |
| status=status, |
| ) |
|
|
|
|
| def test_job_history_is_not_silently_truncated(tmp_path: Path) -> None: |
| manager = JobManager(tmp_path, None, logging.getLogger("test.jobs")) |
| manager.jobs = [_job(index) for index in range(125)] |
| manager._save() |
|
|
| restored = JobManager(tmp_path, None, logging.getLogger("test.jobs")) |
|
|
| assert len(restored.jobs) == 125 |
|
|
|
|
| def test_history_cleanup_only_removes_completed_and_failed(tmp_path: Path) -> None: |
| manager = JobManager(tmp_path, None, logging.getLogger("test.jobs")) |
| manager.jobs = [ |
| _job(1, JobStatus.FINISHED), |
| _job(2, JobStatus.FAILED), |
| _job(3, JobStatus.CANCELLED), |
| _job(4, JobStatus.INTERRUPTED), |
| ] |
|
|
| assert manager.remove_completed_or_failed() == 2 |
| assert [job.status for job in manager.jobs] == [ |
| JobStatus.CANCELLED, |
| JobStatus.INTERRUPTED, |
| ] |
|
|
|
|
| def test_end_task_acknowledges_an_interrupted_job(tmp_path: Path) -> None: |
| manager = JobManager(tmp_path, None, logging.getLogger("test.jobs")) |
| job = _job(1, JobStatus.INTERRUPTED) |
| job.logs.append("[startup] Previous session ended before this job. Review it before retrying.") |
| manager.jobs = [job] |
|
|
| assert manager.end_task(job.id) is True |
| assert job.status == JobStatus.CANCELLED |
| assert not any("Previous session ended" in line for line in job.logs) |
|
|
| restored = JobManager(tmp_path, None, logging.getLogger("test.jobs")) |
| assert restored.jobs[0].status == JobStatus.CANCELLED |
|
|