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