summaryrefslogtreecommitdiffstats
path: root/debian/tests/logind
blob: 07a658bda2e1fc6fbb35051d06c1e7ef9622a567 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#!/bin/sh
set -e

test_started() {
    # ensure the *old* logind from before the upgrade isn't running
    echo " * try-restarting systemd-logind"
    systemctl try-restart systemd-logind

    echo " * daemon is started"
    # should start at boot, not with D-BUS activation
    LOGINDPID=$(pidof systemd-logind)

    # loginctl should succeed
    echo " * loginctl succeeds"
    LOGINCTL_OUT=`loginctl`
}

test_properties() {
    # Default KillUserProcesses should be off for debian/ubuntu builds
    r=$(busctl get-property org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager KillUserProcesses)
    [ "$r" = "b false" ]
}

# args: <timeout>
wait_suspend() {
    timeout=$1
    while [ $timeout -gt 0 ] && [ ! -e /run/suspend.flag ]; do
        sleep 1
        timeout=$((timeout - 1))
        [ $(($timeout % 5)) -ne 0 ] || echo "   waiting for suspend, ${timeout}s remaining..."
    done
    if [ ! -e /run/suspend.flag ]; then
        echo "closing lid did not cause suspend" >&2
        exit 1
    fi
    rm /run/suspend.flag
    echo " * closing lid caused suspend"
}

test_suspend_on_lid() {
    if systemd-detect-virt --quiet --container; then
        echo " * Skipping suspend test in container"
        return
    fi
    if ! grep -q mem /sys/power/state; then
        echo " * suspend not supported on this testbed, skipping"
        return
    fi

    # cleanup handler
    trap 'rm -f /run/udev/rules.d/70-logindtest-*.rules; udevadm control --reload;
          kill $KILL_PID;
          rm /run/systemd/system/systemd-suspend.service;
          if [ -d /sys/module/scsi_debug ]; then rmmod scsi_debug 2>/dev/null || (sleep 2; rmmod scsi_debug ) || true; fi' \
                  EXIT INT QUIT TERM PIPE

    # watch what's going on
    journalctl -f -u systemd-logind.service &
    KILL_PID="$KILL_PID $!"

    # create fake suspend
    UNIT=$(systemctl show -pFragmentPath --value systemd-suspend.service)
    sed '/^ExecStart=/ s_=.*$_=/bin/touch /run/suspend.flag_' $UNIT > /run/systemd/system/systemd-suspend.service
    sync
    systemctl daemon-reload

    # create fake lid switch
    mkdir -p /run/udev/rules.d
    echo 'SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="Fake Lid Switch", TAG+="power-switch"' \
        > /run/udev/rules.d/70-logindtest-lid.rules
    sync
    udevadm control --reload
    evemu-device $(dirname $0)/lidswitch.evemu &
    KILL_PID="$KILL_PID $!"
    while [ -z "$O" ]; do
        sleep 0.1
        O=$(grep -l '^Fake Lid Switch' /sys/class/input/*/device/name)
    done
    O=${O%/device/name}
    LID_DEV=/dev/${O#/sys/class/}

    # 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

    echo " * 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=$(pidof systemd-logind)
    [ "$P" = "$LOGINDPID" ] || { echo "logind crashed" >&2; exit 1; }
}

test_shutdown() {
    echo " * scheduled shutdown with wall message"
    shutdown 2>&1
    sleep 5
    shutdown -c || true
    # logind should still be running
    P=$(pidof systemd-logind)
    [ "$P" = "$LOGINDPID" ] || { echo "logind crashed" >&2; exit 1; }

    echo " * scheduled shutdown without wall message"
    shutdown --no-wall 2>&1
    sleep 5
    shutdown -c --no-wall || true
    P=$(pidof systemd-logind)
    [ "$P" = "$LOGINDPID" ] || { echo "logind crashed" >&2; exit 1; }
}

test_in_logind_session() {
    echo " * XDG_SESSION_ID=$XDG_SESSION_ID"
    # cgroup v1: "1:name=systemd:/user.slice/..."; unified hierarchy: "0::/user.slice"
    if grep -E '(name=systemd|^0:):.*session.*scope' /proc/self/cgroup; then
        echo " * process is in session cgroup"
    else
        echo "FAIL: process is not in session cgroup"
        echo "/proc/self/cgroup:"
        cat /proc/self/cgroup
        loginctl
        loginctl show-session "$XDG_SESSION_ID"
        exit 1
    fi
}

test_acl() {
    # ACL tests
    if ! echo "$LOGINCTL_OUT" | grep -q "seat0"; then
        echo " * Skipping ACL tests, as there is no seat"
        return
    fi
    if systemd-detect-virt --quiet --container; then
        echo " * Skipping ACL tests in container"
        return
    fi

    # determine user
    USER=`echo "$OUT" | grep seat0 | awk '{print $3}'`
    echo "seat user: $USER"

    # scsi_debug should not be loaded yet
    ! test -d /sys/bus/pseudo/drivers/scsi_debug/adapter*/host*/target*/*:*/block

    # 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
    cat <<EOF > /run/udev/rules.d/70-logindtest-scsi_debug-user.rules
SUBSYSTEM=="block", ATTRS{model}=="scsi_debug*", TAG+="uaccess"
EOF
    sync
    udevadm control --reload

    echo " * coldplug: logind started with existing device"
    killall systemd-logind
    modprobe scsi_debug
    while ! dev=/dev/`ls /sys/bus/pseudo/drivers/scsi_debug/adapter*/host*/target*/*:*/block 2>/dev/null`; do sleep 0.1; done
    test -b $dev
    echo "got block device $dev"
    udevadm settle
    # trigger logind
    loginctl > /dev/null
    sleep 1
    if getfacl -p $dev | grep -q "user:$USER:rw-"; then
        echo "$dev has ACL for user $USER"
    else
        echo "$dev has no ACL for user $USER:" >&2
        getfacl -p $dev >&2
        exit 1
    fi

    rmmod scsi_debug

    echo " * hotplug: new device appears while logind is running"
    modprobe scsi_debug
    while ! dev=/dev/`ls /sys/bus/pseudo/drivers/scsi_debug/adapter*/host*/target*/*:*/block`; do sleep 0.1; done
    test -b $dev
    echo "got block device $dev"
    udevadm settle
    sleep 1
    if getfacl -p $dev | grep -q "user:$USER:rw-"; then
        echo "$dev has ACL for user $USER"
    else
        echo "$dev has no ACL for user $USER:" >&2
        getfacl -p $dev >&2
        exit 1
    fi
}

#
# main
#

test_started
test_properties
test_in_logind_session
test_suspend_on_lid
test_shutdown
test_acl