Branch data Line data Source code
1 : : /* GLib testing framework examples and tests
2 : : *
3 : : * Copyright (C) 2008-2010 Red Hat, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : *
20 : : * Author: David Zeuthen <davidz@redhat.com>
21 : : */
22 : :
23 : : #include <gio/gio.h>
24 : : #include <unistd.h>
25 : : #include <string.h>
26 : :
27 : : #include "gdbus-tests.h"
28 : :
29 : : /* all tests rely on a shared mainloop */
30 : : static GMainLoop *loop = NULL;
31 : :
32 : : /* ---------------------------------------------------------------------------------------------------- */
33 : : /* Test introspection parser */
34 : : /* ---------------------------------------------------------------------------------------------------- */
35 : :
36 : : static void
37 : 1 : test_introspection (GDBusProxy *proxy)
38 : : {
39 : : GError *error;
40 : : const gchar *xml_data;
41 : : GDBusNodeInfo *node_info;
42 : : GDBusInterfaceInfo *interface_info;
43 : : GDBusMethodInfo *method_info;
44 : : GDBusSignalInfo *signal_info;
45 : : GVariant *result;
46 : :
47 : 1 : error = NULL;
48 : :
49 : : /*
50 : : * Invoke Introspect(), then parse the output.
51 : : */
52 : 1 : result = g_dbus_proxy_call_sync (proxy,
53 : : "org.freedesktop.DBus.Introspectable.Introspect",
54 : : NULL,
55 : : G_DBUS_CALL_FLAGS_NONE,
56 : : -1,
57 : : NULL,
58 : : &error);
59 : 1 : g_assert_no_error (error);
60 : 1 : g_assert (result != NULL);
61 : 1 : g_variant_get (result, "(&s)", &xml_data);
62 : :
63 : 1 : node_info = g_dbus_node_info_new_for_xml (xml_data, &error);
64 : 1 : g_assert_no_error (error);
65 : 1 : g_assert (node_info != NULL);
66 : :
67 : : /* for now we only check a couple of things. TODO: check more things */
68 : :
69 : 1 : interface_info = g_dbus_node_info_lookup_interface (node_info, "com.example.NonExistantInterface");
70 : 1 : g_assert (interface_info == NULL);
71 : :
72 : 1 : interface_info = g_dbus_node_info_lookup_interface (node_info, "org.freedesktop.DBus.Introspectable");
73 : 1 : g_assert (interface_info != NULL);
74 : 1 : method_info = g_dbus_interface_info_lookup_method (interface_info, "NonExistantMethod");
75 : 1 : g_assert (method_info == NULL);
76 : 1 : method_info = g_dbus_interface_info_lookup_method (interface_info, "Introspect");
77 : 1 : g_assert (method_info != NULL);
78 : 1 : g_assert (method_info->in_args != NULL);
79 : 1 : g_assert (method_info->in_args[0] == NULL);
80 : 1 : g_assert (method_info->out_args != NULL);
81 : 1 : g_assert (method_info->out_args[0] != NULL);
82 : 1 : g_assert (method_info->out_args[1] == NULL);
83 : 1 : g_assert_cmpstr (method_info->out_args[0]->signature, ==, "s");
84 : :
85 : 1 : interface_info = g_dbus_node_info_lookup_interface (node_info, "com.example.Frob");
86 : 1 : g_assert (interface_info != NULL);
87 : 1 : signal_info = g_dbus_interface_info_lookup_signal (interface_info, "TestSignal");
88 : 1 : g_assert (signal_info != NULL);
89 : 1 : g_assert (signal_info->args != NULL);
90 : 1 : g_assert (signal_info->args[0] != NULL);
91 : 1 : g_assert_cmpstr (signal_info->args[0]->signature, ==, "s");
92 : 1 : g_assert (signal_info->args[1] != NULL);
93 : 1 : g_assert_cmpstr (signal_info->args[1]->signature, ==, "o");
94 : 1 : g_assert (signal_info->args[2] != NULL);
95 : 1 : g_assert_cmpstr (signal_info->args[2]->signature, ==, "v");
96 : 1 : g_assert (signal_info->args[3] == NULL);
97 : :
98 : 1 : g_dbus_node_info_unref (node_info);
99 : 1 : g_variant_unref (result);
100 : :
101 : 1 : g_main_loop_quit (loop);
102 : 1 : }
103 : :
104 : : static void
105 : 1 : test_introspection_parser (void)
106 : : {
107 : : GDBusProxy *proxy;
108 : : GDBusConnection *connection;
109 : : GError *error;
110 : :
111 : 1 : error = NULL;
112 : 1 : connection = g_bus_get_sync (G_BUS_TYPE_SESSION,
113 : : NULL,
114 : : &error);
115 : 1 : g_assert_no_error (error);
116 : 1 : error = NULL;
117 : 1 : proxy = g_dbus_proxy_new_sync (connection,
118 : : G_DBUS_PROXY_FLAGS_NONE,
119 : : NULL, /* GDBusInterfaceInfo */
120 : : "com.example.TestService", /* name */
121 : : "/com/example/TestObject", /* object path */
122 : : "com.example.Frob", /* interface */
123 : : NULL, /* GCancellable */
124 : : &error);
125 : 1 : g_assert_no_error (error);
126 : :
127 : : /* this is safe; testserver will exit once the bus goes away */
128 : 1 : g_assert (g_spawn_command_line_async (g_test_get_filename (G_TEST_BUILT, "gdbus-testserver", NULL), NULL));
129 : :
130 : 1 : _g_assert_property_notify (proxy, "g-name-owner");
131 : :
132 : 1 : test_introspection (proxy);
133 : :
134 : 1 : g_object_unref (proxy);
135 : 1 : g_object_unref (connection);
136 : 1 : }
137 : :
138 : : /* check that a parse-generate roundtrip produces identical results
139 : : */
140 : : static void
141 : 1 : test_generate (void)
142 : : {
143 : : GDBusNodeInfo *info;
144 : : GDBusNodeInfo *info2;
145 : : GDBusInterfaceInfo *iinfo;
146 : : GDBusMethodInfo *minfo;
147 : : GDBusSignalInfo *sinfo;
148 : : GDBusArgInfo *arginfo;
149 : : GDBusPropertyInfo *pinfo;
150 : : GDBusAnnotationInfo *aninfo;
151 : 1 : const gchar *data =
152 : : " <node>"
153 : : " <interface name='com.example.Frob'>"
154 : : " <annotation name='foo' value='bar'/>"
155 : : " <method name='PairReturn'>"
156 : : " <annotation name='org.freedesktop.DBus.GLib.Async' value=''/>"
157 : : " <arg type='u' name='somenumber' direction='in'/>"
158 : : " <arg type='s' name='somestring' direction='out'/>"
159 : : " </method>"
160 : : " <signal name='HelloWorld'>"
161 : : " <arg type='s' name='greeting' direction='out'/>"
162 : : " </signal>"
163 : : " <method name='Sleep'>"
164 : : " <arg type='i' name='timeout' direction='in'/>"
165 : : " </method>"
166 : : " <property name='y' type='y' access='readwrite'>"
167 : : " <annotation name='needs-escaping' value='bar<>'"'/>"
168 : : " </property>"
169 : : " </interface>"
170 : : " </node>";
171 : :
172 : : GString *string;
173 : : GString *string2;
174 : : GError *error;
175 : :
176 : 1 : error = NULL;
177 : 1 : info = g_dbus_node_info_new_for_xml (data, &error);
178 : 1 : g_assert_no_error (error);
179 : :
180 : 1 : iinfo = g_dbus_node_info_lookup_interface (info, "com.example.Frob");
181 : 1 : aninfo = iinfo->annotations[0];
182 : 1 : g_assert_cmpstr (aninfo->key, ==, "foo");
183 : 1 : g_assert_cmpstr (aninfo->value, ==, "bar");
184 : 1 : g_assert (iinfo->annotations[1] == NULL);
185 : 1 : minfo = g_dbus_interface_info_lookup_method (iinfo, "PairReturn");
186 : 1 : g_assert_cmpstr (g_dbus_annotation_info_lookup (minfo->annotations, "org.freedesktop.DBus.GLib.Async"), ==, "");
187 : 1 : arginfo = minfo->in_args[0];
188 : 1 : g_assert_cmpstr (arginfo->name, ==, "somenumber");
189 : 1 : g_assert_cmpstr (arginfo->signature, ==, "u");
190 : 1 : g_assert (minfo->in_args[1] == NULL);
191 : 1 : arginfo = minfo->out_args[0];
192 : 1 : g_assert_cmpstr (arginfo->name, ==, "somestring");
193 : 1 : g_assert_cmpstr (arginfo->signature, ==, "s");
194 : 1 : g_assert (minfo->out_args[1] == NULL);
195 : 1 : sinfo = g_dbus_interface_info_lookup_signal (iinfo, "HelloWorld");
196 : 1 : arginfo = sinfo->args[0];
197 : 1 : g_assert_cmpstr (arginfo->name, ==, "greeting");
198 : 1 : g_assert_cmpstr (arginfo->signature, ==, "s");
199 : 1 : g_assert (sinfo->args[1] == NULL);
200 : 1 : pinfo = g_dbus_interface_info_lookup_property (iinfo, "y");
201 : 1 : g_assert_cmpstr (pinfo->signature, ==, "y");
202 : 1 : g_assert_cmpint (pinfo->flags, ==, G_DBUS_PROPERTY_INFO_FLAGS_READABLE |
203 : : G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE);
204 : :
205 : 1 : string = g_string_new ("");
206 : 1 : g_dbus_node_info_generate_xml (info, 2, string);
207 : :
208 : 1 : info2 = g_dbus_node_info_new_for_xml (string->str, &error);
209 : 1 : string2 = g_string_new ("");
210 : 1 : g_dbus_node_info_generate_xml (info2, 2, string2);
211 : :
212 : 1 : g_assert_cmpstr (string->str, ==, string2->str);
213 : 1 : g_string_free (string, TRUE);
214 : 1 : g_string_free (string2, TRUE);
215 : :
216 : 1 : g_dbus_node_info_unref (info);
217 : 1 : g_dbus_node_info_unref (info2);
218 : 1 : }
219 : :
220 : : /* test that omitted direction attributes default to 'out' for signals,
221 : : * and 'in' for methods.
222 : : */
223 : : static void
224 : 1 : test_default_direction (void)
225 : : {
226 : : GDBusNodeInfo *info;
227 : : GDBusInterfaceInfo *iinfo;
228 : : GDBusMethodInfo *minfo;
229 : : GDBusSignalInfo *sinfo;
230 : : GDBusArgInfo *arginfo;
231 : 1 : const gchar *data =
232 : : " <node>"
233 : : " <interface name='com.example.Frob'>"
234 : : " <signal name='HelloWorld'>"
235 : : " <arg type='s' name='greeting'/>"
236 : : " </signal>"
237 : : " <method name='Sleep'>"
238 : : " <arg type='i' name='timeout'/>"
239 : : " </method>"
240 : : " </interface>"
241 : : " </node>";
242 : :
243 : : GError *error;
244 : :
245 : 1 : error = NULL;
246 : 1 : info = g_dbus_node_info_new_for_xml (data, &error);
247 : 1 : g_assert_no_error (error);
248 : :
249 : 1 : iinfo = g_dbus_node_info_lookup_interface (info, "com.example.Frob");
250 : 1 : sinfo = g_dbus_interface_info_lookup_signal (iinfo, "HelloWorld");
251 : 1 : g_assert (sinfo->args != NULL);
252 : 1 : arginfo = sinfo->args[0];
253 : 1 : g_assert_cmpstr (arginfo->name, ==, "greeting");
254 : 1 : g_assert (sinfo->args[1] == NULL);
255 : 1 : minfo = g_dbus_interface_info_lookup_method (iinfo, "Sleep");
256 : 1 : g_assert (minfo->in_args != NULL);
257 : 1 : arginfo = minfo->in_args[0];
258 : 1 : g_assert_cmpstr (arginfo->name, ==, "timeout");
259 : 1 : g_assert (minfo->in_args[1] == NULL);
260 : :
261 : 1 : g_dbus_node_info_unref (info);
262 : 1 : }
263 : :
264 : : static void
265 : 1 : test_extra_data (void)
266 : : {
267 : : GDBusNodeInfo *info;
268 : 1 : const gchar *data =
269 : : " <node>"
270 : : " <interface name='com.example.Frob' version='1.0'>"
271 : : " <doc:doc><doc:description><doc:para>Blah blah</doc:para></doc:description></doc:doc>"
272 : : " <method name='DownloadPackages'>"
273 : : " <arg type='u' name='somenumber' direction='in'>"
274 : : " <doc:doc><doc:summary><doc:para>"
275 : : " See <doc:ulink url='http:///example.com'>example</doc:ulink>"
276 : : " </doc:para></doc:summary></doc:doc>"
277 : : " </arg>"
278 : : " <arg type='s' name='somestring' direction='out'>"
279 : : " <doc:doc><doc:summary><doc:para>"
280 : : " More docs"
281 : : " </doc:para></doc:summary></doc:doc>"
282 : : " </arg>"
283 : : " </method>"
284 : : " <signal name='HelloWorld'>"
285 : : " <arg type='s' name='somestring'/>"
286 : : " </signal>"
287 : : " <method name='Sleep'>"
288 : : " <arg type='i' name='timeout' direction='in'/>"
289 : : " </method>"
290 : : " <property name='y' type='y' access='readwrite'/>"
291 : : " </interface>"
292 : : " </node>";
293 : : GError *error;
294 : :
295 : 1 : error = NULL;
296 : 1 : info = g_dbus_node_info_new_for_xml (data, &error);
297 : 1 : g_assert_no_error (error);
298 : :
299 : 1 : g_dbus_node_info_unref (info);
300 : 1 : }
301 : :
302 : : /* ---------------------------------------------------------------------------------------------------- */
303 : :
304 : : int
305 : 1 : main (int argc,
306 : : char *argv[])
307 : : {
308 : : gint ret;
309 : :
310 : 1 : g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
311 : :
312 : : /* all the tests rely on a shared main loop */
313 : 1 : loop = g_main_loop_new (NULL, FALSE);
314 : :
315 : 1 : g_test_add_func ("/gdbus/introspection-parser", test_introspection_parser);
316 : 1 : g_test_add_func ("/gdbus/introspection-generate", test_generate);
317 : 1 : g_test_add_func ("/gdbus/introspection-default-direction", test_default_direction);
318 : 1 : g_test_add_func ("/gdbus/introspection-extra-data", test_extra_data);
319 : :
320 : 1 : ret = session_bus_run ();
321 : :
322 [ + + ]: 2 : while (g_main_context_iteration (NULL, FALSE));
323 : 1 : g_main_loop_unref (loop);
324 : :
325 : 1 : return ret;
326 : : }
|