Files
hermes-agent/tests/test_desktop_update_shim_profile_cleanup.py

60 lines
2.6 KiB
Python

"""The update hand-off cleans only an atomically claimed browser profile."""
import os
from pathlib import Path
import subprocess
import pytest
@pytest.mark.platforms("linux")
@pytest.mark.parametrize("outcome", ["success", "error", "allocation-failed"])
def test_shim_removes_only_its_owned_profile(tmp_path, outcome):
bin_dir = tmp_path / "bin"
bin_dir.mkdir()
browser = bin_dir / "google-chrome"
browser.write_text(
'#!/usr/bin/env bash\ntrap "exit 0" TERM\n'
'for arg in "$@"; do\n'
'case "$arg" in --user-data-dir=*) dir="${arg#--user-data-dir=}" ;; esac\n'
'done\nmkdir -p "$dir"\nprintf "%s" "$dir" > "$HOME/launched-profile"\n'
'while :; do sleep 0.1; done\n', encoding="utf-8",
)
browser.chmod(0o755)
if outcome == "allocation-failed":
allocator = bin_dir / "mktemp"
allocator.write_text('#!/bin/sh\nprintf "%s\\n" "$HOME"\nexit 1\n', encoding="utf-8")
allocator.chmod(0o755)
config = tmp_path / ".config"
config.mkdir()
(config / "mimeapps.list").write_text(
'[Default Applications]\nx-scheme-handler/http=google-chrome.desktop\n'
'x-scheme-handler/https=google-chrome.desktop\ntext/html=google-chrome.desktop\n',
encoding="utf-8",
)
install = tmp_path / "hermes-agent"
install.mkdir()
env = {**os.environ, "HOME": str(tmp_path), "HERMES_HOME": str(tmp_path),
"XDG_CONFIG_HOME": str(config), "TMPDIR": str(tmp_path),
"PATH": f"{bin_dir}:/usr/bin:/bin", "HERMES_SELFTEST_HOLD_SECONDS": "1",
"HERMES_UPDATE_SHIM_GRACE_SECONDS": "1", "HERMES_SELFTEST_FAIL": "1" if outcome == "error" else ""}
process = subprocess.Popen(
["bash", "-c", 'while [ ! -f "$HOME/start" ]; do sleep .05; done; exec bash "$@"', "probe",
str(Path(__file__).resolve().parents[1] / "scripts/desktop-update/posix.sh"),
"--install-root", str(install), "--self-test-ui"],
env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True,
)
collision = tmp_path / f"hermes-update-ui-{process.pid}"
collision.mkdir()
(collision / "keep").write_text("keep", encoding="utf-8")
(tmp_path / "start").touch()
stdout, stderr = process.communicate(timeout=30)
assert process.returncode == (1 if outcome == "error" else 0), stdout + stderr
launched = tmp_path / "launched-profile"
if outcome == "allocation-failed":
assert not launched.exists()
else:
owned = Path(launched.read_text(encoding="utf-8"))
assert owned != collision
assert not owned.exists()
assert (collision / "keep").read_text(encoding="utf-8") == "keep"