"""Tests for dotfiles/hyprland/.local/bin/airplane-mode. airplane-mode is a stateful toggle. On engage it RECORDS the current state of each lever (wifi on/off, CPU EPP value, brightness, which services were running) to a state file, then applies the low-power settings. On disengage it reads that file and RESTORES exactly what was recorded — so a lever that was already in its low-power position before engaging is left untouched on disengage. That save-and-replay logic is what these tests pin down. The real script runs against command stubs (sudo / nmcli / brightnessctl / systemctl / notify / pkill) placed on PATH, plus fake EPP sysfs files in a temp dir. The stubs log every invocation and report state driven by STUB_* env vars, so the test controls "what was running" without touching the host. No reimplementation of the script — the production body executes. Run from repo root: python3 -m unittest tests.airplane-mode.test_airplane_mode """ import os import shutil import subprocess import tempfile import unittest REPO_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) SCRIPT = os.path.join(REPO_ROOT, "dotfiles/hyprland/.local/bin/airplane-mode") SYSTEM_SERVICES = "svc-a.service svc-b.service svc-c.service" USER_SERVICES = "svc-user.service" class AirplaneModeHarness(unittest.TestCase): def setUp(self): self.tmp = tempfile.mkdtemp(prefix="airplane-mode-test-") self.state_file = os.path.join(self.tmp, "airplane-state") self.stub_log = os.path.join(self.tmp, "stub.log") # Fake EPP sysfs files for two CPUs, pre-set to the normal value. self.epp_dir = os.path.join(self.tmp, "epp") self.epp_files = [] for cpu in ("cpu0", "cpu1"): d = os.path.join(self.epp_dir, cpu) os.makedirs(d) f = os.path.join(d, "energy_performance_preference") self._write(f, "balance_performance\n") self.epp_files.append(f) self.epp_glob = os.path.join(self.epp_dir, "cpu*", "energy_performance_preference") self.stub_dir = os.path.join(self.tmp, "stubs") os.makedirs(self.stub_dir) self._make_stubs() def tearDown(self): shutil.rmtree(self.tmp, ignore_errors=True) # -- helpers -------------------------------------------------------------- def _write(self, path, contents): with open(path, "w") as f: f.write(contents) def _stub(self, name, body): path = os.path.join(self.stub_dir, name) self._write(path, "#!/bin/sh\n" + body) os.chmod(path, 0o755) def _make_stubs(self): # sudo just runs the rest of the command line (no privilege needed in # the test; the fake EPP files are writable by the test user). self._stub("sudo", 'exec "$@"\n') self._stub("nmcli", ( 'echo "nmcli $*" >> "$STUB_LOG"\n' 'if [ "$1" = radio ] && [ "$2" = wifi ] && [ -z "$3" ]; then\n' ' echo "${STUB_WIFI:-enabled}"\n' 'fi\n' 'exit 0\n' )) self._stub("brightnessctl", ( 'echo "brightnessctl $*" >> "$STUB_LOG"\n' 'case "$1" in\n' ' get) echo "${STUB_BRIGHTNESS:-96000}" ;;\n' ' max) echo 96000 ;;\n' 'esac\n' 'exit 0\n' )) self._stub("systemctl", ( 'echo "systemctl $*" >> "$STUB_LOG"\n' 'user=0; sub=""; svc=""\n' 'for a in "$@"; do\n' ' case "$a" in\n' ' --user) user=1 ;;\n' ' --quiet) ;;\n' ' is-active|stop|start) sub="$a" ;;\n' ' *) svc="$a" ;;\n' ' esac\n' 'done\n' 'if [ "$sub" = is-active ]; then\n' ' if [ "$user" = 1 ]; then list="$STUB_ACTIVE_USER"; else list="$STUB_ACTIVE_SYSTEM"; fi\n' ' case " $list " in *" $svc "*) exit 0 ;; *) exit 3 ;; esac\n' 'fi\n' 'exit 0\n' )) self._stub("notify", 'echo "notify $*" >> "$STUB_LOG"\nexit 0\n') self._stub("pkill", 'echo "pkill $*" >> "$STUB_LOG"\nexit 0\n') def run_toggle(self, wifi="enabled", brightness="96000", active_system=SYSTEM_SERVICES, active_user=USER_SERVICES): env = os.environ.copy() env["PATH"] = self.stub_dir + os.pathsep + env["PATH"] env["XDG_RUNTIME_DIR"] = self.tmp env["STUB_LOG"] = self.stub_log env["STUB_WIFI"] = wifi env["STUB_BRIGHTNESS"] = brightness env["STUB_ACTIVE_SYSTEM"] = active_system env["STUB_ACTIVE_USER"] = active_user env["AIRPLANE_EPP_GLOB"] = self.epp_glob env["AIRPLANE_SYSTEM_SERVICES"] = SYSTEM_SERVICES env["AIRPLANE_USER_SERVICES"] = USER_SERVICES env["AIRPLANE_BRIGHTNESS_LOW"] = "35%" return subprocess.run( [SCRIPT], env=env, capture_output=True, text=True, timeout=15, ) def state(self): out = {} with open(self.state_file) as f: for line in f: if "=" in line: k, v = line.rstrip("\n").split("=", 1) out[k] = v return out def log(self): try: with open(self.stub_log) as f: return f.read() except FileNotFoundError: return "" def epp_values(self): vals = [] for f in self.epp_files: with open(f) as fh: vals.append(fh.read().strip()) return vals # ----------------------------------------------------------------------------- # Normal cases — engage from a clean (everything-on) state # ----------------------------------------------------------------------------- class TestEngage(AirplaneModeHarness): def test_engage_writes_mode_on(self): r = self.run_toggle() self.assertEqual(r.returncode, 0, msg=r.stderr) self.assertEqual(self.state()["mode"], "on") def test_engage_turns_wifi_off(self): self.run_toggle(wifi="enabled") self.assertIn("nmcli radio wifi off", self.log()) def test_engage_records_prior_wifi_state(self): self.run_toggle(wifi="enabled") self.assertEqual(self.state()["wifi"], "enabled") def test_engage_sets_epp_to_power_on_all_cpus(self): self.run_toggle() self.assertEqual(self.epp_values(), ["power", "power"]) def test_engage_records_prior_epp(self): self.run_toggle() self.assertEqual(self.state()["epp"], "balance_performance") def test_engage_dims_brightness_and_saves_prior(self): self.run_toggle(brightness="96000") self.assertIn("brightnessctl set 35%", self.log()) self.assertEqual(self.state()["brightness"], "96000") def test_engage_stops_active_services_and_records_them(self): self.run_toggle(active_system="svc-a.service svc-c.service", active_user="svc-user.service") log = self.log() self.assertIn("systemctl stop svc-a.service", log) self.assertIn("systemctl stop svc-c.service", log) self.assertIn("systemctl --user stop svc-user.service", log) self.assertIn("svc-a.service", self.state()["stopped_system"]) self.assertIn("svc-c.service", self.state()["stopped_system"]) self.assertIn("svc-user.service", self.state()["stopped_user"]) def test_engage_does_not_stop_already_inactive_service(self): # svc-b is not in the active list → never stopped, never recorded. self.run_toggle(active_system="svc-a.service", active_user="") log = self.log() self.assertNotIn("systemctl stop svc-b.service", log) self.assertNotIn("svc-b.service", self.state().get("stopped_system", "")) def test_engage_refreshes_waybar(self): self.run_toggle() self.assertIn("pkill -RTMIN+10 waybar", self.log()) # ----------------------------------------------------------------------------- # Normal cases — disengage restores recorded state # ----------------------------------------------------------------------------- class TestDisengage(AirplaneModeHarness): def seed_on(self, wifi="enabled", epp="balance_performance", brightness="96000", stopped_system="svc-a.service svc-c.service", stopped_user="svc-user.service"): self._write(self.state_file, ( f"mode=on\nwifi={wifi}\nepp={epp}\nbrightness={brightness}\n" f"stopped_system={stopped_system}\nstopped_user={stopped_user}\n" )) # EPP files are in low-power state while engaged. for f in self.epp_files: self._write(f, "power\n") def test_disengage_writes_mode_off(self): self.seed_on() r = self.run_toggle() self.assertEqual(r.returncode, 0, msg=r.stderr) self.assertEqual(self.state()["mode"], "off") def test_disengage_restores_wifi_when_it_was_on(self): self.seed_on(wifi="enabled") self.run_toggle() self.assertIn("nmcli radio wifi on", self.log()) def test_disengage_restores_epp(self): self.seed_on(epp="balance_performance") self.run_toggle() self.assertEqual(self.epp_values(), ["balance_performance", "balance_performance"]) def test_disengage_restores_brightness_to_saved_value(self): self.seed_on(brightness="80000") self.run_toggle() self.assertIn("brightnessctl set 80000", self.log()) def test_disengage_restarts_recorded_services(self): self.seed_on(stopped_system="svc-a.service svc-c.service", stopped_user="svc-user.service") log = self.log() # before self.run_toggle() log = self.log() self.assertIn("systemctl start svc-a.service", log) self.assertIn("systemctl start svc-c.service", log) self.assertIn("systemctl --user start svc-user.service", log) # ----------------------------------------------------------------------------- # Boundary — "leave it as it was" cases # ----------------------------------------------------------------------------- class TestPreserveExistingState(AirplaneModeHarness): def test_engage_with_wifi_already_off_records_disabled(self): self.run_toggle(wifi="disabled") self.assertEqual(self.state()["wifi"], "disabled") def test_disengage_does_not_reenable_wifi_that_was_already_off(self): # Seed an engaged state where wifi was already off before engaging. self._write(self.state_file, ( "mode=on\nwifi=disabled\nepp=balance_performance\n" "brightness=96000\nstopped_system=\nstopped_user=\n" )) for f in self.epp_files: self._write(f, "power\n") self.run_toggle() self.assertNotIn("nmcli radio wifi on", self.log()) def test_disengage_only_restarts_recorded_services_not_all_known(self): # Only svc-a was recorded as stopped → svc-b/svc-c must not be started. self._write(self.state_file, ( "mode=on\nwifi=enabled\nepp=balance_performance\n" "brightness=96000\nstopped_system=svc-a.service\nstopped_user=\n" )) for f in self.epp_files: self._write(f, "power\n") self.run_toggle() log = self.log() self.assertIn("systemctl start svc-a.service", log) self.assertNotIn("systemctl start svc-b.service", log) self.assertNotIn("systemctl start svc-c.service", log) def test_disengage_with_no_services_recorded_starts_nothing(self): self._write(self.state_file, ( "mode=on\nwifi=enabled\nepp=balance_performance\n" "brightness=96000\nstopped_system=\nstopped_user=\n" )) for f in self.epp_files: self._write(f, "power\n") self.run_toggle() self.assertNotIn("systemctl start", self.log()) # ----------------------------------------------------------------------------- # Boundary — toggle dispatch # ----------------------------------------------------------------------------- class TestToggleDispatch(AirplaneModeHarness): def test_missing_state_file_engages(self): # No state file → not engaged → first run turns airplane mode ON. self.assertFalse(os.path.exists(self.state_file)) self.run_toggle() self.assertEqual(self.state()["mode"], "on") def test_mode_off_file_engages(self): self._write(self.state_file, "mode=off\n") self.run_toggle() self.assertEqual(self.state()["mode"], "on") if __name__ == "__main__": unittest.main()