tokens -> {client, agents: {модуль: токен}}, agent_status по агентам
(ключ agent, last_call_at), настройки агента и маршруты agent-scope по
модулю токена, min_agent_version переехал в модуль jira.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
94 lines
4.5 KiB
Python
94 lines
4.5 KiB
Python
"""Агенты модулей: токен определяет модуль, миграция v7 сохраняет агента jira (wiki-module, решения 1–3, 6, 15)."""
|
||
import pytest
|
||
|
||
from jira_hub.core import cli, db, queue, settings
|
||
from jira_hub.core.client import HubError
|
||
from v6db import make_v6_db
|
||
|
||
|
||
def test_v6_upgrade_keeps_jira_agent(tmp_path):
|
||
make_v6_db(tmp_path / "hub.sqlite")
|
||
conn = db.connect(tmp_path / "hub.sqlite")
|
||
try:
|
||
assert db._schema_version(conn) == 7
|
||
tok = settings.tokens(conn)
|
||
assert tok["client"] == "T-client" and tok["agents"]["jira"] == "T-agent" and "agent" not in tok
|
||
row = conn.execute("SELECT * FROM agent_status WHERE agent = 'jira'").fetchone()
|
||
assert row["agent_version"] == "14"
|
||
assert conn.execute("SELECT COUNT(*) AS n FROM agent_status").fetchone()["n"] == 1
|
||
assert list((tmp_path / "backups").glob("*schema-v6*")) # копия перед миграцией
|
||
finally:
|
||
conn.close()
|
||
|
||
|
||
def test_v6_upgrade_keeps_settings_and_projects(tmp_path):
|
||
make_v6_db(tmp_path / "hub.sqlite")
|
||
conn = db.connect(tmp_path / "hub.sqlite")
|
||
try:
|
||
assert settings.get(conn, "min_agent_version") == 1
|
||
rows = conn.execute("SELECT label, board_id, board_type FROM project ORDER BY label").fetchall()
|
||
assert [tuple(r) for r in rows] == [("AWPCA", 4216, "scrum"), ("sfm_kedr", None, None)]
|
||
finally:
|
||
conn.close()
|
||
|
||
|
||
def test_migrate_adds_status_row_for_new_agent_module(conn_two_modules):
|
||
"""R-1: строки agent_status для модулей реестра вставляются при каждом migrate, а не только в шаге 6 → 7."""
|
||
names = {r["agent"] for r in conn_two_modules.execute("SELECT agent FROM agent_status")}
|
||
assert names == {"jira", "stub"}
|
||
|
||
|
||
def test_ensure_defaults_adds_missing_agent_token(conn_two_modules):
|
||
tok = settings.tokens(conn_two_modules)
|
||
assert set(tok["agents"]) == {"jira", "stub"} and tok["agents"]["jira"] != tok["agents"]["stub"]
|
||
|
||
|
||
def test_agent_token_routes(hub_server):
|
||
assert hub_server["agent"].post("/agent/claim", {})["command"] is None
|
||
assert hub_server["agent"].get("/agent/settings")["settings_version"] >= 1
|
||
with pytest.raises(HubError) as e:
|
||
hub_server["client"].post("/agent/claim", {})
|
||
assert e.value.status == 401
|
||
|
||
|
||
def test_module_agent_route_requires_own_module(hub_server_two_modules):
|
||
jira, stub = hub_server_two_modules["agents"]["jira"], hub_server_two_modules["agents"]["stub"]
|
||
with pytest.raises(HubError) as e:
|
||
stub.post("/agent/state", {})
|
||
assert e.value.status == 401
|
||
with pytest.raises(HubError) as e:
|
||
jira.post("/agent/stub", {})
|
||
assert e.value.status == 401
|
||
assert stub.post("/agent/stub", {}) == {"agent": "stub"}
|
||
assert jira.post("/agent/claim", {})["command"] is None # маршруты ядра открыты обоим агентам
|
||
assert stub.post("/agent/claim", {})["command"] is None
|
||
|
||
|
||
def test_agent_settings_per_module(hub_server_two_modules):
|
||
jira = hub_server_two_modules["agents"]["jira"].get("/agent/settings")
|
||
stub = hub_server_two_modules["agents"]["stub"].get("/agent/settings")
|
||
assert "project_key" in jira and "transitions_map" in jira and "settings_version" in jira
|
||
assert "stub_key" not in jira and "board_id" not in jira
|
||
assert set(stub) == {"stub_key", "settings_version"}
|
||
|
||
|
||
def test_agent_query_cannot_be_forged(hub_server_two_modules):
|
||
"""Служебный ключ запроса приходит только от диспетчера: _agent в адресе перезаписывается."""
|
||
stub = hub_server_two_modules["agents"]["stub"]
|
||
assert stub.call("POST", "/agent/stub", {}, params={"_agent": "jira"}) == {"agent": "stub"}
|
||
|
||
|
||
def test_tokens_cli_lists_agents(tmp_path, monkeypatch, capsys):
|
||
monkeypatch.setenv("JIRA_HUB_HOME", str(tmp_path))
|
||
assert cli.main(["tokens"]) == 0
|
||
lines = capsys.readouterr().out.splitlines()
|
||
assert lines[0].startswith("клиентский токен: ") and lines[1].startswith("агент jira: ")
|
||
assert lines[2].startswith("база: ")
|
||
|
||
|
||
def test_agent_view_min_version_from_module_key(conn_two_modules):
|
||
conn_two_modules.execute("UPDATE agent_status SET agent_version = '3' WHERE agent = 'jira'")
|
||
settings.set_(conn_two_modules, "min_agent_version", 5)
|
||
assert queue.agent_view(conn_two_modules, "jira")["warning"] == "обновите агента"
|
||
assert queue.agent_view(conn_two_modules, "stub")["warning"] is None
|