test(e2e): xfail the known team multi-window failure and isolate member teardown

Greptile flagged two issues in the mirrored split-gateway commit. The team
multi-window budget test documents a real /team/new write bug (budget_limits go
straight to the Json? column and Prisma 500s, unlike the json.dumps'd key and
/team/update paths) and was left as an unconditional hard failure, which would
turn any live-proxy CI run red; mark it xfail(strict=True) like the custom-pricing
isolation test so the suite stays green while the bug persists and flips to a
failure the moment the write is fixed and the marker should go.

The class-scoped member fixture in test_team_member_budget_e2e.py tore down its
key, user, and team sequentially with no exception isolation, so a failed
delete_key would strand the user and team on the long-lived shared proxy. Route
cleanup through a ResourceManager: register each delete progressively and run them
LIFO best-effort in a finally, so a partial-setup failure still releases what came
before and one failed delete never blocks the rest.
This commit is contained in:
mateo-berri 2026-06-21 00:47:57 +00:00
parent 385b4ff464
commit c7ff2cc083
No known key found for this signature in database
2 changed files with 28 additions and 13 deletions

View file

@ -21,6 +21,7 @@ import pytest
from budget_client import BudgetClient, is_budget_block
from e2e_config import unique_marker
from e2e_http import Success, require_successful_call
from lifecycle import ResourceManager
from models import ChatBody, ChatMessage
pytestmark = pytest.mark.e2e
@ -41,16 +42,23 @@ class _Member:
@pytest.fixture(scope="class")
def member(client: BudgetClient) -> Iterator[_Member]:
"""A team with a large budget plus one member capped at a tiny per-team budget,
and that member's key. Shared across the class; torn down when it finishes."""
marker = unique_marker()
team_id = client.create_team(alias=f"e2e-team-member-{marker}", max_budget=TEAM_BUDGET)
user_id = client.create_user(max_budget=TEAM_BUDGET)
client.add_team_member(team_id, user_id, max_budget_in_team=MEMBER_BUDGET)
key = client.generate_key(team_id=team_id, user_id=user_id)
yield _Member(team_id=team_id, user_id=user_id, key=key)
client.delete_key(key)
client.delete_user(user_id)
client.delete_team(team_id)
and that member's key. Shared across the class; torn down when it finishes.
Cleanups register progressively and run LIFO best-effort through ResourceManager,
so a partial-setup failure still releases what came before and one failed delete
never strands the rest on the shared proxy."""
resources = ResourceManager(client=client.gateway)
try:
marker = unique_marker()
team_id = client.create_team(alias=f"e2e-team-member-{marker}", max_budget=TEAM_BUDGET)
resources.defer(lambda: client.delete_team(team_id))
user_id = client.create_user(max_budget=TEAM_BUDGET)
resources.defer(lambda: client.delete_user(user_id))
client.add_team_member(team_id, user_id, max_budget_in_team=MEMBER_BUDGET)
key = client.generate_key(team_id=team_id, user_id=user_id)
resources.defer(lambda: client.delete_key(key))
yield _Member(team_id=team_id, user_id=user_id, key=key)
finally:
resources.teardown()
def _send(client: BudgetClient, key: str) -> str | None:

View file

@ -7,10 +7,11 @@ the tight window's cap is exceeded, then - once the 30s elapses and the reset jo
and calls flow again. This exercises the reset_budget_windows TEAM branch (raw SQL over
LiteLLM_TeamTable.budget_limits, the literal #25109 path), which had no live coverage.
Currently fails at team creation: /team/new writes the raw window list straight to the
Fails at team creation today: /team/new writes the raw window list straight to the
Json? column, where Prisma rejects it (500), unlike the key path and /team/update which
json.dumps it first. Left failing rather than weakened - it passes once that write is
fixed.
json.dumps it first. Marked xfail(strict=True) so the suite stays green while the bug
persists and flips to a failure the moment the write is fixed and the marker should be
removed.
"""
import time
@ -32,6 +33,12 @@ def _call(client: BudgetClient, key: str):
return client.chat(key, "claude-haiku-4-5", f"team-window {unique_marker()}", max_tokens=16)
@pytest.mark.xfail(
strict=True,
reason="known proxy bug: /team/new writes budget_limits straight to the Json? "
"column and Prisma rejects it (500), unlike the key path and /team/update which "
"json.dumps first; remove this marker once that write is fixed",
)
def test_team_short_window_blocks_then_resets(client: BudgetClient, resources: ResourceManager) -> None:
team_id = client.create_team(
alias=f"e2e-team-window-{unique_marker()}",