ryantimwilson / rpms / systemd

Forked from rpms/systemd a month ago
Clone
8d419f
From 40806a5f552c8d223d1d7ff1878dcf57e4d817c5 Mon Sep 17 00:00:00 2001
8d419f
From: Yu Watanabe <watanabe.yu+github@gmail.com>
8d419f
Date: Wed, 1 Jun 2022 08:56:08 +0900
8d419f
Subject: [PATCH] test: import logind test from debian/ubuntu test suite
8d419f
8d419f
(cherry picked from commit 9c94ab0f6ff22da4278a6e9a93ddc480607c55ac)
8d419f
8d419f
Related: #2087652
8d419f
---
8d419f
 test/TEST-35-LOGIN/Makefile     |   1 +
8d419f
 test/TEST-35-LOGIN/test.sh      |  10 +
8d419f
 test/test-functions             |   8 +
8d419f
 test/units/testsuite-35.service |  10 +
8d419f
 test/units/testsuite-35.sh      | 379 ++++++++++++++++++++++++++++++++
8d419f
 5 files changed, 408 insertions(+)
8d419f
 create mode 120000 test/TEST-35-LOGIN/Makefile
8d419f
 create mode 100755 test/TEST-35-LOGIN/test.sh
8d419f
 create mode 100644 test/units/testsuite-35.service
8d419f
 create mode 100755 test/units/testsuite-35.sh
