]> git.ipfire.org Git - thirdparty/systemd.git/blob - test/units/util.sh
Merge pull request #30284 from YHNdnzj/fstab-wantedby-defaultdeps
[thirdparty/systemd.git] / test / units / util.sh
1 #!/usr/bin/env bash
2 # SPDX-License-Identifier: LGPL-2.1-or-later
3
4 # Utility functions for shell tests
5
6 # shellcheck disable=SC2034
7 [[ -e /var/tmp/.systemd_reboot_count ]] && REBOOT_COUNT="$(</var/tmp/.systemd_reboot_count)" || REBOOT_COUNT=0
8
9 assert_true() {(
10 set +ex
11
12 local rc
13
14 "$@"
15 rc=$?
16 if [[ $rc -ne 0 ]]; then
17 echo "FAIL: command '$*' failed with exit code $rc" >&2
18 exit 1
19 fi
20 )}
21
22 assert_eq() {(
23 set +ex
24
25 if [[ "${1?}" != "${2?}" ]]; then
26 echo "FAIL: expected: '$2' actual: '$1'" >&2
27 exit 1
28 fi
29 )}
30
31 assert_in() {(
32 set +ex
33
34 if ! [[ "${2?}" =~ ${1?} ]]; then
35 echo "FAIL: '$1' not found in:" >&2
36 echo "$2" >&2
37 exit 1
38 fi
39 )}
40
41 assert_not_in() {(
42 set +ex
43
44 if [[ "${2?}" =~ ${1?} ]]; then
45 echo "FAIL: '$1' found in:" >&2
46 echo "$2" >&2
47 exit 1
48 fi
49 )}
50
51 assert_rc() {(
52 set +ex
53
54 local rc exp="${1?}"
55
56 shift
57 "$@"
58 rc=$?
59 assert_eq "$rc" "$exp"
60 )}
61
62 assert_not_reached() {
63 echo >&2 "Code should not be reached at ${BASH_SOURCE[1]}:${BASH_LINENO[1]}, function ${FUNCNAME[1]}()"
64 exit 1
65 }
66
67 run_and_grep() {(
68 set +ex
69
70 local expression
71 local log ec
72 local exp_ec=0
73
74 # Invert the grep condition - i.e. check if the expression is _not_ in command's output
75 if [[ "${1:?}" == "-n" ]]; then
76 exp_ec=1
77 shift
78 fi
79
80 expression="${1:?}"
81 shift
82
83 if [[ $# -eq 0 ]]; then
84 echo >&2 "FAIL: Not enough arguments for ${FUNCNAME[0]}()"
85 return 1
86 fi
87
88 log="$(mktemp)"
89 if ! "$@" |& tee "${log:?}"; then
90 echo >&2 "FAIL: Command '$*' failed"
91 return 1
92 fi
93
94 grep -qE "$expression" "$log" && ec=0 || ec=$?
95 if [[ "$exp_ec" -eq 0 && "$ec" -ne 0 ]]; then
96 echo >&2 "FAIL: Expression '$expression' not found in the output of '$*'"
97 return 1
98 elif [[ "$exp_ec" -ne 0 && "$ec" -eq 0 ]]; then
99 echo >&2 "FAIL: Expression '$expression' found in the output of '$*'"
100 return 1
101 fi
102
103 rm -f "$log"
104 )}
105
106 get_cgroup_hierarchy() {
107 case "$(stat -c '%T' -f /sys/fs/cgroup)" in
108 cgroup2fs)
109 echo "unified"
110 ;;
111 tmpfs)
112 if [[ -d /sys/fs/cgroup/unified && "$(stat -c '%T' -f /sys/fs/cgroup/unified)" == cgroup2fs ]]; then
113 echo "hybrid"
114 else
115 echo "legacy"
116 fi
117 ;;
118 *)
119 echo >&2 "Failed to determine host's cgroup hierarchy"
120 exit 1
121 esac
122 }
123
124 runas() {
125 local userid="${1:?}"
126 shift
127 XDG_RUNTIME_DIR=/run/user/"$(id -u "$userid")" setpriv --reuid="$userid" --init-groups "$@"
128 }
129
130 coverage_create_nspawn_dropin() {
131 # If we're collecting coverage, bind mount the $BUILD_DIR into the nspawn
132 # container so gcov can update the counters. This is mostly for standalone
133 # containers, as machinectl stuff is handled by overriding the systemd-nspawn@.service
134 # (see test/test-functions:install_systemd())
135 local root="${1:?}"
136 local container
137
138 if [[ -z "${COVERAGE_BUILD_DIR:-}" ]]; then
139 return 0
140 fi
141
142 container="$(basename "$root")"
143 mkdir -p "/run/systemd/nspawn"
144 echo -ne "[Files]\nBind=$COVERAGE_BUILD_DIR\n" >"/run/systemd/nspawn/${container:?}.nspawn"
145 }
146
147 create_dummy_container() {
148 local root="${1:?}"
149
150 if [[ ! -d /testsuite-13-container-template ]]; then
151 echo >&2 "Missing container template, probably not running in TEST-13-NSPAWN?"
152 exit 1
153 fi
154
155 mkdir -p "$root"
156 cp -a /testsuite-13-container-template/* "$root"
157 coverage_create_nspawn_dropin "$root"
158 }
159
160 # Bump the reboot counter and call systemctl with the given arguments
161 systemctl_final() {
162 local counter
163
164 if [[ $# -eq 0 ]]; then
165 echo >&2 "Missing arguments"
166 exit 1
167 fi
168
169 [[ -e /var/tmp/.systemd_reboot_count ]] && counter="$(</var/tmp/.systemd_reboot_count)" || counter=0
170 echo "$((counter + 1))" >/var/tmp/.systemd_reboot_count
171
172 systemctl "$@"
173 }
174
175 cgroupfs_supports_user_xattrs() {
176 local xattr
177
178 xattr="user.supported_$RANDOM"
179 # shellcheck disable=SC2064
180 trap "setfattr --remove=$xattr /sys/fs/cgroup || :" RETURN
181
182 setfattr --name="$xattr" --value=254 /sys/fs/cgroup
183 [[ "$(getfattr --name="$xattr" --absolute-names --only-values /sys/fs/cgroup)" -eq 254 ]]
184 }
185
186 tpm_has_pcr() {
187 local algorithm="${1:?}"
188 local pcr="${2:?}"
189
190 [[ -f "/sys/class/tpm/tpm0/pcr-$algorithm/$pcr" ]]
191 }
192
193 openssl_supports_kdf() {
194 local kdf="${1:?}"
195
196 # The arguments will need to be adjusted to make this work for other KDFs than SSKDF,
197 # but let's do that when/if the need arises
198 openssl kdf -keylen 16 -kdfopt digest:SHA2-256 -kdfopt key:foo -out /dev/null "$kdf"
199 }
200
201 kernel_supports_lsm() {
202 local lsm="${1:?}"
203 local items item
204
205 if [[ ! -e /sys/kernel/security/lsm ]]; then
206 echo "/sys/kernel/security/lsm doesn't exist, assuming $lsm is not supported"
207 return 1
208 fi
209
210 mapfile -t -d, items </sys/kernel/security/lsm
211 for item in "${items[@]}"; do
212 if [[ "$item" == "$lsm" ]]; then
213 return 0
214 fi
215 done
216
217 return 1
218 }
219
220 MOUNTED_USR_OVERLAY=false
221
222 maybe_mount_usr_overlay() {
223 if [[ ! -w /usr ]]; then
224 mkdir -p /tmp/usr-overlay/{upperdir,workdir}
225 mount -t overlay -o lowerdir=/usr,upperdir=/tmp/usr-overlay/upperdir,workdir=/tmp/usr-overlay/workdir overlay /usr
226 MOUNTED_USR_OVERLAY=true
227 fi
228 }
229
230 maybe_umount_usr_overlay() {
231 if "$MOUNTED_USR_OVERLAY"; then
232 umount -l /usr
233 fi
234 }