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