CommonAutoRearsh/tests/test_mutation_engine.py

87 lines
3.2 KiB
Python

from __future__ import annotations
import tempfile
import unittest
from pathlib import Path
from engine.artifact_manager import ArtifactManager
from engine.models import (
ArtifactSpec,
BudgetSpec,
ConstraintSpec,
LoggingSpec,
MutationSpec,
ObjectiveSpec,
PolicySpec,
RunnerSpec,
ScorerParseSpec,
ScorerSpec,
TaskSpec,
)
from engine.mutation_engine import MutationValidationError, validate_candidate_changes
def _make_task(root_dir: Path, allowed_file_types: list[str], max_changed_lines: int) -> TaskSpec:
return TaskSpec(
id="mutation-test",
description="Mutation validation fixture.",
artifacts=ArtifactSpec(include=["fixtures/*"], exclude=[], max_files_per_iteration=10),
mutation=MutationSpec(
mode="direct_edit",
allowed_file_types=allowed_file_types,
max_changed_lines=max_changed_lines,
),
runner=RunnerSpec(command="python -c \"print('runner ok')\"", cwd=".", timeout_seconds=30),
scorer=ScorerSpec(
type="command",
command="python -c \"print('{\\\"score\\\": 1.0, \\\"metrics\\\": {}}')\"",
parse=ScorerParseSpec(format="json", score_field="score", metrics_field="metrics"),
),
objective=ObjectiveSpec(primary_metric="score", direction="maximize"),
constraints=[],
policy=PolicySpec(keep_if="better_primary", tie_breakers=[], on_failure="discard"),
budget=BudgetSpec(max_iterations=1, max_failures=1),
logging=LoggingSpec(results_file="work/results.jsonl", candidate_dir="work/candidates"),
root_dir=root_dir,
)
class MutationEngineTest(unittest.TestCase):
def test_rejects_too_many_changed_lines(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root_dir = Path(tmp)
fixture_dir = root_dir / "fixtures"
fixture_dir.mkdir(parents=True)
target = fixture_dir / "note.md"
target.write_text("line 1\nline 2\n", encoding="utf-8")
task = _make_task(root_dir, allowed_file_types=[".md"], max_changed_lines=1)
snapshot = ArtifactManager(task).snapshot()
target.write_text("line 1\nline 2\nline 3\n", encoding="utf-8")
with self.assertRaises(MutationValidationError) as ctx:
validate_candidate_changes(task, snapshot)
self.assertIn("changed lines", str(ctx.exception))
def test_rejects_disallowed_extension(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root_dir = Path(tmp)
fixture_dir = root_dir / "fixtures"
fixture_dir.mkdir(parents=True)
target = fixture_dir / "note.txt"
target.write_text("line 1\n", encoding="utf-8")
task = _make_task(root_dir, allowed_file_types=[".md"], max_changed_lines=10)
snapshot = ArtifactManager(task).snapshot()
target.write_text("line 1 changed\n", encoding="utf-8")
with self.assertRaises(MutationValidationError) as ctx:
validate_candidate_changes(task, snapshot)
self.assertIn("disallowed file type", str(ctx.exception))
if __name__ == "__main__":
unittest.main()