8d419f
8d419f
diff --git a/test/TEST-35-LOGIN/Makefile b/test/TEST-35-LOGIN/Makefile
8d419f
new file mode 120000
8d419f
index 0000000000..e9f93b1104
8d419f
--- /dev/null
8d419f
+++ b/test/TEST-35-LOGIN/Makefile
8d419f
@@ -0,0 +1 @@
8d419f
+../TEST-01-BASIC/Makefile
8d419f
\ No newline at end of file
8d419f
diff --git a/test/TEST-35-LOGIN/test.sh b/test/TEST-35-LOGIN/test.sh
8d419f
new file mode 100755
8d419f
index 0000000000..9762410fa3
8d419f
--- /dev/null
8d419f
+++ b/test/TEST-35-LOGIN/test.sh
8d419f
@@ -0,0 +1,10 @@
8d419f
+#!/usr/bin/env bash
8d419f
+# SPDX-License-Identifier: LGPL-2.1-or-later
8d419f
+set -e
8d419f
+
8d419f
+TEST_DESCRIPTION="LOGIN"
8d419f
+
8d419f
+# shellcheck source=test/test-functions
8d419f
+. "${TEST_BASE_DIR:?}/test-functions"
8d419f
+
8d419f
+do_test "$@"
8d419f
diff --git a/test/test-functions b/test/test-functions
8d419f
index 98efd047d7..d71e2a3328 100644
8d419f
--- a/test/test-functions
8d419f
+++ b/test/test-functions
8d419f
@@ -165,10 +165,12 @@ BASICTOOLS=(
8d419f
     mv
8d419f
     nc
8d419f
     nproc
8d419f
+    pkill
8d419f
     readlink
8d419f
     rev
8d419f
     rm
8d419f
     rmdir
8d419f
+    rmmod
8d419f
     sed
8d419f
     seq
8d419f
     setfattr
8d419f
@@ -193,6 +195,8 @@ BASICTOOLS=(
8d419f
     umount
8d419f
     uname
8d419f
     unshare
8d419f
+    useradd
8d419f
+    userdel
8d419f
     wc
8d419f
     xargs
8d419f
     xzcat
8d419f
@@ -921,6 +925,8 @@ install_modules() {
8d419f
     instmods vfat
8d419f
     instmods nls_ascii =nls
8d419f
     instmods dummy
8d419f
+    # for TEST-35-LOGIN
8d419f
+    instmods scsi_debug uinput
8d419f
 
8d419f
     if get_bool "$LOOKS_LIKE_SUSE"; then
8d419f
         instmods ext4
8d419f
@@ -1702,6 +1708,8 @@ install_basic_tools() {
8d419f
     image_install -o sushell
8d419f
     # in Debian ldconfig is just a shell script wrapper around ldconfig.real
8d419f
     image_install -o ldconfig.real
8d419f
+    # for TEST-35-LOGIN
8d419f
+    image_install -o evemu-device evemu-event
8d419f
 }
8d419f
 
8d419f
 install_debug_tools() {
8d419f
diff --git a/test/units/testsuite-35.service b/test/units/testsuite-35.service
8d419f
new file mode 100644
8d419f
index 0000000000..556a57a384
8d419f
--- /dev/null
8d419f
+++ b/test/units/testsuite-35.service
8d419f
@@ -0,0 +1,10 @@
8d419f
+# SPDX-License-Identifier: LGPL-2.1-or-later
8d419f
+[Unit]
8d419f
+Description=TEST-35-LOGIN
8d419f
+
8d419f
+[Service]
8d419f
+ExecStartPre=rm -f /failed /testok
8d419f
+ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
8d419f
+StandardOutput=journal+console
8d419f
+StandardError=journal+console
8d419f
+Type=oneshot
8d419f
diff --git a/test/units/testsuite-35.sh b/test/units/testsuite-35.sh
8d419f
new file mode 100755
8d419f
index 0000000000..0a7198c3fe
8d419f
--- /dev/null
8d419f
+++ b/test/units/testsuite-35.sh
8d419f
@@ -0,0 +1,379 @@
8d419f
+#!/usr/bin/env bash
8d419f
+# SPDX-License-Identifier: LGPL-2.1-or-later
8d419f
+set -eux
8d419f
+set -o pipefail
8d419f
+
8d419f
+test_enable_debug() {
8d419f
+    mkdir -p /run/systemd/system/systemd-logind.service.d
8d419f
+    cat >/run/systemd/system/systemd-logind.service.d/debug.conf <
8d419f
+[Service]
8d419f
+Environment=SYSTEMD_LOG_LEVEL=debug
8d419f
+EOF
8d419f
+    systemctl daemon-reload
8d419f
+}
8d419f
+
8d419f
+test_properties() {
8d419f
+    mkdir -p /run/systemd/logind.conf.d
8d419f
+
8d419f
+    cat >/run/systemd/logind.conf.d/kill-user-processes.conf <
8d419f
+[Login]
8d419f
+KillUserProcesses=no
8d419f
+EOF
8d419f
+
8d419f
+    systemctl restart systemd-logind.service
8d419f
+    r=$(busctl get-property org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager KillUserProcesses)
8d419f
+    if [[ "$r" != "b false" ]]; then
8d419f
+        echo "Unexpected KillUserProcesses property '$r', expected='b false'" >&2
8d419f
+        exit 1
8d419f
+    fi
8d419f
+
8d419f
+    cat >/run/systemd/logind.conf.d/kill-user-processes.conf <
8d419f
+[Login]
8d419f
+KillUserProcesses=yes
8d419f
+EOF
8d419f
+
8d419f
+    systemctl restart systemd-logind.service
8d419f
+    r=$(busctl get-property org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager KillUserProcesses)
8d419f
+    if [[ "$r" != "b true" ]]; then
8d419f
+        echo "Unexpected KillUserProcesses property '$r', expected='b true'" >&2
8d419f
+        exit 1
8d419f
+    fi
8d419f
+
8d419f
+    rm -rf /run/systemd/logind.conf.d
8d419f
+}
8d419f
+
8d419f
+test_started() {
8d419f
+    systemctl restart systemd-logind.service
8d419f
+
8d419f
+    # should start at boot, not with D-BUS activation
8d419f
+    LOGINDPID=$(systemctl show systemd-logind.service -p ExecMainPID --value)
8d419f
+
8d419f
+    # loginctl should succeed
8d419f
+    loginctl --no-pager
8d419f
+}
8d419f
+
8d419f
+# args: <timeout>
8d419f
+wait_suspend() {
8d419f
+    timeout="$1"
8d419f
+    while [[ $timeout -gt 0 && ! -e /run/suspend.flag ]]; do
8d419f
+        sleep 1
8d419f
+        timeout=$((timeout - 1))
8d419f
+    done
8d419f
+    if [[ ! -e /run/suspend.flag ]]; then
8d419f
+        echo "closing lid did not cause suspend" >&2
8d419f
+        exit 1
8d419f
+    fi
8d419f
+    rm /run/suspend.flag
8d419f
+}
8d419f
+
8d419f
+test_suspend_tear_down() {
8d419f
+    set +e
8d419f
+
8d419f
+    kill "$KILL_PID"
8d419f
+}
8d419f
+
8d419f
+test_suspend_on_lid() {
8d419f
+    if systemd-detect-virt --quiet --container; then
8d419f
+        echo "Skipping suspend test in container"
8d419f
+        return
8d419f
+    fi
8d419f
+    if ! grep -s -q mem /sys/power/state; then
8d419f
+        echo "suspend not supported on this testbed, skipping"
8d419f
+        return
8d419f
+    fi
8d419f
+    if ! command -v evemu-device &>/dev/null; then
8d419f
+        echo "command evemu-device not found, skipping"
8d419f
+        return
8d419f
+    fi
8d419f
+    if ! command -v evemu-event &>/dev/null; then
8d419f
+        echo "command evemu-event not found, skipping"
8d419f
+        return
8d419f
+    fi
8d419f
+
8d419f
+    KILL_PID=
8d419f
+    trap test_suspend_tear_down EXIT
8d419f
+
8d419f
+    # create fake suspend
8d419f
+    mkdir -p /run/systemd/system/systemd-suspend.service.d
8d419f
+    cat >/run/systemd/system/systemd-suspend.service.d/override.conf <
8d419f
+[Service]
8d419f
+ExecStart=
8d419f
+ExecStart=touch /run/suspend.flag
8d419f
+EOF
8d419f
+    systemctl daemon-reload
8d419f
+
8d419f
+    # create fake lid switch
8d419f
+    mkdir -p /run/udev/rules.d
8d419f
+    cat >/run/udev/rules.d/70-logindtest-lid.rules <
8d419f
+SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="Fake Lid Switch", TAG+="power-switch"
8d419f
+EOF
8d419f
+    udevadm control --reload
8d419f
+
8d419f
+    cat >/run/lidswitch.evemu <
8d419f
+# EVEMU 1.2
8d419f
+# Input device name: "Lid Switch"
8d419f
+# Input device ID: bus 0x19 vendor 0000 product 0x05 version 0000
8d419f
+# Supported events:
8d419f
+#   Event type 0 (EV_SYN)
8d419f
+#     Event code 0 (SYN_REPORT)
8d419f
+#     Event code 5 (FF_STATUS_MAX)
8d419f
+#   Event type 5 (EV_SW)
8d419f
+#     Event code 0 (SW_LID)
8d419f
+# Properties:
8d419f
+N: Fake Lid Switch
8d419f
+I: 0019 0000 0005 0000
8d419f
+P: 00 00 00 00 00 00 00 00
8d419f
+B: 00 21 00 00 00 00 00 00 00
8d419f
+B: 01 00 00 00 00 00 00 00 00
8d419f
+B: 01 00 00 00 00 00 00 00 00
8d419f
+B: 01 00 00 00 00 00 00 00 00
8d419f
+B: 01 00 00 00 00 00 00 00 00
8d419f
+B: 01 00 00 00 00 00 00 00 00
8d419f
+B: 01 00 00 00 00 00 00 00 00
8d419f
+B: 01 00 00 00 00 00 00 00 00
8d419f
+B: 01 00 00 00 00 00 00 00 00
8d419f
+B: 01 00 00 00 00 00 00 00 00
8d419f
+B: 01 00 00 00 00 00 00 00 00
8d419f
+B: 01 00 00 00 00 00 00 00 00
8d419f
+B: 01 00 00 00 00 00 00 00 00
8d419f
+B: 02 00 00 00 00 00 00 00 00
8d419f
+B: 03 00 00 00 00 00 00 00 00
8d419f
+B: 04 00 00 00 00 00 00 00 00
8d419f
+B: 05 01 00 00 00 00 00 00 00
8d419f
+B: 11 00 00 00 00 00 00 00 00
8d419f
+B: 12 00 00 00 00 00 00 00 00
8d419f
+B: 15 00 00 00 00 00 00 00 00
8d419f
+B: 15 00 00 00 00 00 00 00 00
8d419f
+EOF
8d419f
+
8d419f
+    evemu-device /run/lidswitch.evemu &
8d419f
+    KILL_PID="$!"
8d419f
+
8d419f
+    for ((i=0;i<20;i++)); do
8d419f
+        if (( i != 0 )); then sleep .5; fi
8d419f
+
8d419f
+        INPUT_NAME=$(grep -l '^Fake Lid Switch' /sys/class/input/*/device/name || :)
8d419f
+        if [[ -n "$INPUT_NAME" ]]; then break; fi
8d419f
+    done
8d419f
+    if [[ -z "$INPUT_NAME" ]]; then
8d419f
+        echo "cannot find fake lid switch." >&2
8d419f
+        exit 1
8d419f
+    fi
8d419f
+    INPUT_NAME=${INPUT_NAME%/device/name}
8d419f
+    LID_DEV=/dev/${INPUT_NAME#/sys/class/}
8d419f
+    udevadm info --wait-for-initialization=10s "$LID_DEV"
8d419f
+    udevadm settle
8d419f
+
8d419f
+    # close lid
8d419f
+    evemu-event "$LID_DEV" --sync --type 5 --code 0 --value 1
8d419f
+    # need to wait for 30s suspend inhibition after boot
8d419f
+    wait_suspend 31
8d419f
+    # open lid again
8d419f
+    evemu-event "$LID_DEV" --sync --type 5 --code 0 --value 0
8d419f
+
8d419f
+    # waiting for 30s inhibition time between suspends
8d419f
+    sleep 30
8d419f
+
8d419f
+    # now closing lid should cause instant suspend
8d419f
+    evemu-event "$LID_DEV" --sync --type 5 --code 0 --value 1
8d419f
+    wait_suspend 2
8d419f
+    evemu-event "$LID_DEV" --sync --type 5 --code 0 --value 0
8d419f
+
8d419f
+    P=$(systemctl show systemd-logind.service -p ExecMainPID --value)
8d419f
+    if [[ "$P" != "$LOGINDPID" ]]; then
8d419f
+        echo "logind crashed" >&2
8d419f
+        exit 1
8d419f
+    fi
8d419f
+
8d419f
+    test_suspend_tear_down
8d419f
+    trap - EXIT
8d419f
+}
8d419f
+
8d419f
+test_shutdown() {
8d419f
+    # scheduled shutdown with wall message
8d419f
+    shutdown 2>&1
8d419f
+    sleep 5
8d419f
+    shutdown -c || :
8d419f
+    # logind should still be running
8d419f
+    P=$(systemctl show systemd-logind.service -p ExecMainPID --value)
8d419f
+    if [[ "$P" != "$LOGINDPID" ]]; then
8d419f
+        echo "logind crashed" >&2
8d419f
+        exit 1
8d419f
+    fi
8d419f
+
8d419f
+    # scheduled shutdown without wall message
8d419f
+    shutdown --no-wall 2>&1
8d419f
+    sleep 5
8d419f
+    shutdown -c --no-wall || true
8d419f
+    P=$(systemctl show systemd-logind.service -p ExecMainPID --value)
8d419f
+    if [[ "$P" != "$LOGINDPID" ]]; then
8d419f
+        echo "logind crashed" >&2
8d419f
+        exit 1
8d419f
+    fi
8d419f
+}
8d419f
+
8d419f
+test_session_tear_down() {
8d419f
+    set +e
8d419f
+
8d419f
+    rm -f /run/udev/rules.d/70-logindtest-scsi_debug-user.rules
8d419f
+    udevadm control --reload
8d419f
+
8d419f
+    systemctl stop getty@tty2.service
8d419f
+    rm -rf /run/systemd/system/getty@tty2.service.d
8d419f
+    systemctl daemon-reload
8d419f
+
8d419f
+    pkill -u logind-test-user
8d419f
+    userdel logind-test-user
8d419f
+
8d419f
+    rmmod scsi_debug
8d419f
+}
8d419f
+
8d419f
+check_session() {
8d419f
+    loginctl
8d419f
+    if [[ $(loginctl --no-legend | grep -c "logind-test-user") != 1 ]]; then
8d419f
+        echo "no session or multile sessions for logind-test-user." >&2
8d419f
+        return 1
8d419f
+    fi
8d419f
+
8d419f
+    SEAT=$(loginctl --no-legend | grep 'logind-test-user *seat' | awk '{ print $4 }')
8d419f
+    if [[ -z "$SEAT" ]]; then
8d419f
+        echo "no seat found for user logind-test-user" >&2
8d419f
+        return 1
8d419f
+    fi
8d419f
+
8d419f
+    SESSION=$(loginctl --no-legend | grep "logind-test-user" | awk '{ print $1 }')
8d419f
+    if [[ -z "$SESSION" ]]; then
8d419f
+        echo "no session found for user logind-test-user" >&2
8d419f
+        return 1
8d419f
+    fi
8d419f
+
8d419f
+    loginctl session-status "$SESSION"
8d419f
+    loginctl session-status "$SESSION" | grep -q "Unit: session-${SESSION}\.scope"
8d419f
+    LEADER_PID=$(loginctl session-status "$SESSION" | grep "Leader:" | awk '{ print $2 }')
8d419f
+    if [[ -z "$LEADER_PID" ]]; then
8d419f
+        echo "cannot found leader process for session $SESSION" >&2
8d419f
+        return 1
8d419f
+    fi
8d419f
+
8d419f
+    # cgroup v1: "1:name=systemd:/user.slice/..."; unified hierarchy: "0::/user.slice"
8d419f
+    if ! grep -q -E '(name=systemd|^0:):.*session.*scope' /proc/"$LEADER_PID"/cgroup; then
8d419f
+        echo "FAIL: process $LEADER_PID is not in the session cgroup" >&2
8d419f
+        cat /proc/self/cgroup
8d419f
+        return 1
8d419f
+    fi
8d419f
+}
8d419f
+
8d419f
+test_session() {
8d419f
+    if systemd-detect-virt --quiet --container; then
8d419f
+        echo " * Skipping ACL tests in container"
8d419f
+        return
8d419f
+    fi
8d419f
+
8d419f
+    trap test_session_tear_down EXIT
8d419f
+
8d419f
+    # add user
8d419f
+    useradd -s /bin/bash logind-test-user
8d419f
+
8d419f
+    # login with the test user to start a session
8d419f
+    mkdir -p /run/systemd/system/getty@tty2.service.d
8d419f
+    cat >/run/systemd/system/getty@tty2.service.d/override.conf <
8d419f
+[Service]
8d419f
+Type=simple
8d419f
+ExecStart=
8d419f
+ExecStart=-/sbin/agetty --autologin logind-test-user --noclear %I $TERM
8d419f
+EOF
8d419f
+    systemctl daemon-reload
8d419f
+    systemctl start getty@tty2.service
8d419f
+
8d419f
+    # check session
8d419f
+    ret=1
8d419f
+    for ((i=0;i<30;i++)); do
8d419f
+        if (( i != 0)); then sleep 1; fi
8d419f
+        if check_session; then
8d419f
+            ret=0
8d419f
+            break
8d419f
+        fi
8d419f
+    done
8d419f
+    if [[ "$ret" == "1" ]]; then
8d419f
+        exit 1
8d419f
+    fi
8d419f
+
8d419f
+    # scsi_debug should not be loaded yet
8d419f
+    if [[ -d /sys/bus/pseudo/drivers/scsi_debug ]]; then
8d419f
+        echo "scsi_debug module is already loaded." >&2
8d419f
+        exit 1
8d419f
+    fi
8d419f
+
8d419f
+    # we use scsi_debug to create new devices which we can put ACLs on
8d419f
+    # tell udev about the tagging, so that logind can pick it up
8d419f
+    mkdir -p /run/udev/rules.d
8d419f
+    cat >/run/udev/rules.d/70-logindtest-scsi_debug-user.rules <
8d419f
+SUBSYSTEM=="block", ATTRS{model}=="scsi_debug*", TAG+="uaccess"
8d419f
+EOF
8d419f
+    udevadm control --reload
8d419f
+
8d419f
+    # coldplug: logind started with existing device
8d419f
+    systemctl stop systemd-logind.service
8d419f
+    modprobe scsi_debug
8d419f
+    for ((i=0;i<30;i++)); do
8d419f
+        if (( i != 0)); then sleep 1; fi
8d419f
+        if dev=/dev/$(ls /sys/bus/pseudo/drivers/scsi_debug/adapter*/host*/target*/*:*/block 2>/dev/null); then
8d419f
+            break
8d419f
+        fi
8d419f
+    done
8d419f
+    if [[ ! -b "$dev" ]]; then
8d419f
+        echo "cannot find suitable scsi block device" >&2
8d419f
+        exit 1
8d419f
+    fi
8d419f
+    udevadm settle
8d419f
+    udevadm info "$dev"
8d419f
+
8d419f
+    # trigger logind and activate session
8d419f
+    loginctl activate "$SESSION"
8d419f
+
8d419f
+    # check ACL
8d419f
+    sleep 1
8d419f
+    if ! getfacl -p "$dev" | grep -q "user:logind-test-user:rw-"; then
8d419f
+        echo "$dev has no ACL for user logind-test-user" >&2
8d419f
+        getfacl -p "$dev" >&2
8d419f
+        exit 1
8d419f
+    fi
8d419f
+
8d419f
+    # hotplug: new device appears while logind is running
8d419f
+    rmmod scsi_debug
8d419f
+    modprobe scsi_debug
8d419f
+    for ((i=0;i<30;i++)); do
8d419f
+        if (( i != 0)); then sleep 1; fi
8d419f
+        if dev=/dev/$(ls /sys/bus/pseudo/drivers/scsi_debug/adapter*/host*/target*/*:*/block 2>/dev/null); then
8d419f
+            break
8d419f
+        fi
8d419f
+    done
8d419f
+    if [[ ! -b "$dev" ]]; then
8d419f
+        echo "cannot find suitable scsi block device" >&2
8d419f
+        exit 1
8d419f
+    fi
8d419f
+    udevadm settle
8d419f
+
8d419f
+    # check ACL
8d419f
+    sleep 1
8d419f
+    if ! getfacl -p "$dev" | grep -q "user:logind-test-user:rw-"; then
8d419f
+        echo "$dev has no ACL for user logind-test-user" >&2
8d419f
+        getfacl -p "$dev" >&2
8d419f
+        exit 1
8d419f
+    fi
8d419f
+
8d419f
+    test_session_tear_down
8d419f
+    trap - EXIT
8d419f
+}
8d419f
+
8d419f
+: >/failed
8d419f
+
8d419f
+test_enable_debug
8d419f
+test_properties
8d419f
+test_started
8d419f
+test_suspend_on_lid
8d419f
+test_shutdown
8d419f
+test_session
8d419f
+
8d419f
+touch /testok
8d419f
+rm /failed