]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-bus/test-bus-marshal.c
Add SPDX license identifiers to source files under the LGPL
[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 {
221 GDBusMessage *g;
222 char *p;
223
224 #if !defined(GLIB_VERSION_2_36)
225 g_type_init();
226 #endif
227
228 g = g_dbus_message_new_from_blob(buffer, sz, 0, NULL);
229 p = g_dbus_message_print(g, 0);
230 log_info("%s", p);
231 g_free(p);
232 g_object_unref(g);
233 }
234 #endif
235
236 #if HAVE_DBUS
237 {
238 DBusMessage *w;
239 DBusError error;
240
241 dbus_error_init(&error);
242
243 w = dbus_message_demarshal(buffer, sz, &error);
244 if (!w)
245 log_error("%s", error.message);
246 else
247 dbus_message_unref(w);
248
249 dbus_error_free(&error);
250 }
251 #endif
252
253 m = sd_bus_message_unref(m);
254
255 r = bus_message_from_malloc(bus, buffer, sz, NULL, 0, NULL, &m);
256 assert_se(r >= 0);
257
258 bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
259
260 fclose(ms);
261 ms = open_memstream(&second, &second_size);
262 bus_message_dump(m, ms, 0);
263 fflush(ms);
264 assert_se(!ferror(ms));
265 assert_se(first_size == second_size);
266 assert_se(memcmp(first, second, first_size) == 0);
267
268 assert_se(sd_bus_message_rewind(m, true) >= 0);
269
270 r = sd_bus_message_read(m, "ssasg", &x, &x2, 2, &y, &z, &a_signature);
271 assert_se(r > 0);
272 assert_se(streq(x, "a string"));
273 assert_se(streq(x2, ""));
274 assert_se(streq(y, "string #1"));
275 assert_se(streq(z, "string #2"));
276 assert_se(streq(a_signature, "sba(tt)ss"));
277
278 r = sd_bus_message_read(m, "sass", &x, 5, &y, &z, &a, &b, &c, &d);
279 assert_se(r > 0);
280 assert_se(streq(x, "foobar"));
281 assert_se(streq(y, "foo"));
282 assert_se(streq(z, "bar"));
283 assert_se(streq(a, "waldo"));
284 assert_se(streq(b, "piep"));
285 assert_se(streq(c, "pap"));
286 assert_se(streq(d, "after"));
287
288 r = sd_bus_message_read(m, "a{yv}", 2, &u, "s", &x, &v, "s", &y);
289 assert_se(r > 0);
290 assert_se(u == 3);
291 assert_se(streq(x, "foo"));
292 assert_se(v == 5);
293 assert_se(streq(y, "waldo"));
294
295 r = sd_bus_message_read(m, "y(ty)", &v, &u64, &u);
296 assert_se(r > 0);
297 assert_se(v == 8);
298 assert_se(u64 == 777);
299 assert_se(u == 7);
300
301 r = sd_bus_message_read(m, "y(yt)", &v, &u, &u64);
302 assert_se(r > 0);
303 assert_se(v == 9);
304 assert_se(u == 77);
305 assert_se(u64 == 7777);
306
307 r = sd_bus_message_read(m, "y", &v);
308 assert_se(r > 0);
309 assert_se(v == 10);
310
311 r = sd_bus_message_read(m, "()");
312 assert_se(r > 0);
313
314 r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d);
315 assert_se(r > 0);
316 assert_se(boolean);
317 assert_se(streq(x, "aaa"));
318 assert_se(streq(y, "1"));
319 assert_se(streq(a, "bbb"));
320 assert_se(streq(b, "2"));
321 assert_se(streq(c, "ccc"));
322 assert_se(streq(d, "3"));
323
324 assert_se(sd_bus_message_verify_type(m, 'a', "s") > 0);
325
326 r = sd_bus_message_read(m, "as", 2, &x, &y);
327 assert_se(r > 0);
328 assert_se(streq(x, "foobar"));
329 assert_se(streq(y, "waldo"));
330
331 r = sd_bus_message_read_basic(m, 's', &s);
332 assert_se(r > 0);
333 assert_se(streq(s, "hallo"));
334
335 r = sd_bus_message_read_array(m, 'i', (const void**) &return_array, &sz);
336 assert_se(r > 0);
337 assert_se(sz == sizeof(integer_array));
338 assert_se(memcmp(integer_array, return_array, sz) == 0);
339
340 r = sd_bus_message_read_array(m, 'u', (const void**) &return_array, &sz);
341 assert_se(r > 0);
342 assert_se(sz == 0);
343
344 r = sd_bus_message_read(m, "a(stdo)", 1, &x, &u64, &dbl, &y);
345 assert_se(r > 0);
346 assert_se(streq(x, "foo"));
347 assert_se(u64 == 815ULL);
348 assert_se(fabs(dbl - 47.0) < 0.1);
349 assert_se(streq(y, "/"));
350
351 r = sd_bus_message_peek_type(m, NULL, NULL);
352 assert_se(r == 0);
353
354 r = sd_bus_message_new_method_call(bus, &copy, "foobar.waldo", "/", "foobar.waldo", "Piep");
355 assert_se(r >= 0);
356
357 r = sd_bus_message_rewind(m, true);
358 assert_se(r >= 0);
359
360 r = sd_bus_message_copy(copy, m, true);
361 assert_se(r >= 0);
362
363 r = sd_bus_message_seal(copy, 4712, 0);
364 assert_se(r >= 0);
365
366 fclose(ms);
367 ms = open_memstream(&third, &third_size);
368 bus_message_dump(copy, ms, 0);
369 fflush(ms);
370 assert_se(!ferror(ms));
371
372 printf("<%.*s>\n", (int) first_size, first);
373 printf("<%.*s>\n", (int) third_size, third);
374
375 assert_se(first_size == third_size);
376 assert_se(memcmp(first, third, third_size) == 0);
377
378 r = sd_bus_message_rewind(m, true);
379 assert_se(r >= 0);
380
381 assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0);
382
383 r = sd_bus_message_skip(m, "ssasg");
384 assert_se(r > 0);
385
386 assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0);
387
388 r = sd_bus_message_skip(m, "sass");
389 assert_se(r >= 0);
390
391 assert_se(sd_bus_message_verify_type(m, 'a', "{yv}") > 0);
392
393 r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y()");
394 assert_se(r >= 0);
395
396 assert_se(sd_bus_message_verify_type(m, 'b', NULL) > 0);
397
398 r = sd_bus_message_read(m, "b", &boolean);
399 assert_se(r > 0);
400 assert_se(boolean);
401
402 r = sd_bus_message_enter_container(m, 0, NULL);
403 assert_se(r > 0);
404
405 r = sd_bus_message_read(m, "(ss)", &x, &y);
406 assert_se(r > 0);
407
408 r = sd_bus_message_read(m, "(ss)", &a, &b);
409 assert_se(r > 0);
410
411 r = sd_bus_message_read(m, "(ss)", &c, &d);
412 assert_se(r > 0);
413
414 r = sd_bus_message_read(m, "(ss)", &x, &y);
415 assert_se(r == 0);
416
417 r = sd_bus_message_exit_container(m);
418 assert_se(r >= 0);
419
420 assert_se(streq(x, "aaa"));
421 assert_se(streq(y, "1"));
422 assert_se(streq(a, "bbb"));
423 assert_se(streq(b, "2"));
424 assert_se(streq(c, "ccc"));
425 assert_se(streq(d, "3"));
426
427 test_bus_label_escape();
428 test_bus_path_encode();
429 test_bus_path_encode_unique();
430 test_bus_path_encode_many();
431
432 return 0;
433 }