diff options
| -rwxr-xr-x | archsetup | 16 | ||||
| -rw-r--r-- | tests/installer-steps/test_configure_service_discovery.py | 85 |
2 files changed, 98 insertions, 3 deletions
@@ -2103,8 +2103,18 @@ configure_service_discovery() { run_task "enabling avahi for mDNS discovery" systemctl enable avahi-daemon.service fi - pacman_install wsdd - run_task "enabling wsdd for Windows network discovery" systemctl enable wsdd.service + # wsdd.service used to be enabled here "for Windows network discovery". + # That is the host daemon: it advertises THIS machine as a Samba host to + # Windows clients, and nothing here runs Samba, so it advertised a + # share server that doesn't exist while listening on every interface + # including the VPN and tailscale links (2026-09-12). Browsing Windows + # shares is the other direction and is gvfs-wsdd's job; it spawns its + # own wsdd in discovery mode (see supplemental_software). A machine set + # up before this change still has the unit enabled, so a re-run turns it + # off; a fresh install has no unit yet and the guard skips quietly. + if systemctl is-enabled --quiet wsdd.service 2>/dev/null; then + run_task "disabling wsdd.service (no Samba host to advertise)" systemctl disable --now wsdd.service + fi pacman_install geoclue # geolocation service for location-aware apps run_task "enabling geoclue geolocation service" systemctl enable geoclue.service @@ -3396,7 +3406,7 @@ supplemental_software() { aur_install nsxiv # image viewer aur_install snore-git # sleep with feedback pacman_install gvfs-smb # SMB network share browsing in Nautilus - pacman_install wsdd # WS-Discovery daemon (Windows network discovery) + pacman_install wsdd # WS-Discovery client, spawned by gvfs-wsdd; wsdd.service stays off (no Samba here) pacman_install gvfs-wsdd # WS-Discovery backend for gvfs (browse Windows shares) aur_install topgrade # upgrade everything utility aur_install ueberzug # allows for displaying images in terminals diff --git a/tests/installer-steps/test_configure_service_discovery.py b/tests/installer-steps/test_configure_service_discovery.py new file mode 100644 index 0000000..90ce041 --- /dev/null +++ b/tests/installer-steps/test_configure_service_discovery.py @@ -0,0 +1,85 @@ +"""Pin configure_service_discovery's source: the WS-Discovery host daemon +is never enabled. + +wsdd.service advertises this machine as a Samba host to Windows clients. +Nothing the installer sets up runs Samba, so enabled it advertised a share +server that doesn't exist while listening on every interface, VPN and +tailscale links included (2026-09-12). Browsing Windows shares is the other +direction: gvfs-wsdd spawns its own wsdd in discovery mode and needs only +the package. + +Method: the step writes straight to /etc (geoclue.conf, the dbus-broker +drop-in) with no directory parameter, so unlike the other step tests this +one can't run the function in a temp dir. It sed-extracts the source and +asserts on the calls it contains. + + python3 -m unittest tests.installer-steps.test_configure_service_discovery +""" + +import os +import re +import unittest + +REPO_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) +ARCHSETUP = os.path.join(REPO_ROOT, "archsetup") + + +def function_source(name): + with open(ARCHSETUP) as f: + text = f.read() + m = re.search(r"^%s\(\) \{\n.*?^\}\n" % re.escape(name), text, re.S | re.M) + assert m, "function %s not found in archsetup" % name + return m.group(0) + + +ENABLE_WSDD = r"(systemctl\s+enable|enable_service)\s+(--now\s+)?wsdd\b" + + +def calls(src): + """Non-comment lines — what the function actually runs.""" + return [l for l in src.splitlines() if l.strip() and not l.strip().startswith("#")] + + +class ConfigureServiceDiscovery(unittest.TestCase): + # ------------------------------------------------------------ normal ---- + def test_does_not_enable_the_wsdd_host_daemon(self): + # Both spellings the script uses: a raw systemctl call and the + # enable_service helper (which takes the bare unit name). + body = "\n".join(calls(function_source("configure_service_discovery"))) + self.assertNotRegex(body, ENABLE_WSDD) + + def test_turns_off_a_previously_enabled_wsdd_on_rerun(self): + # Machines installed before this change still have the unit + # enabled; a re-run converges them. The guard keeps a fresh install + # (no unit yet) quiet. + body = "\n".join(calls(function_source("configure_service_discovery"))) + self.assertRegex(body, r"systemctl\s+is-enabled\s+(--quiet\s+)?wsdd\.service") + self.assertRegex(body, r"systemctl\s+disable\s+--now\s+wsdd\.service") + + def test_still_enables_the_discovery_it_does_want(self): + # Characterization: removing wsdd must not have taken avahi (mDNS) + # or geoclue with it. + body = "\n".join(calls(function_source("configure_service_discovery"))) + self.assertIn("systemctl enable avahi-daemon.service", body) + self.assertIn("systemctl enable geoclue.service", body) + + # ---------------------------------------------------------- boundary ---- + def test_wsdd_package_still_installed_for_gvfs(self): + # The package stays: gvfs-wsdd depends on it and spawns its own + # discovery-mode instance. Only the host service is gone. + body = "\n".join(calls(function_source("supplemental_software"))) + self.assertRegex(body, r"pacman_install\s+wsdd\b") + self.assertRegex(body, r"pacman_install\s+gvfs-wsdd\b") + + # ------------------------------------------------------------- error ---- + def test_no_other_step_enables_wsdd_either(self): + # A regression that re-enables it from a different step is the same + # bug; scan the whole script, not just the one function. + with open(ARCHSETUP) as f: + lines = [l for l in f if l.strip() and not l.strip().startswith("#")] + offenders = [l.rstrip() for l in lines if re.search(ENABLE_WSDD, l)] + self.assertEqual(offenders, []) + + +if __name__ == "__main__": + unittest.main() |
