test(assets): make seed content unique per test for isolation
Some checks failed
Build package / Build Test (3.10) (push) Has been cancelled
Python Linting / Run Ruff (push) Has been cancelled
Python Linting / Run Pylint (push) Has been cancelled
Build package / Build Test (3.11) (push) Has been cancelled
Build package / Build Test (3.12) (push) Has been cancelled
Build package / Build Test (3.13) (push) Has been cancelled
Build package / Build Test (3.14) (push) Has been cancelled

Removing the delete_content param means delete is always a soft delete, so
content created by one test now survives into the next. The suite had been
relying on hard-delete teardown for isolation, so shared fixed-content
fixtures started colliding: seeded_asset (b"A"*4096) and
make_asset_bytes (deterministic on name) produced the same hash every test,
so the second seed deduped to the surviving asset and returned 200 instead
of 201, cascading into ~14 failures/errors.

Salt both fixtures with a per-test uuid so each test creates fresh content
(created_new True, 201), while keeping content deterministic within a test
(same name/size -> same bytes) and preserving exact byte length so size-based
list/sort assertions are unaffected.
This commit is contained in:
Matt Miller 2026-06-02 11:52:55 -07:00
parent 795927b954
commit d600c76b46

View File

@ -6,6 +6,7 @@ import subprocess
import sys import sys
import tempfile import tempfile
import time import time
import uuid
from pathlib import Path from pathlib import Path
from typing import Callable, Iterator, Optional from typing import Callable, Iterator, Optional
@ -188,9 +189,17 @@ def _post_multipart_asset(
@pytest.fixture @pytest.fixture
def make_asset_bytes() -> Callable[[str, int], bytes]: def make_asset_bytes() -> Callable[[str, int], bytes]:
# Salt content per test so it never collides with assets left over from
# earlier tests. Delete is now always a soft delete (content is preserved),
# so the suite can no longer rely on hard-deleting content for isolation.
# Deterministic within a test: the same (name, size) yields the same bytes.
salt = uuid.uuid4().bytes
def _make(name: str, size: int = 8192) -> bytes: def _make(name: str, size: int = 8192) -> bytes:
seed = sum(ord(c) for c in name) % 251 seed = sum(ord(c) for c in name) % 251
return bytes((i * 31 + seed) % 256 for i in range(size)) body = bytearray((i * 31 + seed) % 256 for i in range(size))
body[: len(salt)] = salt[:size]
return bytes(body)
return _make return _make
@ -227,7 +236,11 @@ def seeded_asset(request: pytest.FixtureRequest, http: requests.Session, api_bas
if tags is None: if tags is None:
tags = ["models", "checkpoints", "unit-tests", "alpha"] tags = ["models", "checkpoints", "unit-tests", "alpha"]
meta = {"purpose": "test", "epoch": 1, "flags": ["x", "y"], "nullable": None} meta = {"purpose": "test", "epoch": 1, "flags": ["x", "y"], "nullable": None}
files = {"file": (name, b"A" * 4096, "application/octet-stream")} # Unique content per test so the seed always creates a fresh asset (201).
# Delete is now always a soft delete, so content from a prior test survives
# and would otherwise dedup this upload into an existing asset (200).
content = uuid.uuid4().bytes + b"A" * (4096 - 16)
files = {"file": (name, content, "application/octet-stream")}
form_data = { form_data = {
"tags": json.dumps(tags), "tags": json.dumps(tags),
"name": name, "name": name,