]> git.ipfire.org Git - thirdparty/systemd.git/blob - test/units/testsuite-38.sh
e58bae81fec23d461c3b3c55134483f452bac773
[thirdparty/systemd.git] / test / units / testsuite-38.sh
1 #!/usr/bin/env bash
2
3 set -eux
4 set -o pipefail
5
6 systemd-analyze log-level debug
7 systemd-analyze log-target console
8
9 unit=testsuite-38-sleep.service
10
11 start_test_service() {
12 systemctl daemon-reload
13 systemctl start "${unit}"
14 }
15
16 dbus_freeze() {
17 local name object_path suffix
18
19 suffix="${1##*.}"
20 name="${1%.$suffix}"
21 object_path="/org/freedesktop/systemd1/unit/${name//-/_2d}_2e${suffix}"
22
23 busctl call \
24 org.freedesktop.systemd1 \
25 "${object_path}" \
26 org.freedesktop.systemd1.Unit \
27 Freeze
28 }
29
30 dbus_thaw() {
31 local name object_path suffix
32
33 suffix="${1##*.}"
34 name="${1%.$suffix}"
35 object_path="/org/freedesktop/systemd1/unit/${name//-/_2d}_2e${suffix}"
36
37 busctl call \
38 org.freedesktop.systemd1 \
39 "${object_path}" \
40 org.freedesktop.systemd1.Unit \
41 Thaw
42 }
43
44 dbus_freeze_unit() {
45 busctl call \
46 org.freedesktop.systemd1 \
47 /org/freedesktop/systemd1 \
48 org.freedesktop.systemd1.Manager \
49 FreezeUnit \
50 s \
51 "$1"
52 }
53
54 dbus_thaw_unit() {
55 busctl call \
56 org.freedesktop.systemd1 \
57 /org/freedesktop/systemd1 \
58 org.freedesktop.systemd1.Manager \
59 ThawUnit \
60 s \
61 "$1"
62 }
63
64 dbus_can_freeze() {
65 local name object_path suffix
66
67 suffix="${1##*.}"
68 name="${1%.$suffix}"
69 object_path="/org/freedesktop/systemd1/unit/${name//-/_2d}_2e${suffix}"
70
71 busctl get-property \
72 org.freedesktop.systemd1 \
73 "${object_path}" \
74 org.freedesktop.systemd1.Unit \
75 CanFreeze
76 }
77
78 check_freezer_state() {
79 local name object_path suffix
80
81 suffix="${1##*.}"
82 name="${1%.$suffix}"
83 object_path="/org/freedesktop/systemd1/unit/${name//-/_2d}_2e${suffix}"
84
85 for _ in {0..10}; do
86 state=$(busctl get-property \
87 org.freedesktop.systemd1 \
88 "${object_path}" \
89 org.freedesktop.systemd1.Unit \
90 FreezerState | cut -d " " -f2 | tr -d '"')
91
92 # Ignore the intermediate freezing & thawing states in case we check
93 # the unit state too quickly
94 [[ "$state" =~ ^(freezing|thawing)$ ]] || break
95 sleep .5
96 done
97
98 [ "$state" = "$2" ] || {
99 echo "error: unexpected freezer state, expected: $2, actual: $state" >&2
100 exit 1
101 }
102 }
103
104 check_cgroup_state() {
105 grep -q "frozen $2" /sys/fs/cgroup/system.slice/"$1"/cgroup.events
106 }
107
108 test_dbus_api() {
109 echo "Test that DBus API works:"
110 echo -n " - Freeze(): "
111 dbus_freeze "${unit}"
112 check_freezer_state "${unit}" "frozen"
113 check_cgroup_state "$unit" 1
114 echo "[ OK ]"
115
116 echo -n " - Thaw(): "
117 dbus_thaw "${unit}"
118 check_freezer_state "${unit}" "running"
119 check_cgroup_state "$unit" 0
120 echo "[ OK ]"
121
122 echo -n " - FreezeUnit(): "
123 dbus_freeze_unit "${unit}"
124 check_freezer_state "${unit}" "frozen"
125 check_cgroup_state "$unit" 1
126 echo "[ OK ]"
127
128 echo -n " - ThawUnit(): "
129 dbus_thaw_unit "${unit}"
130 check_freezer_state "${unit}" "running"
131 check_cgroup_state "$unit" 0
132 echo "[ OK ]"
133
134 echo -n " - CanFreeze(): "
135 output=$(dbus_can_freeze "${unit}")
136 [ "$output" = "b true" ]
137 echo "[ OK ]"
138
139 echo
140 }
141
142 test_jobs() {
143 local pid_before=
144 local pid_after=
145 echo "Test that it is possible to apply jobs on frozen units:"
146
147 systemctl start "${unit}"
148 dbus_freeze "${unit}"
149 check_freezer_state "${unit}" "frozen"
150
151 echo -n " - restart: "
152 pid_before=$(systemctl show -p MainPID "${unit}" --value)
153 systemctl restart "${unit}"
154 pid_after=$(systemctl show -p MainPID "${unit}" --value)
155 [ "$pid_before" != "$pid_after" ] && echo "[ OK ]"
156
157 dbus_freeze "${unit}"
158 check_freezer_state "${unit}" "frozen"
159
160 echo -n " - stop: "
161 timeout 5s systemctl stop "${unit}"
162 echo "[ OK ]"
163
164 echo
165 }
166
167 test_systemctl() {
168 echo "Test that systemctl freeze/thaw verbs:"
169
170 systemctl start "$unit"
171
172 echo -n " - freeze: "
173 systemctl freeze "$unit"
174 check_freezer_state "${unit}" "frozen"
175 check_cgroup_state "$unit" 1
176 # Freezing already frozen unit should be NOP and return quickly
177 timeout 3s systemctl freeze "$unit"
178 echo "[ OK ]"
179
180 echo -n " - thaw: "
181 systemctl thaw "$unit"
182 check_freezer_state "${unit}" "running"
183 check_cgroup_state "$unit" 0
184 # Likewise thawing already running unit shouldn't block
185 timeout 3s systemctl thaw "$unit"
186 echo "[ OK ]"
187
188 systemctl stop "$unit"
189
190 echo
191 }
192
193 test_systemctl_show() {
194 echo "Test systemctl show integration:"
195
196 systemctl start "$unit"
197
198 echo -n " - FreezerState property: "
199 state=$(systemctl show -p FreezerState --value "$unit")
200 [ "$state" = "running" ]
201 systemctl freeze "$unit"
202 state=$(systemctl show -p FreezerState --value "$unit")
203 [ "$state" = "frozen" ]
204 systemctl thaw "$unit"
205 echo "[ OK ]"
206
207 echo -n " - CanFreeze property: "
208 state=$(systemctl show -p CanFreeze --value "$unit")
209 [ "$state" = "yes" ]
210 echo "[ OK ]"
211
212 systemctl stop "$unit"
213 echo
214 }
215
216 test_recursive() {
217 local slice="bar.slice"
218 local unit="baz.service"
219
220 systemd-run --unit "$unit" --slice "$slice" sleep 3600 >/dev/null 2>&1
221
222 echo "Test recursive freezing:"
223
224 echo -n " - freeze: "
225 systemctl freeze "$slice"
226 check_freezer_state "${slice}" "frozen"
227 check_freezer_state "${unit}" "frozen"
228 grep -q "frozen 1" /sys/fs/cgroup/"${slice}"/cgroup.events
229 grep -q "frozen 1" /sys/fs/cgroup/"${slice}"/"${unit}"/cgroup.events
230 echo "[ OK ]"
231
232 echo -n " - thaw: "
233 systemctl thaw "$slice"
234 check_freezer_state "${unit}" "running"
235 check_freezer_state "${slice}" "running"
236 grep -q "frozen 0" /sys/fs/cgroup/"${slice}"/cgroup.events
237 grep -q "frozen 0" /sys/fs/cgroup/"${slice}"/"${unit}"/cgroup.events
238 echo "[ OK ]"
239
240 systemctl stop "$unit"
241 systemctl stop "$slice"
242
243 echo
244 }
245
246 test_preserve_state() {
247 local slice="bar.slice"
248 local unit="baz.service"
249
250 systemd-run --unit "$unit" --slice "$slice" sleep 3600 >/dev/null 2>&1
251
252 echo "Test that freezer state is preserved when recursive freezing is initiated from outside (e.g. by manager up the tree):"
253
254 echo -n " - freeze from outside: "
255 echo 1 >/sys/fs/cgroup/"${slice}"/cgroup.freeze
256 # Give kernel some time to freeze the slice
257 sleep 1
258
259 # Our state should not be affected
260 check_freezer_state "${slice}" "running"
261 check_freezer_state "${unit}" "running"
262
263 # However actual kernel state should be frozen
264 grep -q "frozen 1" /sys/fs/cgroup/"${slice}"/cgroup.events
265 grep -q "frozen 1" /sys/fs/cgroup/"${slice}"/"${unit}"/cgroup.events
266 echo "[ OK ]"
267
268 echo -n " - thaw from outside: "
269 echo 0 >/sys/fs/cgroup/"${slice}"/cgroup.freeze
270 sleep 1
271
272 check_freezer_state "${unit}" "running"
273 check_freezer_state "${slice}" "running"
274 grep -q "frozen 0" /sys/fs/cgroup/"${slice}"/cgroup.events
275 grep -q "frozen 0" /sys/fs/cgroup/"${slice}"/"${unit}"/cgroup.events
276 echo "[ OK ]"
277
278 echo -n " - thaw from outside while inner service is frozen: "
279 systemctl freeze "$unit"
280 check_freezer_state "${unit}" "frozen"
281 echo 1 >/sys/fs/cgroup/"${slice}"/cgroup.freeze
282 echo 0 >/sys/fs/cgroup/"${slice}"/cgroup.freeze
283 check_freezer_state "${slice}" "running"
284 check_freezer_state "${unit}" "frozen"
285 echo "[ OK ]"
286
287 systemctl stop "$unit"
288 systemctl stop "$slice"
289
290 echo
291 }
292
293 test -e /sys/fs/cgroup/system.slice/cgroup.freeze && {
294 start_test_service
295 test_dbus_api
296 test_systemctl
297 test_systemctl_show
298 test_jobs
299 test_recursive
300 test_preserve_state
301 }
302
303 echo OK >/testok
304 exit 0