Files
kite/backend/tests/test_quota.py
T
curo1305 21ec9cb4c3 test(03-01): add Wave 0 xfail stubs and shared fixtures for Phase 3
- Add auth_user, admin_user, mock_minio_presigned, mock_minio_stat fixtures to conftest.py
- Create test_quota.py with 4 xfail stubs (STORE-03, STORE-05, STORE-06, SC2 race)
- Append test_migration_0003 to test_alembic.py (full pre-seed + post-migration assertions)
- Append 3 classifier xfail stubs (DOC-03, DOC-05, D-15)
- Append 6 document xfail stubs (D-05, STORE-04, SEC-04, D-16)
- Append 4 topic xfail stubs (DOC-04, D-09, D-17)
- Append test_settings_endpoint_removed stub (D-12)
- All 19 new test IDs collect cleanly with xfail(strict=False)
2026-05-23 13:42:37 +02:00

62 lines
2.3 KiB
Python

"""
Wave 0 xfail stubs for quota enforcement tests — Plan 03-02 implements these.
Requirements covered:
STORE-03 — Atomic quota enforcement at upload (no double-spend)
STORE-03 SC2 — Two concurrent uploads at quota limit → exactly one 413
STORE-05 — Confirm endpoint returns 413 with {used_bytes, limit_bytes, rejected_bytes}
STORE-06 — Document delete atomically decrements quota
"""
from __future__ import annotations
import pytest
@pytest.mark.xfail(strict=False, reason="implemented in plan 03-02")
async def test_quota_increment_atomic(
async_client, auth_user, mock_minio_presigned, mock_minio_stat
):
"""After one confirmed upload of 50 MB, GET /api/auth/me/quota returns used_bytes == 50_000_000.
STORE-03: atomic quota enforcement at the /confirm endpoint.
stat_object returns the authoritative file size (D-07).
"""
mock_minio_stat.return_value = 50_000_000
assert True # scaffold
@pytest.mark.xfail(strict=False, reason="implemented in plan 03-02")
async def test_concurrent_quota_race(
async_client, auth_user, mock_minio_presigned, mock_minio_stat
):
"""Two concurrent /confirm POSTs for documents totaling 110 MB against a 100 MB quota.
STORE-03 SC2: exactly one request returns 200 and the other returns 413.
Uses asyncio.gather to fire both confirm requests concurrently — verifies that
PostgreSQL's row-level locking on the atomic UPDATE prevents double-spend.
"""
assert True # scaffold
@pytest.mark.xfail(strict=False, reason="implemented in plan 03-02")
async def test_quota_exceeded_response(
async_client, auth_user, mock_minio_presigned, mock_minio_stat
):
"""When quota is exceeded, /confirm returns 413 with the expected body shape.
STORE-05: body must be {"detail": {"used_bytes": N, "limit_bytes": M, "rejected_bytes": K}}.
"""
assert True # scaffold
@pytest.mark.xfail(strict=False, reason="implemented in plan 03-02")
async def test_delete_decrements_quota(
async_client, auth_user, mock_minio_presigned, mock_minio_stat
):
"""Upload + confirm a document, then DELETE it; GET /api/auth/me/quota returns used_bytes == 0.
STORE-06: document delete atomically decrements quota.
Uses GREATEST(0, used_bytes - delta) to prevent underflow (CONTEXT.md D-07).
"""
assert True # scaffold