141 lines
5.4 KiB
Python
141 lines
5.4 KiB
Python
"""Unit tests for the Linux Windows-font mismatch warning (browser.py).
|
|
|
|
The warning fires once per environment when spoofing Windows on a font-less
|
|
Linux host. These tests mock platform, fc-list, and the cache dir so they are
|
|
host-independent and need no binary. The warning is written straight to stderr
|
|
(like the welcome banner and the JS/.NET wrappers), so capture it with capsys.
|
|
"""
|
|
|
|
import subprocess
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
|
|
import cloakbrowser.browser as browser
|
|
|
|
WIN_ARGS = ["--fingerprint-platform=windows", "--no-sandbox"]
|
|
MSG = "Incomplete Windows font set"
|
|
|
|
# fc-list output containing all 8 Windows tell fonts (the complete set).
|
|
ALL_WIN_FONTS = (
|
|
"Segoe UI:style=Regular\nSegoe UI Light:style=Light\nCalibri:style=Regular\n"
|
|
"Marlett:style=Regular\nMS UI Gothic:style=Regular\n"
|
|
"Franklin Gothic Medium:style=Regular\nConsolas:style=Regular\n"
|
|
"Courier New:style=Regular"
|
|
)
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _reset_in_process_flag():
|
|
"""Each test starts with the once-per-process guard cleared."""
|
|
browser._font_warning_checked = False
|
|
yield
|
|
browser._font_warning_checked = False
|
|
|
|
|
|
def _fc_list(returncode=0, stdout=""):
|
|
"""Build a subprocess.run side effect mimicking fc-list output."""
|
|
def _run(*args, **kwargs):
|
|
return subprocess.CompletedProcess(args, returncode, stdout=stdout, stderr="")
|
|
return _run
|
|
|
|
|
|
def test_warns_when_no_windows_fonts(tmp_path, capsys, monkeypatch):
|
|
monkeypatch.delenv("CLOAKBROWSER_SUPPRESS_FONT_WARNING", raising=False)
|
|
with (
|
|
patch("platform.system", return_value="Linux"),
|
|
patch("subprocess.run", side_effect=_fc_list(0, "DejaVu Sans:style=Book")),
|
|
patch("cloakbrowser.config.get_cache_dir", return_value=tmp_path),
|
|
):
|
|
browser._maybe_warn_windows_fonts(WIN_ARGS)
|
|
assert MSG in capsys.readouterr().err
|
|
assert (tmp_path / ".font_warning_shown").exists()
|
|
|
|
|
|
def test_in_process_flag_blocks_second_call(tmp_path, capsys):
|
|
with (
|
|
patch("platform.system", return_value="Linux"),
|
|
patch("subprocess.run", side_effect=_fc_list(0, "DejaVu")) as mrun,
|
|
patch("cloakbrowser.config.get_cache_dir", return_value=tmp_path),
|
|
):
|
|
browser._maybe_warn_windows_fonts(WIN_ARGS)
|
|
assert MSG in capsys.readouterr().err # first call warns (and drains buffer)
|
|
browser._maybe_warn_windows_fonts(WIN_ARGS)
|
|
assert MSG not in capsys.readouterr().err
|
|
assert mrun.call_count == 1 # probe ran only once
|
|
|
|
|
|
def test_marker_suppresses_across_processes(tmp_path, capsys):
|
|
"""An existing marker (prior process) skips the warning even after a flag reset."""
|
|
(tmp_path / ".font_warning_shown").write_text("")
|
|
with (
|
|
patch("platform.system", return_value="Linux"),
|
|
patch("subprocess.run", side_effect=_fc_list(0, "DejaVu")),
|
|
patch("cloakbrowser.config.get_cache_dir", return_value=tmp_path),
|
|
):
|
|
browser._maybe_warn_windows_fonts(WIN_ARGS)
|
|
assert MSG not in capsys.readouterr().err
|
|
|
|
|
|
def test_env_suppresses_and_writes_no_marker(tmp_path, capsys, monkeypatch):
|
|
monkeypatch.setenv("CLOAKBROWSER_SUPPRESS_FONT_WARNING", "1")
|
|
with (
|
|
patch("platform.system", return_value="Linux"),
|
|
patch("subprocess.run", side_effect=_fc_list(0, "")),
|
|
patch("cloakbrowser.config.get_cache_dir", return_value=tmp_path),
|
|
):
|
|
browser._maybe_warn_windows_fonts(WIN_ARGS)
|
|
assert MSG not in capsys.readouterr().err
|
|
assert not (tmp_path / ".font_warning_shown").exists()
|
|
|
|
|
|
def test_no_warn_on_non_linux(tmp_path, capsys):
|
|
with (
|
|
patch("platform.system", return_value="Darwin"),
|
|
patch("cloakbrowser.config.get_cache_dir", return_value=tmp_path),
|
|
):
|
|
browser._maybe_warn_windows_fonts(WIN_ARGS)
|
|
assert MSG not in capsys.readouterr().err
|
|
|
|
|
|
def test_no_warn_when_platform_overridden(tmp_path, capsys):
|
|
with (
|
|
patch("platform.system", return_value="Linux"),
|
|
patch("cloakbrowser.config.get_cache_dir", return_value=tmp_path),
|
|
):
|
|
browser._maybe_warn_windows_fonts(["--fingerprint-platform=linux"])
|
|
assert MSG not in capsys.readouterr().err
|
|
|
|
|
|
def test_no_warn_no_crash_when_fc_list_absent(tmp_path, capsys):
|
|
with (
|
|
patch("platform.system", return_value="Linux"),
|
|
patch("subprocess.run", side_effect=FileNotFoundError()),
|
|
patch("cloakbrowser.config.get_cache_dir", return_value=tmp_path),
|
|
):
|
|
browser._maybe_warn_windows_fonts(WIN_ARGS) # must not raise
|
|
assert MSG not in capsys.readouterr().err
|
|
assert not (tmp_path / ".font_warning_shown").exists()
|
|
|
|
|
|
def test_no_warn_when_full_set_present(tmp_path, capsys):
|
|
with (
|
|
patch("platform.system", return_value="Linux"),
|
|
patch("subprocess.run", side_effect=_fc_list(0, ALL_WIN_FONTS)),
|
|
patch("cloakbrowser.config.get_cache_dir", return_value=tmp_path),
|
|
):
|
|
browser._maybe_warn_windows_fonts(WIN_ARGS)
|
|
assert MSG not in capsys.readouterr().err
|
|
|
|
|
|
def test_warns_on_partial_set(tmp_path, capsys):
|
|
# Only 1 of the 8 tells present — strict check treats this as incomplete.
|
|
listing = "/usr/share/fonts/segoeui.ttf: Segoe UI:style=Regular"
|
|
with (
|
|
patch("platform.system", return_value="Linux"),
|
|
patch("subprocess.run", side_effect=_fc_list(0, listing)),
|
|
patch("cloakbrowser.config.get_cache_dir", return_value=tmp_path),
|
|
):
|
|
browser._maybe_warn_windows_fonts(WIN_ARGS)
|
|
assert MSG in capsys.readouterr().err
|