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