""" tests/test_release_check_platform_review.py Tests for platform_review_required release gate: - warn mode: always pass=True + recommendations when score >= warn_at - strict mode: should_fail=True when score >= fail_at - skipped gracefully when no service_name - non-fatal on errors """ import sys, os sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../services/router")) import asyncio import pytest from unittest.mock import AsyncMock, MagicMock, patch from release_check_runner import _run_platform_review_required def _make_tool_manager(pressure_score: int, band: str, requires_review: bool = False, signals_summary=None, fail: bool = False) -> MagicMock: tm = MagicMock() if fail: result = MagicMock(success=False, result=None, error="test error") else: result = MagicMock( success=True, result={ "score": pressure_score, "band": band, "requires_arch_review": requires_review, "signals_summary": signals_summary or [], "components": {}, }, ) tm.execute_tool = AsyncMock(return_value=result) return tm class TestPlatformReviewRequiredGate: def test_warn_mode_pass_below_threshold(self): """Score below warn_at → pass, no recommendations, no failure.""" tm = _make_tool_manager(30, "medium") ok, gate = asyncio.run( _run_platform_review_required(tm, "agent_ops", "gateway", "prod") ) assert ok is True assert gate["name"] == "platform_review_required" assert gate.get("skipped") is False assert gate.get("should_fail") is False assert gate.get("recommendations", []) == [] def test_warn_mode_adds_recommendation_above_warn_at(self): """Score >= warn_at → pass=True but recommendation added.""" tm = _make_tool_manager( 65, "high", signals_summary=["High recurrence in 30d"] ) ok, gate = asyncio.run( _run_platform_review_required(tm, "agent_ops", "router", "prod") ) assert ok is True assert len(gate.get("recommendations", [])) >= 1 assert gate.get("should_fail") is False def test_fail_at_sets_should_fail_true(self): """Score >= fail_at → should_fail=True (gate decides blocking in strict mode).""" tm = _make_tool_manager(90, "critical", requires_review=True) ok, gate = asyncio.run( _run_platform_review_required(tm, "agent_ops", "gateway", "prod") ) assert ok is True assert gate.get("should_fail") is True # Always pass=True in warn mode (caller handles strict) def test_arch_review_required_adds_recommendation(self): """When requires_arch_review=True, an extra recommendation is added.""" tm = _make_tool_manager(65, "high", requires_review=True) _, gate = asyncio.run( _run_platform_review_required(tm, "agent_ops", "svc", "prod") ) recs = gate.get("recommendations", []) assert any("Architecture review" in r or "architecture" in r.lower() for r in recs) def test_skipped_when_no_service_name(self): """Gate skips gracefully when no service_name provided.""" tm = _make_tool_manager(0, "low") ok, gate = asyncio.run( _run_platform_review_required(tm, "agent_ops", service_name="") ) assert ok is True assert gate.get("skipped") is True def test_non_fatal_on_tool_error(self): """Tool failure → skip (never block release).""" tm = _make_tool_manager(0, "low", fail=True) ok, gate = asyncio.run( _run_platform_review_required(tm, "agent_ops", "svc", "prod") ) assert ok is True assert gate.get("skipped") is True def test_non_fatal_on_exception(self): """Any exception in gate → skip.""" tm = MagicMock() tm.execute_tool = AsyncMock(side_effect=RuntimeError("unexpected")) ok, gate = asyncio.run( _run_platform_review_required(tm, "agent_ops", "svc", "prod") ) assert ok is True assert gate.get("skipped") is True def test_gate_includes_score_and_band(self): tm = _make_tool_manager(55, "high") _, gate = asyncio.run( _run_platform_review_required(tm, "agent_ops", "svc", "prod") ) assert gate.get("score") == 55 assert gate.get("band") == "high" def test_gate_includes_warn_fail_thresholds(self): tm = _make_tool_manager(50, "medium") _, gate = asyncio.run( _run_platform_review_required(tm, "agent_ops", "svc", "prod") ) assert "warn_at" in gate assert "fail_at" in gate def test_score_below_fail_at_should_fail_false(self): tm = _make_tool_manager(75, "critical", requires_review=True) _, gate = asyncio.run( _run_platform_review_required(tm, "agent_ops", "svc", "prod") ) # 75 < fail_at (85) → should_fail = False assert gate.get("should_fail") is False def test_score_exactly_at_fail_at_should_fail_true(self): tm = _make_tool_manager(85, "critical", requires_review=True) _, gate = asyncio.run( _run_platform_review_required(tm, "agent_ops", "svc", "prod") ) assert gate.get("should_fail") is True def test_note_includes_score(self): tm = _make_tool_manager(60, "high") _, gate = asyncio.run( _run_platform_review_required(tm, "agent_ops", "svc", "prod") ) assert "60" in gate.get("note", "")