Files
vLLM/tests/entrypoints/unit_tests/test_download_kernels_cli.py
2026-10-09 21:22:35 -07:00

114 lines
4.2 KiB
Python

# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
import importlib.metadata
import os
import subprocess
from importlib.util import find_spec
from pathlib import Path
from types import SimpleNamespace
import pytest
import regex as re
import vllm.utils.flashinfer as fi
from vllm.entrypoints.cli import download_kernels
@pytest.mark.skipif(find_spec("flashinfer") is None, reason="requires FlashInfer")
def test_download_kernels_resolves_kernel_warning(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
capfd: pytest.CaptureFixture[str],
caplog_vllm: pytest.LogCaptureFixture,
disable_log_dedup,
):
"""Runs the installed FlashInfer CLI, so a FlashInfer release that renames
its kernel packages, CLI or version check fails here instead of leaving
users with a warning that its own fix cannot clear."""
# A vLLM upgrade leaves kernels from the previous FlashInfer behind, which
# FlashInfer rejects on import. The command must work in that state.
stale_cubin = tmp_path / "flashinfer_cubin"
stale_cubin.mkdir()
(stale_cubin / "__init__.py").write_text(
f'__version__ = "0"\ndef get_cubin_dir(): return "{stale_cubin}"\n'
)
monkeypatch.setenv(
"PYTHONPATH", os.pathsep.join([str(tmp_path), os.getenv("PYTHONPATH", "")])
)
assert download_kernels._download_flashinfer_kernels(dry_run=True) == 0
kernels = dict(re.findall(r"Requirement: ([\w-]+)==(\S+)", capfd.readouterr().out))
assert kernels
installed = {"flashinfer-python": importlib.metadata.version("flashinfer-python")}
def version(name: str) -> str:
if name not in installed:
raise importlib.metadata.PackageNotFoundError(name)
return installed[name]
def warns() -> bool:
caplog_vllm.clear()
fi.warn_if_flashinfer_kernels_missing()
return "Run `vllm download-kernels`" in caplog_vllm.text
monkeypatch.delenv("VLLM_HAS_FLASHINFER_CUBIN", raising=False)
monkeypatch.setattr(importlib.metadata, "version", version)
monkeypatch.setattr(fi, "has_flashinfer", lambda: True)
monkeypatch.setattr(
fi,
"current_platform",
SimpleNamespace(is_cuda=lambda: True, has_device_capability=lambda _: True),
)
assert warns()
installed.update(dict.fromkeys(kernels, "0"))
assert warns()
installed.update(kernels)
assert not warns()
def test_cuda_without_jit_cache_wheels_needs_only_cubin(
monkeypatch: pytest.MonkeyPatch,
caplog_vllm: pytest.LogCaptureFixture,
disable_log_dedup,
):
"""FlashInfer publishes no flashinfer-jit-cache below CUDA 12.9, so the
command must not fail on it and the warning must not ask for it."""
commands = []
installed = {"flashinfer-python": "1.0", "flashinfer-cubin": "1.0"}
def version(name: str) -> str:
if name not in installed:
raise importlib.metadata.PackageNotFoundError(name)
return installed[name]
def run(cmd: list[str], **kwargs) -> SimpleNamespace:
commands.append(cmd)
return SimpleNamespace(returncode=0)
monkeypatch.delenv("VLLM_HAS_FLASHINFER_CUBIN", raising=False)
monkeypatch.setattr(fi.torch.version, "cuda", "12.8")
monkeypatch.setattr(download_kernels, "find_spec", lambda name: object())
monkeypatch.setattr(subprocess, "run", run)
monkeypatch.setattr(importlib.metadata, "version", version)
monkeypatch.setattr(fi, "has_flashinfer", lambda: True)
monkeypatch.setattr(
fi,
"current_platform",
SimpleNamespace(is_cuda=lambda: True, has_device_capability=lambda _: True),
)
assert download_kernels._download_flashinfer_kernels(dry_run=False) == 0
assert commands[0][-1] == "install-cubin-wheel"
fi.warn_if_flashinfer_kernels_missing()
assert "vllm download-kernels" not in caplog_vllm.text
def test_download_kernels_skips_without_flashinfer(monkeypatch: pytest.MonkeyPatch):
"""Builds without FlashInfer (CPU, ROCm, XPU) have nothing to download."""
monkeypatch.setattr(download_kernels, "find_spec", lambda name: None)
monkeypatch.setattr(subprocess, "run", pytest.fail)
assert download_kernels._download_flashinfer_kernels(dry_run=False) == 0