"""Test configure_tlp_power's radio-enable line and laptop gating. systemd-rfkill is masked on laptops because it fights TLP's radio handling — which means nothing restores radio state at boot unless TLP is told to. The velox 2026-04-10 setup found wifi and bluetooth soft-blocked on first boot for exactly this reason. The conf written here must carry DEVICES_TO_ENABLE_ON_STARTUP so a fresh install comes up with radios on. Method: sed-extract configure_tlp_power from the real `archsetup`, point it at a temp tlp.d dir and a temp power-supply dir, and fake pacman_install / run_task / display / error_warn / systemctl. Run from repo root: python3 -m unittest tests.installer-steps.test_configure_tlp_power """ import os import stat import subprocess import tempfile import textwrap import unittest REPO_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) ARCHSETUP = os.path.join(REPO_ROOT, "archsetup") def run(battery=True, bat_name="BAT0", unwritable_tlpd=False): with tempfile.TemporaryDirectory() as d: psdir = os.path.join(d, "power_supply") os.makedirs(psdir) if battery: open(os.path.join(psdir, bat_name), "w").close() tlpd = os.path.join(d, "tlp.d") if unwritable_tlpd: os.makedirs(tlpd) os.chmod(tlpd, stat.S_IRUSR | stat.S_IXUSR) # The real mask call redirects stdout into $logfile, so the fake # systemctl records to a side file the test reads back instead. script = textwrap.dedent(f"""\ logfile=/dev/null action="" display() {{ :; }} pacman_install() {{ echo "INSTALL: $1"; }} run_task() {{ echo "TASK: $1"; }} systemctl() {{ echo "SYSTEMCTL: $*" >> "{d}/systemctl.log"; }} error_warn() {{ echo "WARN: $1"; return 1; }} source <(sed -n '/^configure_tlp_power() {{/,/^}}/p' "{ARCHSETUP}") configure_tlp_power "{tlpd}" "{psdir}" echo "RC=$?" echo "CONF:[$(cat "{tlpd}/01-custom.conf" 2>/dev/null)]" [ -f "{d}/systemctl.log" ] && cat "{d}/systemctl.log" exit 0 """) r = subprocess.run( ["bash", "-c", script], capture_output=True, text=True, timeout=10, ) if unwritable_tlpd: os.chmod(tlpd, stat.S_IRWXU) return r class ConfigureTlpPower(unittest.TestCase): # ------------------------------------------------------------ normal ---- def test_laptop_gets_tlp_with_radio_enable_line(self): r = run(battery=True) self.assertIn("INSTALL: tlp", r.stdout) conf = r.stdout.split("CONF:[")[1] self.assertIn('DEVICES_TO_ENABLE_ON_STARTUP="bluetooth wifi"', conf, "radios must be re-enabled at boot: systemd-rfkill is " "masked, so TLP is the only thing that can do it") self.assertIn("CPU_ENERGY_PERF_POLICY_ON_AC", conf) self.assertIn("SYSTEMCTL: mask systemd-rfkill.service systemd-rfkill.socket", r.stdout) self.assertIn("TASK: enabling TLP service", r.stdout) def test_radio_line_is_active_not_commented(self): r = run(battery=True) conf = r.stdout.split("CONF:[")[1].split("]")[0] for line in conf.splitlines(): if "DEVICES_TO_ENABLE_ON_STARTUP" in line: self.assertFalse(line.lstrip().startswith("#"), "the radio-enable line must not be commented out") break else: self.fail("DEVICES_TO_ENABLE_ON_STARTUP line missing from conf") # ---------------------------------------------------------- boundary ---- def test_desktop_without_battery_is_a_no_op(self): r = run(battery=False) self.assertNotIn("INSTALL:", r.stdout) self.assertNotIn("SYSTEMCTL:", r.stdout) self.assertIn("CONF:[]", r.stdout, "no conf may be written on a desktop") def test_second_battery_index_still_counts_as_laptop(self): r = run(battery=True, bat_name="BAT1") self.assertIn("INSTALL: tlp", r.stdout) self.assertIn('DEVICES_TO_ENABLE_ON_STARTUP', r.stdout) # ------------------------------------------------------------- error ---- @unittest.skipUnless(os.geteuid() != 0, "root ignores directory write bits") def test_unwritable_tlpd_warns_and_does_not_crash(self): r = run(battery=True, unwritable_tlpd=True) self.assertIn("WARN:", r.stdout, "a failed conf write must surface through error_warn") self.assertEqual(r.returncode, 0) if __name__ == "__main__": unittest.main()