项目文件夹

文件
wehub-resource-sync eec33d25b2
Build Wheel / build (3.11) (push) Failing after 1s
Build Wheel / build (3.12) (push) Failing after 0s
pre-commit / pre-commit (push) Failing after 1s
chore: import upstream snapshot with attribution
2026-07-13 12:29:08 +08:00

188 行
5.9 KiB
Python

# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
"""Unit tests for decode_audio_url helper."""
import asyncio
import base64
import os
import httpx
import pytest
from vllm_omni.entrypoints.openai.errors import InvalidInputReferenceError
from vllm_omni.entrypoints.openai.video_api_utils import decode_audio_url
pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
def _run(coro):
return asyncio.run(coro)
def _cleanup(path):
if path and os.path.exists(path):
os.unlink(path)
class TestDecodeAudioUrlDataUrl:
"""Tests for base64 data URL decoding."""
def test_valid_mp3_data_url(self):
audio_bytes = b"\xff\xfb\x90\x00" * 100
b64 = base64.b64encode(audio_bytes).decode()
url = f"data:audio/mp3;base64,{b64}"
path = _run(decode_audio_url(url))
try:
assert os.path.isfile(path)
assert path.endswith(".mp3")
with open(path, "rb") as f:
assert f.read() == audio_bytes
finally:
_cleanup(path)
def test_valid_wav_data_url(self):
audio_bytes = b"RIFF" + b"\x00" * 100
b64 = base64.b64encode(audio_bytes).decode()
url = f"data:audio/wav;base64,{b64}"
path = _run(decode_audio_url(url))
try:
assert path.endswith(".wav")
with open(path, "rb") as f:
assert f.read() == audio_bytes
finally:
_cleanup(path)
def test_valid_mpeg_data_url_uses_mp3_suffix(self):
audio_bytes = b"\xff\xfb\x90\x00" * 50
b64 = base64.b64encode(audio_bytes).decode()
url = f"data:audio/mpeg;base64,{b64}"
path = _run(decode_audio_url(url))
try:
assert path.endswith(".mp3")
finally:
_cleanup(path)
def test_valid_ogg_data_url(self):
audio_bytes = b"OggS" + b"\x00" * 100
b64 = base64.b64encode(audio_bytes).decode()
url = f"data:audio/ogg;base64,{b64}"
path = _run(decode_audio_url(url))
try:
assert path.endswith(".ogg")
finally:
_cleanup(path)
def test_invalid_base64_raises(self):
url = "data:audio/mp3;base64,!!!not-valid-base64!!!"
with pytest.raises(InvalidInputReferenceError, match="not valid base64"):
_run(decode_audio_url(url))
def test_empty_audio_data_raises(self):
url = "data:audio/mp3;base64,"
with pytest.raises(InvalidInputReferenceError, match="audio data is empty"):
_run(decode_audio_url(url))
class TestDecodeAudioUrlSuffixSanitization:
"""Tests for MIME extension sanitization (path traversal prevention)."""
def test_path_traversal_in_mime_is_neutralized(self):
audio_bytes = b"\x00" * 100
b64 = base64.b64encode(audio_bytes).decode()
url = f"data:audio/../..;base64,{b64}"
path = _run(decode_audio_url(url))
try:
# ".." contains non-alnum dots, so falls back to .wav
assert path.endswith(".wav")
assert os.path.dirname(path) == "/tmp"
finally:
_cleanup(path)
def test_non_alnum_extension_falls_back_to_wav(self):
audio_bytes = b"\x00" * 100
b64 = base64.b64encode(audio_bytes).decode()
url = f"data:audio/foo-bar;base64,{b64}"
path = _run(decode_audio_url(url))
try:
assert path.endswith(".wav")
finally:
_cleanup(path)
def test_too_long_extension_falls_back_to_wav(self):
audio_bytes = b"\x00" * 100
b64 = base64.b64encode(audio_bytes).decode()
url = f"data:audio/verylongextension;base64,{b64}"
path = _run(decode_audio_url(url))
try:
assert path.endswith(".wav")
finally:
_cleanup(path)
def test_valid_short_alnum_extension_is_used(self):
audio_bytes = b"\x00" * 100
b64 = base64.b64encode(audio_bytes).decode()
url = f"data:audio/flac;base64,{b64}"
path = _run(decode_audio_url(url))
try:
assert path.endswith(".flac")
finally:
_cleanup(path)
class TestDecodeAudioUrlHttp:
"""Tests for HTTP URL decoding."""
def test_valid_http_url(self, monkeypatch):
audio_bytes = b"\xff\xfb\x90\x00" * 50
fake_resp = httpx.Response(200, content=audio_bytes)
async def _mock_get(self, url):
return fake_resp
monkeypatch.setattr(httpx.AsyncClient, "get", _mock_get)
monkeypatch.setattr(httpx.Response, "raise_for_status", lambda self: None)
path = _run(decode_audio_url("https://example.com/audio.mp3"))
try:
assert os.path.isfile(path)
assert path.endswith(".wav")
with open(path, "rb") as f:
assert f.read() == audio_bytes
finally:
_cleanup(path)
def test_http_error_raises(self, monkeypatch):
async def _mock_get(self, url):
raise httpx.HTTPStatusError("Not Found", request=httpx.Request("GET", url), response=httpx.Response(404))
monkeypatch.setattr(httpx.AsyncClient, "get", _mock_get)
with pytest.raises(InvalidInputReferenceError, match="failed to download audio"):
_run(decode_audio_url("https://example.com/missing.mp3"))
class TestDecodeAudioUrlInvalid:
"""Tests for invalid URL schemes."""
def test_local_file_path_raises(self):
with pytest.raises(InvalidInputReferenceError, match="must be an http.*URL or data URL"):
_run(decode_audio_url("/path/to/local/file.mp3"))
def test_ftp_url_raises(self):
with pytest.raises(InvalidInputReferenceError, match="must be an http.*URL or data URL"):
_run(decode_audio_url("ftp://example.com/file.mp3"))
def test_empty_string_raises(self):
with pytest.raises(InvalidInputReferenceError, match="must be an http.*URL or data URL"):
_run(decode_audio_url(""))