diff options
Diffstat (limited to 'scripts/testing/tests/test_services.py')
| -rw-r--r-- | scripts/testing/tests/test_services.py | 98 |
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 |
