"""Tests for meshbay_node.platform — the OS-specific paths and tool resolution. The behaviour is selected on `sys.platform` at call time, so it is exercised here by monkeypatching that (and `os.environ`) rather than only on the OS the suite happens to run on. """ import asyncio import sys from pathlib import Path from unittest.mock import Mock import pytest from meshbay_node import platform as plat # ── Directories ────────────────────────────────────────────────────────────── @pytest.mark.parametrize("fn,tail", [ (plat.config_dir, ()), (plat.data_dir, ("data",)), (plat.state_dir, ("state",)), ]) def test_windows_dirs_live_under_localappdata(fn, tail, monkeypatch, tmp_path): monkeypatch.setattr(sys, "platform", "win32") monkeypatch.setenv("LOCALAPPDATA", str(tmp_path)) assert fn() == tmp_path.joinpath("meshbay", *tail) @pytest.mark.parametrize("fn,expected_tail", [ (plat.config_dir, (".config", "meshbay")), (plat.data_dir, (".local", "share", "meshbay")), (plat.state_dir, (".local", "state", "meshbay")), ]) def test_posix_dirs_follow_xdg(fn, expected_tail, monkeypatch): monkeypatch.setattr(sys, "platform", "linux") assert fn() == Path.home().joinpath(*expected_tail) def test_windows_dirs_fall_back_to_home_without_localappdata(monkeypatch): monkeypatch.setattr(sys, "platform", "win32") monkeypatch.delenv("LOCALAPPDATA", raising=False) assert plat.config_dir() == Path.home() / "meshbay" # ── File permissions ───────────────────────────────────────────────────────── def test_chmod_private_is_a_noop_on_windows(monkeypatch): monkeypatch.setattr(sys, "platform", "win32") fake = Mock(spec=Path) plat.chmod_private(fake) fake.chmod.assert_not_called() def test_chmod_private_applies_mode_off_windows(monkeypatch, tmp_path): monkeypatch.setattr(sys, "platform", "linux") f = tmp_path / "secret" f.write_text("x", encoding="utf-8") called = {} monkeypatch.setattr(type(f), "chmod", lambda self, m: called.setdefault("mode", m)) plat.chmod_private(f) assert called["mode"] == 0o600 # ── Media tools ────────────────────────────────────────────────────────────── def test_check_media_tools_raises_when_ffmpeg_is_missing(monkeypatch): monkeypatch.setattr(plat.shutil, "which", lambda _n: None) with pytest.raises(RuntimeError, match="not found in PATH"): plat.check_media_tools() def test_check_media_tools_stores_the_resolved_paths(monkeypatch): monkeypatch.setattr(plat.shutil, "which", lambda n: f"/opt/bin/{n}.exe") plat.check_media_tools("ffmpeg", "ffprobe") assert plat.ffmpeg_cmd() == "/opt/bin/ffmpeg.exe" assert plat.ffprobe_cmd() == "/opt/bin/ffprobe.exe" # ── Event loop ─────────────────────────────────────────────────────────────── def test_configure_event_loop_is_a_noop_off_windows(monkeypatch): monkeypatch.setattr(sys, "platform", "linux") monkeypatch.setenv("MESHBAY_NODE_EVENT_LOOP", "selector") before = asyncio.get_event_loop_policy() plat.configure_event_loop() assert asyncio.get_event_loop_policy() is before def test_configure_event_loop_leaves_the_default_loop_alone_without_the_opt_in(monkeypatch): monkeypatch.setattr(sys, "platform", "win32") monkeypatch.delenv("MESHBAY_NODE_EVENT_LOOP", raising=False) before = asyncio.get_event_loop_policy() plat.configure_event_loop() assert asyncio.get_event_loop_policy() is before @pytest.mark.skipif(sys.platform != "win32", reason="WindowsSelectorEventLoopPolicy exists only on win32") def test_configure_event_loop_selector_opt_in(monkeypatch): monkeypatch.setenv("MESHBAY_NODE_EVENT_LOOP", "selector") plat.configure_event_loop() assert isinstance(asyncio.get_event_loop_policy(), asyncio.WindowsSelectorEventLoopPolicy) # ── Autostart ──────────────────────────────────────────────────────────────── # # On Windows autostart is a `.vbs` in the per-user Startup folder (a logon task # would need elevation). Tests point APPDATA at a tmp dir so the real Startup # folder is never touched, and force sys.platform. @pytest.fixture def win_startup(monkeypatch, tmp_path): monkeypatch.setattr(sys, "platform", "win32") monkeypatch.setenv("APPDATA", str(tmp_path)) return (tmp_path / "Microsoft" / "Windows" / "Start Menu" / "Programs" / "Startup" / "MeshBay Node.vbs") def test_autostart_supported_tracks_the_platform(monkeypatch): monkeypatch.setattr(sys, "platform", "win32") assert plat.autostart_supported() is True monkeypatch.setattr(sys, "platform", "linux") assert plat.autostart_supported() is False def test_autostart_status_is_inert_off_windows(monkeypatch): monkeypatch.setattr(sys, "platform", "linux") assert plat.autostart_status() == {"installed": False, "state": ""} def test_autostart_install_writes_a_hidden_launcher_in_the_startup_folder(win_startup): exe = r"C:\Program Files\MeshBay\meshbay-node.exe" plat.autostart_install(exe=exe) assert win_startup.exists() assert plat.autostart_status() == {"installed": True, "state": ""} raw = win_startup.read_bytes() assert b"\r\n" in raw and b"\n\n" not in raw # CRLF, no stray LF text = raw.decode("utf-8") assert f'"{exe}"' in text # path is quote-wrapped assert "Chr(34)" in text and ", 0, False" in text # hidden, non-blocking def test_autostart_remove_deletes_the_launcher_and_is_idempotent(win_startup): plat.autostart_install(exe=r"C:\x\meshbay-node.exe") assert win_startup.exists() plat.autostart_remove() assert not win_startup.exists() plat.autostart_remove() # no error second time def test_autostart_install_needs_a_locatable_launcher(win_startup, monkeypatch): monkeypatch.setattr(plat, "_node_exe", lambda: None) with pytest.raises(RuntimeError, match="locate the meshbay-node launcher"): plat.autostart_install() def test_autostart_install_refuses_off_windows(monkeypatch): monkeypatch.setattr(sys, "platform", "linux") with pytest.raises(RuntimeError, match="Windows-only"): plat.autostart_install(exe="/usr/bin/meshbay-node") def test_autostart_run_launches_the_resolved_exe_detached(win_startup, monkeypatch): monkeypatch.setattr(plat, "_node_exe", lambda: r"C:\x\meshbay-node.exe") calls = {} monkeypatch.setattr(plat.subprocess, "Popen", lambda argv, **kw: calls.update(argv=argv, kw=kw)) plat.autostart_run() assert calls["argv"] == [r"C:\x\meshbay-node.exe"] assert calls["kw"]["creationflags"] & 0x08000000 # CREATE_NO_WINDOW def test_autostart_run_refuses_off_windows(monkeypatch): monkeypatch.setattr(sys, "platform", "linux") with pytest.raises(RuntimeError, match="Windows-only"): plat.autostart_run()