from __future__ import annotations from io import BytesIO import pytest from starlette.datastructures import UploadFile from src.core.security import extract_image_fingerprint, generate_hmac_chain @pytest.mark.asyncio async def test_extract_image_fingerprint_is_deterministic_and_resets_pointer() -> None: payload = (b"0123456789abcdef" * 8192) + b"end" upload = UploadFile(filename="sample.bin", file=BytesIO(payload)) fp1 = await extract_image_fingerprint(upload) prefix = await upload.read(16) assert prefix == payload[:16] await upload.seek(0) fp2 = await extract_image_fingerprint(upload) assert fp1 == fp2 def test_generate_hmac_chain_is_stable_and_order_sensitive() -> None: secret = b"super-secret" ordered_parts = [b"ts", b"POST", b"/v1/predict", b"DEV-1", b"fingerprint"] reordered_parts = [b"POST", b"ts", b"/v1/predict", b"DEV-1", b"fingerprint"] sig1 = generate_hmac_chain(ordered_parts, secret) sig2 = generate_hmac_chain(ordered_parts, secret) sig3 = generate_hmac_chain(reordered_parts, secret) assert sig1 == sig2 assert sig1 != sig3