Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions ui/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,51 @@
# Global flag to track initialization
_initialized = False

# Isolation: the tests write QSettings (~/.config/opensnitch/settings.conf),
# delete settings.conf, and toggle the autostart .desktop file. Redirect HOME
# and the XDG dirs to a throwaway directory *before* opensnitch or Qt cache
# any path, so a test run never touches an installed OpenSnitch UI.
import hashlib
import os
import pwd
import shutil
import sys
import tempfile

if any(m == "opensnitch" or m.startswith("opensnitch.") for m in sys.modules):
raise RuntimeError("opensnitch was imported before tests/conftest.py could isolate HOME; refusing to run")

_REAL_HOME = pwd.getpwuid(os.getuid()).pw_dir
_SANDBOX = tempfile.mkdtemp(prefix="opensnitch-ui-tests-")
for _var, _sub in (
("HOME", ""),
("XDG_CONFIG_HOME", ".config"),
("XDG_DATA_HOME", ".local/share"),
("XDG_CACHE_HOME", ".cache"),
("XDG_STATE_HOME", ".local/state"),
("XDG_RUNTIME_DIR", "run")):
_path = os.path.join(_SANDBOX, _sub)
os.makedirs(_path, mode=0o700, exist_ok=True)
os.environ[_var] = _path
# no desktop notifications or other D-Bus traffic to the real session
os.environ.pop("DBUS_SESSION_BUS_ADDRESS", None)

# files of a real installation that a test run must never modify
_REAL_FILES = [
os.path.join(_REAL_HOME, ".config/opensnitch/settings.conf"),
os.path.join(_REAL_HOME, ".config/autostart/opensnitch_ui.desktop"),
]

def _snapshot_real_files():
snap = {}
for path in _REAL_FILES:
try:
with open(path, "rb") as f:
snap[path] = hashlib.sha256(f.read()).hexdigest()
except FileNotFoundError:
snap[path] = None
return snap

def init_test_environment():
"""Initialize database and config after QApplication exists."""
global _initialized
Expand All @@ -35,6 +80,27 @@ def init_test_environment():

_initialized = True

@pytest.fixture(scope="session", autouse=True)
def isolated_home():
"""Fail loudly if anything resolves outside the sandbox, or if the
real installation's files changed during the run."""
try:
from PyQt6 import QtCore
from opensnitch.utils import xdg
except ImportError:
# tests that run without Qt: only the check of the real files applies
pass
else:
settings_file = QtCore.QSettings("opensnitch", "settings").fileName()
for path in (settings_file, xdg.xdg_config_home, xdg.xdg_runtime_dir, xdg.Autostart().userAutostart):
assert path.startswith(_SANDBOX + os.sep), f"not isolated: {path} is outside {_SANDBOX}"

before = _snapshot_real_files()
yield _SANDBOX
after = _snapshot_real_files()
shutil.rmtree(_SANDBOX, ignore_errors=True)
assert before == after, f"test run modified the real installation: {before} -> {after}"

@pytest.fixture(scope="session")
def qapp():
"""Create QApplication for the entire test session."""
Expand Down