1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
"""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()
|