File size: 4,462 Bytes
e0ea7df 0d8512e e0ea7df 0d8512e cc826a1 0d8512e e0ea7df 0d8512e e0ea7df 0d8512e e0ea7df 0d8512e e0ea7df 0d8512e e0ea7df 0d8512e e0ea7df 0d8512e e0ea7df 0d8512e e0ea7df 0d8512e e0ea7df 0d8512e e0ea7df 0d8512e e0ea7df 0d8512e e0ea7df 0d8512e e0ea7df 0d8512e e0ea7df | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | """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) # 不抛即 OK
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
|