]> git.proxmox.com Git - systemd.git/blame - src/libsystemd/sd-device/test-sd-device-monitor.c
New upstream version 249~rc1
[systemd.git] / src / libsystemd / sd-device / test-sd-device-monitor.c
CommitLineData
a032b68d 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
6e866b33
MB
2
3#include <stdbool.h>
4#include <unistd.h>
5
6#include "sd-device.h"
7#include "sd-event.h"
8
9#include "device-monitor-private.h"
10#include "device-private.h"
11#include "device-util.h"
12#include "macro.h"
13#include "string-util.h"
14#include "tests.h"
15#include "util.h"
16#include "virt.h"
17
18static int monitor_handler(sd_device_monitor *m, sd_device *d, void *userdata) {
19 const char *s, *syspath = userdata;
20
21 assert_se(sd_device_get_syspath(d, &s) >= 0);
22 assert_se(streq(s, syspath));
23
7c20daf6 24 return sd_event_exit(sd_device_monitor_get_event(m), 100);
6e866b33
MB
25}
26
7c20daf6 27static int test_receive_device_fail(void) {
6e866b33 28 _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
7c20daf6
FS
29 _cleanup_(sd_device_unrefp) sd_device *loopback = NULL;
30 const char *syspath;
6e866b33
MB
31 int r;
32
7c20daf6
FS
33 log_info("/* %s */", __func__);
34
35 /* Try to send device with invalid action and without seqnum. */
36 assert_se(sd_device_new_from_syspath(&loopback, "/sys/class/net/lo") >= 0);
37 assert_se(device_add_property(loopback, "ACTION", "hoge") >= 0);
38
39 assert_se(sd_device_get_syspath(loopback, &syspath) >= 0);
40
41 assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0);
42 assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0);
43 assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0);
44
45 assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0);
46 assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0);
47 assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
48 assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
49
50 /* Do not use assert_se() here. */
51 r = device_monitor_send_device(monitor_server, monitor_client, loopback);
52 if (r < 0)
53 return log_error_errno(r, "Failed to send loopback device: %m");
54
55 assert_se(sd_event_run(sd_device_monitor_get_event(monitor_client), 0) >= 0);
56
57 return 0;
58}
59
60static void test_send_receive_one(sd_device *device, bool subsystem_filter, bool tag_filter, bool use_bpf) {
61 _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
62 const char *syspath, *subsystem, *tag, *devtype = NULL;
63
6e866b33
MB
64 log_device_info(device, "/* %s(subsystem_filter=%s, tag_filter=%s, use_bpf=%s) */", __func__,
65 true_false(subsystem_filter), true_false(tag_filter), true_false(use_bpf));
66
67 assert_se(sd_device_get_syspath(device, &syspath) >= 0);
68
69 assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0);
70 assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0);
71 assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0);
72
73 assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0);
74 assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0);
75 assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
76 assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
77
78 if (subsystem_filter) {
79 assert_se(sd_device_get_subsystem(device, &subsystem) >= 0);
80 (void) sd_device_get_devtype(device, &devtype);
81 assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, subsystem, devtype) >= 0);
82 }
83
84 if (tag_filter)
85 FOREACH_DEVICE_TAG(device, tag)
86 assert_se(sd_device_monitor_filter_add_match_tag(monitor_client, tag) >= 0);
87
88 if ((subsystem_filter || tag_filter) && use_bpf)
89 assert_se(sd_device_monitor_filter_update(monitor_client) >= 0);
90
7c20daf6
FS
91 assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0);
92 assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100);
6e866b33
MB
93}
94
95static void test_subsystem_filter(sd_device *device) {
96 _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
97 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
8b3d4ff0 98 const char *syspath, *subsystem;
6e866b33
MB
99 sd_device *d;
100
8b3d4ff0 101 log_device_info(device, "/* %s */", __func__);
6e866b33
MB
102
103 assert_se(sd_device_get_syspath(device, &syspath) >= 0);
104 assert_se(sd_device_get_subsystem(device, &subsystem) >= 0);
105
106 assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0);
107 assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0);
108 assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0);
109
110 assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0);
111 assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0);
112 assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, subsystem, NULL) >= 0);
113 assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
114 assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
115
116 assert_se(sd_device_enumerator_new(&e) >= 0);
117 assert_se(sd_device_enumerator_add_match_subsystem(e, subsystem, false) >= 0);
118 FOREACH_DEVICE(e, d) {
8b3d4ff0
MB
119 const char *p, *s;
120
6e866b33
MB
121 assert_se(sd_device_get_syspath(d, &p) >= 0);
122 assert_se(sd_device_get_subsystem(d, &s) >= 0);
123
8b3d4ff0
MB
124 log_device_debug(d, "Sending device subsystem:%s syspath:%s", s, p);
125 assert_se(device_monitor_send_device(monitor_server, monitor_client, d) >= 0);
126 }
127
128 log_device_info(device, "Sending device subsystem:%s syspath:%s", subsystem, syspath);
129 assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0);
130 assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100);
131}
132
133static void test_tag_filter(sd_device *device) {
134 _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
135 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
136 const char *syspath;
137 sd_device *d;
138
139 log_device_info(device, "/* %s */", __func__);
140
141 assert_se(sd_device_get_syspath(device, &syspath) >= 0);
142
143 assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0);
144 assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0);
145 assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0);
146
147 assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0);
148 assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0);
149 assert_se(sd_device_monitor_filter_add_match_tag(monitor_client, "TEST_SD_DEVICE_MONITOR") >= 0);
150 assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
151 assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
152
153 assert_se(sd_device_enumerator_new(&e) >= 0);
154 FOREACH_DEVICE(e, d) {
155 const char *p;
156
157 assert_se(sd_device_get_syspath(d, &p) >= 0);
158
159 log_device_debug(d, "Sending device syspath:%s", p);
6e866b33
MB
160 assert_se(device_monitor_send_device(monitor_server, monitor_client, d) >= 0);
161 }
162
8b3d4ff0 163 log_device_info(device, "Sending device syspath:%s", syspath);
6e866b33 164 assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0);
7c20daf6 165 assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100);
8b3d4ff0
MB
166
167}
168
169static void test_sysattr_filter(sd_device *device, const char *sysattr) {
170 _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
171 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
172 const char *syspath, *subsystem, *sysattr_value;
173 sd_device *d;
174
175 log_device_info(device, "/* %s(%s) */", __func__, sysattr);
176
177 assert_se(sd_device_get_syspath(device, &syspath) >= 0);
178 assert_se(sd_device_get_subsystem(device, &subsystem) >= 0);
179 assert_se(sd_device_get_sysattr_value(device, sysattr, &sysattr_value) >= 0);
180
181 assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0);
182 assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0);
183 assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0);
184
185 assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0);
186 assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0);
187 /* The sysattr filter is not implemented in BPF yet, so the below device_monito_send_device()
188 * may cause EAGAIN. So, let's also filter devices with subsystem. */
189 assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, subsystem, NULL) >= 0);
190 assert_se(sd_device_monitor_filter_add_match_sysattr(monitor_client, sysattr, sysattr_value, true) >= 0);
191 assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
192 assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
193
194 assert_se(sd_device_enumerator_new(&e) >= 0);
195 assert_se(sd_device_enumerator_add_match_sysattr(e, sysattr, sysattr_value, false) >= 0);
196 FOREACH_DEVICE(e, d) {
197 const char *p;
198
199 assert_se(sd_device_get_syspath(d, &p) >= 0);
200
201 log_device_debug(d, "Sending device syspath:%s", p);
202 assert_se(device_monitor_send_device(monitor_server, monitor_client, d) >= 0);
203 }
204
205 log_device_info(device, "Sending device syspath:%s", syspath);
206 assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0);
207 assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100);
208
209}
210
211static void test_parent_filter(sd_device *device) {
212 _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
213 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
214 const char *syspath, *subsystem;
215 sd_device *parent, *d;
216 int r;
217
218 log_device_info(device, "/* %s */", __func__);
219
220 assert_se(sd_device_get_syspath(device, &syspath) >= 0);
221 assert_se(sd_device_get_subsystem(device, &subsystem) >= 0);
222 r = sd_device_get_parent(device, &parent);
223 if (r < 0)
224 return (void) log_device_info(device, "Device does not have parent, skipping.");
225
226 assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0);
227 assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0);
228 assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0);
229
230 assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0);
231 assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0);
232 /* The parent filter is not implemented in BPF yet, so the below device_monito_send_device()
233 * may cause EAGAIN. So, let's also filter devices with subsystem. */
234 assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, subsystem, NULL) >= 0);
235 assert_se(sd_device_monitor_filter_add_match_parent(monitor_client, parent, true) >= 0);
236 assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
237 assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
238
239 assert_se(sd_device_enumerator_new(&e) >= 0);
240 FOREACH_DEVICE(e, d) {
241 const char *p;
242
243 assert_se(sd_device_get_syspath(d, &p) >= 0);
244
245 log_device_debug(d, "Sending device syspath:%s", p);
246 assert_se(device_monitor_send_device(monitor_server, monitor_client, d) >= 0);
247 }
248
249 log_device_info(device, "Sending device syspath:%s", syspath);
250 assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0);
251 assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100);
252
7c20daf6
FS
253}
254
255static void test_sd_device_monitor_filter_remove(sd_device *device) {
256 _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
257 const char *syspath;
258
259 log_device_info(device, "/* %s */", __func__);
260
261 assert_se(sd_device_get_syspath(device, &syspath) >= 0);
262
263 assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0);
264 assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0);
265 assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0);
266
267 assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0);
268 assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0);
269 assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
270 assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
271
272 assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, "hoge", NULL) >= 0);
273 assert_se(sd_device_monitor_filter_update(monitor_client) >= 0);
274
275 assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0);
276 assert_se(sd_event_run(sd_device_monitor_get_event(monitor_client), 0) >= 0);
277
278 assert_se(sd_device_monitor_filter_remove(monitor_client) >= 0);
279
280 assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0);
281 assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100);
282}
283
284static void test_device_copy_properties(sd_device *device) {
285 _cleanup_(sd_device_unrefp) sd_device *copy = NULL;
286
287 assert_se(device_shallow_clone(device, &copy) >= 0);
288 assert_se(device_copy_properties(copy, device) >= 0);
289
290 test_send_receive_one(copy, false, false, false);
6e866b33
MB
291}
292
293int main(int argc, char *argv[]) {
294 _cleanup_(sd_device_unrefp) sd_device *loopback = NULL, *sda = NULL;
295 int r;
296
297 test_setup_logging(LOG_INFO);
298
299 if (getuid() != 0)
300 return log_tests_skipped("not root");
301
7c20daf6 302 r = test_receive_device_fail();
6e866b33
MB
303 if (r < 0) {
304 assert_se(r == -EPERM && detect_container() > 0);
305 return log_tests_skipped("Running in container? Skipping remaining tests");
306 }
307
7c20daf6
FS
308 assert_se(sd_device_new_from_syspath(&loopback, "/sys/class/net/lo") >= 0);
309 assert_se(device_add_property(loopback, "ACTION", "add") >= 0);
310 assert_se(device_add_property(loopback, "SEQNUM", "10") >= 0);
8b3d4ff0 311 assert_se(device_add_tag(loopback, "TEST_SD_DEVICE_MONITOR", true) >= 0);
7c20daf6
FS
312
313 test_send_receive_one(loopback, false, false, false);
314 test_send_receive_one(loopback, true, false, false);
315 test_send_receive_one(loopback, false, true, false);
316 test_send_receive_one(loopback, true, true, false);
317 test_send_receive_one(loopback, true, false, true);
318 test_send_receive_one(loopback, false, true, true);
319 test_send_receive_one(loopback, true, true, true);
6e866b33
MB
320
321 test_subsystem_filter(loopback);
8b3d4ff0
MB
322 test_tag_filter(loopback);
323 test_sysattr_filter(loopback, "ifindex");
7c20daf6
FS
324 test_sd_device_monitor_filter_remove(loopback);
325 test_device_copy_properties(loopback);
6e866b33
MB
326
327 r = sd_device_new_from_subsystem_sysname(&sda, "block", "sda");
328 if (r < 0) {
329 log_info_errno(r, "Failed to create sd_device for sda, skipping remaining tests: %m");
330 return 0;
331 }
332
333 assert_se(device_add_property(sda, "ACTION", "change") >= 0);
334 assert_se(device_add_property(sda, "SEQNUM", "11") >= 0);
335
7c20daf6
FS
336 test_send_receive_one(sda, false, false, false);
337 test_send_receive_one(sda, true, false, false);
338 test_send_receive_one(sda, false, true, false);
339 test_send_receive_one(sda, true, true, false);
340 test_send_receive_one(sda, true, false, true);
341 test_send_receive_one(sda, false, true, true);
342 test_send_receive_one(sda, true, true, true);
6e866b33 343
8b3d4ff0
MB
344 test_parent_filter(sda);
345
6e866b33
MB
346 return 0;
347}