Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
"""Tests for the cron usage_audit.jsonl logger.
|
||||
|
||||
Covers:
|
||||
- successful write produces a single valid JSONL line with full schema
|
||||
- missing token info still writes a line with null fields
|
||||
- writer exception is swallowed (json.dumps raises) — call must return cleanly
|
||||
- file path is created if parent dir is missing
|
||||
- timestamp format is RFC3339 UTC with millisecond precision and 'Z' suffix
|
||||
- path resolves through _get_hermes_home() (profile-safe)
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from cron import scheduler
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def tmp_hermes_home(tmp_path, monkeypatch):
|
||||
"""Redirect _get_hermes_home() so the audit logger writes under tmp_path."""
|
||||
fake_home = tmp_path / "home" / ".hermes"
|
||||
fake_home.mkdir(parents=True)
|
||||
monkeypatch.setattr(scheduler, "_get_hermes_home", lambda: fake_home)
|
||||
return fake_home
|
||||
|
||||
|
||||
def _read_jsonl(path: Path) -> list[dict]:
|
||||
return [json.loads(line) for line in path.read_text(encoding="utf-8").splitlines() if line]
|
||||
|
||||
|
||||
class TestUsageAuditPath:
|
||||
def test_resolves_through_get_hermes_home(self, tmp_hermes_home):
|
||||
p = scheduler._usage_audit_path()
|
||||
assert p == tmp_hermes_home / "cron" / "usage_audit.jsonl"
|
||||
|
||||
def test_does_not_use_path_home(self, tmp_hermes_home):
|
||||
"""Audit path must NOT hardcode Path.home() — it bypasses profile-aware resolution."""
|
||||
with patch.object(Path, "home") as mock_home:
|
||||
p = scheduler._usage_audit_path()
|
||||
mock_home.assert_not_called()
|
||||
assert p == tmp_hermes_home / "cron" / "usage_audit.jsonl"
|
||||
|
||||
|
||||
class TestUtcnowIsoMs:
|
||||
def test_format_has_millisecond_precision_and_z(self):
|
||||
ts = scheduler._utcnow_iso_ms()
|
||||
# YYYY-MM-DDTHH:MM:SS.mmmZ
|
||||
assert re.match(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$", ts), ts
|
||||
|
||||
|
||||
class TestWriteUsageAudit:
|
||||
def test_successful_write_produces_valid_jsonl(self, tmp_hermes_home):
|
||||
record = {
|
||||
"ts": "2026-05-01T04:23:11.123Z",
|
||||
"job_id": "bluenode-dispatch-recommend-sweep",
|
||||
"fire_id": "deadbeefcafe",
|
||||
"prompt_tokens": 11894,
|
||||
"completion_tokens": 287,
|
||||
"total_tokens": 12181,
|
||||
"response_silent": False,
|
||||
"deliver_target": None,
|
||||
"model": "google/gemma-4-31b-it",
|
||||
"duration_ms": 4231,
|
||||
"error": None,
|
||||
}
|
||||
scheduler._write_usage_audit(record)
|
||||
|
||||
path = scheduler._usage_audit_path()
|
||||
assert path.exists()
|
||||
lines = _read_jsonl(path)
|
||||
assert len(lines) == 1
|
||||
assert lines[0] == record
|
||||
|
||||
def test_missing_token_info_writes_line_with_null_fields(self, tmp_hermes_home):
|
||||
record = {
|
||||
"ts": "2026-05-01T04:23:11.123Z",
|
||||
"job_id": "j",
|
||||
"fire_id": "f",
|
||||
"prompt_tokens": None,
|
||||
"completion_tokens": None,
|
||||
"total_tokens": None,
|
||||
"response_silent": True,
|
||||
"deliver_target": "telegram",
|
||||
"model": None,
|
||||
"duration_ms": 12,
|
||||
"error": "boom",
|
||||
}
|
||||
scheduler._write_usage_audit(record)
|
||||
lines = _read_jsonl(scheduler._usage_audit_path())
|
||||
assert len(lines) == 1
|
||||
assert lines[0]["prompt_tokens"] is None
|
||||
assert lines[0]["completion_tokens"] is None
|
||||
assert lines[0]["total_tokens"] is None
|
||||
assert lines[0]["error"] == "boom"
|
||||
|
||||
def test_writer_exception_swallowed(self, tmp_hermes_home, caplog):
|
||||
# Force json.dumps to raise — writer must NOT propagate.
|
||||
with patch("cron.scheduler.json.dumps", side_effect=RuntimeError("kaboom")):
|
||||
scheduler._write_usage_audit({"job_id": "x"})
|
||||
|
||||
# File never created.
|
||||
assert not scheduler._usage_audit_path().exists()
|
||||
# Warning logged with our marker.
|
||||
assert any("usage_audit write failed" in rec.message for rec in caplog.records)
|
||||
|
||||
def test_parent_dir_created_if_missing(self, tmp_hermes_home):
|
||||
# Ensure the cron path does not exist yet.
|
||||
target = tmp_hermes_home / "cron"
|
||||
assert not target.exists()
|
||||
|
||||
scheduler._write_usage_audit({"k": "v"})
|
||||
|
||||
assert target.exists() and target.is_dir()
|
||||
assert (target / "usage_audit.jsonl").exists()
|
||||
|
||||
def test_appends_multiple_records(self, tmp_hermes_home):
|
||||
scheduler._write_usage_audit({"i": 1})
|
||||
scheduler._write_usage_audit({"i": 2})
|
||||
scheduler._write_usage_audit({"i": 3})
|
||||
lines = _read_jsonl(scheduler._usage_audit_path())
|
||||
assert [r["i"] for r in lines] == [1, 2, 3]
|
||||
|
||||
def test_unicode_preserved_not_escaped(self, tmp_hermes_home):
|
||||
# ensure_ascii=False so non-ASCII model names / job names round-trip cleanly.
|
||||
scheduler._write_usage_audit({"job_id": "한글", "model": "gemma"})
|
||||
text = scheduler._usage_audit_path().read_text(encoding="utf-8")
|
||||
assert "한글" in text
|
||||
Reference in New Issue
Block a user