]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/udev/test-udev-spawn.c
man/systemd-sysext: list ephemeral/ephemeral-import in the list of options
[thirdparty/systemd.git] / src / udev / test-udev-spawn.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <stdlib.h>
4
5 #include "sd-device.h"
6
7 #include "alloc-util.h"
8 #include "mountpoint-util.h"
9 #include "path-util.h"
10 #include "signal-util.h"
11 #include "string-util.h"
12 #include "strv.h"
13 #include "tests.h"
14 #include "udev-event.h"
15 #include "udev-spawn.h"
16
17 #define BUF_SIZE 1024
18
19 static void test_event_spawn_core(bool with_pidfd, const char *cmd, char *result_buf, size_t buf_size) {
20 _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
21 _cleanup_(udev_event_unrefp) UdevEvent *event = NULL;
22
23 ASSERT_OK_ERRNO(setenv("SYSTEMD_PIDFD", yes_no(with_pidfd), 1));
24
25 ASSERT_OK(sd_device_new_from_syspath(&dev, "/sys/class/net/lo"));
26 ASSERT_NOT_NULL((event = udev_event_new(dev, NULL, EVENT_TEST_SPAWN)));
27 ASSERT_OK_ZERO(udev_event_spawn(event, false, cmd, result_buf, buf_size, NULL));
28
29 ASSERT_OK_ERRNO(unsetenv("SYSTEMD_PIDFD"));
30 }
31
32 static void test_event_spawn_cat(bool with_pidfd, size_t buf_size) {
33 _cleanup_strv_free_ char **lines = NULL;
34 _cleanup_free_ char *cmd = NULL;
35 char result_buf[BUF_SIZE];
36
37 log_debug("/* %s(%s) */", __func__, yes_no(with_pidfd));
38
39 ASSERT_OK(find_executable("cat", &cmd));
40 ASSERT_NOT_NULL(strextend_with_separator(&cmd, " ", "/sys/class/net/lo/uevent"));
41
42 test_event_spawn_core(with_pidfd, cmd, result_buf,
43 buf_size >= BUF_SIZE ? BUF_SIZE : buf_size);
44
45 ASSERT_NOT_NULL((lines = strv_split_newlines(result_buf)));
46 strv_print(lines);
47
48 if (buf_size >= BUF_SIZE) {
49 ASSERT_TRUE(strv_contains(lines, "INTERFACE=lo"));
50 ASSERT_TRUE(strv_contains(lines, "IFINDEX=1"));
51 }
52 }
53
54 static void test_event_spawn_self(const char *self, const char *arg, bool with_pidfd) {
55 _cleanup_strv_free_ char **lines = NULL;
56 _cleanup_free_ char *cmd = NULL;
57 char result_buf[BUF_SIZE];
58
59 log_debug("/* %s(%s, %s) */", __func__, arg, yes_no(with_pidfd));
60
61 /* 'self' may contain spaces, hence needs to be quoted. */
62 ASSERT_NOT_NULL((cmd = strjoin("'", self, "' ", arg)));
63
64 test_event_spawn_core(with_pidfd, cmd, result_buf, BUF_SIZE);
65
66 ASSERT_NOT_NULL((lines = strv_split_newlines(result_buf)));
67 strv_print(lines);
68
69 ASSERT_TRUE(strv_contains(lines, "aaa"));
70 ASSERT_TRUE(strv_contains(lines, "bbb"));
71 }
72
73 static void test1(void) {
74 fprintf(stdout, "aaa\nbbb");
75 fprintf(stderr, "ccc\nddd");
76 }
77
78 static void test2(void) {
79 char buf[16384];
80
81 fprintf(stdout, "aaa\nbbb");
82
83 memset(buf, 'a', sizeof(buf) - 1);
84 char_array_0(buf);
85 fputs(buf, stderr);
86 }
87
88 int main(int argc, char *argv[]) {
89 _cleanup_free_ char *self = NULL;
90
91 if (path_is_mount_point("/sys") <= 0)
92 return log_tests_skipped("/sys is not mounted");
93
94 if (argc > 1) {
95 if (streq(argv[1], "test1"))
96 test1();
97 else if (streq(argv[1], "test2"))
98 test2();
99 else
100 assert_not_reached();
101
102 return 0;
103 }
104
105 test_setup_logging(LOG_DEBUG);
106
107 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
108
109 test_event_spawn_cat(true, SIZE_MAX);
110 test_event_spawn_cat(false, SIZE_MAX);
111 test_event_spawn_cat(true, 5);
112 test_event_spawn_cat(false, 5);
113
114 assert_se(path_make_absolute_cwd(argv[0], &self) >= 0);
115 path_simplify(self);
116
117 test_event_spawn_self(self, "test1", true);
118 test_event_spawn_self(self, "test1", false);
119
120 test_event_spawn_self(self, "test2", true);
121 test_event_spawn_self(self, "test2", false);
122
123 return 0;
124 }