From 8c64c6ad902bf805719d71fb463ba42efb040a05 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 28 Sep 2026 18:01:15 +0200 Subject: [PATCH] test: cover logind metrics --- .../lib/systemd/system-preset/00-mkosi.preset | 1 + test/units/TEST-35-LOGIN.sh | 104 ++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/mkosi/mkosi.extra.common/usr/lib/systemd/system-preset/00-mkosi.preset b/mkosi/mkosi.extra.common/usr/lib/systemd/system-preset/00-mkosi.preset index 09198f75cb2..f97b0f79c56 100644 --- a/mkosi/mkosi.extra.common/usr/lib/systemd/system-preset/00-mkosi.preset +++ b/mkosi/mkosi.extra.common/usr/lib/systemd/system-preset/00-mkosi.preset @@ -32,6 +32,7 @@ enable systemd-userdbd.socket # The metrics sockets are disabled by default on OpenSUSE, and can't be started at runtime while the services # they belong to are already running. enable systemd-journald-metrics.socket +enable systemd-logind-metrics.socket # We install dnf in some images but it's only going to be used rarely, # so let's not have dnf create its cache. diff --git a/test/units/TEST-35-LOGIN.sh b/test/units/TEST-35-LOGIN.sh index f3974ed7b7a..bcb84ef8fa6 100755 --- a/test/units/TEST-35-LOGIN.sh +++ b/test/units/TEST-35-LOGIN.sh @@ -1012,6 +1012,110 @@ EOF echo "$no_sess_rel" | grep NoSuchSession >/dev/null } +teardown_metrics() ( + set +ex + + systemctl stop metrics-sleeper-background-light.service metrics-sleeper-user.service + rm -f /etc/pam.d/"$PAMSERVICE" + return 0 +) + +login_metric() { + # Prints the value of the specified io.systemd.Login metric with the specified field value + varlinkctl --more call /run/systemd/report/io.systemd.Login io.systemd.Metrics.List '{}' | + jq --seq -r --arg n "io.systemd.Login.$1" --arg k "$2" --arg v "$3" \ + 'select(.name == $n and .fields[$k] == $v) | .value | tostring' +} + +wait_session_gone() { + # Waits until no session of the specified class of the test user is known to logind anymore + timeout 30 bash -c "while loginctl --no-legend | grep logind-test-user | grep -w -- '$1' >/dev/null; do sleep .5; done" +} + +testcase_metrics() { + local uid list c before_started before_current started current + + uid=$(id -u logind-test-user) + + PAMSERVICE="pammetrics$RANDOM" + trap teardown_metrics RETURN + + cat >/etc/pam.d/"$PAMSERVICE" </dev/null + jq --seq -r '.name' <<<"$list" | grep '^io.systemd.Login.SessionsStarted$' >/dev/null + jq --seq -r '.name' <<<"$list" | grep '^io.systemd.Login.SuspendCounter$' >/dev/null + + # One row per session class, except for "none" + list="$(varlinkctl --more call /run/systemd/report/io.systemd.Login io.systemd.Metrics.List '{}')" + for c in user user-early user-incomplete user-light user-early-light greeter lock-screen background background-light manager manager-early; do + [[ "$(jq --seq -r --arg c "$c" 'select(.name == "io.systemd.Login.SessionsStarted" and .fields.class == $c) | .name' <<<"$list" | wc -l)" -eq 1 ]] + [[ "$(jq --seq -r --arg c "$c" 'select(.name == "io.systemd.Login.CurrentSessions" and .fields.class == $c) | .name' <<<"$list" | wc -l)" -eq 1 ]] + done + [[ -z "$(jq --seq -r 'select(.fields.class == "none") | .name' <<<"$list")" ]] + + # Start a session without service manager + wait_session_gone background-light + before_started="$(login_metric SessionsStarted class background-light)" + before_current="$(login_metric CurrentSessions class background-light)" + systemd-run -u metrics-sleeper-background-light.service -p PAMName="$PAMSERVICE" -p Type=exec \ + -p Environment=XDG_SESSION_CLASS=background-light -p User=logind-test-user sleep infinity + started="$(login_metric SessionsStarted class background-light)" + current="$(login_metric CurrentSessions class background-light)" + (( started == before_started + 1 )) + (( current == before_current + 1 )) + + # A restart of logind neither resets nor increases the counter, and the session is still current. Reset + # the start rate limit afterwards, so that later test cases which restart logind don't trip over it. + systemctl restart systemd-logind.service + systemctl reset-failed systemd-logind.service + (( $(login_metric SessionsStarted class background-light) == started )) + (( $(login_metric CurrentSessions class background-light) == current )) + + # Logging out decreases the number of current sessions, but not the counter + systemctl stop metrics-sleeper-background-light.service + wait_session_gone background-light + (( $(login_metric SessionsStarted class background-light) == started )) + (( $(login_metric CurrentSessions class background-light) == before_current )) + + # A full user session also starts the service manager, which gets its own session + systemctl stop user@"$uid".service + wait_session_gone manager + before_started="$(login_metric SessionsStarted class manager)" + systemd-run -u metrics-sleeper-user.service -p PAMName="$PAMSERVICE" -p Type=exec \ + -p Environment=XDG_SESSION_CLASS=user -p User=logind-test-user sleep infinity + (( $(login_metric SessionsStarted class manager) == before_started + 1 )) + (( $(login_metric CurrentSessions class manager) >= 1 )) + systemctl stop metrics-sleeper-user.service + + # The suspend counters are taken from the kernel as they are, but are suppressed in containers + if [[ -e /sys/power/suspend_stats/success ]] && ! systemd-detect-virt --quiet --container; then + (( $(login_metric SuspendCounter result success) == $(cat /sys/power/suspend_stats/success) )) + (( $(login_metric SuspendCounter result fail) == $(cat /sys/power/suspend_stats/fail) )) + else + [[ -z "$(varlinkctl --more call /run/systemd/report/io.systemd.Login io.systemd.Metrics.List '{}' | jq --seq -r 'select(.name == "io.systemd.Login.SuspendCounter") | .name')" ]] + fi +} + testcase_restart() { local classes unit c