diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2022-07-07 10:10:05 +0900 |
---|---|---|
committer | Frantisek Sumsal <frantisek@sumsal.cz> | 2022-07-07 13:15:00 +0000 |
commit | 63663a0f0f0e1dcd6036cecf013de3f1de87cd99 (patch) | |
tree | d666634ee4f996afcf8e5f2bf08ceadb2b645d57 /test/units/testsuite-35.sh | |
parent | 1f7eed4c3504ea6e852d64057c1e6b8df2091eeb (diff) | |
download | systemd-63663a0f0f0e1dcd6036cecf013de3f1de87cd99.tar.gz |
test: several cleanups for TEST-35-LOGIN
- use test_append_files() to install additional commands
- drop use of expect
- include assert.sh and use assertions at several places
- use timeout command at several places
- always use logind-test-user
- etc
Diffstat (limited to 'test/units/testsuite-35.sh')
-rwxr-xr-x | test/units/testsuite-35.sh | 408 |
1 files changed, 188 insertions, 220 deletions
diff --git a/test/units/testsuite-35.sh b/test/units/testsuite-35.sh index 98283cad25..147604e293 100755 --- a/test/units/testsuite-35.sh +++ b/test/units/testsuite-35.sh @@ -3,6 +3,24 @@ set -eux set -o pipefail +# shellcheck source=test/units/assert.sh +. "$(dirname "$0")"/assert.sh + +cleanup_test_user() ( + set +ex + + pkill -u "$(id -u logind-test-user)" + sleep 1 + pkill -KILL -u "$(id -u logind-test-user)" + userdel -r logind-test-user +) + +setup_test_user() { + mkdir -p /var/spool/cron /var/spool/mail + useradd -m -s /bin/bash logind-test-user + trap cleanup_test_user EXIT +} + test_enable_debug() { mkdir -p /run/systemd/system/systemd-logind.service.d cat >/run/systemd/system/systemd-logind.service.d/debug.conf <<EOF @@ -10,6 +28,7 @@ test_enable_debug() { Environment=SYSTEMD_LOG_LEVEL=debug EOF systemctl daemon-reload + systemctl stop systemd-logind.service } test_properties() { @@ -21,11 +40,7 @@ KillUserProcesses=no EOF systemctl restart systemd-logind.service - r=$(busctl get-property org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager KillUserProcesses) - if [[ "$r" != "b false" ]]; then - echo "Unexpected KillUserProcesses property '$r', expected='b false'" >&2 - exit 1 - fi + assert_eq "$(busctl get-property org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager KillUserProcesses)" "b false" cat >/run/systemd/logind.conf.d/kill-user-processes.conf <<EOF [Login] @@ -33,46 +48,46 @@ KillUserProcesses=yes EOF systemctl restart systemd-logind.service - r=$(busctl get-property org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager KillUserProcesses) - if [[ "$r" != "b true" ]]; then - echo "Unexpected KillUserProcesses property '$r', expected='b true'" >&2 - exit 1 - fi + assert_eq "$(busctl get-property org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager KillUserProcesses)" "b true" rm -rf /run/systemd/logind.conf.d } test_started() { + local pid + systemctl restart systemd-logind.service # should start at boot, not with D-BUS activation - LOGINDPID=$(systemctl show systemd-logind.service -p ExecMainPID --value) + pid=$(systemctl show systemd-logind.service -p ExecMainPID --value) # loginctl should succeed - loginctl --no-pager + loginctl + + # logind should still be running + assert_eq "$(systemctl show systemd-logind.service -p ExecMainPID --value)" "$pid" } -# args: <timeout> 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 + timeout "${1?}" bash -c "while [[ ! -e /run/suspend.flag ]]; do sleep 1; done" rm /run/suspend.flag } -test_suspend_tear_down() { - set +e +teardown_suspend() ( + set +eux - kill "$KILL_PID" -} + pkill evemu-device + + rm -rf /run/systemd/system/systemd-suspend.service.d + systemctl daemon-reload + + rm -f /run/udev/rules.d/70-logindtest-lid.rules + udevadm control --reload +) test_suspend_on_lid() { + local pid input_name lid_dev + if systemd-detect-virt --quiet --container; then echo "Skipping suspend test in container" return @@ -90,8 +105,10 @@ test_suspend_on_lid() { return fi - KILL_PID= - trap test_suspend_tear_down RETURN + trap teardown_suspend RETURN + + # save pid + pid=$(systemctl show systemd-logind.service -p ExecMainPID --value) # create fake suspend mkdir -p /run/systemd/system/systemd-suspend.service.d @@ -147,129 +164,127 @@ B: 15 00 00 00 00 00 00 00 00 EOF evemu-device /run/lidswitch.evemu & - KILL_PID="$!" - - for ((i = 0; i < 20; i++)); do - if (( i != 0 )); then sleep .5; fi - INPUT_NAME=$(grep -l '^Fake Lid Switch' /sys/class/input/*/device/name || :) - if [[ -n "$INPUT_NAME" ]]; then break; fi - done - if [[ -z "$INPUT_NAME" ]]; then + timeout 20 bash -c 'while ! grep "^Fake Lid Switch" /sys/class/input/*/device/name; do sleep .5; done' + input_name=$(grep -l '^Fake Lid Switch' /sys/class/input/*/device/name || :) + if [[ -z "$input_name" ]]; then echo "cannot find fake lid switch." >&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" + 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 + 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 + 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 + 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 + 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 + assert_eq "$(systemctl show systemd-logind.service -p ExecMainPID --value)" "$pid" } test_shutdown() { + local pid + + # save pid + pid=$(systemctl show systemd-logind.service -p ExecMainPID --value) + # 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 + assert_eq "$(systemctl show systemd-logind.service -p ExecMainPID --value)" "$pid" # 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 + assert_eq "$(systemctl show systemd-logind.service -p ExecMainPID --value)" "$pid" } -test_session_tear_down() { - set +e - - rm -f /run/udev/rules.d/70-logindtest-scsi_debug-user.rules - udevadm control --reload +teardown_session() ( + set +ex 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 + pkill -u "$(id -u logind-test-user)" + sleep 1 + pkill -KILL -u "$(id -u logind-test-user)" + rm -f /run/udev/rules.d/70-logindtest-scsi_debug-user.rules + udevadm control --reload rmmod scsi_debug -} +) + +check_session() ( + set +ex + + local seat session leader_pid -check_session() { - loginctl if [[ $(loginctl --no-legend | grep -c "logind-test-user") != 1 ]]; then echo "no session or multiple 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 + 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 + 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 + if ! loginctl session-status "$session" | grep -q "Unit: session-${session}\.scope"; then + echo "cannot find scope unit for session $session" >&2 + return 1 + fi + + 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 + 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() { + local dev + if systemd-detect-virt --quiet --container; then - echo " * Skipping ACL tests in container" + echo "Skipping ACL tests in container" return fi - trap test_session_tear_down RETURN + if [[ ! -c /dev/tty2 ]]; then + echo "/dev/tty2 does not exist, skipping test ${FUNCNAME[0]}." + return + fi - # add user - useradd -s /bin/bash logind-test-user + trap teardown_session RETURN # login with the test user to start a session mkdir -p /run/systemd/system/getty@tty2.service.d @@ -280,20 +295,14 @@ ExecStart= ExecStart=-/sbin/agetty --autologin logind-test-user --noclear %I $TERM EOF systemctl daemon-reload - systemctl start getty@tty2.service + systemctl restart getty@tty2.service # check session - ret=1 for ((i = 0; i < 30; i++)); do - if (( i != 0)); then sleep 1; fi - if check_session; then - ret=0 - break - fi + (( i != 0 )) && sleep 1 + check_session && break done - if [[ "$ret" == "1" ]]; then - exit 1 - fi + check_session # scsi_debug should not be loaded yet if [[ -d /sys/bus/pseudo/drivers/scsi_debug ]]; then @@ -312,12 +321,8 @@ EOF # coldplug: logind started with existing device systemctl stop systemd-logind.service 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 + timeout 30 bash -c 'while ! ls /sys/bus/pseudo/drivers/scsi_debug/adapter*/host*/target*/*:*/block 2>/dev/null; do sleep 1; done' + dev=/dev/$(ls /sys/bus/pseudo/drivers/scsi_debug/adapter*/host*/target*/*:*/block 2>/dev/null) if [[ ! -b "$dev" ]]; then echo "cannot find suitable scsi block device" >&2 exit 1 @@ -326,25 +331,17 @@ EOF udevadm info "$dev" # trigger logind and activate session - loginctl activate "$SESSION" + loginctl activate "$(loginctl --no-legend | grep "logind-test-user" | awk '{ print $1 }')" # 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 + assert_in "user:logind-test-user:rw-" "$(getfacl -p "$dev")" # 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 + timeout 30 bash -c 'while ! ls /sys/bus/pseudo/drivers/scsi_debug/adapter*/host*/target*/*:*/block 2>/dev/null; do sleep 1; done' + dev=/dev/$(ls /sys/bus/pseudo/drivers/scsi_debug/adapter*/host*/target*/*:*/block 2>/dev/null) if [[ ! -b "$dev" ]]; then echo "cannot find suitable scsi block device" >&2 exit 1 @@ -353,161 +350,132 @@ EOF # 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 + assert_in "user:logind-test-user:rw-" "$(getfacl -p "$dev")" } -setup_idle_action_lock() { - useradd testuser ||: +teardown_lock_idle_action() ( + set +eux - mkdir -p /run/systemd/logind.conf.d/ - cat >/run/systemd/logind.conf.d/idle-action-lock.conf <<EOF -[Login] -IdleAction=lock -IdleActionSec=1s -EOF - systemctl restart systemd-logind.service - systemctl service-log-level systemd-logind.service debug -} + systemctl stop getty@tty2.service + rm -rf /run/systemd/system/getty@tty2.service.d + systemctl daemon-reload + + pkill -u "$(id -u logind-test-user)" + sleep 1 + pkill -KILL -u "$(id -u logind-test-user)" -teardown_idle_action_lock() {( - set +ex rm -f /run/systemd/logind.conf.d/idle-action-lock.conf - pkill -9 -u "$(id -u testuser)" - userdel -r testuser systemctl restart systemd-logind.service -)} +) test_lock_idle_action() { - if ! command -v expect >/dev/null ; then - echo >&2 "expect not installed, skipping test ${FUNCNAME[0]}" - return 0 + local ts + + if [[ ! -c /dev/tty2 ]]; then + echo "/dev/tty2 does not exist, skipping test ${FUNCNAME[0]}." + return fi - setup_idle_action_lock - trap teardown_idle_action_lock RETURN + trap teardown_lock_idle_action RETURN - if loginctl --no-legend | awk '{ print $3; }' | sort -u | grep -q testuser ; then - echo >&2 "Session of the \'testuser\' is already present." - return 1 + mkdir -p /run/systemd/logind.conf.d + cat >/run/systemd/logind.conf.d/idle-action-lock.conf <<EOF +[Login] +IdleAction=lock +IdleActionSec=1s +EOF + systemctl restart systemd-logind.service + + if loginctl --no-legend | grep -q logind-test-user; then + echo >&2 "Session of the \'logind-test-user\' is already present." + exit 1 fi - # IdleActionSec is set 1s but the accuracy of associated timer is 30s so we - # need to sleep in worst case for 31s to make sure timer elapsed. We sleep - # here for 35s to accommodate for any possible scheduling delays. - cat > /tmp/test.exp <<EOF -spawn systemd-run -G -t -p PAMName=login -p User=testuser bash -send "sleep 35\r" -send "echo foobar\r" -send "sleep 35\r" -send "exit\r" -interact -wait + # 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 <<EOF +[Service] +Type=simple +ExecStart= +ExecStart=-/sbin/agetty --autologin logind-test-user --noclear %I $TERM EOF + systemctl daemon-reload ts="$(date '+%H:%M:%S')" - busctl --match "type='signal',sender='org.freedesktop.login1',interface='org.freedesktop.login1.Session',member='Lock'" monitor > dbus.log & - - expect /tmp/test.exp & - - # Sleep a bit to give expect time to spawn systemd-run before we check for - # the presence of resulting session. - sleep 1 - if [ "$(loginctl --no-legend | awk '{ print $3; }' | sort -u | grep -c testuser)" != 1 ] ; then - echo >&2 "\'testuser\' is expected to have exactly one session running." - return 1 - fi + systemctl restart getty@tty2.service - wait %2 - kill %1 + # check session + for ((i = 0; i < 30; i++)); do + (( i != 0 )) && sleep 1 + check_session && break + done + check_session + assert_eq "$(loginctl --no-legend | awk '$3=="logind-test-user" { print $5 }')" "tty2" - # We slept for 35s , in that interval all sessions should have become idle + # Wait for 35s, in that interval all sessions should have become idle # and "Lock" signal should have been sent out. Then we wrote to tty to make # session active again and next we slept for another 35s so sessions have # become idle again. 'Lock' signal is sent out for each session, we have at # least one session, so minimum of 2 "Lock" signals must have been sent. - if [ "$(grep -c Member=Lock dbus.log)" -lt 2 ]; then - echo >&2 "Too few 'Lock' D-Bus signal sent, expected at least 2." - return 1 - fi + timeout 35 bash -c "while [[ \"\$(journalctl -b -u systemd-logind.service --since=$ts | grep -c 'Sent message type=signal .* member=Lock')\" -lt 1 ]]; do sleep 1; done" - journalctl -b -u systemd-logind.service --since="$ts" > logind.log - if [ "$(grep -c 'System idle. Will be locked now.' logind.log)" -lt 2 ]; then - echo >&2 "System haven't entered idle state at least 2 times." - return 1 - fi + # Wakeup + touch /dev/tty2 - rm -f dbus.log logind.log -} + # Wait again + timeout 35 bash -c "while [[ \"\$(journalctl -b -u systemd-logind.service --since=$ts | grep -c 'Sent message type=signal .* member=Lock')\" -lt 2 ]]; do sleep 1; done" -setup_cron() { - # Setup test user and cron - useradd test || : - crond -s -n & - # Install crontab for the test user that runs sleep every minute. But let's sleep for - # 65 seconds to make sure there is overlap between two consecutive runs, i.e. we have - # always a cron session running. - crontab -u test - <<EOF -RANDOM_DELAY=0 -* * * * * /bin/sleep 65 -EOF - # Let's wait (at most one interval plus 10s to accomodate for slow machines) for at least one session of test user - timeout 70s bash -c "while true; do loginctl --no-legend list-sessions | awk '{ print \$3 }' | grep -q test && break || sleep 1 ; done" + if [[ "$(journalctl -b -u systemd-logind.service --since="$ts" | grep -c 'System idle. Will be locked now.')" -lt 2 ]]; then + echo >&2 "System haven't entered idle state at least 2 times." + exit 1 + fi } teardown_cron() ( set +ex - pkill -9 -u "$(id -u test)" + + pkill -u "$(id -u logind-test-user)" + sleep 1 + pkill -KILL -u "$(id -u logind-test-user)" pkill crond - crontab -r -u test - userdel -r test + crontab -r -u logind-test-user ) test_no_user_instance_for_cron() { if ! command -v crond || ! command -v crontab ; then - echo >&2 "Skipping test for background cron sessions because cron is missing." + echo "Skipping test for background cron sessions because cron is missing." return fi - trap teardown_cron EXIT - setup_cron + trap teardown_cron RETURN - if [[ $(loginctl --no-legend list-sessions | grep -c test) -lt 1 ]]; then - echo >&2 '"test" user should have at least one session' - loginctl list-sessions - return 1 - fi + # Setup cron + crond -s -n & + # Install crontab for the test user that runs sleep every minute. But let's sleep for + # 65 seconds to make sure there is overlap between two consecutive runs, i.e. we have + # always a cron session running. + crontab -u logind-test-user - <<EOF +RANDOM_DELAY=0 +* * * * * /bin/sleep 65 +EOF + + # Let's wait (at most one interval plus 10s to accommodate for slow machines) for at least one session + # of the test user + timeout 70 bash -c "while ! loginctl --no-legend list-sessions | grep -q logind-test-user; do sleep 1; done" # Check that all sessions of test user have class=background and no user instance was started # for the test user. while read -r s _; do - local class - - class=$(loginctl --property Class --value show-session "$s") - if [[ "$class" != "background" ]]; then - echo >&2 "Session has incorrect class, expected \"background\", got \"$class\"." - return 1 - fi - done < <(loginctl --no-legend list-sessions | grep test) - - state=$(systemctl --property ActiveState --value show user@"$(id -u test)".service) - if [[ "$state" != "inactive" ]]; then - echo >&2 "User instance state is unexpected, expected \"inactive\", got \"$state\"" - return 1 - fi + assert_eq "$(loginctl --property Class --value show-session "$s")" "background" + done < <(loginctl --no-legend list-sessions | grep logind-test-user) - state=$(systemctl --property SubState --value show user@"$(id -u test)".service) - if [[ "$state" != "dead" ]]; then - echo >&2 "User instance state is unexpected, expected \"dead\", got \"$state\"" - return 1 - fi + assert_eq "$(systemctl --property ActiveState --value show user@"$(id -u logind-test-user)".service)" "inactive" + assert_eq "$(systemctl --property SubState --value show user@"$(id -u logind-test-user)".service)" "dead" } : >/failed +setup_test_user test_enable_debug test_properties test_started |