Files
hermes-agent/tests/gateway/test_telegram_cold_boot_queue.py
teknium1 982165203d test: purge low-value tests, lane py09 (263 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

107 lines
3.9 KiB
Python

"""Cold-boot pending-queue knob for the Telegram adapter.
Contract: a cold boot drops Telegram's server-side pending updates unless
``extra.drop_pending_on_cold_boot`` is false; a watcher reconnect always
preserves them. Conflict recovery is a separate path and is not covered here.
"""
import logging
from types import SimpleNamespace
from unittest.mock import AsyncMock
import pytest
from gateway.config import PlatformConfig
from plugins.platforms.telegram.adapter import TelegramAdapter
def _make_adapter(extra=None) -> TelegramAdapter:
return TelegramAdapter(PlatformConfig(enabled=True, token="test-token", extra=extra or {}))
async def _capture_drop_pending(adapter: TelegramAdapter, *, is_reconnect: bool):
"""Run _start_polling_mode with staging mocked; return the forwarded flag."""
captured = {}
adapter._delete_webhook_best_effort = AsyncMock()
async def _fake_resilient(*, drop_pending_updates, error_callback, require_progress=False):
captured["drop_pending_updates"] = drop_pending_updates
captured["require_progress"] = require_progress
return True
adapter._start_polling_resilient = _fake_resilient
await adapter._start_polling_mode(is_reconnect=is_reconnect)
return captured
@pytest.mark.asyncio
async def test_cold_boot_drops_queue_by_default():
"""Default config: cold boot drops, reconnect preserves."""
adapter = _make_adapter()
assert adapter._drop_pending_on_cold_boot is True
cold = await _capture_drop_pending(adapter, is_reconnect=False)
assert cold["drop_pending_updates"] is True
warm = await _capture_drop_pending(adapter, is_reconnect=True)
assert warm["drop_pending_updates"] is False
@pytest.mark.asyncio
async def test_cold_boot_preserves_queue_when_opted_out():
"""extra.drop_pending_on_cold_boot=false: cold boot preserves the backlog."""
adapter = _make_adapter(extra={"drop_pending_on_cold_boot": False})
assert adapter._drop_pending_on_cold_boot is False
cold = await _capture_drop_pending(adapter, is_reconnect=False)
assert cold["drop_pending_updates"] is False
warm = await _capture_drop_pending(adapter, is_reconnect=True)
assert warm["drop_pending_updates"] is False
async def _capture_webhook_drop_pending(
adapter: TelegramAdapter, monkeypatch, *, is_reconnect: bool
):
"""Run _start_webhook_mode against a stub updater; return the forwarded flag."""
captured = {}
async def _fake_start_webhook(**kwargs):
captured.update(kwargs)
adapter._app = SimpleNamespace(
updater=SimpleNamespace(start_webhook=AsyncMock(side_effect=_fake_start_webhook))
)
monkeypatch.setenv("TELEGRAM_WEBHOOK_URL", "https://example.test/telegram")
monkeypatch.setenv("TELEGRAM_WEBHOOK_SECRET", "test-secret")
await adapter._start_webhook_mode(
"https://example.test/telegram", is_reconnect=is_reconnect
)
return captured
@pytest.mark.asyncio
async def test_webhook_cold_boot_honors_the_knob_and_logs_the_decision(monkeypatch, caplog):
"""The webhook start path forwards the same policy as polling, and says which one
it applied. The flag is not a no-op there: PTB feeds it to delete_webhook /
set_webhook, which drop Telegram's stored updates."""
adapter = _make_adapter(extra={"drop_pending_on_cold_boot": False})
with caplog.at_level(logging.INFO, logger="plugins.platforms.telegram.adapter"):
captured = await _capture_webhook_drop_pending(
adapter, monkeypatch, is_reconnect=False
)
assert captured["drop_pending_updates"] is False
@pytest.mark.asyncio
async def test_webhook_reconnect_preserves_queue_regardless_of_the_knob(monkeypatch):
"""A watcher reconnect keeps #46621's guarantee even when the knob asks cold
boots to drop."""
adapter = _make_adapter()
captured = await _capture_webhook_drop_pending(adapter, monkeypatch, is_reconnect=True)
assert captured["drop_pending_updates"] is False