bifroest/tests/test_storage.py
2026-10-27 08:34:17 +01:00

81 lines
3.6 KiB
Python

"""Speicherkontingent je Workspace für Uploads."""
from pathlib import Path
import pytest
from fastapi.testclient import TestClient
from sqlalchemy import select
from app.identity.models import User
from app.main import create_app
from app.uploads.models import Upload
from app.workspaces.models import Workspace
from helpers import create_workspace
CSV = b"region,umsatz\nNord,100\nSued,250\n"
@pytest.fixture
def ws(browser, people, db):
with db.session() as session:
session.get(User, people["anna"]).is_admin = True
anna = browser("anna")
workspace_id = create_workspace(anna, people["team_demo"], "Speicher")
anna.post(f"/workspaces/{workspace_id}/members", {"username": "ben", "role": "member"})
return {"anna": anna, "ben": browser("ben"), "id": workspace_id, "team": people["team_demo"]}
def upload(b, workspace_id, name="umsatz.csv"):
return b.post(f"/workspaces/{workspace_id}/uploads", files={"file": (name, CSV)})
def test_belegung_wird_angezeigt_und_gezaehlt(ws, db):
assert upload(ws["ben"], ws["id"]).status_code == 303
with db.session() as session:
stored = session.scalar(select(Upload.stored_size))
assert stored > 0
page = ws["ben"].get(f"/workspaces/{ws['id']}/data").text
assert "von 500 MB belegt" in page and "<meter" in page
def test_kontingent_voll_lehnt_ab(ws, db, settings):
upload(ws["ben"], ws["id"])
with db.session() as session:
session.get(Workspace, ws["id"]).storage_limit_mb = 1
# Eine DuckDB-Datei ist mindestens ~0,5 MB: die zweite passt nicht mehr ins Kontingent von 1 MB
response = upload(ws["ben"], ws["id"], "zwei.csv")
assert response.status_code == 400 and "Speicherkontingent" in response.text
with db.session() as session:
assert session.scalar(select(Upload).where(Upload.filename == "zwei.csv")) is None
files = {u.id for u in session.scalars(select(Upload))}
assert {int(p.stem) for p in (Path(settings.upload_dir) / str(ws["id"])).glob("*.duckdb")} == files
assert "von 1 MB belegt" in ws["ben"].get(f"/workspaces/{ws['id']}/data").text
# Voll: schon vor dem Hochladen abgelehnt, mit Hinweis auf der Seite
with db.session() as session:
session.scalar(select(Upload)).stored_size = 2 * 1024 * 1024
assert "ausgeschöpft" in upload(ws["ben"], ws["id"], "drei.csv").text
assert "ausgeschöpft" in ws["ben"].get(f"/workspaces/{ws['id']}/data").text
def test_nur_plattform_admin_setzt_kontingent(ws, db, people):
url = f"/admin/teams/{ws['team']}/workspaces/{ws['id']}/storage"
assert ws["ben"].post(url, {"limit_mb": "5"}).status_code == 403
response = ws["anna"].post(url, {"limit_mb": "abc"})
assert response.status_code == 400 and "ganze Zahl" in response.text
assert "gespeichert" in ws["anna"].post(url, {"limit_mb": "2000"}).text
with db.session() as session:
assert session.get(Workspace, ws["id"]).storage_limit_mb == 2000
assert "von 2000 MB belegt" in ws["ben"].get(f"/workspaces/{ws['id']}/data").text
ws["anna"].post(url, {"limit_mb": ""})
with db.session() as session:
assert session.get(Workspace, ws["id"]).storage_limit_mb is None
def test_metrik_meldet_volle_workspaces(ws, db, settings):
upload(ws["ben"], ws["id"])
with db.session() as session:
session.get(Workspace, ws["id"]).storage_limit_mb = 1
session.scalar(select(Upload)).stored_size = 900 * 1024
client = TestClient(create_app(settings.model_copy(update={"metrics_token": "t-123456"}), listen=False))
text = client.get("/metrics", headers={"Authorization": "Bearer t-123456"}).text
assert "aiw_workspaces_storage_high 1.0" in text