Files
hermes-agent/tests/gateway/test_exec_approval_template.py
teknium1 61fa0f47ec test: purge low-value tests, lane py07 (216 removed)
Change-detectors, tautologies, source-reading tests, redundant duplicates,
mock-echo tests and dead/unrunnable tests. Per-test rationale in the lane
ledger (category + reason for every removal).
2026-09-23 03:15:26 -07:00

91 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Invariants for the exec-approval template method on BasePlatformAdapter.
The choice set (once / session / always / deny, minus the persistent tiers under a smart deny)
used to be re-derived in every button adapter and needed three separate "same fix × N adapters"
sweeps. It now comes from one place; adapters only render it.
"""
from typing import Any, Dict
import pytest
from gateway.config import Platform, PlatformConfig
from gateway.platforms.base import BasePlatformAdapter, ExecApprovalPrompt, SendResult
from gateway.run_turn_runner import _renders_exec_approval_buttons
class _Plain(BasePlatformAdapter):
def __init__(self):
super().__init__(PlatformConfig(enabled=True), Platform.TELEGRAM)
async def connect(self, *, is_reconnect: bool = False) -> bool:
return True
async def disconnect(self) -> None:
pass
async def send(self, *a: Any, **k: Any) -> SendResult:
return SendResult(success=True)
async def get_chat_info(self, chat_id: str) -> Dict[str, Any]:
return {}
class _Buttons(_Plain):
def __init__(self):
super().__init__()
self.prompts: list = []
async def _send_exec_approval_prompt(self, prompt: ExecApprovalPrompt) -> SendResult:
self.prompts.append(prompt)
return SendResult(success=True, message_id="m1")
@pytest.mark.parametrize(
"allow_permanent, allow_session, smart_denied, expected",
[
(True, True, False, ["once", "session", "always", "deny"]),
(False, True, False, ["once", "session", "deny"]),
(True, False, False, ["once", "deny"]), # no session tier → no permanent tier either
(True, True, True, ["once", "deny"]), # smart deny: owner override is one-shot
(False, False, True, ["once", "deny"]),
],
)
@pytest.mark.asyncio
async def test_choice_set_follows_the_shared_rule(allow_permanent, allow_session, smart_denied, expected):
adapter = _Buttons()
result = await adapter.send_exec_approval(
"chat", "rm -rf /tmp/x", "sess", description="cleanup",
allow_permanent=allow_permanent, allow_session=allow_session, smart_denied=smart_denied)
assert result.success
(prompt,) = adapter.prompts
assert prompt.choices == expected
assert "rm -rf /tmp/x" in prompt.text and "cleanup" in prompt.text
@pytest.mark.asyncio
async def test_command_is_truncated_to_the_platform_budget():
class _Small(_Buttons):
_EA_CMD_BUDGET = 20
adapter = _Small()
await adapter.send_exec_approval("chat", "x" * 100, "sess")
(prompt,) = adapter.prompts
assert "x" * 20 + "..." in prompt.text and "x" * 21 not in prompt.text
assert prompt.command == "x" * 100 # the raw command stays available for embeds/cards
def test_runner_only_offers_buttons_to_adapters_that_render_them():
"""Plain adapters get the text ``/approve`` prompt; the base send_exec_approval must not make
the runner believe every adapter has buttons (its default reports failure and the runner would
log a spurious fallback on every approval)."""
assert _renders_exec_approval_buttons(_Buttons) is True
assert _renders_exec_approval_buttons(_Plain) is False
class _DuckTyped:
async def send_exec_approval(self, *a, **k):
return SendResult(success=True)
assert _renders_exec_approval_buttons(_DuckTyped) is True
assert _renders_exec_approval_buttons(object) is False