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