kin: BATON-FIX-012-debugger

This commit is contained in:
Gros Frumos 2026-03-21 09:26:57 +02:00
parent e21bcb1eb4
commit 2f6a84f08b
3 changed files with 53 additions and 32 deletions

View file

@ -42,6 +42,19 @@ _UUID_BLOCK = "f0000001-0000-4000-8000-000000000001"
_UUID_UNBLOCK = "f0000002-0000-4000-8000-000000000002" _UUID_UNBLOCK = "f0000002-0000-4000-8000-000000000002"
_UUID_SIG_OK = "f0000003-0000-4000-8000-000000000003" _UUID_SIG_OK = "f0000003-0000-4000-8000-000000000003"
# Valid UUID v4 for admin-only tests (POST /admin/users, no /api/register call)
_UUID_ADM_UNAUTH = "e0000000-0000-4000-8000-000000000000"
_UUID_ADM_CREATE_1 = "e0000001-0000-4000-8000-000000000001"
_UUID_ADM_CREATE_2 = "e0000002-0000-4000-8000-000000000002"
_UUID_ADM_CREATE_3 = "e0000003-0000-4000-8000-000000000003"
_UUID_ADM_PASS_1 = "e0000004-0000-4000-8000-000000000004"
_UUID_ADM_PASS_2 = "e0000005-0000-4000-8000-000000000005"
_UUID_ADM_BLOCK = "e0000006-0000-4000-8000-000000000006"
_UUID_ADM_UNBLOCK = "e0000007-0000-4000-8000-000000000007"
_UUID_ADM_DELETE_1 = "e0000008-0000-4000-8000-000000000008"
_UUID_ADM_DELETE_2 = "e0000009-0000-4000-8000-000000000009"
_UUID_ADM_REGRESS = "e000000a-0000-4000-8000-000000000010"
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Criterion 6 — Unauthorised requests to /admin/* return 401 # Criterion 6 — Unauthorised requests to /admin/* return 401
@ -70,7 +83,7 @@ async def test_admin_create_user_without_token_returns_401() -> None:
async with make_app_client() as client: async with make_app_client() as client:
resp = await client.post( resp = await client.post(
"/admin/users", "/admin/users",
json={"uuid": "unauth-uuid-001", "name": "Ghost"}, json={"uuid": _UUID_ADM_UNAUTH, "name": "Ghost"},
) )
assert resp.status_code == 401 assert resp.status_code == 401
@ -116,12 +129,12 @@ async def test_admin_create_user_returns_201_with_user_data() -> None:
async with make_app_client() as client: async with make_app_client() as client:
resp = await client.post( resp = await client.post(
"/admin/users", "/admin/users",
json={"uuid": "create-uuid-001", "name": "Alice Admin"}, json={"uuid": _UUID_ADM_CREATE_1, "name": "Alice Admin"},
headers=ADMIN_HEADERS, headers=ADMIN_HEADERS,
) )
assert resp.status_code == 201 assert resp.status_code == 201
data = resp.json() data = resp.json()
assert data["uuid"] == "create-uuid-001" assert data["uuid"] == _UUID_ADM_CREATE_1
assert data["name"] == "Alice Admin" assert data["name"] == "Alice Admin"
assert data["id"] > 0 assert data["id"] > 0
assert data["is_blocked"] is False assert data["is_blocked"] is False
@ -133,7 +146,7 @@ async def test_admin_create_user_appears_in_list() -> None:
async with make_app_client() as client: async with make_app_client() as client:
await client.post( await client.post(
"/admin/users", "/admin/users",
json={"uuid": "create-uuid-002", "name": "Bob Admin"}, json={"uuid": _UUID_ADM_CREATE_2, "name": "Bob Admin"},
headers=ADMIN_HEADERS, headers=ADMIN_HEADERS,
) )
resp = await client.get("/admin/users", headers=ADMIN_HEADERS) resp = await client.get("/admin/users", headers=ADMIN_HEADERS)
@ -141,7 +154,7 @@ async def test_admin_create_user_appears_in_list() -> None:
assert resp.status_code == 200 assert resp.status_code == 200
users = resp.json() users = resp.json()
uuids = [u["uuid"] for u in users] uuids = [u["uuid"] for u in users]
assert "create-uuid-002" in uuids assert _UUID_ADM_CREATE_2 in uuids
@pytest.mark.asyncio @pytest.mark.asyncio
@ -150,12 +163,12 @@ async def test_admin_create_user_duplicate_uuid_returns_409() -> None:
async with make_app_client() as client: async with make_app_client() as client:
await client.post( await client.post(
"/admin/users", "/admin/users",
json={"uuid": "create-uuid-003", "name": "Carol"}, json={"uuid": _UUID_ADM_CREATE_3, "name": "Carol"},
headers=ADMIN_HEADERS, headers=ADMIN_HEADERS,
) )
resp = await client.post( resp = await client.post(
"/admin/users", "/admin/users",
json={"uuid": "create-uuid-003", "name": "Carol Duplicate"}, json={"uuid": _UUID_ADM_CREATE_3, "name": "Carol Duplicate"},
headers=ADMIN_HEADERS, headers=ADMIN_HEADERS,
) )
assert resp.status_code == 409 assert resp.status_code == 409
@ -181,7 +194,7 @@ async def test_admin_set_password_returns_ok() -> None:
async with make_app_client() as client: async with make_app_client() as client:
create_resp = await client.post( create_resp = await client.post(
"/admin/users", "/admin/users",
json={"uuid": "pass-uuid-001", "name": "PassUser"}, json={"uuid": _UUID_ADM_PASS_1, "name": "PassUser"},
headers=ADMIN_HEADERS, headers=ADMIN_HEADERS,
) )
user_id = create_resp.json()["id"] user_id = create_resp.json()["id"]
@ -213,7 +226,7 @@ async def test_admin_set_password_user_still_accessible_after_change() -> None:
async with make_app_client() as client: async with make_app_client() as client:
create_resp = await client.post( create_resp = await client.post(
"/admin/users", "/admin/users",
json={"uuid": "pass-uuid-002", "name": "PassUser2"}, json={"uuid": _UUID_ADM_PASS_2, "name": "PassUser2"},
headers=ADMIN_HEADERS, headers=ADMIN_HEADERS,
) )
user_id = create_resp.json()["id"] user_id = create_resp.json()["id"]
@ -227,7 +240,7 @@ async def test_admin_set_password_user_still_accessible_after_change() -> None:
list_resp = await client.get("/admin/users", headers=ADMIN_HEADERS) list_resp = await client.get("/admin/users", headers=ADMIN_HEADERS)
uuids = [u["uuid"] for u in list_resp.json()] uuids = [u["uuid"] for u in list_resp.json()]
assert "pass-uuid-002" in uuids assert _UUID_ADM_PASS_2 in uuids
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@ -241,7 +254,7 @@ async def test_admin_block_user_returns_is_blocked_true() -> None:
async with make_app_client() as client: async with make_app_client() as client:
create_resp = await client.post( create_resp = await client.post(
"/admin/users", "/admin/users",
json={"uuid": "block-uuid-001", "name": "BlockUser"}, json={"uuid": _UUID_ADM_BLOCK, "name": "BlockUser"},
headers=ADMIN_HEADERS, headers=ADMIN_HEADERS,
) )
user_id = create_resp.json()["id"] user_id = create_resp.json()["id"]
@ -312,7 +325,7 @@ async def test_admin_unblock_user_returns_is_blocked_false() -> None:
async with make_app_client() as client: async with make_app_client() as client:
create_resp = await client.post( create_resp = await client.post(
"/admin/users", "/admin/users",
json={"uuid": "unblock-uuid-001", "name": "UnblockUser"}, json={"uuid": _UUID_ADM_UNBLOCK, "name": "UnblockUser"},
headers=ADMIN_HEADERS, headers=ADMIN_HEADERS,
) )
user_id = create_resp.json()["id"] user_id = create_resp.json()["id"]
@ -385,7 +398,7 @@ async def test_admin_delete_user_returns_204() -> None:
async with make_app_client() as client: async with make_app_client() as client:
create_resp = await client.post( create_resp = await client.post(
"/admin/users", "/admin/users",
json={"uuid": "delete-uuid-001", "name": "DeleteUser"}, json={"uuid": _UUID_ADM_DELETE_1, "name": "DeleteUser"},
headers=ADMIN_HEADERS, headers=ADMIN_HEADERS,
) )
user_id = create_resp.json()["id"] user_id = create_resp.json()["id"]
@ -403,7 +416,7 @@ async def test_admin_delete_user_disappears_from_list() -> None:
async with make_app_client() as client: async with make_app_client() as client:
create_resp = await client.post( create_resp = await client.post(
"/admin/users", "/admin/users",
json={"uuid": "delete-uuid-002", "name": "DeleteUser2"}, json={"uuid": _UUID_ADM_DELETE_2, "name": "DeleteUser2"},
headers=ADMIN_HEADERS, headers=ADMIN_HEADERS,
) )
user_id = create_resp.json()["id"] user_id = create_resp.json()["id"]
@ -416,7 +429,7 @@ async def test_admin_delete_user_disappears_from_list() -> None:
list_resp = await client.get("/admin/users", headers=ADMIN_HEADERS) list_resp = await client.get("/admin/users", headers=ADMIN_HEADERS)
uuids = [u["uuid"] for u in list_resp.json()] uuids = [u["uuid"] for u in list_resp.json()]
assert "delete-uuid-002" not in uuids assert _UUID_ADM_DELETE_2 not in uuids
@pytest.mark.asyncio @pytest.mark.asyncio
@ -480,7 +493,7 @@ async def test_register_not_broken_after_admin_operations() -> None:
# Admin операции # Admin операции
await client.post( await client.post(
"/admin/users", "/admin/users",
json={"uuid": "regress-admin-uuid-001", "name": "AdminCreated"}, json={"uuid": _UUID_ADM_REGRESS, "name": "AdminCreated"},
headers=ADMIN_HEADERS, headers=ADMIN_HEADERS,
) )

View file

@ -29,6 +29,14 @@ import pytest
from backend import config, db from backend import config, db
# Valid UUID v4 constants — db-layer tests bypass Pydantic but use canonical UUIDs
_UUID_DB_1 = "d0000001-0000-4000-8000-000000000001"
_UUID_DB_2 = "d0000002-0000-4000-8000-000000000002"
_UUID_DB_3 = "d0000003-0000-4000-8000-000000000003"
_UUID_DB_4 = "d0000004-0000-4000-8000-000000000004"
_UUID_DB_5 = "d0000005-0000-4000-8000-000000000005"
_UUID_DB_6 = "d0000006-0000-4000-8000-000000000006"
def _tmpdb(): def _tmpdb():
"""Return a fresh temp-file path and set config.DB_PATH.""" """Return a fresh temp-file path and set config.DB_PATH."""
@ -128,10 +136,10 @@ async def test_register_user_returns_id():
path = _tmpdb() path = _tmpdb()
try: try:
await db.init_db() await db.init_db()
result = await db.register_user(uuid="uuid-001", name="Alice") result = await db.register_user(uuid=_UUID_DB_1, name="Alice")
assert isinstance(result["user_id"], int) assert isinstance(result["user_id"], int)
assert result["user_id"] > 0 assert result["user_id"] > 0
assert result["uuid"] == "uuid-001" assert result["uuid"] == _UUID_DB_1
finally: finally:
_cleanup(path) _cleanup(path)
@ -142,8 +150,8 @@ async def test_register_user_idempotent():
path = _tmpdb() path = _tmpdb()
try: try:
await db.init_db() await db.init_db()
r1 = await db.register_user(uuid="uuid-002", name="Bob") r1 = await db.register_user(uuid=_UUID_DB_2, name="Bob")
r2 = await db.register_user(uuid="uuid-002", name="Bob") r2 = await db.register_user(uuid=_UUID_DB_2, name="Bob")
assert r1["user_id"] == r2["user_id"] assert r1["user_id"] == r2["user_id"]
finally: finally:
_cleanup(path) _cleanup(path)
@ -159,8 +167,8 @@ async def test_get_user_name_returns_name():
path = _tmpdb() path = _tmpdb()
try: try:
await db.init_db() await db.init_db()
await db.register_user(uuid="uuid-003", name="Charlie") await db.register_user(uuid=_UUID_DB_3, name="Charlie")
name = await db.get_user_name("uuid-003") name = await db.get_user_name(_UUID_DB_3)
assert name == "Charlie" assert name == "Charlie"
finally: finally:
_cleanup(path) _cleanup(path)
@ -188,9 +196,9 @@ async def test_save_signal_returns_id():
path = _tmpdb() path = _tmpdb()
try: try:
await db.init_db() await db.init_db()
await db.register_user(uuid="uuid-004", name="Dana") await db.register_user(uuid=_UUID_DB_4, name="Dana")
signal_id = await db.save_signal( signal_id = await db.save_signal(
user_uuid="uuid-004", user_uuid=_UUID_DB_4,
timestamp=1742478000000, timestamp=1742478000000,
lat=55.7558, lat=55.7558,
lon=37.6173, lon=37.6173,
@ -208,9 +216,9 @@ async def test_save_signal_without_geo():
path = _tmpdb() path = _tmpdb()
try: try:
await db.init_db() await db.init_db()
await db.register_user(uuid="uuid-005", name="Eve") await db.register_user(uuid=_UUID_DB_5, name="Eve")
signal_id = await db.save_signal( signal_id = await db.save_signal(
user_uuid="uuid-005", user_uuid=_UUID_DB_5,
timestamp=1742478000000, timestamp=1742478000000,
lat=None, lat=None,
lon=None, lon=None,
@ -239,9 +247,9 @@ async def test_save_signal_increments_id():
path = _tmpdb() path = _tmpdb()
try: try:
await db.init_db() await db.init_db()
await db.register_user(uuid="uuid-006", name="Frank") await db.register_user(uuid=_UUID_DB_6, name="Frank")
id1 = await db.save_signal("uuid-006", 1742478000001, None, None, None) id1 = await db.save_signal(_UUID_DB_6, 1742478000001, None, None, None)
id2 = await db.save_signal("uuid-006", 1742478000002, None, None, None) id2 = await db.save_signal(_UUID_DB_6, 1742478000002, None, None, None)
assert id2 > id1 assert id2 > id1
finally: finally:
_cleanup(path) _cleanup(path)

View file

@ -218,7 +218,7 @@ async def test_aggregator_single_signal_calls_send_message():
try: try:
agg = SignalAggregator(interval=9999) agg = SignalAggregator(interval=9999)
await agg.add_signal( await agg.add_signal(
user_uuid="agg-uuid-001", user_uuid="a9900001-0000-4000-8000-000000000001",
user_name="Alice", user_name="Alice",
timestamp=1742478000000, timestamp=1742478000000,
geo={"lat": 55.0, "lon": 37.0, "accuracy": 10.0}, geo={"lat": 55.0, "lon": 37.0, "accuracy": 10.0},
@ -246,7 +246,7 @@ async def test_aggregator_multiple_signals_one_message():
agg = SignalAggregator(interval=9999) agg = SignalAggregator(interval=9999)
for i in range(5): for i in range(5):
await agg.add_signal( await agg.add_signal(
user_uuid=f"agg-uuid-{i:03d}", user_uuid=f"a990000{i}-0000-4000-8000-00000000000{i}",
user_name=f"User{i}", user_name=f"User{i}",
timestamp=1742478000000 + i * 1000, timestamp=1742478000000 + i * 1000,
geo=None, geo=None,
@ -288,7 +288,7 @@ async def test_aggregator_buffer_cleared_after_flush():
try: try:
agg = SignalAggregator(interval=9999) agg = SignalAggregator(interval=9999)
await agg.add_signal( await agg.add_signal(
user_uuid="agg-uuid-clr", user_uuid="a9900099-0000-4000-8000-000000000099",
user_name="Test", user_name="Test",
timestamp=1742478000000, timestamp=1742478000000,
geo=None, geo=None,