]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-bus/test-bus-marshal.c
Merge pull request #2409 from snakeroot/dropin-doc-2
[thirdparty/systemd.git] / src / libsystemd / sd-bus / test-bus-marshal.c
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 <math.h>
23 #include <stdlib.h>
24
25 #ifdef HAVE_GLIB
26 #include <gio/gio.h>
27 #endif
28
29 #ifdef HAVE_DBUS
30 #include <dbus/dbus.h>
31 #endif
32
33 #include "sd-bus.h"
34
35 #include "alloc-util.h"
36 #include "bus-dump.h"
37 #include "bus-label.h"
38 #include "bus-message.h"
39 #include "bus-util.h"
40 #include "fd-util.h"
41 #include "hexdecoct.h"
42 #include "log.h"
43 #include "util.h"
44
45 static void test_bus_path_encode_unique(void) {
46 _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;
47
48 assert_se(bus_path_encode_unique(NULL, "/foo/bar", "some.sender", "a.suffix", &a) >= 0 && streq_ptr(a, "/foo/bar/some_2esender/a_2esuffix"));
49 assert_se(bus_path_decode_unique(a, "/foo/bar", &b, &c) > 0 && streq_ptr(b, "some.sender") && streq_ptr(c, "a.suffix"));
50 assert_se(bus_path_decode_unique(a, "/bar/foo", &d, &d) == 0 && !d);
51 assert_se(bus_path_decode_unique("/foo/bar/onlyOneSuffix", "/foo/bar", &d, &d) == 0 && !d);
52 assert_se(bus_path_decode_unique("/foo/bar/_/_", "/foo/bar", &d, &e) > 0 && streq_ptr(d, "") && streq_ptr(e, ""));
53 }
54
55 static void test_bus_path_encode(void) {
56 _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *f = NULL;
57
58 assert_se(sd_bus_path_encode("/foo/bar", "waldo", &a) >= 0 && streq(a, "/foo/bar/waldo"));
59 assert_se(sd_bus_path_decode(a, "/waldo", &b) == 0 && b == NULL);
60 assert_se(sd_bus_path_decode(a, "/foo/bar", &b) > 0 && streq(b, "waldo"));
61
62 assert_se(sd_bus_path_encode("xxxx", "waldo", &c) < 0);
63 assert_se(sd_bus_path_encode("/foo/", "waldo", &c) < 0);
64
65 assert_se(sd_bus_path_encode("/foo/bar", "", &c) >= 0 && streq(c, "/foo/bar/_"));
66 assert_se(sd_bus_path_decode(c, "/foo/bar", &d) > 0 && streq(d, ""));
67
68 assert_se(sd_bus_path_encode("/foo/bar", "foo.bar", &e) >= 0 && streq(e, "/foo/bar/foo_2ebar"));
69 assert_se(sd_bus_path_decode(e, "/foo/bar", &f) > 0 && streq(f, "foo.bar"));
70 }
71
72 static void test_bus_path_encode_many(void) {
73 _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *f = NULL;
74
75 assert_se(sd_bus_path_decode_many("/foo/bar", "/prefix/%", NULL) == 0);
76 assert_se(sd_bus_path_decode_many("/prefix/bar", "/prefix/%bar", NULL) == 1);
77 assert_se(sd_bus_path_decode_many("/foo/bar", "/prefix/%/suffix", NULL) == 0);
78 assert_se(sd_bus_path_decode_many("/prefix/foobar/suffix", "/prefix/%/suffix", &a) == 1 && streq_ptr(a, "foobar"));
79 assert_se(sd_bus_path_decode_many("/prefix/one_foo_two/mid/three_bar_four/suffix", "/prefix/one_%_two/mid/three_%_four/suffix", &b, &c) == 1 && streq_ptr(b, "foo") && streq_ptr(c, "bar"));
80 assert_se(sd_bus_path_decode_many("/prefix/one_foo_two/mid/three_bar_four/suffix", "/prefix/one_%_two/mid/three_%_four/suffix", NULL, &d) == 1 && streq_ptr(d, "bar"));
81
82 assert_se(sd_bus_path_decode_many("/foo/bar", "/foo/bar/%", NULL) == 0);
83 assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/bar%", NULL) == 0);
84 assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/bar", NULL) == 0);
85 assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%bar", NULL) == 0);
86 assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/bar/suffix") == 1);
87 assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%%/suffix", NULL, NULL) == 0); /* multiple '%' are treated verbatim */
88 assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/suffi", NULL) == 0);
89 assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/suffix", &e) == 1 && streq_ptr(e, "bar"));
90 assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/%", NULL, NULL) == 1);
91 assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/%/%", NULL, NULL, NULL) == 1);
92 assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "%/%/%", NULL, NULL, NULL) == 0);
93 assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/%", NULL, NULL) == 0);
94 assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/%/", NULL, NULL) == 0);
95 assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/", NULL) == 0);
96 assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%", NULL) == 0);
97 assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "%", NULL) == 0);
98
99 assert_se(sd_bus_path_encode_many(&f, "/prefix/one_%_two/mid/three_%_four/suffix", "foo", "bar") >= 0 && streq_ptr(f, "/prefix/one_foo_two/mid/three_bar_four/suffix"));
100 }
101
102 static void test_bus_label_escape_one(const char *a, const char *b) {
103 _cleanup_free_ char *t = NULL, *x = NULL, *y = NULL;
104
105 assert_se(t = bus_label_escape(a));
106 assert_se(streq(t, b));
107
108 assert_se(x = bus_label_unescape(t));
109 assert_se(streq(a, x));
110
111 assert_se(y = bus_label_unescape(b));
112 assert_se(streq(a, y));
113 }
114
115 static void test_bus_label_escape(void) {
116 test_bus_label_escape_one("foo123bar", "foo123bar");
117 test_bus_label_escape_one("foo.bar", "foo_2ebar");
118 test_bus_label_escape_one("foo_2ebar", "foo_5f2ebar");
119 test_bus_label_escape_one("", "_");
120 test_bus_label_escape_one("_", "_5f");
121 test_bus_label_escape_one("1", "_31");
122 test_bus_label_escape_one(":1", "_3a1");
123 }
124
125 int main(int argc, char *argv[]) {
126 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *copy = NULL;
127 int r, boolean;
128 const char *x, *x2, *y, *z, *a, *b, *c, *d, *a_signature;
129 uint8_t u, v;
130 void *buffer = NULL;
131 size_t sz;
132 char *h;
133 const int32_t integer_array[] = { -1, -2, 0, 1, 2 }, *return_array;
134 char *s;
135 _cleanup_free_ char *first = NULL, *second = NULL, *third = NULL;
136 _cleanup_fclose_ FILE *ms = NULL;
137 size_t first_size = 0, second_size = 0, third_size = 0;
138 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
139 double dbl;
140 uint64_t u64;
141
142 r = sd_bus_default_system(&bus);
143 if (r < 0)
144 return EXIT_TEST_SKIP;
145
146 r = sd_bus_message_new_method_call(bus, &m, "foobar.waldo", "/", "foobar.waldo", "Piep");
147 assert_se(r >= 0);
148
149 r = sd_bus_message_append(m, "");
150 assert_se(r >= 0);
151
152 r = sd_bus_message_append(m, "s", "a string");
153 assert_se(r >= 0);
154
155 r = sd_bus_message_append(m, "s", NULL);
156 assert_se(r >= 0);
157
158 r = sd_bus_message_append(m, "asg", 2, "string #1", "string #2", "sba(tt)ss");
159 assert_se(r >= 0);
160
161 r = sd_bus_message_append(m, "sass", "foobar", 5, "foo", "bar", "waldo", "piep", "pap", "after");
162 assert_se(r >= 0);
163
164 r = sd_bus_message_append(m, "a{yv}", 2, 3, "s", "foo", 5, "s", "waldo");
165 assert_se(r >= 0);
166
167 r = sd_bus_message_append(m, "y(ty)y(yt)y", 8, 777ULL, 7, 9, 77, 7777ULL, 10);
168 assert_se(r >= 0);
169
170 r = sd_bus_message_append(m, "()");
171 assert_se(r >= 0);
172
173 r = sd_bus_message_append(m, "ba(ss)", 255, 3, "aaa", "1", "bbb", "2", "ccc", "3");
174 assert_se(r >= 0);
175
176 r = sd_bus_message_open_container(m, 'a', "s");
177 assert_se(r >= 0);
178
179 r = sd_bus_message_append_basic(m, 's', "foobar");
180 assert_se(r >= 0);
181
182 r = sd_bus_message_append_basic(m, 's', "waldo");
183 assert_se(r >= 0);
184
185 r = sd_bus_message_close_container(m);
186 assert_se(r >= 0);
187
188 r = sd_bus_message_append_string_space(m, 5, &s);
189 assert_se(r >= 0);
190 strcpy(s, "hallo");
191
192 r = sd_bus_message_append_array(m, 'i', integer_array, sizeof(integer_array));
193 assert_se(r >= 0);
194
195 r = sd_bus_message_append_array(m, 'u', NULL, 0);
196 assert_se(r >= 0);
197
198 r = sd_bus_message_append(m, "a(stdo)", 1, "foo", 815ULL, 47.0, "/");
199 assert_se(r >= 0);
200
201 r = bus_message_seal(m, 4711, 0);
202 assert_se(r >= 0);
203
204 bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
205
206 ms = open_memstream(&first, &first_size);
207 bus_message_dump(m, ms, 0);
208 fflush(ms);
209 assert_se(!ferror(ms));
210
211 r = bus_message_get_blob(m, &buffer, &sz);
212 assert_se(r >= 0);
213
214 h = hexmem(buffer, sz);
215 assert_se(h);
216
217 log_info("message size = %zu, contents =\n%s", sz, h);
218 free(h);
219
220 #ifdef HAVE_GLIB
221 {
222 GDBusMessage *g;
223 char *p;
224
225 #if !defined(GLIB_VERSION_2_36)
226 g_type_init();
227 #endif
228
229 g = g_dbus_message_new_from_blob(buffer, sz, 0, NULL);
230 p = g_dbus_message_print(g, 0);
231 log_info("%s", p);
232 g_free(p);
233 g_object_unref(g);
234 }
235 #endif
236
237 #ifdef HAVE_DBUS
238 {
239 DBusMessage *w;
240 DBusError error;
241
242 dbus_error_init(&error);
243
244 w = dbus_message_demarshal(buffer, sz, &error);
245 if (!w)
246 log_error("%s", error.message);
247 else
248 dbus_message_unref(w);
249
250 dbus_error_free(&error);
251 }
252 #endif
253
254 m = sd_bus_message_unref(m);
255
256 r = bus_message_from_malloc(bus, buffer, sz, NULL, 0, NULL, &m);
257 assert_se(r >= 0);
258
259 bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
260
261 fclose(ms);
262 ms = open_memstream(&second, &second_size);
263 bus_message_dump(m, ms, 0);
264 fflush(ms);
265 assert_se(!ferror(ms));
266 assert_se(first_size == second_size);
267 assert_se(memcmp(first, second, first_size) == 0);
268
269 assert_se(sd_bus_message_rewind(m, true) >= 0);
270
271 r = sd_bus_message_read(m, "ssasg", &x, &x2, 2, &y, &z, &a_signature);
272 assert_se(r > 0);
273 assert_se(streq(x, "a string"));
274 assert_se(streq(x2, ""));
275 assert_se(streq(y, "string #1"));
276 assert_se(streq(z, "string #2"));
277 assert_se(streq(a_signature, "sba(tt)ss"));
278
279 r = sd_bus_message_read(m, "sass", &x, 5, &y, &z, &a, &b, &c, &d);
280 assert_se(r > 0);
281 assert_se(streq(x, "foobar"));
282 assert_se(streq(y, "foo"));
283 assert_se(streq(z, "bar"));
284 assert_se(streq(a, "waldo"));
285 assert_se(streq(b, "piep"));
286 assert_se(streq(c, "pap"));
287 assert_se(streq(d, "after"));
288
289 r = sd_bus_message_read(m, "a{yv}", 2, &u, "s", &x, &v, "s", &y);
290 assert_se(r > 0);
291 assert_se(u == 3);
292 assert_se(streq(x, "foo"));
293 assert_se(v == 5);
294 assert_se(streq(y, "waldo"));
295
296 r = sd_bus_message_read(m, "y(ty)", &v, &u64, &u);
297 assert_se(r > 0);
298 assert_se(v == 8);
299 assert_se(u64 == 777);
300 assert_se(u == 7);
301
302 r = sd_bus_message_read(m, "y(yt)", &v, &u, &u64);
303 assert_se(r > 0);
304 assert_se(v == 9);
305 assert_se(u == 77);
306 assert_se(u64 == 7777);
307
308 r = sd_bus_message_read(m, "y", &v);
309 assert_se(r > 0);
310 assert_se(v == 10);
311
312 r = sd_bus_message_read(m, "()");
313 assert_se(r > 0);
314
315 r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d);
316 assert_se(r > 0);
317 assert_se(boolean);
318 assert_se(streq(x, "aaa"));
319 assert_se(streq(y, "1"));
320 assert_se(streq(a, "bbb"));
321 assert_se(streq(b, "2"));
322 assert_se(streq(c, "ccc"));
323 assert_se(streq(d, "3"));
324
325 assert_se(sd_bus_message_verify_type(m, 'a', "s") > 0);
326
327 r = sd_bus_message_read(m, "as", 2, &x, &y);
328 assert_se(r > 0);
329 assert_se(streq(x, "foobar"));
330 assert_se(streq(y, "waldo"));
331
332 r = sd_bus_message_read_basic(m, 's', &s);
333 assert_se(r > 0);
334 assert_se(streq(s, "hallo"));
335
336 r = sd_bus_message_read_array(m, 'i', (const void**) &return_array, &sz);
337 assert_se(r > 0);
338 assert_se(sz == sizeof(integer_array));
339 assert_se(memcmp(integer_array, return_array, sz) == 0);
340
341 r = sd_bus_message_read_array(m, 'u', (const void**) &return_array, &sz);
342 assert_se(r > 0);
343 assert_se(sz == 0);
344
345 r = sd_bus_message_read(m, "a(stdo)", 1, &x, &u64, &dbl, &y);
346 assert_se(r > 0);
347 assert_se(streq(x, "foo"));
348 assert_se(u64 == 815ULL);
349 assert_se(fabs(dbl - 47.0) < 0.1);
350 assert_se(streq(y, "/"));
351
352 r = sd_bus_message_peek_type(m, NULL, NULL);
353 assert_se(r == 0);
354
355 r = sd_bus_message_new_method_call(bus, &copy, "foobar.waldo", "/", "foobar.waldo", "Piep");
356 assert_se(r >= 0);
357
358 r = sd_bus_message_rewind(m, true);
359 assert_se(r >= 0);
360
361 r = sd_bus_message_copy(copy, m, true);
362 assert_se(r >= 0);
363
364 r = bus_message_seal(copy, 4712, 0);
365 assert_se(r >= 0);
366
367 fclose(ms);
368 ms = open_memstream(&third, &third_size);
369 bus_message_dump(copy, ms, 0);
370 fflush(ms);
371 assert_se(!ferror(ms));
372
373 printf("<%.*s>\n", (int) first_size, first);
374 printf("<%.*s>\n", (int) third_size, third);
375
376 assert_se(first_size == third_size);
377 assert_se(memcmp(first, third, third_size) == 0);
378
379 r = sd_bus_message_rewind(m, true);
380 assert_se(r >= 0);
381
382 assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0);
383
384 r = sd_bus_message_skip(m, "ssasg");
385 assert_se(r > 0);
386
387 assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0);
388
389 r = sd_bus_message_skip(m, "sass");
390 assert_se(r >= 0);
391
392 assert_se(sd_bus_message_verify_type(m, 'a', "{yv}") > 0);
393
394 r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y()");
395 assert_se(r >= 0);
396
397 assert_se(sd_bus_message_verify_type(m, 'b', NULL) > 0);
398
399 r = sd_bus_message_read(m, "b", &boolean);
400 assert_se(r > 0);
401 assert_se(boolean);
402
403 r = sd_bus_message_enter_container(m, 0, NULL);
404 assert_se(r > 0);
405
406 r = sd_bus_message_read(m, "(ss)", &x, &y);
407 assert_se(r > 0);
408
409 r = sd_bus_message_read(m, "(ss)", &a, &b);
410 assert_se(r > 0);
411
412 r = sd_bus_message_read(m, "(ss)", &c, &d);
413 assert_se(r > 0);
414
415 r = sd_bus_message_read(m, "(ss)", &x, &y);
416 assert_se(r == 0);
417
418 r = sd_bus_message_exit_container(m);
419 assert_se(r >= 0);
420
421 assert_se(streq(x, "aaa"));
422 assert_se(streq(y, "1"));
423 assert_se(streq(a, "bbb"));
424 assert_se(streq(b, "2"));
425 assert_se(streq(c, "ccc"));
426 assert_se(streq(d, "3"));
427
428 test_bus_label_escape();
429 test_bus_path_encode();
430 test_bus_path_encode_unique();
431 test_bus_path_encode_many();
432
433 return 0;
434 }