| """binary_locator.py 探测逻辑测试。 |
| |
| 用 monkeypatch 模拟环境变量、PATH、可执行性检查,覆盖 env/path/common/wsl/全失败分支。 |
| """ |
|
|
| import os |
| import platform |
| from pathlib import Path |
| from unittest.mock import patch |
|
|
| import pytest |
|
|
| from plugins.browser.browser import binary_locator |
|
|
|
|
| def _make_executable(tmp_path: Path, name: str = "lightpanda") -> Path: |
| """在 tmp_path 下造一个可执行文件。""" |
| p = tmp_path / name |
| p.write_text("#!/bin/sh\n") |
| p.chmod(0o755) |
| return p |
|
|
|
|
| def test_env_path_detected(tmp_path, monkeypatch): |
| """LIGHTPANDA_BINARY 指向可执行文件时 source=env。""" |
| binp = _make_executable(tmp_path) |
| monkeypatch.setenv("LIGHTPANDA_BINARY", str(binp)) |
| monkeypatch.setattr(binary_locator.shutil, "which", lambda _: None) |
| monkeypatch.setattr(binary_locator, "_read_version", lambda b: "0.2.0") |
|
|
| r = binary_locator.locate_lightpanda() |
| assert r.available is True |
| assert r.path == str(binp) |
| assert r.source == "env" |
| assert r.version == "0.2.0" |
|
|
|
|
| def test_env_path_not_executable_falls_through(tmp_path, monkeypatch): |
| """LIGHTPANDA_BINARY 指向不可执行文件时不命中。 |
| |
| 注:Windows 不用 Unix 权限位判定可执行性,故直接 mock _check_path_executable |
| 返回 False 来模拟"存在但不可执行"。 |
| """ |
| p = tmp_path / "lightpanda" |
| p.write_text("not executable") |
| monkeypatch.setenv("LIGHTPANDA_BINARY", str(p)) |
| monkeypatch.setattr(binary_locator.shutil, "which", lambda _: None) |
| monkeypatch.setattr(binary_locator, "_probe_wsl_interop", lambda: None) |
| monkeypatch.setattr(binary_locator, "_check_path_executable", lambda path: False) |
|
|
| r = binary_locator.locate_lightpanda() |
| assert r.available is False |
|
|
|
|
| def test_path_detected(tmp_path, monkeypatch): |
| """shutil.which 找到可执行文件时 source=path。""" |
| binp = _make_executable(tmp_path) |
| monkeypatch.delenv("LIGHTPANDA_BINARY", raising=False) |
| monkeypatch.setattr(binary_locator.shutil, "which", lambda _: str(binp)) |
| monkeypatch.setattr(binary_locator, "_read_version", lambda b: "0.2.0") |
| monkeypatch.setattr(binary_locator, "_probe_wsl_interop", lambda: None) |
|
|
| r = binary_locator.locate_lightpanda() |
| assert r.available is True |
| assert r.source == "path" |
|
|
|
|
| def test_all_fail_returns_unavailable(monkeypatch): |
| """全部探测失败时 available=False 且 source=none。""" |
| monkeypatch.delenv("LIGHTPANDA_BINARY", raising=False) |
| monkeypatch.setattr(binary_locator.shutil, "which", lambda _: None) |
| monkeypatch.setattr(binary_locator, "_probe_wsl_interop", lambda: None) |
| monkeypatch.setattr(binary_locator, "_check_path_executable", lambda p: False) |
|
|
| r = binary_locator.locate_lightpanda() |
| assert r.available is False |
| assert r.source == "none" |
| assert r.error |
| assert r.install_hints |
|
|
|
|
| def test_install_hints_contain_docker_and_wsl(monkeypatch): |
| """install_hints 总是包含 docker 和 wsl 备选。""" |
| monkeypatch.delenv("LIGHTPANDA_BINARY", raising=False) |
| monkeypatch.setattr(binary_locator.shutil, "which", lambda _: None) |
| monkeypatch.setattr(binary_locator, "_probe_wsl_interop", lambda: None) |
| monkeypatch.setattr(binary_locator, "_check_path_executable", lambda p: False) |
|
|
| r = binary_locator.locate_lightpanda() |
| assert "docker" in r.install_hints |
| assert "wsl" in r.install_hints |
|
|
|
|
| def test_to_dict_serializable(monkeypatch): |
| """to_dict 返回可 JSON 序列化的 dict。""" |
| import json |
| monkeypatch.delenv("LIGHTPANDA_BINARY", raising=False) |
| monkeypatch.setattr(binary_locator.shutil, "which", lambda _: None) |
| monkeypatch.setattr(binary_locator, "_probe_wsl_interop", lambda: None) |
| monkeypatch.setattr(binary_locator, "_check_path_executable", lambda p: False) |
|
|
| r = binary_locator.locate_lightpanda() |
| d = r.to_dict() |
| json.dumps(d) |
| assert d["available"] is False |
|
|
|
|
| def test_is_binary_available_consistent(monkeypatch): |
| """is_binary_available 与 locate_lightpanda().available 一致。""" |
| monkeypatch.delenv("LIGHTPANDA_BINARY", raising=False) |
| monkeypatch.setattr(binary_locator.shutil, "which", lambda _: None) |
| monkeypatch.setattr(binary_locator, "_probe_wsl_interop", lambda: None) |
| monkeypatch.setattr(binary_locator, "_check_path_executable", lambda p: False) |
|
|
| assert binary_locator.is_binary_available() is False |
|
|