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