test: verify our own units (where applicable)

This is inspired by one of our internal tests that does pretty much the
same thing. However, it is slightly more convoluted than I'd like it to
be, since I really don't want to duplicate the list of our units in
another place, so we need to, somehow, pass the list from the meson file
to the test script. I originally envisioned this to be a part of the
unit test suite, but this doesn't work for unit files with absolute
paths to binaries, as we'd have to install the build first (maybe using
a chroot would work?).

It doesn't check man pages (since they might not be installed on the
test machine) and also skip recursive dependencies (as that would trip
over issues in files that are not under our direct control), but it
should still cover typos and such.

There are currently two units for which the check had to be disabled -
syslog.socket, as the corresponding syslog.service might not be
installed, and rc-local.service as that's a compat API and the necessary
/etc/rc.d/rc.local file may not (and most likely won't be) present.
This commit is contained in:
Frantisek Sumsal 2024-02-19 20:41:49 +01:00
parent 3e7b1b5cb9
commit 5083e42765
3 changed files with 73 additions and 0 deletions

View file

@ -2695,6 +2695,14 @@ if not meson.is_cross_build()
command : [export_dbus_interfaces_py, '@OUTPUT@', dbus_programs])
endif
meson_extract_unit_files = find_program('tools/meson-extract-unit-files.py')
custom_target('installed-unit-files.txt',
output : 'installed-unit-files.txt',
capture : true,
install : want_tests != 'no' and install_tests,
install_dir : testdata_dir,
command : [meson_extract_unit_files, project_build_root])
#####################################################################
alt_time_epoch = run_command('date', '-Is', '-u', '-d', '@@0@'.format(time_epoch),

View file

@ -0,0 +1,45 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
# shellcheck disable=SC2016
set -eux
set -o pipefail
# Verify our own unit files (where applicable)
# This is generated by meson during build
UNIT_FILE_LIST="/usr/lib/systemd/tests/testdata/installed-unit-files.txt"
if [[ ! -f "$UNIT_FILE_LIST" ]]; then
echo "Couldn't find the list of installed units, skipping the test"
exit 0
fi
if ! command -v systemd-analyze >/dev/null; then
echo "Built without systemd-analyze, skipping the test"
exit 0
fi
mapfile -t UNIT_FILES <"$UNIT_FILE_LIST"
if [[ "${#UNIT_FILES[@]}" -le 0 ]]; then
echo >&2 "The unit file list is empty, this is most likely a bug"
exit 1
fi
for unit_file in "${UNIT_FILES[@]}"; do
# Skip the check for a couple of units, namely:
# - syslog.socket: the corresponding syslog.service might not be installed
# - rc-local.service: compat API, /etc/rc.d/rc.local most likely won't be present
if [[ "$unit_file" =~ /(syslog.socket|rc-local.service)$ ]]; then
continue
fi
# Skip missing unit files - this is useful for $NO_BUILD runs, where certain unit files might be dropped
# in distro packaging
if [[ ! -e "$unit_file" ]]; then
echo "$unit_file not found, skipping"
continue
fi
systemd-analyze --recursive-errors=no --man=no verify "$unit_file"
done

View file

@ -0,0 +1,20 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later
import json
import re
import subprocess
import sys
def main():
build_dir = sys.argv[1]
out = subprocess.run(["meson", "introspect", "--installed", build_dir],
stdout=subprocess.PIPE, check=True)
files = json.loads(out.stdout)
for file in sorted(files.values()):
if re.search("^/usr/lib/systemd/(system|user)/", file) and not file.endswith(".conf"):
print(file)
if __name__ == "__main__":
main()