import contextlib import io import json import os import tempfile import unittest from _common import agent class JournalTest(unittest.TestCase): def setUp(self): self.dir = tempfile.TemporaryDirectory() self.path = os.path.join(self.dir.name, "journal.jsonl") self.j = agent.Journal(self.path) def tearDown(self): self.dir.cleanup() def test_empty(self): self.assertEqual(self.j.records(), []) self.assertEqual(self.j.unacked_finished(), []) self.assertEqual(self.j.unfinished_started(), []) def test_lifecycle(self): self.j.started(1) self.assertEqual(self.j.unfinished_started(), [1]) self.j.finished(1, "done", {"key": "A-1"}, None, 2, 0) self.assertEqual(self.j.unfinished_started(), []) pending = self.j.unacked_finished() self.assertEqual(len(pending), 1) self.assertEqual(pending[0]["command_id"], 1) self.assertEqual(pending[0]["result"], {"key": "A-1"}) self.assertEqual(pending[0]["jira_calls"], 2) self.j.acked(1) self.assertEqual(self.j.unacked_finished(), []) self.j.started(2) self.j.started(3) self.j.finished(3, "failed", None, "HTTP 400", 1, 0) self.assertEqual(self.j.unfinished_started(), [2]) self.assertEqual([r["command_id"] for r in self.j.unacked_finished()], [3]) def test_broken_line_is_skipped(self): self.j.started(1) with open(self.path, "a", encoding="utf-8") as f: f.write("{не json\n") self.j.finished(1, "done", None, None, 1, 0) out = io.StringIO() with contextlib.redirect_stdout(out): records = self.j.records() self.assertEqual(len(records), 2) self.assertIn("строка 2 не читается", out.getvalue()) def test_prune_keeps_unacked_and_recent(self): self.j.started(1) self.j.finished(1, "done", None, None, 1, 0) self.j.append({"kind": "acked", "command_id": 1, "at": "2020-01-01T00:00:00+00:00"}) self.j.started(2) self.j.finished(2, "done", None, None, 1, 0) self.j.acked(2) self.j.started(3) removed = self.j.prune(days=30) self.assertEqual(removed, 3) ids = [(r["kind"], r["command_id"]) for r in self.j.records()] self.assertEqual(ids, [("started", 2), ("finished", 2), ("acked", 2), ("started", 3)]) self.assertEqual(self.j.prune(days=30), 0) def test_no_secrets_in_records(self): self.j.finished(1, "done", {"key": "A-1"}, None, 1, 0) with open(self.path, encoding="utf-8") as f: text = f.read() self.assertNotIn("password", text) self.assertEqual(json.loads(text.splitlines()[0])["kind"], "finished") if __name__ == "__main__": unittest.main()