1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <pthread.h>
4 #include <stdlib.h>
5 
6 #include "sd-bus.h"
7 
8 #include "alloc-util.h"
9 #include "bus-dump.h"
10 #include "bus-internal.h"
11 #include "bus-message.h"
12 #include "log.h"
13 #include "macro.h"
14 #include "strv.h"
15 #include "util.h"
16 
17 struct context {
18         int fds[2];
19         bool quit;
20         char *something;
21         char *automatic_string_property;
22         uint32_t automatic_integer_property;
23 };
24 
something_handler(sd_bus_message * m,void * userdata,sd_bus_error * error)25 static int something_handler(sd_bus_message *m, void *userdata, sd_bus_error *error) {
26         struct context *c = userdata;
27         const char *s;
28         char *n = NULL;
29         int r;
30 
31         r = sd_bus_message_read(m, "s", &s);
32         assert_se(r > 0);
33 
34         n = strjoin("<<<", s, ">>>");
35         assert_se(n);
36 
37         free(c->something);
38         c->something = n;
39 
40         log_info("AlterSomething() called, got %s, returning %s", s, n);
41 
42         /* This should fail, since the return type doesn't match */
43         assert_se(sd_bus_reply_method_return(m, "u", 4711) == -ENOMSG);
44 
45         r = sd_bus_reply_method_return(m, "s", n);
46         assert_se(r >= 0);
47 
48         return 1;
49 }
50 
exit_handler(sd_bus_message * m,void * userdata,sd_bus_error * error)51 static int exit_handler(sd_bus_message *m, void *userdata, sd_bus_error *error) {
52         struct context *c = userdata;
53         int r;
54 
55         c->quit = true;
56 
57         log_info("Exit called");
58 
59         r = sd_bus_reply_method_return(m, "");
60         assert_se(r >= 0);
61 
62         return 1;
63 }
64 
get_handler(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)65 static 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) {
66         struct context *c = userdata;
67         int r;
68 
69         log_info("property get for %s called, returning \"%s\".", property, c->something);
70 
71         r = sd_bus_message_append(reply, "s", c->something);
72         assert_se(r >= 0);
73 
74         return 1;
75 }
76 
set_handler(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * value,void * userdata,sd_bus_error * error)77 static 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) {
78         struct context *c = userdata;
79         const char *s;
80         char *n;
81         int r;
82 
83         log_info("property set for %s called", property);
84 
85         r = sd_bus_message_read(value, "s", &s);
86         assert_se(r >= 0);
87 
88         n = strdup(s);
89         assert_se(n);
90 
91         free(c->something);
92         c->something = n;
93 
94         return 1;
95 }
96 
value_handler(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)97 static 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) {
98         _cleanup_free_ char *s = NULL;
99         const char *x;
100         int r;
101 
102         assert_se(asprintf(&s, "object %p, path %s", userdata, path) >= 0);
103         r = sd_bus_message_append(reply, "s", s);
104         assert_se(r >= 0);
105 
106         assert_se(x = startswith(path, "/value/"));
107 
108         assert_se(PTR_TO_UINT(userdata) == 30);
109 
110         return 1;
111 }
112 
notify_test(sd_bus_message * m,void * userdata,sd_bus_error * error)113 static int notify_test(sd_bus_message *m, void *userdata, sd_bus_error *error) {
114         int r;
115 
116         assert_se(sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.ValueTest", "Value", NULL) >= 0);
117 
118         r = sd_bus_reply_method_return(m, NULL);
119         assert_se(r >= 0);
120 
121         return 1;
122 }
123 
notify_test2(sd_bus_message * m,void * userdata,sd_bus_error * error)124 static int notify_test2(sd_bus_message *m, void *userdata, sd_bus_error *error) {
125         int r;
126 
127         assert_se(sd_bus_emit_properties_changed_strv(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.ValueTest", NULL) >= 0);
128 
129         r = sd_bus_reply_method_return(m, NULL);
130         assert_se(r >= 0);
131 
132         return 1;
133 }
134 
emit_interfaces_added(sd_bus_message * m,void * userdata,sd_bus_error * error)135 static int emit_interfaces_added(sd_bus_message *m, void *userdata, sd_bus_error *error) {
136         int r;
137 
138         assert_se(sd_bus_emit_interfaces_added(sd_bus_message_get_bus(m), "/value/a/x", "org.freedesktop.systemd.ValueTest", NULL) >= 0);
139 
140         r = sd_bus_reply_method_return(m, NULL);
141         assert_se(r >= 0);
142 
143         return 1;
144 }
145 
emit_interfaces_removed(sd_bus_message * m,void * userdata,sd_bus_error * error)146 static int emit_interfaces_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
147         int r;
148 
149         assert_se(sd_bus_emit_interfaces_removed(sd_bus_message_get_bus(m), "/value/a/x", "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 
emit_object_added(sd_bus_message * m,void * userdata,sd_bus_error * error)157 static int emit_object_added(sd_bus_message *m, void *userdata, sd_bus_error *error) {
158         int r;
159 
160         assert_se(sd_bus_emit_object_added(sd_bus_message_get_bus(m), "/value/a/x") >= 0);
161 
162         r = sd_bus_reply_method_return(m, NULL);
163         assert_se(r >= 0);
164 
165         return 1;
166 }
167 
emit_object_removed(sd_bus_message * m,void * userdata,sd_bus_error * error)168 static int emit_object_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
169         int r;
170 
171         assert_se(sd_bus_emit_object_removed(sd_bus_message_get_bus(m), "/value/a/x") >= 0);
172 
173         r = sd_bus_reply_method_return(m, NULL);
174         assert_se(r >= 0);
175 
176         return 1;
177 }
178 
179 static const sd_bus_vtable vtable[] = {
180         SD_BUS_VTABLE_START(0),
181         SD_BUS_METHOD("AlterSomething", "s", "s", something_handler, 0),
182         SD_BUS_METHOD("Exit", "", "", exit_handler, 0),
183         SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0),
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),
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),
189         SD_BUS_METHOD("EmitObjectAdded", NULL, NULL, emit_object_added, 0),
190         SD_BUS_METHOD("EmitObjectRemoved", NULL, NULL, emit_object_removed, 0),
191         SD_BUS_VTABLE_END
192 };
193 
194 static const sd_bus_vtable vtable2[] = {
195         SD_BUS_VTABLE_START(0),
196         SD_BUS_METHOD("NotifyTest", "", "", notify_test, 0),
197         SD_BUS_METHOD("NotifyTest2", "", "", notify_test2, 0),
198         SD_BUS_PROPERTY("Value", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
199         SD_BUS_PROPERTY("Value2", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
200         SD_BUS_PROPERTY("Value3", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_CONST),
201         SD_BUS_PROPERTY("Value4", "s", value_handler, 10, 0),
202         SD_BUS_PROPERTY("AnExplicitProperty", "s", NULL, offsetof(struct context, something), SD_BUS_VTABLE_PROPERTY_EXPLICIT|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
203         SD_BUS_VTABLE_END
204 };
205 
enumerator_callback(sd_bus * bus,const char * path,void * userdata,char *** nodes,sd_bus_error * error)206 static int enumerator_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
207 
208         if (object_path_startswith("/value", path))
209                 assert_se(*nodes = strv_new("/value/a", "/value/b", "/value/c"));
210 
211         return 1;
212 }
213 
enumerator2_callback(sd_bus * bus,const char * path,void * userdata,char *** nodes,sd_bus_error * error)214 static int enumerator2_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
215 
216         if (object_path_startswith("/value/a", path))
217                 assert_se(*nodes = strv_new("/value/a/x", "/value/a/y", "/value/a/z"));
218 
219         return 1;
220 }
221 
enumerator3_callback(sd_bus * bus,const char * path,void * userdata,char *** nodes,sd_bus_error * error)222 static int enumerator3_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
223         _cleanup_strv_free_ char **v = NULL;
224 
225         if (!object_path_startswith("/value/b", path))
226                 return 1;
227 
228         for (unsigned i = 0; i < 30; i++)
229                 assert_se(strv_extendf(&v, "/value/b/%u", i) >= 0);
230 
231         *nodes = TAKE_PTR(v);
232         return 1;
233 }
234 
server(void * p)235 static void *server(void *p) {
236         struct context *c = p;
237         sd_bus *bus = NULL;
238         sd_id128_t id;
239         int r;
240 
241         c->quit = false;
242 
243         assert_se(sd_id128_randomize(&id) >= 0);
244 
245         assert_se(sd_bus_new(&bus) >= 0);
246         assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
247         assert_se(sd_bus_set_server(bus, 1, id) >= 0);
248 
249         assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test", vtable, c) >= 0);
250         assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0);
251         assert_se(sd_bus_add_fallback_vtable(bus, NULL, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0);
252         assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value", enumerator_callback, NULL) >= 0);
253         assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value/a", enumerator2_callback, NULL) >= 0);
254         assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value/b", enumerator3_callback, NULL) >= 0);
255         assert_se(sd_bus_add_object_manager(bus, NULL, "/value") >= 0);
256         assert_se(sd_bus_add_object_manager(bus, NULL, "/value/a") >= 0);
257 
258         assert_se(sd_bus_start(bus) >= 0);
259 
260         log_error("Entering event loop on server");
261 
262         while (!c->quit) {
263                 log_error("Loop!");
264 
265                 r = sd_bus_process(bus, NULL);
266                 if (r < 0) {
267                         log_error_errno(r, "Failed to process requests: %m");
268                         goto fail;
269                 }
270 
271                 if (r == 0) {
272                         r = sd_bus_wait(bus, UINT64_MAX);
273                         if (r < 0) {
274                                 log_error_errno(r, "Failed to wait: %m");
275                                 goto fail;
276                         }
277 
278                         continue;
279                 }
280         }
281 
282         r = 0;
283 
284 fail:
285         if (bus) {
286                 sd_bus_flush(bus);
287                 sd_bus_unref(bus);
288         }
289 
290         return INT_TO_PTR(r);
291 }
292 
client(struct context * c)293 static int client(struct context *c) {
294         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
295         _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
296         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
297         _cleanup_strv_free_ char **lines = NULL;
298         const char *s;
299         int r;
300 
301         assert_se(sd_bus_new(&bus) >= 0);
302         assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
303         assert_se(sd_bus_start(bus) >= 0);
304 
305         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "NoOperation", &error, NULL, NULL);
306         assert_se(r >= 0);
307 
308         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "s", "hallo");
309         assert_se(r >= 0);
310 
311         r = sd_bus_message_read(reply, "s", &s);
312         assert_se(r >= 0);
313         assert_se(streq(s, "<<<hallo>>>"));
314 
315         reply = sd_bus_message_unref(reply);
316 
317         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, "");
318         assert_se(r < 0);
319         assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
320 
321         sd_bus_error_free(&error);
322 
323         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, NULL); /* NULL and "" are equivalent */
324         assert_se(r < 0);
325         assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
326 
327         sd_bus_error_free(&error);
328 
329         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "as", 1, "hallo");
330         assert_se(r < 0);
331         assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_INVALID_ARGS));
332 
333         sd_bus_error_free(&error);
334 
335         r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s");
336         assert_se(r >= 0);
337 
338         r = sd_bus_message_read(reply, "s", &s);
339         assert_se(r >= 0);
340         assert_se(streq(s, "<<<hallo>>>"));
341 
342         reply = sd_bus_message_unref(reply);
343 
344         r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, "s", "test");
345         assert_se(r >= 0);
346 
347         r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s");
348         assert_se(r >= 0);
349 
350         r = sd_bus_message_read(reply, "s", &s);
351         assert_se(r >= 0);
352         assert_se(streq(s, "test"));
353 
354         reply = sd_bus_message_unref(reply);
355 
356         r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticIntegerProperty", &error, "u", 815);
357         assert_se(r >= 0);
358 
359         assert_se(c->automatic_integer_property == 815);
360 
361         r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticStringProperty", &error, "s", "Du Dödel, Du!");
362         assert_se(r >= 0);
363 
364         assert_se(streq(c->automatic_string_property, "Du Dödel, Du!"));
365 
366         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
367         assert_se(r >= 0);
368 
369         r = sd_bus_message_read(reply, "s", &s);
370         assert_se(r >= 0);
371         fputs(s, stdout);
372 
373         reply = sd_bus_message_unref(reply);
374 
375         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, NULL); /* NULL and "" are equivalent */
376         assert_se(r >= 0);
377 
378         r = sd_bus_message_read(reply, "s", &s);
379         assert_se(r >= 0);
380         fputs(s, stdout);
381 
382         reply = sd_bus_message_unref(reply);
383 
384         r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/value/xuzz", "org.freedesktop.systemd.ValueTest", "Value", &error, &reply, "s");
385         assert_se(r >= 0);
386 
387         r = sd_bus_message_read(reply, "s", &s);
388         assert_se(r >= 0);
389         log_info("read %s", s);
390 
391         reply = sd_bus_message_unref(reply);
392 
393         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, NULL);
394         assert_se(r >= 0);
395 
396         r = sd_bus_message_read(reply, "s", &s);
397         assert_se(r >= 0);
398         fputs(s, stdout);
399 
400         reply = sd_bus_message_unref(reply);
401 
402         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, NULL);
403         assert_se(r >= 0);
404 
405         r = sd_bus_message_read(reply, "s", &s);
406         assert_se(r >= 0);
407         fputs(s, stdout);
408 
409         reply = sd_bus_message_unref(reply);
410 
411         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, NULL);
412         assert_se(r >= 0);
413 
414         r = sd_bus_message_read(reply, "s", &s);
415         assert_se(r >= 0);
416         fputs(s, stdout);
417 
418         assert_se(lines = strv_split_newlines(s));
419         assert_se(strv_contains(lines, " <node name=\"x\"/>"));
420         assert_se(strv_contains(lines, " <node name=\"y\"/>"));
421         assert_se(strv_contains(lines, " <node name=\"z\"/>"));
422         lines = strv_free(lines);
423 
424         reply = sd_bus_message_unref(reply);
425 
426         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/b", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, NULL);
427         assert_se(r >= 0);
428 
429         r = sd_bus_message_read(reply, "s", &s);
430         assert_se(r >= 0);
431         fputs(s, stdout);
432 
433         assert_se(lines = strv_split_newlines(s));
434         for (unsigned i = 0; i < 30; i++) {
435                 _cleanup_free_ char *n = NULL;
436 
437                 assert_se(asprintf(&n, " <node name=\"%u\"/>", i) >= 0);
438                 assert_se(strv_contains(lines, n));
439         }
440         lines = strv_free(lines);
441 
442         reply = sd_bus_message_unref(reply);
443 
444         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", NULL);
445         assert_se(r >= 0);
446 
447         sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
448 
449         reply = sd_bus_message_unref(reply);
450 
451         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "org.freedesktop.systemd.ValueTest2");
452         assert_se(r < 0);
453         assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_INTERFACE));
454         sd_bus_error_free(&error);
455 
456         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, NULL);
457         assert_se(r < 0);
458         assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
459         sd_bus_error_free(&error);
460 
461         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, NULL);
462         assert_se(r >= 0);
463 
464         sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
465 
466         reply = sd_bus_message_unref(reply);
467 
468         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest", &error, NULL, NULL);
469         assert_se(r >= 0);
470 
471         r = sd_bus_process(bus, &reply);
472         assert_se(r > 0);
473 
474         assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
475         sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
476 
477         reply = sd_bus_message_unref(reply);
478 
479         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest2", &error, NULL, NULL);
480         assert_se(r >= 0);
481 
482         r = sd_bus_process(bus, &reply);
483         assert_se(r > 0);
484 
485         assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
486         sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
487 
488         reply = sd_bus_message_unref(reply);
489 
490         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesAdded", &error, NULL, NULL);
491         assert_se(r >= 0);
492 
493         r = sd_bus_process(bus, &reply);
494         assert_se(r > 0);
495 
496         assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
497         sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
498 
499         reply = sd_bus_message_unref(reply);
500 
501         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesRemoved", &error, NULL, NULL);
502         assert_se(r >= 0);
503 
504         r = sd_bus_process(bus, &reply);
505         assert_se(r > 0);
506 
507         assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"));
508         sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
509 
510         reply = sd_bus_message_unref(reply);
511 
512         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectAdded", &error, NULL, NULL);
513         assert_se(r >= 0);
514 
515         r = sd_bus_process(bus, &reply);
516         assert_se(r > 0);
517 
518         assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
519         sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
520 
521         reply = sd_bus_message_unref(reply);
522 
523         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectRemoved", &error, NULL, NULL);
524         assert_se(r >= 0);
525 
526         r = sd_bus_process(bus, &reply);
527         assert_se(r > 0);
528 
529         assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"));
530         sd_bus_message_dump(reply, stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
531 
532         reply = sd_bus_message_unref(reply);
533 
534         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Exit", &error, NULL, NULL);
535         assert_se(r >= 0);
536 
537         sd_bus_flush(bus);
538 
539         return 0;
540 }
541 
main(int argc,char * argv[])542 int main(int argc, char *argv[]) {
543         struct context c = {};
544         pthread_t s;
545         void *p;
546         int r, q;
547 
548         c.automatic_integer_property = 4711;
549         assert_se(c.automatic_string_property = strdup("dudeldu"));
550 
551         assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0);
552 
553         r = pthread_create(&s, NULL, server, &c);
554         if (r != 0)
555                 return -r;
556 
557         r = client(&c);
558 
559         q = pthread_join(s, &p);
560         if (q != 0)
561                 return -q;
562 
563         if (r < 0)
564                 return r;
565 
566         if (PTR_TO_INT(p) < 0)
567                 return PTR_TO_INT(p);
568 
569         free(c.something);
570         free(c.automatic_string_property);
571 
572         return EXIT_SUCCESS;
573 }
574