]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/units/util.sh
test: Drop /usr overlay workaround
[thirdparty/systemd.git] / test / units / util.sh
CommitLineData
759ed0a2
YW
1#!/usr/bin/env bash
2# SPDX-License-Identifier: LGPL-2.1-or-later
3
cb153b4f 4# Utility functions for shell tests
759ed0a2 5
c1b129f4
FS
6# shellcheck disable=SC2034
7[[ -e /var/tmp/.systemd_reboot_count ]] && REBOOT_COUNT="$(</var/tmp/.systemd_reboot_count)" || REBOOT_COUNT=0
8
d170b475 9assert_true() {(
d170b475
YW
10 set +ex
11
386427cf
YW
12 local rc
13
759ed0a2
YW
14 "$@"
15 rc=$?
d170b475 16 if [[ $rc -ne 0 ]]; then
759ed0a2
YW
17 echo "FAIL: command '$*' failed with exit code $rc" >&2
18 exit 1
19 fi
d170b475
YW
20)}
21
d170b475
YW
22assert_eq() {(
23 set +ex
759ed0a2 24
d170b475 25 if [[ "${1?}" != "${2?}" ]]; then
759ed0a2
YW
26 echo "FAIL: expected: '$2' actual: '$1'" >&2
27 exit 1
28 fi
d170b475
YW
29)}
30
ce35bb95
MK
31assert_le() {(
32 set +ex
33
34 if [[ "${1:?}" -gt "${2:?}" ]]; then
35 echo "FAIL: '$1' > '$2'" >&2
36 exit 1
37 fi
38)}
39
d170b475
YW
40assert_in() {(
41 set +ex
759ed0a2 42
d170b475 43 if ! [[ "${2?}" =~ ${1?} ]]; then
759ed0a2
YW
44 echo "FAIL: '$1' not found in:" >&2
45 echo "$2" >&2
46 exit 1
47 fi
d170b475
YW
48)}
49
50assert_not_in() {(
51 set +ex
52
53 if [[ "${2?}" =~ ${1?} ]]; then
54 echo "FAIL: '$1' found in:" >&2
55 echo "$2" >&2
56 exit 1
57 fi
58)}
59
60assert_rc() {(
d170b475 61 set +ex
759ed0a2 62
386427cf
YW
63 local rc exp="${1?}"
64
759ed0a2 65 shift
759ed0a2
YW
66 "$@"
67 rc=$?
759ed0a2 68 assert_eq "$rc" "$exp"
d170b475 69)}
5ff1c6fc 70
c1b129f4
FS
71assert_not_reached() {
72 echo >&2 "Code should not be reached at ${BASH_SOURCE[1]}:${BASH_LINENO[1]}, function ${FUNCNAME[1]}()"
73 exit 1
74}
75
1a36d267
FS
76run_and_grep() {(
77 set +ex
78
79 local expression
80 local log ec
81 local exp_ec=0
82
83 # Invert the grep condition - i.e. check if the expression is _not_ in command's output
84 if [[ "${1:?}" == "-n" ]]; then
85 exp_ec=1
86 shift
87 fi
88
89 expression="${1:?}"
90 shift
91
92 if [[ $# -eq 0 ]]; then
93 echo >&2 "FAIL: Not enough arguments for ${FUNCNAME[0]}()"
94 return 1
95 fi
96
97 log="$(mktemp)"
98 if ! "$@" |& tee "${log:?}"; then
99 echo >&2 "FAIL: Command '$*' failed"
100 return 1
101 fi
102
103 grep -qE "$expression" "$log" && ec=0 || ec=$?
104 if [[ "$exp_ec" -eq 0 && "$ec" -ne 0 ]]; then
105 echo >&2 "FAIL: Expression '$expression' not found in the output of '$*'"
106 return 1
107 elif [[ "$exp_ec" -ne 0 && "$ec" -eq 0 ]]; then
108 echo >&2 "FAIL: Expression '$expression' found in the output of '$*'"
109 return 1
110 fi
111
112 rm -f "$log"
113)}
114
5ff1c6fc
FS
115get_cgroup_hierarchy() {
116 case "$(stat -c '%T' -f /sys/fs/cgroup)" in
117 cgroup2fs)
118 echo "unified"
119 ;;
120 tmpfs)
121 if [[ -d /sys/fs/cgroup/unified && "$(stat -c '%T' -f /sys/fs/cgroup/unified)" == cgroup2fs ]]; then
122 echo "hybrid"
123 else
124 echo "legacy"
125 fi
126 ;;
127 *)
128 echo >&2 "Failed to determine host's cgroup hierarchy"
129 exit 1
130 esac
131}
7c6fa5bf
FS
132
133runas() {
134 local userid="${1:?}"
135 shift
136 XDG_RUNTIME_DIR=/run/user/"$(id -u "$userid")" setpriv --reuid="$userid" --init-groups "$@"
137}
5656759d 138
28ed2326
FS
139coverage_create_nspawn_dropin() {
140 # If we're collecting coverage, bind mount the $BUILD_DIR into the nspawn
141 # container so gcov can update the counters. This is mostly for standalone
142 # containers, as machinectl stuff is handled by overriding the systemd-nspawn@.service
143 # (see test/test-functions:install_systemd())
144 local root="${1:?}"
145 local container
146
147 if [[ -z "${COVERAGE_BUILD_DIR:-}" ]]; then
148 return 0
149 fi
150
151 container="$(basename "$root")"
152 mkdir -p "/run/systemd/nspawn"
153 echo -ne "[Files]\nBind=$COVERAGE_BUILD_DIR\n" >"/run/systemd/nspawn/${container:?}.nspawn"
154}
155
5656759d
FS
156create_dummy_container() {
157 local root="${1:?}"
158
047d5b6a 159 if [[ ! -d /usr/share/testsuite-13-container-template ]]; then
5656759d
FS
160 echo >&2 "Missing container template, probably not running in TEST-13-NSPAWN?"
161 exit 1
162 fi
163
164 mkdir -p "$root"
047d5b6a 165 cp -a /usr/share/testsuite-13-container-template/* "$root"
28ed2326 166 coverage_create_nspawn_dropin "$root"
5656759d 167}
c1b129f4
FS
168
169# Bump the reboot counter and call systemctl with the given arguments
170systemctl_final() {
171 local counter
172
173 if [[ $# -eq 0 ]]; then
174 echo >&2 "Missing arguments"
175 exit 1
176 fi
177
178 [[ -e /var/tmp/.systemd_reboot_count ]] && counter="$(</var/tmp/.systemd_reboot_count)" || counter=0
179 echo "$((counter + 1))" >/var/tmp/.systemd_reboot_count
180
181 systemctl "$@"
182}
a2dd5920
FS
183
184cgroupfs_supports_user_xattrs() {
185 local xattr
186
187 xattr="user.supported_$RANDOM"
188 # shellcheck disable=SC2064
189 trap "setfattr --remove=$xattr /sys/fs/cgroup || :" RETURN
190
191 setfattr --name="$xattr" --value=254 /sys/fs/cgroup
192 [[ "$(getfattr --name="$xattr" --absolute-names --only-values /sys/fs/cgroup)" -eq 254 ]]
193}
29be5955
FS
194
195tpm_has_pcr() {
196 local algorithm="${1:?}"
197 local pcr="${2:?}"
198
199 [[ -f "/sys/class/tpm/tpm0/pcr-$algorithm/$pcr" ]]
200}
52a09e62
FS
201
202openssl_supports_kdf() {
203 local kdf="${1:?}"
204
205 # The arguments will need to be adjusted to make this work for other KDFs than SSKDF,
206 # but let's do that when/if the need arises
207 openssl kdf -keylen 16 -kdfopt digest:SHA2-256 -kdfopt key:foo -out /dev/null "$kdf"
208}
4a43c2b3
FS
209
210kernel_supports_lsm() {
211 local lsm="${1:?}"
212 local items item
213
214 if [[ ! -e /sys/kernel/security/lsm ]]; then
215 echo "/sys/kernel/security/lsm doesn't exist, assuming $lsm is not supported"
216 return 1
217 fi
218
219 mapfile -t -d, items </sys/kernel/security/lsm
220 for item in "${items[@]}"; do
221 if [[ "$item" == "$lsm" ]]; then
222 return 0
223 fi
224 done
225
226 return 1
227}
87993468 228
c77dad70
DDM
229install_extension_images() {
230 local os_release
231 os_release="$(test -e /etc/os-release && echo /etc/os-release || echo /usr/lib/os-release)"
232
233 # Rolling distros like Arch do not set VERSION_ID
234 local version_id=""
235 if grep -q "^VERSION_ID=" "$os_release"; then
236 version_id="$(grep "^VERSION_ID=" "$os_release")"
237 fi
238
239 local initdir="/var/tmp/app0"
240 mkdir -p "$initdir/usr/lib/extension-release.d" "$initdir/usr/lib/systemd/system" "$initdir/opt"
241 grep "^ID=" "$os_release" >"$initdir/usr/lib/extension-release.d/extension-release.app0"
242 echo "$version_id" >>"$initdir/usr/lib/extension-release.d/extension-release.app0"
243 (
244 echo "$version_id"
245 echo "SYSEXT_IMAGE_ID=app"
246 ) >>"$initdir/usr/lib/extension-release.d/extension-release.app0"
247 cat >"$initdir/usr/lib/systemd/system/app0.service" <<EOF
248[Service]
249Type=oneshot
250RemainAfterExit=yes
251ExecStart=/opt/script0.sh
252TemporaryFileSystem=/var/lib
253StateDirectory=app0
254RuntimeDirectory=app0
255EOF
256 cat >"$initdir/opt/script0.sh" <<EOF
257#!/bin/bash
258set -e
259test -e /usr/lib/os-release
260echo bar >\${STATE_DIRECTORY}/foo
261cat /usr/lib/extension-release.d/extension-release.app0
262EOF
263 chmod +x "$initdir/opt/script0.sh"
264 echo MARKER=1 >"$initdir/usr/lib/systemd/system/some_file"
265 mksquashfs "$initdir" /tmp/app0.raw -noappend
266
267 initdir="/var/tmp/conf0"
268 mkdir -p "$initdir/etc/extension-release.d" "$initdir/etc/systemd/system" "$initdir/opt"
269 grep "^ID=" "$os_release" >"$initdir/etc/extension-release.d/extension-release.conf0"
270 echo "$version_id" >>"$initdir/etc/extension-release.d/extension-release.conf0"
271 (
272 echo "$version_id"
273 echo "CONFEXT_IMAGE_ID=app"
274 ) >>"$initdir/etc/extension-release.d/extension-release.conf0"
275 echo MARKER_1 >"$initdir/etc/systemd/system/some_file"
276 mksquashfs "$initdir" /tmp/conf0.raw -noappend
277
278 initdir="/var/tmp/app1"
279 mkdir -p "$initdir/usr/lib/extension-release.d" "$initdir/usr/lib/systemd/system" "$initdir/opt"
280 grep "^ID=" "$os_release" >"$initdir/usr/lib/extension-release.d/extension-release.app2"
281 (
282 echo "$version_id"
283 echo "SYSEXT_SCOPE=portable"
284 echo "SYSEXT_IMAGE_ID=app"
285 echo "SYSEXT_IMAGE_VERSION=1"
286 echo "PORTABLE_PREFIXES=app1"
287 ) >>"$initdir/usr/lib/extension-release.d/extension-release.app2"
288 setfattr -n user.extension-release.strict -v false "$initdir/usr/lib/extension-release.d/extension-release.app2"
289 cat >"$initdir/usr/lib/systemd/system/app1.service" <<EOF
290[Service]
291Type=oneshot
292RemainAfterExit=yes
293ExecStart=/opt/script1.sh
294StateDirectory=app1
295RuntimeDirectory=app1
296EOF
297 cat >"$initdir/opt/script1.sh" <<EOF
298#!/bin/bash
299set -e
300test -e /usr/lib/os-release
301echo baz >\${STATE_DIRECTORY}/foo
302cat /usr/lib/extension-release.d/extension-release.app2
303EOF
304 chmod +x "$initdir/opt/script1.sh"
305 echo MARKER=1 >"$initdir/usr/lib/systemd/system/other_file"
306 mksquashfs "$initdir" /tmp/app1.raw -noappend
307
308 initdir="/var/tmp/app-nodistro"
309 mkdir -p "$initdir/usr/lib/extension-release.d" "$initdir/usr/lib/systemd/system"
310 (
311 echo "ID=_any"
312 echo "ARCHITECTURE=_any"
313 ) >"$initdir/usr/lib/extension-release.d/extension-release.app-nodistro"
314 echo MARKER=1 >"$initdir/usr/lib/systemd/system/some_file"
315 mksquashfs "$initdir" /tmp/app-nodistro.raw -noappend
316
317 initdir="/var/tmp/service-scoped-test"
318 mkdir -p "$initdir/etc/extension-release.d" "$initdir/etc/systemd/system"
319 (
320 echo "ID=_any"
321 echo "ARCHITECTURE=_any"
322 ) >"$initdir/etc/extension-release.d/extension-release.service-scoped-test"
323 echo MARKER_CONFEXT_123 >"$initdir/etc/systemd/system/some_file"
324 mksquashfs "$initdir" /etc/service-scoped-test.raw -noappend
325
326 # We need to create a dedicated sysext image to test the reload mechanism. If we share an image to install the
327 # 'foo.service' it will be loaded from another test run, which will impact the targeted test.
328 initdir="/var/tmp/app-reload"
329 mkdir -p "$initdir/usr/lib/extension-release.d" "$initdir/usr/lib/systemd/system"
330 (
331 echo "ID=_any"
332 echo "ARCHITECTURE=_any"
333 echo "EXTENSION_RELOAD_MANAGER=1"
334 ) >"$initdir/usr/lib/extension-release.d/extension-release.app-reload"
335 mkdir -p "$initdir/usr/lib/systemd/system/multi-user.target.d"
336 cat >"$initdir/usr/lib/systemd/system/foo.service" <<EOF
337[Service]
338Type=oneshot
339RemainAfterExit=yes
340ExecStart=echo foo
341
342[Install]
343WantedBy=multi-user.target
344EOF
345 echo -e "[Unit]\nUpholds=foo.service" >"$initdir/usr/lib/systemd/system/multi-user.target.d/10-foo-service.conf"
346 mksquashfs "$initdir" /tmp/app-reload.raw -noappend
347}