Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
225 changes: 174 additions & 51 deletions test/TEST-35-LOGIN/testsuite.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,141 @@
set -eux
set -o pipefail

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

return 0
)

setup_test_user() {
mkdir -p /var/spool/cron /var/spool/mail /var/run/console
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
[Service]
Environment=SYSTEMD_LOG_LEVEL=debug
EOF
systemctl daemon-reload
systemctl stop systemd-logind.service
}

check_session() (
set +ex

local seat session leader_pid

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
echo "no seat found for user logind-test-user" >&2
return 1
fi

session=$(loginctl --no-legend | awk '$3 == "logind-test-user" { print $1 }')
if [[ -z "$session" ]]; then
echo "no session found for user logind-test-user" >&2
return 1
fi

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" | awk '$1 == "Leader:" { 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
)

create_session() {
# 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
Restart=no
EOF
systemctl daemon-reload

systemctl restart getty@tty2.service

# check session
for ((i = 0; i < 30; i++)); do
(( i != 0 )) && sleep 1
check_session && break
done
check_session
[[ "$(loginctl --no-legend | awk '$3=="logind-test-user" { print $5 }')" == "tty2" ]]
}

cleanup_session() (
set +ex

local uid s

uid=$(id -u logind-test-user)

loginctl disable-linger logind-test-user

systemctl stop getty@tty2.service

for s in $(loginctl --no-legend list-sessions | awk '$3 == "logind-test-user" { print $1 }'); do
echo "INFO: stopping session $s"
loginctl terminate-session "$s"
done

loginctl terminate-user logind-test-user

if ! timeout 30 bash -c "while loginctl --no-legend | grep -q logind-test-user; do sleep 1; done"; then
echo "WARNING: session for logind-test-user still active, ignoring."
fi

pkill -u "$uid"
sleep 1
pkill -KILL -u "$uid"

if ! timeout 30 bash -c "while systemctl is-active --quiet user@${uid}.service; do sleep 1; done"; then
echo "WARNING: user@${uid}.service is still active, ignoring."
fi

if ! timeout 30 bash -c "while systemctl is-active --quiet user-runtime-dir@${uid}.service; do sleep 1; done"; then
echo "WARNING: user-runtime-dir@${uid}.service is still active, ignoring."
fi

if ! timeout 30 bash -c "while systemctl is-active --quiet user-${uid}.slice; do sleep 1; done"; then
echo "WARNING: user-${uid}.slice is still active, ignoring."
fi

rm -rf /run/systemd/system/getty@tty2.service.d
systemctl daemon-reload

return 0
)

setup_idle_action_lock() {
useradd testuser ||:

Expand All @@ -19,83 +154,71 @@ EOF
Environment=SYSTEMD_LOG_LEVEL=debug
EOF

systemd-analyze cat-config --no-pager systemd/logind.conf
systemctl restart systemd-logind.service
}

teardown_idle_action_lock() {(
set +ex
teardown_lock_idle_action() (
set +eux

rm -f /run/systemd/logind.conf.d/idle-action-lock.conf
rm -f /run/systemd/systemd-logind.service.d/debug.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, skiping test ${FUNCNAME[0]}"
return 0
fi
cleanup_session

setup_idle_action_lock
trap teardown_idle_action_lock RETURN
return 0
)

if loginctl --no-legend | awk '{ print $3; }' | sort -u | grep -q testuser ; then
echo >&2 "Session of the \'testuser\' is already present."
return 1
test_lock_idle_action() {
local ts

if [[ ! -c /dev/tty2 ]]; then
echo "/dev/tty2 does not exist, skipping test ${FUNCNAME[0]}."
return
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 accomodate for any possible scheudling 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
EOF
if loginctl --no-legend | grep -q logind-test-user; then
echo >&2 "Session of the \'logind-test-user\' is already present."
exit 1
fi

ts="$(date '+%H:%M:%S')"
busctl --match "type='signal',sender='org.freedesktop.login1',interface='org.freedesktop.login1.Session',member='Lock'" monitor > dbus.log &
trap teardown_lock_idle_action RETURN

expect /tmp/test.exp &
create_session

# Sleep a bit to give expect time to spawn systemd-run before we check for
# the presence of resulting session.
sleep 2
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
ts="$(date '+%H:%M:%S')"

wait %2
sleep 20
kill %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

# 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"

# Wakeup
touch /dev/tty2

# 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"

journalctl -b -u systemd-logind.service --since="$ts" > logind.log
if [ "$(grep -c 'System idle. Doing lock operation.' logind.log)" -lt 2 ]; then
if [[ "$(journalctl -b -u systemd-logind.service --since="$ts" | grep -c 'System idle. Doing lock operation.')" -lt 2 ]]; then
echo >&2 "System haven't entered idle state at least 2 times."
return 1
exit 1
fi

rm -f dbus.log logind.log
}

: >/failed

setup_test_user
test_enable_debug
test_lock_idle_action

touch /testok
Expand Down
2 changes: 1 addition & 1 deletion test/test-functions
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fi

PATH_TO_INIT=$ROOTLIBDIR/systemd

BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm true false chmod chown ln xargs env mktemp mountpoint useradd userdel"
BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm true false chmod chown ln xargs env mktemp mountpoint useradd userdel timeout"
DEBUGTOOLS="df free ls stty cat ps ln ip route dmesg dhclient mkdir cp ping dhclient strace less grep id tty touch du sort hostname find"

STATEDIR="${BUILD_DIR:-.}/test/$(basename $(dirname $(realpath $0)))"
Expand Down