hermes-agent/tests/gateway/test_session_store_expiry_finalized.py
Teknium 39975613b1
test: prune wave 2 + speed fixes — 28,106 → 19,757 test functions, suite wall 315s → 294s
Second, deeper pass over tools/gateway/hermes_cli plus first pass over
the trees wave 1 missed (acp, acp_adapter, skills, computer_use, docker,
dashboard, conformance, monitoring, secret_sources, hermes_state,
providers). Same rubric as wave 1 (AGENTS.md test policy); security,
alternation/caching invariants, issue-number regressions, and E2E kept.

Real test-quality fixes found and rooted out along the way:
- tests/tools/test_command_guards.py made real auxiliary-LLM HTTPS calls
  (DEFAULT_CONFIG smart-approval leaked in) — pinned approval
  mode=manual via autouse fixture: 17.4s → 0.4s.
- test_model_switch_custom_providers.py / test_user_providers_model_switch.py
  silently probed live provider catalogs (~2s/test) — stubbed
  cached_provider_model_ids/provider_model_ids/fetch_api_models.
- test_telegram_noise_filter.py: 15-platform copy-paste matrix over
  shared gateway.run logic → 3 representative platforms (55s → 3.9s).
- test_gateway_shutdown.py: stop()'s 5s interrupt-deadline loop spun on
  MagicMock agents — interrupt.side_effect now clears _running_agents
  (22s → 1.0s).
- test_gateway_inactivity_timeout.py poll-harness timings shrunk 3-5x
  (24s → 1.1s); test_mcp_stability.py backoff/SIGTERM-grace sleeps
  patched (15.4s → 2.5s); test_async_delegation.py negative-drain wait
  5s → 0.5s.
- test_telegram_init_deadline.py: loop-block margin restored to 1.0s
  with rationale comment — the watchdog-dump assertion needs the loop
  blocked well past deadline+grace under parallel load (flaked once in
  the 40-worker verification run at a 0.2s margin).

Verification: full hermetic suite via scripts/run_tests.sh —
2,438 files, 21,718 tests passed, 0 failed, 293.9s wall.
Suite totals vs original baseline: 46,820 → 19,757 test functions
(−57.8%), wall 583.5s → 293.9s (−50%), subprocess CPU 13,564s → 11,623s.
2026-07-29 13:39:40 -07:00

97 lines
3.4 KiB
Python

"""Session expiry finalization closes sessions as session_reset.
Regression coverage for #61220: the expiry watcher marks a session expired,
then agent cleanup can close it as ``agent_close``. Stale routing recovery treats
``agent_close`` as recoverable, so expired sessions were reopened with full
history unless expiry finalization also persisted the real conversation boundary
as ``end_reason='session_reset'``.
These tests use a real ``SessionDB`` (in-memory) to verify the actual recovery
contract in ``find_latest_gateway_session_for_peer`` — not just call counts on
a MagicMock.
"""
from __future__ import annotations
import time
from pathlib import Path
import pytest
from hermes_state import SessionDB
@pytest.fixture
def db(tmp_path: Path) -> SessionDB:
return SessionDB(tmp_path / "state.db")
_SESSION_KEY = "agent:main:telegram:dm:8494508720"
_SOURCE = "telegram"
_USER_ID = "8494508720"
# ------------------------------------------------------------------
# promote_to_session_reset — unit tests on real DB
# ------------------------------------------------------------------
class TestPromoteToSessionReset:
"""promote_to_session_reset promotes only safe rows."""
def test_promotes_live_row(self, db: SessionDB) -> None:
"""A live row (ended_at IS NULL) is promoted to session_reset."""
db.create_session(
"sid-live", _SOURCE,
user_id=_USER_ID, session_key=_SESSION_KEY,
chat_id="8494508720", chat_type="dm",
)
# Seed a message so recovery would match
db.append_message("sid-live", "user", "hello")
assert db.promote_to_session_reset("sid-live") is True
row = db.get_session("sid-live")
assert row["end_reason"] == "session_reset"
assert row["ended_at"] is not None
def test_does_not_overwrite_existing_session_reset(self, db: SessionDB) -> None:
"""Already-promoted rows are idempotently skipped."""
db.create_session(
"sid-reset", _SOURCE,
user_id=_USER_ID, session_key=_SESSION_KEY,
chat_id="8494508720", chat_type="dm",
)
db.end_session("sid-reset", "session_reset")
# Should be a no-op (rowcount = 0)
assert db.promote_to_session_reset("sid-reset") is False
row = db.get_session("sid-reset")
assert row["end_reason"] == "session_reset"
# ------------------------------------------------------------------
# Integration: promotion blocks stale-route recovery
# ------------------------------------------------------------------
class TestPromotionBlocksRecovery:
"""After promotion, find_latest_gateway_session_for_peer must NOT
recover the session — it is now ended with session_reset, which
the recovery query excludes (only live/agent_close are recoverable).
"""
def test_live_session_recoverable_before_promotion(self, db: SessionDB) -> None:
db.create_session(
"sid-pre", _SOURCE,
user_id=_USER_ID, session_key=_SESSION_KEY,
chat_id="8494508720", chat_type="dm",
)
db.append_message("sid-pre", "user", "hello")
recovered = db.find_latest_gateway_session_for_peer(
source=_SOURCE, session_key=_SESSION_KEY,
user_id=_USER_ID, chat_id="8494508720", chat_type="dm",
)
assert recovered is not None
assert recovered["id"] == "sid-pre"