]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/test-bus-objects.c
treewide: use log_*_errno whenever %m is in the format string
[thirdparty/systemd.git] / src / libsystemd / sd-bus / test-bus-objects.c
CommitLineData
29ddb38f
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <assert.h>
23#include <stdlib.h>
24#include <pthread.h>
25#include <unistd.h>
26#include <fcntl.h>
27
28#include "log.h"
29#include "util.h"
30#include "macro.h"
31#include "strv.h"
32
33#include "sd-bus.h"
34#include "bus-internal.h"
35#include "bus-message.h"
40ca29a1 36#include "bus-util.h"
d311601f 37#include "bus-dump.h"
29ddb38f 38
29ddb38f
LP
39struct context {
40 int fds[2];
41 bool quit;
42 char *something;
9db76355 43 char *automatic_string_property;
adcdb374 44 uint32_t automatic_integer_property;
29ddb38f
LP
45};
46
ebcf1f97 47static int something_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
29ddb38f
LP
48 struct context *c = userdata;
49 const char *s;
50 char *n = NULL;
51 int r;
52
53 r = sd_bus_message_read(m, "s", &s);
54 assert_se(r > 0);
55
56 n = strjoin("<<<", s, ">>>", NULL);
57 assert_se(n);
58
59 free(c->something);
60 c->something = n;
61
62 log_info("AlterSomething() called, got %s, returning %s", s, n);
63
6717d473
LP
64 /* This should fail, since the return type doesn't match */
65 assert_se(sd_bus_reply_method_return(m, "u", 4711) == -ENOMSG);
66
df2d202e 67 r = sd_bus_reply_method_return(m, "s", n);
29ddb38f
LP
68 assert_se(r >= 0);
69
70 return 1;
71}
72
ebcf1f97 73static int exit_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
29ddb38f
LP
74 struct context *c = userdata;
75 int r;
76
77 c->quit = true;
78
79 log_info("Exit called");
80
df2d202e 81 r = sd_bus_reply_method_return(m, "");
29ddb38f
LP
82 assert_se(r >= 0);
83
84 return 1;
85}
86
ebcf1f97 87static int get_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
29ddb38f
LP
88 struct context *c = userdata;
89 int r;
90
ebcf1f97 91 log_info("property get for %s called, returning \"%s\".", property, c->something);
29ddb38f
LP
92
93 r = sd_bus_message_append(reply, "s", c->something);
94 assert_se(r >= 0);
95
96 return 1;
97}
98
ebcf1f97 99static int set_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error) {
29ddb38f
LP
100 struct context *c = userdata;
101 const char *s;
102 char *n;
103 int r;
104
105 log_info("property set for %s called", property);
106
107 r = sd_bus_message_read(value, "s", &s);
108 assert_se(r >= 0);
109
110 n = strdup(s);
111 assert_se(n);
112
113 free(c->something);
114 c->something = n;
115
116 return 1;
117}
118
ebcf1f97 119static int value_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
29ddb38f
LP
120 _cleanup_free_ char *s = NULL;
121 const char *x;
122 int r;
123
124 assert_se(asprintf(&s, "object %p, path %s", userdata, path) >= 0);
125 r = sd_bus_message_append(reply, "s", s);
126 assert_se(r >= 0);
127
128 assert_se(x = startswith(path, "/value/"));
129
130 assert_se(PTR_TO_UINT(userdata) == 30);
131
62b5c2ae
LP
132 return 1;
133}
134
ebcf1f97 135static int notify_test(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
62b5c2ae
LP
136 int r;
137
138 assert_se(sd_bus_emit_properties_changed(bus, m->path, "org.freedesktop.systemd.ValueTest", "Value", NULL) >= 0);
139
df2d202e 140 r = sd_bus_reply_method_return(m, NULL);
62b5c2ae 141 assert_se(r >= 0);
29ddb38f
LP
142
143 return 1;
144}
145
a03e4337
LP
146static int notify_test2(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
147 int r;
148
149 assert_se(sd_bus_emit_properties_changed_strv(bus, m->path, "org.freedesktop.systemd.ValueTest", NULL) >= 0);
150
151 r = sd_bus_reply_method_return(m, NULL);
152 assert_se(r >= 0);
153
154 return 1;
155}
156
ebcf1f97 157static int emit_interfaces_added(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
4be39163
LP
158 int r;
159
160 assert_se(sd_bus_emit_interfaces_added(bus, m->path, "org.freedesktop.systemd.test", NULL) >= 0);
161
df2d202e 162 r = sd_bus_reply_method_return(m, NULL);
4be39163
LP
163 assert_se(r >= 0);
164
165 return 1;
166}
167
ebcf1f97 168static int emit_interfaces_removed(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
4be39163
LP
169 int r;
170
171 assert_se(sd_bus_emit_interfaces_removed(bus, m->path, "org.freedesktop.systemd.test", NULL) >= 0);
172
df2d202e 173 r = sd_bus_reply_method_return(m, NULL);
4be39163
LP
174 assert_se(r >= 0);
175
176 return 1;
177}
178
29ddb38f
LP
179static const sd_bus_vtable vtable[] = {
180 SD_BUS_VTABLE_START(0),
adcdb374
LP
181 SD_BUS_METHOD("AlterSomething", "s", "s", something_handler, 0),
182 SD_BUS_METHOD("Exit", "", "", exit_handler, 0),
29ddb38f 183 SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0),
9db76355
LP
184 SD_BUS_WRITABLE_PROPERTY("AutomaticStringProperty", "s", NULL, NULL, offsetof(struct context, automatic_string_property), 0),
185 SD_BUS_WRITABLE_PROPERTY("AutomaticIntegerProperty", "u", NULL, NULL, offsetof(struct context, automatic_integer_property), 0),
4be39163
LP
186 SD_BUS_METHOD("NoOperation", NULL, NULL, NULL, 0),
187 SD_BUS_METHOD("EmitInterfacesAdded", NULL, NULL, emit_interfaces_added, 0),
188 SD_BUS_METHOD("EmitInterfacesRemoved", NULL, NULL, emit_interfaces_removed, 0),
29ddb38f
LP
189 SD_BUS_VTABLE_END
190};
191
192static const sd_bus_vtable vtable2[] = {
193 SD_BUS_VTABLE_START(0),
adcdb374 194 SD_BUS_METHOD("NotifyTest", "", "", notify_test, 0),
a03e4337 195 SD_BUS_METHOD("NotifyTest2", "", "", notify_test2, 0),
62b5c2ae 196 SD_BUS_PROPERTY("Value", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
a03e4337
LP
197 SD_BUS_PROPERTY("Value2", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
198 SD_BUS_PROPERTY("Value3", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_CONST),
199 SD_BUS_PROPERTY("Value4", "s", value_handler, 10, 0),
29ddb38f
LP
200 SD_BUS_VTABLE_END
201};
202
19befb2d 203static int enumerator_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
29ddb38f
LP
204
205 if (object_path_startswith("/value", path))
206 assert_se(*nodes = strv_new("/value/a", "/value/b", "/value/c", NULL));
207
208 return 1;
209}
210
211static void *server(void *p) {
212 struct context *c = p;
213 sd_bus *bus = NULL;
214 sd_id128_t id;
215 int r;
216
217 c->quit = false;
218
219 assert_se(sd_id128_randomize(&id) >= 0);
220
221 assert_se(sd_bus_new(&bus) >= 0);
222 assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
223 assert_se(sd_bus_set_server(bus, 1, id) >= 0);
224
19befb2d
LP
225 assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test", vtable, c) >= 0);
226 assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0);
227 assert_se(sd_bus_add_fallback_vtable(bus, NULL, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0);
228 assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value", enumerator_callback, NULL) >= 0);
229 assert_se(sd_bus_add_object_manager(bus, NULL, "/value") >= 0);
29ddb38f
LP
230
231 assert_se(sd_bus_start(bus) >= 0);
232
233 log_error("Entering event loop on server");
234
235 while (!c->quit) {
236 log_error("Loop!");
237
238 r = sd_bus_process(bus, NULL);
239 if (r < 0) {
da927ba9 240 log_error_errno(r, "Failed to process requests: %m");
29ddb38f
LP
241 goto fail;
242 }
243
244 if (r == 0) {
245 r = sd_bus_wait(bus, (uint64_t) -1);
246 if (r < 0) {
da927ba9 247 log_error_errno(r, "Failed to wait: %m");
29ddb38f
LP
248 goto fail;
249 }
250
251 continue;
252 }
253 }
254
255 r = 0;
256
257fail:
258 if (bus) {
259 sd_bus_flush(bus);
260 sd_bus_unref(bus);
261 }
262
263 return INT_TO_PTR(r);
264}
265
266static int client(struct context *c) {
267 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
268 _cleanup_bus_unref_ sd_bus *bus = NULL;
269 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
270 const char *s;
271 int r;
272
273 assert_se(sd_bus_new(&bus) >= 0);
274 assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
275 assert_se(sd_bus_start(bus) >= 0);
276
43a43f50
LP
277 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "NoOperation", &error, NULL, NULL);
278 assert_se(r >= 0);
279
29ddb38f
LP
280 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "s", "hallo");
281 assert_se(r >= 0);
282
283 r = sd_bus_message_read(reply, "s", &s);
284 assert_se(r >= 0);
285 assert_se(streq(s, "<<<hallo>>>"));
286
287 sd_bus_message_unref(reply);
288 reply = NULL;
289
290 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, "");
291 assert_se(r < 0);
40ca29a1 292 assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
29ddb38f
LP
293
294 sd_bus_error_free(&error);
295
296 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "as", 1, "hallo");
297 assert_se(r < 0);
40ca29a1 298 assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_INVALID_ARGS));
29ddb38f
LP
299
300 sd_bus_error_free(&error);
301
302 r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s");
303 assert_se(r >= 0);
304
305 r = sd_bus_message_read(reply, "s", &s);
306 assert_se(r >= 0);
307 assert_se(streq(s, "<<<hallo>>>"));
308
309 sd_bus_message_unref(reply);
310 reply = NULL;
311
312 r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, "s", "test");
313 assert_se(r >= 0);
314
315 r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s");
316 assert_se(r >= 0);
317
318 r = sd_bus_message_read(reply, "s", &s);
319 assert_se(r >= 0);
320 assert_se(streq(s, "test"));
321
322 sd_bus_message_unref(reply);
323 reply = NULL;
324
9db76355
LP
325 r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticIntegerProperty", &error, "u", 815);
326 assert_se(r >= 0);
327
328 assert_se(c->automatic_integer_property == 815);
329
330 r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticStringProperty", &error, "s", "Du Dödel, Du!");
331 assert_se(r >= 0);
332
333 assert_se(streq(c->automatic_string_property, "Du Dödel, Du!"));
334
29ddb38f 335 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
5d12cc3e 336 assert_se(r >= 0);
29ddb38f
LP
337
338 r = sd_bus_message_read(reply, "s", &s);
339 assert_se(r >= 0);
340 fputs(s, stdout);
341
342 sd_bus_message_unref(reply);
343 reply = NULL;
344
345 r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/value/xuzz", "org.freedesktop.systemd.ValueTest", "Value", &error, &reply, "s");
346 assert_se(r >= 0);
347
348 r = sd_bus_message_read(reply, "s", &s);
349 assert_se(r >= 0);
350 log_info("read %s", s);
351
352 sd_bus_message_unref(reply);
353 reply = NULL;
354
355 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
5d12cc3e 356 assert_se(r >= 0);
29ddb38f
LP
357
358 r = sd_bus_message_read(reply, "s", &s);
359 assert_se(r >= 0);
360 fputs(s, stdout);
361
362 sd_bus_message_unref(reply);
363 reply = NULL;
364
365 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
5d12cc3e 366 assert_se(r >= 0);
29ddb38f
LP
367
368 r = sd_bus_message_read(reply, "s", &s);
369 assert_se(r >= 0);
370 fputs(s, stdout);
371
372 sd_bus_message_unref(reply);
373 reply = NULL;
374
375 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
5d12cc3e 376 assert_se(r >= 0);
29ddb38f
LP
377
378 r = sd_bus_message_read(reply, "s", &s);
379 assert_se(r >= 0);
380 fputs(s, stdout);
381
382 sd_bus_message_unref(reply);
383 reply = NULL;
384
385 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "");
5d12cc3e 386 assert_se(r >= 0);
29ddb38f 387
d55192ad 388 bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
29ddb38f
LP
389
390 sd_bus_message_unref(reply);
391 reply = NULL;
392
393 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "org.freedesktop.systemd.ValueTest2");
394 assert_se(r < 0);
40ca29a1 395 assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_INTERFACE));
29ddb38f
LP
396 sd_bus_error_free(&error);
397
5d12cc3e
LP
398 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, "");
399 assert_se(r < 0);
40ca29a1 400 assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
5d12cc3e
LP
401 sd_bus_error_free(&error);
402
403 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, "");
404 assert_se(r >= 0);
405
d55192ad 406 bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
5d12cc3e
LP
407
408 sd_bus_message_unref(reply);
409 reply = NULL;
410
62b5c2ae
LP
411 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest", &error, NULL, "");
412 assert_se(r >= 0);
413
414 r = sd_bus_process(bus, &reply);
415 assert_se(r > 0);
416
417 assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
d55192ad 418 bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
a03e4337
LP
419
420 sd_bus_message_unref(reply);
421 reply = NULL;
422
423 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest2", &error, NULL, "");
424 assert_se(r >= 0);
425
426 r = sd_bus_process(bus, &reply);
427 assert_se(r > 0);
428
429 assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
d55192ad 430 bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
4be39163
LP
431
432 sd_bus_message_unref(reply);
433 reply = NULL;
434
435 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesAdded", &error, NULL, "");
436 assert_se(r >= 0);
437
438 r = sd_bus_process(bus, &reply);
439 assert_se(r > 0);
440
441 assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
d55192ad 442 bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
4be39163
LP
443
444 sd_bus_message_unref(reply);
445 reply = NULL;
446
447 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesRemoved", &error, NULL, "");
448 assert_se(r >= 0);
449
450 r = sd_bus_process(bus, &reply);
451 assert_se(r > 0);
452
453 assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"));
d55192ad 454 bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
62b5c2ae
LP
455
456 sd_bus_message_unref(reply);
457 reply = NULL;
458
29ddb38f
LP
459 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Exit", &error, NULL, "");
460 assert_se(r >= 0);
461
462 sd_bus_flush(bus);
463
464 return 0;
465}
466
467int main(int argc, char *argv[]) {
ebcf1f97 468 struct context c = {};
29ddb38f
LP
469 pthread_t s;
470 void *p;
471 int r, q;
472
473 zero(c);
474
adcdb374 475 c.automatic_integer_property = 4711;
9db76355 476 assert_se(c.automatic_string_property = strdup("dudeldu"));
adcdb374 477
29ddb38f
LP
478 assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0);
479
480 r = pthread_create(&s, NULL, server, &c);
481 if (r != 0)
482 return -r;
483
484 r = client(&c);
485
486 q = pthread_join(s, &p);
487 if (q != 0)
488 return -q;
489
490 if (r < 0)
491 return r;
492
493 if (PTR_TO_INT(p) < 0)
494 return PTR_TO_INT(p);
495
496 free(c.something);
9db76355 497 free(c.automatic_string_property);
29ddb38f
LP
498
499 return EXIT_SUCCESS;
500}