Commita governance, user-wizard, operational-feed e catálogo RBAC; adiciona deploy-desk-full.sh, smoke-desk.sh e regra anti-deploy parcial; documenta credencial VM112 @betinplace. Co-authored-by: Cursor <cursoragent@cursor.com>
84 lines
2.7 KiB
Python
84 lines
2.7 KiB
Python
"""Unit tests — Spec 033 stack health probes (expect_status hardening)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
import sys
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
API_ROOT = Path(__file__).resolve().parent
|
|
if not (API_ROOT / "app" / "stack_health.py").is_file():
|
|
API_ROOT = API_ROOT.parent
|
|
|
|
|
|
def _load_stack_health():
|
|
path = API_ROOT / "app/stack_health.py"
|
|
spec = importlib.util.spec_from_file_location("stack_health_033", path)
|
|
if spec is None or spec.loader is None:
|
|
raise ImportError(path)
|
|
mod = importlib.util.module_from_spec(spec)
|
|
sys.modules["stack_health_033"] = mod
|
|
spec.loader.exec_module(mod)
|
|
return mod
|
|
|
|
|
|
sh = _load_stack_health()
|
|
|
|
|
|
class TestNormalizeExpectStatus(unittest.TestCase):
|
|
def test_single_int(self):
|
|
self.assertEqual(sh._normalize_expect_status(200), (200,))
|
|
|
|
def test_single_element_tuple_with_comma(self):
|
|
self.assertEqual(sh._normalize_expect_status((200,)), (200,))
|
|
|
|
def test_multi_status_tuple(self):
|
|
self.assertEqual(sh._normalize_expect_status((200, 301, 302)), (200, 301, 302))
|
|
|
|
def test_list_from_yaml_contract(self):
|
|
self.assertEqual(sh._normalize_expect_status([200, 403]), (200, 403))
|
|
|
|
def test_invalid_type_raises(self):
|
|
with self.assertRaises(TypeError):
|
|
sh._normalize_expect_status("200") # type: ignore[arg-type]
|
|
|
|
|
|
class TestProbeHttpExpectStatus(unittest.TestCase):
|
|
@patch("stack_health_033.httpx.Client")
|
|
def test_int_expect_status_does_not_crash(self, client_cls):
|
|
res = MagicMock()
|
|
res.status_code = 200
|
|
client_cls.return_value.__enter__.return_value.get.return_value = res
|
|
|
|
out = sh._probe_http(url="http://example.test/health", expect_status=200)
|
|
|
|
self.assertTrue(out["ok"])
|
|
self.assertEqual(out["http_status"], 200)
|
|
self.assertEqual(out["detail"], "HTTP 200")
|
|
|
|
@patch("stack_health_033.httpx.Client")
|
|
def test_default_expect_status_tuple(self, client_cls):
|
|
res = MagicMock()
|
|
res.status_code = 200
|
|
client_cls.return_value.__enter__.return_value.get.return_value = res
|
|
|
|
out = sh._probe_http(url="http://example.test/")
|
|
|
|
self.assertTrue(out["ok"])
|
|
|
|
@patch("stack_health_033.httpx.Client")
|
|
def test_wrong_status_marks_check(self, client_cls):
|
|
res = MagicMock()
|
|
res.status_code = 503
|
|
client_cls.return_value.__enter__.return_value.get.return_value = res
|
|
|
|
out = sh._probe_http(url="http://example.test/", expect_status=(200,))
|
|
|
|
self.assertFalse(out["ok"])
|
|
self.assertEqual(out["status"], "check")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|