import unittest from detector.models import MetricRule, RuleScope, parse_duration class TestParseDuration(unittest.TestCase): def test_units(self): self.assertEqual(parse_duration("60s"), 60) self.assertEqual(parse_duration("5m"), 300) self.assertEqual(parse_duration("1h"), 3600) self.assertEqual(parse_duration("1h30m"), 5400) self.assertEqual(parse_duration("90"), 90) self.assertEqual(parse_duration(""), 0) self.assertEqual(parse_duration(None), 0) def test_invalid(self): with self.assertRaises(ValueError): parse_duration("abc") class TestRuleScope(unittest.TestCase): def test_all(self): scope = RuleScope(scope_type="all") self.assertTrue(scope.matches("h-1", "web", "svc")) self.assertTrue(scope.matches("h-2", None, None)) def test_host_ids(self): scope = RuleScope(scope_type="host_ids", host_ids=["h-1", "h-2"]) self.assertTrue(scope.matches("h-1", None, None)) self.assertFalse(scope.matches("h-3", None, None)) def test_host_group(self): scope = RuleScope(scope_type="host_group", host_group="web") self.assertTrue(scope.matches("h-1", "web", None)) self.assertFalse(scope.matches("h-1", "db", None)) self.assertFalse(scope.matches("h-1", None, None)) class TestMetricRuleSerialization(unittest.TestCase): def test_round_trip(self): rule = MetricRule( rule_id="r-1", name="cpu", metric="cpu_usage", operator="gt", threshold=90, scope=RuleScope(scope_type="host_group", host_group="web"), labels={"service": "web"}, notify_channels=["email"], ) data = rule.to_dict() restored = MetricRule.from_dict(data) self.assertEqual(restored.rule_id, "r-1") self.assertEqual(restored.threshold, 90) self.assertEqual(restored.scope.host_group, "web") self.assertEqual(restored.labels, {"service": "web"}) self.assertEqual(restored.notify_channels, ["email"]) if __name__ == "__main__": unittest.main()