fault-log-analyzer/tests/test_models.py

127 lines
4.1 KiB
Python

"""数据模型测试。"""
import _bootstrap # noqa: F401
import unittest
from datetime import datetime, timezone
from fault_log_analyzer.models import (
Event,
FaultFilterRule,
FaultLog,
FaultType,
ParsedLog,
RootCause,
_to_dt,
)
class TestToDt(unittest.TestCase):
def test_none_returns_now(self):
self.assertIsInstance(_to_dt(None), datetime)
def test_datetime_naive_gets_utc(self):
dt = datetime(2025, 1, 1, 10, 0, 0)
out = _to_dt(dt)
self.assertEqual(out.tzinfo, timezone.utc)
def test_datetime_aware_kept(self):
dt = datetime(2025, 1, 1, 10, 0, 0, tzinfo=timezone.utc)
self.assertEqual(_to_dt(dt), dt)
def test_timestamp(self):
ts = 1735722000.0
out = _to_dt(ts)
self.assertEqual(out.tzinfo, timezone.utc)
self.assertEqual(int(out.timestamp()), int(ts))
def test_iso_string_z(self):
out = _to_dt("2025-01-01T10:18:00Z")
self.assertEqual(out.tzinfo, timezone.utc)
self.assertEqual(out.hour, 10)
def test_iso_string_space(self):
out = _to_dt("2025-01-01 10:18:00")
self.assertEqual(out.hour, 10)
class TestFaultLog(unittest.TestCase):
def test_to_from_dict_roundtrip(self):
log = FaultLog(
fault_log_id="fl-1",
host_id="h-1",
message="No space left on device",
level="ERROR",
fingerprint="abc",
fault_type="disk_full",
cluster_id="c-1",
occurred_at=datetime(2025, 1, 1, 10, 18, 0, tzinfo=timezone.utc),
)
data = log.to_dict()
self.assertEqual(data["fault_log_id"], "fl-1")
restored = FaultLog.from_dict(data)
self.assertEqual(restored.fault_log_id, "fl-1")
self.assertEqual(restored.occurred_at, log.occurred_at)
self.assertEqual(restored.fault_type, "disk_full")
def test_from_dict_ignores_unknown_fields(self):
log = FaultLog.from_dict({"fault_log_id": "x", "host_id": "h", "message": "m", "extra": 1})
self.assertEqual(log.fault_log_id, "x")
self.assertFalse(hasattr(log, "extra"))
class TestRootCause(unittest.TestCase):
def test_to_from_dict(self):
rc = RootCause(
fault_log_id="fl-1",
cause_type="disk_full",
evidence=[{"type": "event", "metric": "disk_used_percent"}],
confidence=0.92,
)
data = rc.to_dict()
restored = RootCause.from_dict(data)
self.assertEqual(restored.cause_type, "disk_full")
self.assertEqual(restored.confidence, 0.92)
self.assertEqual(restored.evidence[0]["metric"], "disk_used_percent")
class TestFaultType(unittest.TestCase):
def test_to_from_dict(self):
ft = FaultType(fault_type="disk_full", name="磁盘空间不足", pattern="no space left")
restored = FaultType.from_dict(ft.to_dict())
self.assertEqual(restored.fault_type, "disk_full")
self.assertEqual(restored.pattern, "no space left")
class TestFaultFilterRule(unittest.TestCase):
def test_to_from_dict(self):
rule = FaultFilterRule(name="oom", level="ERROR", pattern="out of memory")
restored = FaultFilterRule.from_dict(rule.to_dict())
self.assertEqual(restored.name, "oom")
self.assertEqual(restored.level, "ERROR")
class TestEvent(unittest.TestCase):
def test_to_from_dict(self):
event = Event(
event_id="e-1",
host_id="h-1",
metric="disk_used_percent",
value=97.2,
threshold=90.0,
fired_at=datetime(2025, 1, 1, 10, 18, 0, tzinfo=timezone.utc),
)
restored = Event.from_dict(event.to_dict())
self.assertEqual(restored.event_id, "e-1")
self.assertEqual(restored.value, 97.2)
class TestParsedLog(unittest.TestCase):
def test_to_dict(self):
pl = ParsedLog(host_id="h-1", level="ERROR", message="boom", raw="boom")
data = pl.to_dict()
self.assertEqual(data["host_id"], "h-1")
self.assertIn("timestamp", data)
if __name__ == "__main__":
unittest.main()