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