"""registra_giro (src/live/giri.py, #16): il registro che i sorveglianti scrivono a ogni giro. Il contratto e' quello di cc01_regime_watch, generalizzato: appende `{"ts": , **campi}` come riga jsonl e non solleva MAI — un registro che fallisce non deve buttare via una misura gia' fatta. """ from __future__ import annotations import json import sys import time from pathlib import Path ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT)) from src.live.giri import registra_giro # noqa: E402 def test_scrive_una_riga_con_ts_in_millisecondi(tmp_path): p = tmp_path / "sub" / "runs.jsonl" prima = time.time() * 1000 assert registra_giro(p, stato="OK", n=3) is True riga = json.loads(p.read_text().strip()) assert abs(riga["ts"] - prima) < 5_000 assert isinstance(riga["ts"], int) assert riga["stato"] == "OK" and riga["n"] == 3 def test_crea_la_cartella_se_manca(tmp_path): p = tmp_path / "non-esiste-ancora" / "runs.jsonl" assert not p.parent.exists() registra_giro(p, x=1) assert p.exists() def test_appende_senza_troncare(tmp_path): p = tmp_path / "runs.jsonl" registra_giro(p, giro=1) registra_giro(p, giro=2) righe = [json.loads(r) for r in p.read_text().splitlines()] assert [r["giro"] for r in righe] == [1, 2] def test_default_str_copre_i_valori_non_serializzabili(tmp_path): """json.dumps(default=str): un valore che non e' nativamente JSON (es. un Path, o un dataclass senza __dict__ diretto) non deve far fallire l'append — diventa la sua str().""" p = tmp_path / "runs.jsonl" assert registra_giro(p, percorso=Path("/tmp/x")) is True riga = json.loads(p.read_text().strip()) assert riga["percorso"] == str(Path("/tmp/x")) def test_oserror_ritorna_false_senza_sollevare(tmp_path, capsys): """Un percorso impossibile (qui: dentro un FILE, non una cartella) e' un OSError alla mkdir/scrittura. Il chiamante non deve vedere un'eccezione: la misura e' gia' fatta.""" ostacolo = tmp_path / "non-e-una-cartella" ostacolo.write_text("sono un file") p = ostacolo / "runs.jsonl" assert registra_giro(p, stato="OK") is False err = capsys.readouterr().err assert "registra_giro" in err and str(p) in err def test_un_valore_non_serializzabile_diventa_stringa_non_solleva(tmp_path): p = tmp_path / "runs.jsonl" oggetto = object() assert registra_giro(p, oggetto=oggetto) is True riga = json.loads(p.read_text().strip()) assert riga["oggetto"] == str(oggetto)