Files
ai-video-fullstack/backend/tests/test_openai_response_state_contract.py
T

173 lines
5.6 KiB
Python
Raw Normal View History

2026-09-07 14:25:48 +08:00
from __future__ import annotations
from types import SimpleNamespace
import unittest
from unittest.mock import patch
from services.openai_responses.protocol import ResponsesAPIError
from services.openai_responses.state import (
IDEMPOTENCY_CONSTRAINT,
_integrity_constraint_name,
_load_chain,
delete_response,
get_idempotent_response,
get_response,
)
from sqlalchemy.exc import IntegrityError
class _ScalarResult:
def __init__(self, value):
self.value = value
def scalar_one_or_none(self):
return self.value
class _FakeSession:
def __init__(self, rows, *, selected=None):
self.rows = rows
self.selected = selected
self.commits = 0
async def __aenter__(self):
return self
async def __aexit__(self, *_args):
return None
async def get(self, _model, row_id, **_kwargs):
return self.rows.get(row_id)
async def execute(self, _statement):
return _ScalarResult(self.selected)
async def commit(self):
self.commits += 1
async def refresh(self, _row):
return None
def _row(
row_id,
*,
api_key_id="key_a",
previous_response_id=None,
deleted_at=None,
status="completed",
):
return SimpleNamespace(
id=row_id,
api_key_id=api_key_id,
previous_response_id=previous_response_id,
deleted_at=deleted_at,
status=status,
idempotency_key=None,
request_hash=None,
)
class ResponseTombstoneTests(unittest.IsolatedAsyncioTestCase):
async def test_deleted_ancestor_remains_available_to_existing_child_chain(self):
root = _row("resp_root", deleted_at=object())
child = _row("resp_child", previous_response_id=root.id)
rows = {root.id: root, child.id: child}
with patch(
"services.openai_responses.state.SessionLocal",
side_effect=lambda: _FakeSession(rows),
):
chain = await _load_chain(child.id, api_key_id="key_a")
self.assertEqual([row.id for row in chain], [root.id, child.id])
with self.assertRaises(ResponsesAPIError) as raised:
await _load_chain(root.id, api_key_id="key_a")
self.assertEqual(raised.exception.status_code, 404)
async def test_deleted_and_cross_key_resources_are_hidden(self):
rows = {
"resp_deleted": _row("resp_deleted", deleted_at=object()),
"resp_other": _row("resp_other", api_key_id="key_b"),
}
with patch(
"services.openai_responses.state.SessionLocal",
side_effect=lambda: _FakeSession(rows),
):
for response_id in rows:
with self.assertRaises(ResponsesAPIError) as raised:
await get_response(response_id, api_key_id="key_a")
self.assertEqual(raised.exception.status_code, 404)
async def test_delete_rejects_in_progress_and_tombstones_terminal_response(self):
running = _row("resp_running", status="in_progress")
completed = _row("resp_completed")
rows = {running.id: running, completed.id: completed}
with patch(
"services.openai_responses.state.SessionLocal",
side_effect=lambda: _FakeSession(rows),
):
with self.assertRaises(ResponsesAPIError) as raised:
await delete_response(running.id, api_key_id="key_a")
self.assertEqual(raised.exception.status_code, 409)
deleted = await delete_response(completed.id, api_key_id="key_a")
self.assertIsNotNone(deleted.deleted_at)
class ResponseIdempotencyTests(unittest.IsolatedAsyncioTestCase):
def test_only_named_unique_constraint_is_classified_as_idempotency(self):
original = RuntimeError("unique violation")
original.constraint_name = IDEMPOTENCY_CONSTRAINT
error = IntegrityError("insert", {}, original)
self.assertEqual(
_integrity_constraint_name(error),
IDEMPOTENCY_CONSTRAINT,
)
self.assertIsNone(
_integrity_constraint_name(
IntegrityError("insert", {}, RuntimeError("other failure"))
)
)
driver_error = RuntimeError("asyncpg unique violation")
driver_error.constraint_name = IDEMPOTENCY_CONSTRAINT
adapter_error = RuntimeError("SQLAlchemy asyncpg adapter")
adapter_error.__cause__ = driver_error
self.assertEqual(
_integrity_constraint_name(
IntegrityError("insert", {}, adapter_error)
),
IDEMPOTENCY_CONSTRAINT,
)
async def test_same_request_replays_and_different_request_conflicts(self):
stored = _row("resp_idempotent")
stored.idempotency_key = "request-1"
stored.request_hash = "hash-a"
with patch(
"services.openai_responses.state.SessionLocal",
side_effect=lambda: _FakeSession({}, selected=stored),
):
replay = await get_idempotent_response(
api_key_id="key_a",
idempotency_key="request-1",
request_hash="hash-a",
)
self.assertIs(replay, stored)
with self.assertRaises(ResponsesAPIError) as raised:
await get_idempotent_response(
api_key_id="key_a",
idempotency_key="request-1",
request_hash="hash-b",
)
self.assertEqual(raised.exception.code, "idempotency_key_conflict")
self.assertEqual(raised.exception.status_code, 409)
if __name__ == "__main__":
unittest.main()