aboutsummaryrefslogtreecommitdiff
path: root/scripts/testing/tests/test_services.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/testing/tests/test_services.py')
-rw-r--r--scripts/testing/tests/test_services.py98
1 files changed, 94 insertions, 4 deletions
diff --git a/scripts/testing/tests/test_services.py b/scripts/testing/tests/test_services.py
index dc89e74..0ca3970 100644
--- a/scripts/testing/tests/test_services.py
+++ b/scripts/testing/tests/test_services.py
@@ -1,13 +1,103 @@
# SPDX-License-Identifier: GPL-3.0-or-later
-"""Post-install checks: essential services archsetup enables.
+"""Post-install checks: services, timers, and their functional health.
-Parity port of validate_firewall from validation.sh (more to follow in P2).
+Parity port of validate_firewall, validate_dns_config, validate_avahi,
+validate_fail2ban, validate_networkmanager, and validate_all_services /
+validate_service_functions.
+
+Mapping of the shell sweep's three outcomes:
+ - validation_fail (hard) -> assert
+ - validation_warn (soft) -> pytest.skip with the reason (visible, never red)
+ - validation_skip (precond)-> pytest.skip gated on a fixture
"""
import pytest
+# Required services: (name, must_be_active). ufw can't activate in the VM (no
+# iptables kernel modules), so it's enabled-only; cronie/atd are enabled-only too.
+REQUIRED_ENABLED_ACTIVE = ["sshd", "systemd-resolved", "fail2ban", "NetworkManager", "rngd"]
+REQUIRED_ENABLED_ONLY = ["ufw", "cronie", "atd"]
+REQUIRED_TIMERS = ["reflector.timer", "paccache.timer"]
+OPTIONAL_SERVICES = ["avahi-daemon", "bluetooth", "cups", "docker", "tailscaled"]
+
+
+@pytest.mark.attribution("archsetup")
+@pytest.mark.parametrize("svc", REQUIRED_ENABLED_ACTIVE)
+def test_required_service_enabled_and_active(host, svc):
+ s = host.service(svc)
+ assert s.is_enabled, "%s should be enabled" % svc
+ assert s.is_running, "%s should be active" % svc
+
+
@pytest.mark.smoke
@pytest.mark.attribution("archsetup")
-def test_ufw_firewall_enabled(host):
- assert host.service("ufw").is_enabled
+@pytest.mark.parametrize("svc", REQUIRED_ENABLED_ONLY)
+def test_required_service_enabled(host, svc):
+ assert host.service(svc).is_enabled, "%s should be enabled" % svc
+
+
+@pytest.mark.attribution("archsetup")
+@pytest.mark.parametrize("timer", REQUIRED_TIMERS)
+def test_required_timer_enabled(host, timer):
+ assert host.service(timer).is_enabled, "%s should be enabled" % timer
+
+
+@pytest.mark.parametrize("svc", OPTIONAL_SERVICES)
+def test_optional_service(host, svc):
+ # Optional: warn-if-missing in the shell sweep -> skip here so it never reds.
+ if not host.service(svc).is_enabled:
+ pytest.skip("%s not enabled (optional)" % svc)
+
+
+@pytest.mark.attribution("archsetup")
+def test_dns_over_tls_dropin_present(host):
+ # archsetup ships /etc/systemd/resolved.conf.d/dns-over-tls.conf.
+ assert host.file("/etc/systemd/resolved.conf.d/dns-over-tls.conf").exists
+
+
+@pytest.mark.attribution("archsetup")
+def test_fail2ban_responds(host):
+ assert host.run("fail2ban-client status").rc == 0
+
+
+@pytest.mark.attribution("archsetup")
+def test_networkmanager_responds(host):
+ assert host.run("nmcli general status").rc == 0
+
+
+@pytest.mark.attribution("archsetup")
+def test_log_cleanup_cron_installed(host, target_user):
+ out = host.run("sudo -u %s crontab -l" % target_user).stdout
+ assert "log-cleanup" in out, "log-cleanup entry missing from user crontab"
+
+
+@pytest.mark.attribution("archsetup")
+def test_syncthing_user_lingering_enabled(host, target_user):
+ # syncthing runs as a user service; lingering must be on for autostart.
+ assert host.file("/var/lib/systemd/linger/%s" % target_user).exists
+
+
+def test_dns_resolution(host):
+ # Network-dependent; advisory in the shell sweep. Skip on failure.
+ if host.run("resolvectl query archlinux.org").rc != 0:
+ pytest.skip("DNS resolution query failed (network-dependent)")
+
+
+def test_mdns_resolves(host, on_slirp):
+ # mDNS needs multicast, which QEMU slirp doesn't pass.
+ if on_slirp:
+ pytest.skip("mDNS not possible on slirp networking (no multicast)")
+ if not host.service("avahi-daemon").is_enabled:
+ pytest.skip("avahi-daemon not enabled")
+ hostname = host.run("hostname").stdout.strip()
+ assert host.run("ping -c 1 -W 2 %s.local" % hostname).rc == 0
+
+
+def test_docker_functional(host):
+ if not host.service("docker").is_enabled:
+ pytest.skip("docker not enabled")
+ if not host.service("docker").is_running:
+ # archsetup enables docker for next boot, not --now; pre-reboot this is correct.
+ pytest.skip("docker enabled but not started (starts on boot by design)")
+ assert host.run("docker info").rc == 0