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