1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
9 #include "device-monitor-private.h"
10 #include "device-private.h"
11 #include "device-util.h"
13 #include "path-util.h"
14 #include "stat-util.h"
15 #include "string-util.h"
20 static int monitor_handler(sd_device_monitor
*m
, sd_device
*d
, void *userdata
) {
21 const char *s
, *syspath
= userdata
;
23 assert_se(sd_device_get_syspath(d
, &s
) >= 0);
24 assert_se(streq(s
, syspath
));
26 return sd_event_exit(sd_device_monitor_get_event(m
), 100);
29 static void test_receive_device_fail(void) {
30 _cleanup_(sd_device_monitor_unrefp
) sd_device_monitor
*monitor_server
= NULL
, *monitor_client
= NULL
;
31 _cleanup_(sd_device_unrefp
) sd_device
*loopback
= NULL
;
34 log_info("/* %s */", __func__
);
36 /* Try to send device with invalid action and without seqnum. */
37 assert_se(sd_device_new_from_syspath(&loopback
, "/sys/class/net/lo") >= 0);
38 assert_se(device_add_property(loopback
, "ACTION", "hoge") >= 0);
40 assert_se(sd_device_get_syspath(loopback
, &syspath
) >= 0);
42 assert_se(device_monitor_new_full(&monitor_server
, MONITOR_GROUP_NONE
, -1) >= 0);
43 assert_se(sd_device_monitor_set_description(monitor_server
, "sender") >= 0);
44 assert_se(sd_device_monitor_start(monitor_server
, NULL
, NULL
) >= 0);
46 assert_se(device_monitor_new_full(&monitor_client
, MONITOR_GROUP_NONE
, -1) >= 0);
47 assert_se(sd_device_monitor_set_description(monitor_client
, "receiver") >= 0);
48 assert_se(device_monitor_allow_unicast_sender(monitor_client
, monitor_server
) >= 0);
49 assert_se(sd_device_monitor_start(monitor_client
, monitor_handler
, (void *) syspath
) >= 0);
51 assert_se(device_monitor_send_device(monitor_server
, monitor_client
, loopback
) >= 0);
52 assert_se(sd_event_run(sd_device_monitor_get_event(monitor_client
), 0) >= 0);
55 static void test_send_receive_one(sd_device
*device
, bool subsystem_filter
, bool tag_filter
, bool use_bpf
) {
56 _cleanup_(sd_device_monitor_unrefp
) sd_device_monitor
*monitor_server
= NULL
, *monitor_client
= NULL
;
57 const char *syspath
, *subsystem
, *tag
, *devtype
= NULL
;
59 log_device_info(device
, "/* %s(subsystem_filter=%s, tag_filter=%s, use_bpf=%s) */", __func__
,
60 true_false(subsystem_filter
), true_false(tag_filter
), true_false(use_bpf
));
62 assert_se(sd_device_get_syspath(device
, &syspath
) >= 0);
64 assert_se(device_monitor_new_full(&monitor_server
, MONITOR_GROUP_NONE
, -1) >= 0);
65 assert_se(sd_device_monitor_set_description(monitor_server
, "sender") >= 0);
66 assert_se(sd_device_monitor_start(monitor_server
, NULL
, NULL
) >= 0);
68 assert_se(device_monitor_new_full(&monitor_client
, MONITOR_GROUP_NONE
, -1) >= 0);
69 assert_se(sd_device_monitor_set_description(monitor_client
, "receiver") >= 0);
70 assert_se(device_monitor_allow_unicast_sender(monitor_client
, monitor_server
) >= 0);
71 assert_se(sd_device_monitor_start(monitor_client
, monitor_handler
, (void *) syspath
) >= 0);
73 if (subsystem_filter
) {
74 assert_se(sd_device_get_subsystem(device
, &subsystem
) >= 0);
75 (void) sd_device_get_devtype(device
, &devtype
);
76 assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client
, subsystem
, devtype
) >= 0);
80 FOREACH_DEVICE_TAG(device
, tag
)
81 assert_se(sd_device_monitor_filter_add_match_tag(monitor_client
, tag
) >= 0);
83 if ((subsystem_filter
|| tag_filter
) && use_bpf
)
84 assert_se(sd_device_monitor_filter_update(monitor_client
) >= 0);
86 assert_se(device_monitor_send_device(monitor_server
, monitor_client
, device
) >= 0);
87 assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client
)) == 100);
90 static void test_subsystem_filter(sd_device
*device
) {
91 _cleanup_(sd_device_monitor_unrefp
) sd_device_monitor
*monitor_server
= NULL
, *monitor_client
= NULL
;
92 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
93 const char *syspath
, *subsystem
;
96 log_device_info(device
, "/* %s */", __func__
);
98 assert_se(sd_device_get_syspath(device
, &syspath
) >= 0);
99 assert_se(sd_device_get_subsystem(device
, &subsystem
) >= 0);
101 assert_se(device_monitor_new_full(&monitor_server
, MONITOR_GROUP_NONE
, -1) >= 0);
102 assert_se(sd_device_monitor_set_description(monitor_server
, "sender") >= 0);
103 assert_se(sd_device_monitor_start(monitor_server
, NULL
, NULL
) >= 0);
105 assert_se(device_monitor_new_full(&monitor_client
, MONITOR_GROUP_NONE
, -1) >= 0);
106 assert_se(sd_device_monitor_set_description(monitor_client
, "receiver") >= 0);
107 assert_se(device_monitor_allow_unicast_sender(monitor_client
, monitor_server
) >= 0);
108 assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client
, subsystem
, NULL
) >= 0);
109 assert_se(sd_device_monitor_start(monitor_client
, monitor_handler
, (void *) syspath
) >= 0);
111 assert_se(sd_device_enumerator_new(&e
) >= 0);
112 assert_se(sd_device_enumerator_add_match_subsystem(e
, subsystem
, false) >= 0);
113 FOREACH_DEVICE(e
, d
) {
116 assert_se(sd_device_get_syspath(d
, &p
) >= 0);
117 assert_se(sd_device_get_subsystem(d
, &s
) >= 0);
119 assert_se(device_add_property(d
, "ACTION", "add") >= 0);
120 assert_se(device_add_property(d
, "SEQNUM", "10") >= 0);
122 log_device_debug(d
, "Sending device subsystem:%s syspath:%s", s
, p
);
123 assert_se(device_monitor_send_device(monitor_server
, monitor_client
, d
) >= 0);
126 log_device_info(device
, "Sending device subsystem:%s syspath:%s", subsystem
, syspath
);
127 assert_se(device_monitor_send_device(monitor_server
, monitor_client
, device
) >= 0);
128 assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client
)) == 100);
131 static void test_tag_filter(sd_device
*device
) {
132 _cleanup_(sd_device_monitor_unrefp
) sd_device_monitor
*monitor_server
= NULL
, *monitor_client
= NULL
;
133 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
137 log_device_info(device
, "/* %s */", __func__
);
139 assert_se(sd_device_get_syspath(device
, &syspath
) >= 0);
141 assert_se(device_monitor_new_full(&monitor_server
, MONITOR_GROUP_NONE
, -1) >= 0);
142 assert_se(sd_device_monitor_set_description(monitor_server
, "sender") >= 0);
143 assert_se(sd_device_monitor_start(monitor_server
, NULL
, NULL
) >= 0);
145 assert_se(device_monitor_new_full(&monitor_client
, MONITOR_GROUP_NONE
, -1) >= 0);
146 assert_se(sd_device_monitor_set_description(monitor_client
, "receiver") >= 0);
147 assert_se(device_monitor_allow_unicast_sender(monitor_client
, monitor_server
) >= 0);
148 assert_se(sd_device_monitor_filter_add_match_tag(monitor_client
, "TEST_SD_DEVICE_MONITOR") >= 0);
149 assert_se(sd_device_monitor_start(monitor_client
, monitor_handler
, (void *) syspath
) >= 0);
151 assert_se(sd_device_enumerator_new(&e
) >= 0);
152 FOREACH_DEVICE(e
, d
) {
155 assert_se(sd_device_get_syspath(d
, &p
) >= 0);
157 assert_se(device_add_property(d
, "ACTION", "add") >= 0);
158 assert_se(device_add_property(d
, "SEQNUM", "10") >= 0);
160 log_device_debug(d
, "Sending device syspath:%s", p
);
161 assert_se(device_monitor_send_device(monitor_server
, monitor_client
, d
) >= 0);
164 log_device_info(device
, "Sending device syspath:%s", syspath
);
165 assert_se(device_monitor_send_device(monitor_server
, monitor_client
, device
) >= 0);
166 assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client
)) == 100);
170 static void test_sysattr_filter(sd_device
*device
, const char *sysattr
) {
171 _cleanup_(sd_device_monitor_unrefp
) sd_device_monitor
*monitor_server
= NULL
, *monitor_client
= NULL
;
172 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
173 const char *syspath
, *sysattr_value
;
176 log_device_info(device
, "/* %s(%s) */", __func__
, sysattr
);
178 assert_se(sd_device_get_syspath(device
, &syspath
) >= 0);
179 assert_se(sd_device_get_sysattr_value(device
, sysattr
, &sysattr_value
) >= 0);
181 assert_se(device_monitor_new_full(&monitor_server
, MONITOR_GROUP_NONE
, -1) >= 0);
182 assert_se(sd_device_monitor_set_description(monitor_server
, "sender") >= 0);
183 assert_se(sd_device_monitor_start(monitor_server
, NULL
, NULL
) >= 0);
185 assert_se(device_monitor_new_full(&monitor_client
, MONITOR_GROUP_NONE
, -1) >= 0);
186 assert_se(sd_device_monitor_set_description(monitor_client
, "receiver") >= 0);
187 assert_se(device_monitor_allow_unicast_sender(monitor_client
, monitor_server
) >= 0);
188 assert_se(sd_device_monitor_filter_add_match_sysattr(monitor_client
, sysattr
, sysattr_value
, true) >= 0);
189 assert_se(sd_device_monitor_start(monitor_client
, monitor_handler
, (void *) syspath
) >= 0);
191 assert_se(sd_device_enumerator_new(&e
) >= 0);
192 assert_se(sd_device_enumerator_add_match_sysattr(e
, sysattr
, sysattr_value
, false) >= 0);
193 FOREACH_DEVICE(e
, d
) {
196 assert_se(sd_device_get_syspath(d
, &p
) >= 0);
198 assert_se(device_add_property(d
, "ACTION", "add") >= 0);
199 assert_se(device_add_property(d
, "SEQNUM", "10") >= 0);
201 log_device_debug(d
, "Sending device syspath:%s", p
);
202 assert_se(device_monitor_send_device(monitor_server
, monitor_client
, d
) >= 0);
204 /* The sysattr filter is not implemented in BPF yet. So, sending multiple devices may fills up
205 * buffer and device_monitor_send_device() may return EAGAIN. Let's send one device here,
206 * which should be filtered out by the receiver. */
210 log_device_info(device
, "Sending device syspath:%s", syspath
);
211 assert_se(device_monitor_send_device(monitor_server
, monitor_client
, device
) >= 0);
212 assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client
)) == 100);
216 static void test_parent_filter(sd_device
*device
) {
217 _cleanup_(sd_device_monitor_unrefp
) sd_device_monitor
*monitor_server
= NULL
, *monitor_client
= NULL
;
218 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
219 const char *syspath
, *parent_syspath
;
220 sd_device
*parent
, *d
;
223 log_device_info(device
, "/* %s */", __func__
);
225 assert_se(sd_device_get_syspath(device
, &syspath
) >= 0);
226 r
= sd_device_get_parent(device
, &parent
);
228 return (void) log_device_info(device
, "Device does not have parent, skipping.");
229 assert_se(sd_device_get_syspath(parent
, &parent_syspath
) >= 0);
231 assert_se(device_monitor_new_full(&monitor_server
, MONITOR_GROUP_NONE
, -1) >= 0);
232 assert_se(sd_device_monitor_set_description(monitor_server
, "sender") >= 0);
233 assert_se(sd_device_monitor_start(monitor_server
, NULL
, NULL
) >= 0);
235 assert_se(device_monitor_new_full(&monitor_client
, MONITOR_GROUP_NONE
, -1) >= 0);
236 assert_se(sd_device_monitor_set_description(monitor_client
, "receiver") >= 0);
237 assert_se(device_monitor_allow_unicast_sender(monitor_client
, monitor_server
) >= 0);
238 assert_se(sd_device_monitor_filter_add_match_parent(monitor_client
, parent
, true) >= 0);
239 assert_se(sd_device_monitor_start(monitor_client
, monitor_handler
, (void *) syspath
) >= 0);
241 assert_se(sd_device_enumerator_new(&e
) >= 0);
242 FOREACH_DEVICE(e
, d
) {
245 assert_se(sd_device_get_syspath(d
, &p
) >= 0);
246 if (path_startswith(p
, parent_syspath
))
249 assert_se(device_add_property(d
, "ACTION", "add") >= 0);
250 assert_se(device_add_property(d
, "SEQNUM", "10") >= 0);
252 log_device_debug(d
, "Sending device syspath:%s", p
);
253 assert_se(device_monitor_send_device(monitor_server
, monitor_client
, d
) >= 0);
255 /* The parent filter is not implemented in BPF yet. So, sending multiple devices may fills up
256 * buffer and device_monitor_send_device() may return EAGAIN. Let's send one device here,
257 * which should be filtered out by the receiver. */
261 log_device_info(device
, "Sending device syspath:%s", syspath
);
262 assert_se(device_monitor_send_device(monitor_server
, monitor_client
, device
) >= 0);
263 assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client
)) == 100);
267 static void test_sd_device_monitor_filter_remove(sd_device
*device
) {
268 _cleanup_(sd_device_monitor_unrefp
) sd_device_monitor
*monitor_server
= NULL
, *monitor_client
= NULL
;
271 log_device_info(device
, "/* %s */", __func__
);
273 assert_se(sd_device_get_syspath(device
, &syspath
) >= 0);
275 assert_se(device_monitor_new_full(&monitor_server
, MONITOR_GROUP_NONE
, -1) >= 0);
276 assert_se(sd_device_monitor_set_description(monitor_server
, "sender") >= 0);
277 assert_se(sd_device_monitor_start(monitor_server
, NULL
, NULL
) >= 0);
279 assert_se(device_monitor_new_full(&monitor_client
, MONITOR_GROUP_NONE
, -1) >= 0);
280 assert_se(sd_device_monitor_set_description(monitor_client
, "receiver") >= 0);
281 assert_se(device_monitor_allow_unicast_sender(monitor_client
, monitor_server
) >= 0);
282 assert_se(sd_device_monitor_start(monitor_client
, monitor_handler
, (void *) syspath
) >= 0);
284 assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client
, "hoge", NULL
) >= 0);
285 assert_se(sd_device_monitor_filter_update(monitor_client
) >= 0);
287 assert_se(device_monitor_send_device(monitor_server
, monitor_client
, device
) >= 0);
288 assert_se(sd_event_run(sd_device_monitor_get_event(monitor_client
), 0) >= 0);
290 assert_se(sd_device_monitor_filter_remove(monitor_client
) >= 0);
292 assert_se(device_monitor_send_device(monitor_server
, monitor_client
, device
) >= 0);
293 assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client
)) == 100);
296 static void test_device_copy_properties(sd_device
*device
) {
297 _cleanup_(sd_device_unrefp
) sd_device
*copy
= NULL
;
299 assert_se(device_shallow_clone(device
, ©
) >= 0);
300 assert_se(device_copy_properties(copy
, device
) >= 0);
302 test_send_receive_one(copy
, false, false, false);
305 int main(int argc
, char *argv
[]) {
306 _cleanup_(sd_device_unrefp
) sd_device
*loopback
= NULL
, *sda
= NULL
;
309 test_setup_logging(LOG_INFO
);
312 return log_tests_skipped("not root");
314 if (path_is_read_only_fs("/sys") > 0)
315 return log_tests_skipped("Running in container");
317 test_receive_device_fail();
319 assert_se(sd_device_new_from_syspath(&loopback
, "/sys/class/net/lo") >= 0);
320 assert_se(device_add_property(loopback
, "ACTION", "add") >= 0);
321 assert_se(device_add_property(loopback
, "SEQNUM", "10") >= 0);
322 assert_se(device_add_tag(loopback
, "TEST_SD_DEVICE_MONITOR", true) >= 0);
324 test_send_receive_one(loopback
, false, false, false);
325 test_send_receive_one(loopback
, true, false, false);
326 test_send_receive_one(loopback
, false, true, false);
327 test_send_receive_one(loopback
, true, true, false);
328 test_send_receive_one(loopback
, true, false, true);
329 test_send_receive_one(loopback
, false, true, true);
330 test_send_receive_one(loopback
, true, true, true);
332 test_subsystem_filter(loopback
);
333 test_tag_filter(loopback
);
334 test_sysattr_filter(loopback
, "ifindex");
335 test_sd_device_monitor_filter_remove(loopback
);
336 test_device_copy_properties(loopback
);
338 r
= sd_device_new_from_subsystem_sysname(&sda
, "block", "sda");
340 log_info_errno(r
, "Failed to create sd_device for sda, skipping remaining tests: %m");
344 assert_se(device_add_property(sda
, "ACTION", "change") >= 0);
345 assert_se(device_add_property(sda
, "SEQNUM", "11") >= 0);
347 test_send_receive_one(sda
, false, false, false);
348 test_send_receive_one(sda
, true, false, false);
349 test_send_receive_one(sda
, false, true, false);
350 test_send_receive_one(sda
, true, true, false);
351 test_send_receive_one(sda
, true, false, true);
352 test_send_receive_one(sda
, false, true, true);
353 test_send_receive_one(sda
, true, true, true);
355 test_parent_filter(sda
);