| /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
| |
| #include "path-util.h" |
| #include "signal-util.h" |
| #include "strv.h" |
| #include "tests.h" |
| #include "udev-event.h" |
| #include "util.h" |
| |
| #define BUF_SIZE 1024 |
| |
| static void test_event_spawn_core(bool with_pidfd, const char *cmd, char result_buf[BUF_SIZE]) { |
| _cleanup_(sd_device_unrefp) sd_device *dev = NULL; |
| _cleanup_(udev_event_freep) UdevEvent *event = NULL; |
| |
| assert_se(setenv("SYSTEMD_PIDFD", yes_no(with_pidfd), 1) >= 0); |
| |
| assert_se(sd_device_new_from_syspath(&dev, "/sys/class/net/lo") >= 0); |
| assert_se(event = udev_event_new(dev, 0, NULL, LOG_DEBUG)); |
| assert_se(udev_event_spawn(event, 5 * USEC_PER_SEC, SIGKILL, false, cmd, result_buf, BUF_SIZE) == 0); |
| |
| assert_se(unsetenv("SYSTEMD_PIDFD") >= 0); |
| } |
| |
| static void test_event_spawn_cat(bool with_pidfd) { |
| _cleanup_strv_free_ char **lines = NULL; |
| _cleanup_free_ char *cmd = NULL; |
| char result_buf[BUF_SIZE]; |
| |
| log_debug("/* %s(%s) */", __func__, yes_no(with_pidfd)); |
| |
| assert_se(find_executable("cat", &cmd) >= 0); |
| assert_se(strextend_with_separator(&cmd, " ", "/sys/class/net/lo/uevent")); |
| |
| test_event_spawn_core(with_pidfd, cmd, result_buf); |
| |
| assert_se(lines = strv_split_newlines(result_buf)); |
| strv_print(lines); |
| |
| assert_se(strv_contains(lines, "INTERFACE=lo")); |
| assert_se(strv_contains(lines, "IFINDEX=1")); |
| } |
| |
| static void test_event_spawn_self(const char *self, const char *arg, bool with_pidfd) { |
| _cleanup_strv_free_ char **lines = NULL; |
| _cleanup_free_ char *cmd = NULL; |
| char result_buf[BUF_SIZE]; |
| |
| log_debug("/* %s(%s, %s) */", __func__, arg, yes_no(with_pidfd)); |
| |
| assert_se(cmd = strjoin(self, " ", arg)); |
| |
| test_event_spawn_core(with_pidfd, cmd, result_buf); |
| |
| assert_se(lines = strv_split_newlines(result_buf)); |
| strv_print(lines); |
| |
| assert_se(strv_contains(lines, "aaa")); |
| assert_se(strv_contains(lines, "bbb")); |
| } |
| |
| static void test1(void) { |
| fprintf(stdout, "aaa\nbbb"); |
| fprintf(stderr, "ccc\nddd"); |
| } |
| |
| static void test2(void) { |
| char buf[16384]; |
| |
| fprintf(stdout, "aaa\nbbb"); |
| |
| memset(buf, 'a', sizeof(buf) - 1); |
| char_array_0(buf); |
| fputs(buf, stderr); |
| } |
| |
| int main(int argc, char *argv[]) { |
| _cleanup_free_ char *self = NULL; |
| |
| if (argc > 1) { |
| if (streq(argv[1], "test1")) |
| test1(); |
| else if (streq(argv[1], "test2")) |
| test2(); |
| else |
| assert_not_reached("unknown command."); |
| |
| return 0; |
| } |
| |
| test_setup_logging(LOG_DEBUG); |
| |
| assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0); |
| |
| test_event_spawn_cat(true); |
| test_event_spawn_cat(false); |
| |
| assert_se(path_make_absolute_cwd(argv[0], &self) >= 0); |
| path_simplify(self); |
| |
| test_event_spawn_self(self, "test1", true); |
| test_event_spawn_self(self, "test1", false); |
| |
| test_event_spawn_self(self, "test2", true); |
| test_event_spawn_self(self, "test2", false); |
| |
| return 0; |
| } |