21ec9cb4c3
- 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)
62 lines
2.3 KiB
Python
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
|