]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/test-bus-objects.c
Add support for saving/restoring keyboard backlights
[thirdparty/systemd.git] / src / libsystemd-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"
36
37/* Test:
29ddb38f
LP
38 *
39 * Add in:
40 *
adcdb374
LP
41 * automatic properties for Set()
42 * automatic NULL method
43 * allow NULL as signatures in vtable
29ddb38f
LP
44 * node hierarchy updates during dispatching
45 * emit_interfaces_added/emit_interfaces_removed
46 *
47 */
48
49struct context {
50 int fds[2];
51 bool quit;
52 char *something;
adcdb374
LP
53 const char *automatic_string_property;
54 uint32_t automatic_integer_property;
29ddb38f
LP
55};
56
57static int something_handler(sd_bus *bus, sd_bus_message *m, void *userdata) {
58 struct context *c = userdata;
59 const char *s;
60 char *n = NULL;
61 int r;
62
63 r = sd_bus_message_read(m, "s", &s);
64 assert_se(r > 0);
65
66 n = strjoin("<<<", s, ">>>", NULL);
67 assert_se(n);
68
69 free(c->something);
70 c->something = n;
71
72 log_info("AlterSomething() called, got %s, returning %s", s, n);
73
74 r = sd_bus_reply_method_return(bus, m, "s", n);
75 assert_se(r >= 0);
76
77 return 1;
78}
79
80static int exit_handler(sd_bus *bus, sd_bus_message *m, void *userdata) {
81 struct context *c = userdata;
82 int r;
83
84 c->quit = true;
85
86 log_info("Exit called");
87
88 r = sd_bus_reply_method_return(bus, m, "");
89 assert_se(r >= 0);
90
91 return 1;
92}
93
94static int get_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata) {
95 struct context *c = userdata;
96 int r;
97
98 log_info("property get for %s called", property);
99
100 r = sd_bus_message_append(reply, "s", c->something);
101 assert_se(r >= 0);
102
103 return 1;
104}
105
106static int set_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, sd_bus_error *error, void *userdata) {
107 struct context *c = userdata;
108 const char *s;
109 char *n;
110 int r;
111
112 log_info("property set for %s called", property);
113
114 r = sd_bus_message_read(value, "s", &s);
115 assert_se(r >= 0);
116
117 n = strdup(s);
118 assert_se(n);
119
120 free(c->something);
121 c->something = n;
122
123 return 1;
124}
125
126static int value_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata) {
127 _cleanup_free_ char *s = NULL;
128 const char *x;
129 int r;
130
131 assert_se(asprintf(&s, "object %p, path %s", userdata, path) >= 0);
132 r = sd_bus_message_append(reply, "s", s);
133 assert_se(r >= 0);
134
135 assert_se(x = startswith(path, "/value/"));
136
137 assert_se(PTR_TO_UINT(userdata) == 30);
138
62b5c2ae
LP
139 return 1;
140}
141
142static int notify_test(sd_bus *bus, sd_bus_message *m, void *userdata) {
143 int r;
144
145 assert_se(sd_bus_emit_properties_changed(bus, m->path, "org.freedesktop.systemd.ValueTest", "Value", NULL) >= 0);
146
147 r = sd_bus_reply_method_return(bus, m, NULL);
148 assert_se(r >= 0);
29ddb38f
LP
149
150 return 1;
151}
152
153static const sd_bus_vtable vtable[] = {
154 SD_BUS_VTABLE_START(0),
adcdb374
LP
155 SD_BUS_METHOD("AlterSomething", "s", "s", something_handler, 0),
156 SD_BUS_METHOD("Exit", "", "", exit_handler, 0),
29ddb38f 157 SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0),
adcdb374
LP
158 SD_BUS_PROPERTY("AutomaticStringProperty", "s", NULL, offsetof(struct context, automatic_string_property), 0),
159 SD_BUS_PROPERTY("AutomaticIntegerProperty", "u", NULL, offsetof(struct context, automatic_integer_property), 0),
29ddb38f
LP
160 SD_BUS_VTABLE_END
161};
162
163static const sd_bus_vtable vtable2[] = {
164 SD_BUS_VTABLE_START(0),
adcdb374 165 SD_BUS_METHOD("NotifyTest", "", "", notify_test, 0),
62b5c2ae 166 SD_BUS_PROPERTY("Value", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
29ddb38f
LP
167 SD_BUS_VTABLE_END
168};
169
170static int enumerator_callback(sd_bus *b, const char *path, char ***nodes, void *userdata) {
171
172 if (object_path_startswith("/value", path))
173 assert_se(*nodes = strv_new("/value/a", "/value/b", "/value/c", NULL));
174
175 return 1;
176}
177
178static void *server(void *p) {
179 struct context *c = p;
180 sd_bus *bus = NULL;
181 sd_id128_t id;
182 int r;
183
184 c->quit = false;
185
186 assert_se(sd_id128_randomize(&id) >= 0);
187
188 assert_se(sd_bus_new(&bus) >= 0);
189 assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
190 assert_se(sd_bus_set_server(bus, 1, id) >= 0);
191
192 assert_se(sd_bus_add_object_vtable(bus, "/foo", "org.freedesktop.systemd.test", vtable, c) >= 0);
193 assert_se(sd_bus_add_object_vtable(bus, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0);
194 assert_se(sd_bus_add_fallback_vtable(bus, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0);
195 assert_se(sd_bus_add_node_enumerator(bus, "/value", enumerator_callback, NULL) >= 0);
5d12cc3e 196 assert_se(sd_bus_add_object_manager(bus, "/value") >= 0);
29ddb38f
LP
197
198 assert_se(sd_bus_start(bus) >= 0);
199
200 log_error("Entering event loop on server");
201
202 while (!c->quit) {
203 log_error("Loop!");
204
205 r = sd_bus_process(bus, NULL);
206 if (r < 0) {
207 log_error("Failed to process requests: %s", strerror(-r));
208 goto fail;
209 }
210
211 if (r == 0) {
212 r = sd_bus_wait(bus, (uint64_t) -1);
213 if (r < 0) {
214 log_error("Failed to wait: %s", strerror(-r));
215 goto fail;
216 }
217
218 continue;
219 }
220 }
221
222 r = 0;
223
224fail:
225 if (bus) {
226 sd_bus_flush(bus);
227 sd_bus_unref(bus);
228 }
229
230 return INT_TO_PTR(r);
231}
232
233static int client(struct context *c) {
234 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
235 _cleanup_bus_unref_ sd_bus *bus = NULL;
236 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
237 const char *s;
238 int r;
239
240 assert_se(sd_bus_new(&bus) >= 0);
241 assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
242 assert_se(sd_bus_start(bus) >= 0);
243
244 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "s", "hallo");
245 assert_se(r >= 0);
246
247 r = sd_bus_message_read(reply, "s", &s);
248 assert_se(r >= 0);
249 assert_se(streq(s, "<<<hallo>>>"));
250
251 sd_bus_message_unref(reply);
252 reply = NULL;
253
254 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, "");
255 assert_se(r < 0);
256 assert_se(sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.UnknownMethod"));
257
258 sd_bus_error_free(&error);
259
260 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "as", 1, "hallo");
261 assert_se(r < 0);
262 assert_se(sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.InvalidArgs"));
263
264 sd_bus_error_free(&error);
265
266 r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s");
267 assert_se(r >= 0);
268
269 r = sd_bus_message_read(reply, "s", &s);
270 assert_se(r >= 0);
271 assert_se(streq(s, "<<<hallo>>>"));
272
273 sd_bus_message_unref(reply);
274 reply = NULL;
275
276 r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, "s", "test");
277 assert_se(r >= 0);
278
279 r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s");
280 assert_se(r >= 0);
281
282 r = sd_bus_message_read(reply, "s", &s);
283 assert_se(r >= 0);
284 assert_se(streq(s, "test"));
285
286 sd_bus_message_unref(reply);
287 reply = NULL;
288
289 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
5d12cc3e 290 assert_se(r >= 0);
29ddb38f
LP
291
292 r = sd_bus_message_read(reply, "s", &s);
293 assert_se(r >= 0);
294 fputs(s, stdout);
295
296 sd_bus_message_unref(reply);
297 reply = NULL;
298
299 r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/value/xuzz", "org.freedesktop.systemd.ValueTest", "Value", &error, &reply, "s");
300 assert_se(r >= 0);
301
302 r = sd_bus_message_read(reply, "s", &s);
303 assert_se(r >= 0);
304 log_info("read %s", s);
305
306 sd_bus_message_unref(reply);
307 reply = NULL;
308
309 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
5d12cc3e 310 assert_se(r >= 0);
29ddb38f
LP
311
312 r = sd_bus_message_read(reply, "s", &s);
313 assert_se(r >= 0);
314 fputs(s, stdout);
315
316 sd_bus_message_unref(reply);
317 reply = NULL;
318
319 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
5d12cc3e 320 assert_se(r >= 0);
29ddb38f
LP
321
322 r = sd_bus_message_read(reply, "s", &s);
323 assert_se(r >= 0);
324 fputs(s, stdout);
325
326 sd_bus_message_unref(reply);
327 reply = NULL;
328
329 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
5d12cc3e 330 assert_se(r >= 0);
29ddb38f
LP
331
332 r = sd_bus_message_read(reply, "s", &s);
333 assert_se(r >= 0);
334 fputs(s, stdout);
335
336 sd_bus_message_unref(reply);
337 reply = NULL;
338
339 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "");
5d12cc3e 340 assert_se(r >= 0);
29ddb38f
LP
341
342 bus_message_dump(reply);
343
344 sd_bus_message_unref(reply);
345 reply = NULL;
346
347 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "org.freedesktop.systemd.ValueTest2");
348 assert_se(r < 0);
349 assert_se(sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.UnknownInterface"));
350 sd_bus_error_free(&error);
351
5d12cc3e
LP
352 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, "");
353 assert_se(r < 0);
354 assert_se(sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.UnknownMethod"));
355 sd_bus_error_free(&error);
356
357 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, "");
358 assert_se(r >= 0);
359
360 bus_message_dump(reply);
361
362 sd_bus_message_unref(reply);
363 reply = NULL;
364
62b5c2ae
LP
365 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest", &error, NULL, "");
366 assert_se(r >= 0);
367
368 r = sd_bus_process(bus, &reply);
369 assert_se(r > 0);
370
371 assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
372 bus_message_dump(reply);
373
374 sd_bus_message_unref(reply);
375 reply = NULL;
376
29ddb38f
LP
377 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Exit", &error, NULL, "");
378 assert_se(r >= 0);
379
380 sd_bus_flush(bus);
381
382 return 0;
383}
384
385int main(int argc, char *argv[]) {
386 struct context c;
387 pthread_t s;
388 void *p;
389 int r, q;
390
391 zero(c);
392
adcdb374
LP
393 c.automatic_integer_property = 4711;
394 c.automatic_string_property = "dudeldu";
395
29ddb38f
LP
396 assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0);
397
398 r = pthread_create(&s, NULL, server, &c);
399 if (r != 0)
400 return -r;
401
402 r = client(&c);
403
404 q = pthread_join(s, &p);
405 if (q != 0)
406 return -q;
407
408 if (r < 0)
409 return r;
410
411 if (PTR_TO_INT(p) < 0)
412 return PTR_TO_INT(p);
413
414 free(c.something);
415
416 return EXIT_SUCCESS;
417}