From: Michal Sekletar Date: Mon, 30 Oct 2023 11:12:28 +0000 (+0100) Subject: tests: add test for StartAuxiliaryScope() X-Git-Tag: v256-rc1~1327^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F28836%2Fhead;p=thirdparty%2Fsystemd.git tests: add test for StartAuxiliaryScope() --- diff --git a/src/test/meson.build b/src/test/meson.build index aec125d483a..1230bafab98 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -600,4 +600,8 @@ executables += [ libudev_basic, ], }, + test_template + { + 'sources' : files('test-aux-scope.c'), + 'type' : 'manual', + }, ] diff --git a/src/test/test-aux-scope.c b/src/test/test-aux-scope.c new file mode 100644 index 00000000000..175757b1c18 --- /dev/null +++ b/src/test/test-aux-scope.c @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include +#include +#include + +#include "sd-event.h" + +#include "bus-error.h" +#include "bus-message.h" +#include "bus-wait-for-jobs.h" +#include "fd-util.h" +#include "log.h" +#include "missing_syscall.h" +#include "process-util.h" +#include "tests.h" + +static int on_sigusr1(sd_event_source *s, const struct signalfd_siginfo *ssi, void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; + PidRef *pids = (PidRef *) userdata; + const char *job; + int r; + + assert(pids); + + r = sd_bus_open_system(&bus); + if (r < 0) + return log_error_errno(r, "Failed to acquire bus: %m"); + + r = sd_bus_message_new_method_call(bus, &message, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartAuxiliaryScope"); + if (r < 0) + return log_error_errno(r, "Failed to create bus message: %m"); + + r = sd_bus_message_append_basic(message, 's', "test-aux-scope.scope"); + if (r < 0) + return log_error_errno(r, "Failed to attach scope name: %m"); + + r = sd_bus_message_open_container(message, 'a', "h"); + if (r < 0) + return log_error_errno(r, "Failed to create array of FDs: %m"); + + for (size_t i = 0; i < 10; i++) { + r = sd_bus_message_append_basic(message, 'h', &pids[i].fd); + if (r < 0) + return log_error_errno(r, "Failed to append PIDFD to message: %m"); + } + + r = sd_bus_message_close_container(message); + if (r < 0) + return log_error_errno(r, "Failed to close container: %m"); + + r = sd_bus_message_append(message, "ta(sv)", UINT64_C(0), 1, "Description", "s", "Test auxiliary scope"); + if (r < 0) + return log_error_errno(r, "Failed to append unit properties: %m"); + + r = sd_bus_call(bus, message, 0, &error, &reply); + if (r < 0) + return log_error_errno(r, "Failed to start auxiliary scope: %s", bus_error_message(&error, r)); + + r = sd_bus_message_read(reply, "o", &job); + if (r < 0) + return log_error_errno(r, "Failed to read reply: %m"); + + r = bus_wait_for_jobs_new(bus, &w); + if (r < 0) + return log_error_errno(r, "Could not watch jobs: %m"); + + r = bus_wait_for_jobs_one(w, job, false, NULL); + if (r < 0) + return r; + + return 0; +} + +static void destroy_pidrefs(PidRef *pids, size_t npids) { + assert(pids || npids == 0); + + for (size_t i = 0; i < npids; i++) + pidref_done(&pids[i]); + + free(pids); +} + +int main(int argc, char *argv[]) { + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + PidRef *pids = NULL; + size_t npids = 0; + int r, fd; + + CLEANUP_ARRAY(pids, npids, destroy_pidrefs); + + test_setup_logging(LOG_INFO); + + fd = pidfd_open(getpid_cached(), 0); + if (fd < 0 && (ERRNO_IS_NOT_SUPPORTED(errno) || ERRNO_IS_PRIVILEGE(errno))) + return log_tests_skipped("pidfds are not available"); + else if (fd < 0) { + log_error_errno(errno, "pidfd_open() failed: %m"); + return EXIT_FAILURE; + } + safe_close(fd); + + r = sd_event_new(&event); + if (r < 0) { + log_error_errno(r, "Failed to allocate event loop: %m"); + return EXIT_FAILURE; + } + + npids = 10; + pids = new0(PidRef, npids); + assert(pids); + + r = sd_event_add_signal(event, NULL, SIGUSR1|SD_EVENT_SIGNAL_PROCMASK, on_sigusr1, pids); + if (r < 0) { + log_error_errno(r, "Failed to setup SIGUSR1 signal handling: %m"); + return EXIT_FAILURE; + } + + for (size_t i = 0; i < npids; i++) { + PidRef pidref = PIDREF_NULL; + pid_t pid; + + r = safe_fork("(worker)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS, &pid); + if (r < 0) { + log_error_errno(r, "Failed to fork(): %m"); + return EXIT_FAILURE; + } + + if (r == 0) { + /* Worker */ + sleep(3600); + _exit(EXIT_SUCCESS); + } + + r = pidref_set_pid(&pidref, pid); + if (r < 0) { + log_error_errno(r, "Failed to initialize PID ref: %m"); + return EXIT_FAILURE; + } + + assert_se(pidref.pid == pid); + assert_se(pidref.fd != -EBADF); + + pids[i] = TAKE_PIDREF(pidref); + } + + r = sd_event_loop(event); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + return 0; +} diff --git a/test/units/testsuite-07.aux-scope.sh b/test/units/testsuite-07.aux-scope.sh new file mode 100755 index 00000000000..4e46e1bb7e3 --- /dev/null +++ b/test/units/testsuite-07.aux-scope.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: LGPL-2.1-or-later +set -ex +set -o pipefail + +export SYSTEMD_PAGER=cat + +if ! grep -q pidfd_open /proc/kallsyms; then + echo "pidfds not available, skipping the test..." + exit 0 +fi + +systemd-run --unit test-aux-scope.service \ + -p Slice=aux.slice -p Type=exec -p TasksMax=99 -p CPUWeight=199 -p IPAccounting=yes \ + /usr/lib/systemd/tests/unit-tests/manual/test-aux-scope +kill -s USR1 "$(systemctl show --value --property MainPID test-aux-scope.service)" + +sleep 1 + +systemctl status test-aux-scope.service +# shellcheck disable=SC2009 +test "$(ps -eo pid,unit | grep -c test-aux-scope.service)" = 1 + +systemctl status test-aux-scope.scope +# shellcheck disable=SC2009 +test "$(ps -eo pid,unit | grep -c test-aux-scope.scope)" = 10 + +test "$(systemctl show -p Slice --value test-aux-scope.scope)" = aux.slice +test "$(systemctl show -p TasksMax --value test-aux-scope.scope)" = 99 +test "$(systemctl show -p CPUWeight --value test-aux-scope.scope)" = 199 +test "$(systemctl show -p IPAccounting --value test-aux-scope.scope)" = yes + +systemctl stop test-aux-scope.scope +systemctl stop test-aux-scope.service