Branch data Line data Source code
1 : : /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 : : *
3 : : * Copyright © 2018 Endless Mobile, Inc.
4 : : *
5 : : * This library is free software; you can redistribute it and/or
6 : : * modify it under the terms of the GNU Lesser General Public
7 : : * License as published by the Free Software Foundation; either
8 : : * version 2.1 of the License, or (at your option) any later version.
9 : : *
10 : : * This library is distributed in the hope that it will be useful,
11 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : : * Lesser General Public License for more details.
14 : : *
15 : : * You should have received a copy of the GNU Lesser General Public
16 : : * License along with this library; if not, write to the Free Software
17 : : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 : : *
19 : : * Authors:
20 : : * - Philip Withnall <withnall@endlessm.com>
21 : : */
22 : :
23 : : #include <gio/gio.h>
24 : : #include <glib.h>
25 : : #include <libglib-testing/dbus-queue.h>
26 : : #include <locale.h>
27 : : #include "test-service-iface.h"
28 : :
29 : : /* Test that creating and destroying a D-Bus queue works. A basic smoketest. */
30 : : static void
31 : 2 : test_dbus_queue_construction (void)
32 : : {
33 : 2 : g_autoptr(GtDBusQueue) queue = NULL;
34 : 2 : queue = gt_dbus_queue_new ();
35 : :
36 : : /* Call a method to avoid warnings about unused variables. */
37 [ - + ]: 2 : g_assert_cmpuint (gt_dbus_queue_get_n_messages (queue), ==, 0);
38 : 2 : }
39 : :
40 : : /* Fixture for tests which interact with the com.example.Test service over
41 : : * D-Bus.
42 : : *
43 : : * It exports one object (with ID 123) and an manager object. The method return
44 : : * values from ID 123 are up to the test in question.
45 : : */
46 : : typedef struct
47 : : {
48 : : GtDBusQueue *queue; /* (owned) */
49 : : guint valid_id;
50 : : } BusFixture;
51 : :
52 : : static void
53 : 3 : bus_set_up (BusFixture *fixture,
54 : : gconstpointer test_data)
55 : : {
56 : 2 : g_autoptr(GError) local_error = NULL;
57 : 2 : g_autofree gchar *object_path = NULL;
58 : :
59 : 3 : fixture->valid_id = 123; /* arbitrarily chosen */
60 : 3 : fixture->queue = gt_dbus_queue_new ();
61 : :
62 : 3 : gt_dbus_queue_connect (fixture->queue, &local_error);
63 [ - + ]: 2 : g_assert_no_error (local_error);
64 : :
65 : 2 : gt_dbus_queue_own_name (fixture->queue, "com.example.Test");
66 : :
67 : 2 : object_path = g_strdup_printf ("/com/example/Test/Object%u", fixture->valid_id);
68 : 2 : gt_dbus_queue_export_object (fixture->queue,
69 : : object_path,
70 : : (GDBusInterfaceInfo *) &object_interface_info,
71 : : &local_error);
72 [ - + ]: 2 : g_assert_no_error (local_error);
73 : :
74 : 2 : gt_dbus_queue_export_object (fixture->queue,
75 : : "/com/example/Test",
76 : : (GDBusInterfaceInfo *) &manager_interface_info,
77 : : &local_error);
78 [ - + ]: 2 : g_assert_no_error (local_error);
79 : 2 : }
80 : :
81 : : static void
82 : 2 : bus_tear_down (BusFixture *fixture,
83 : : gconstpointer test_data)
84 : : {
85 : 2 : gt_dbus_queue_disconnect (fixture->queue, TRUE);
86 [ + - ]: 2 : g_clear_pointer (&fixture->queue, gt_dbus_queue_free);
87 : 2 : }
88 : :
89 : : /* Helper #GAsyncReadyCallback which returns the #GAsyncResult in its @user_data. */
90 : : static void
91 : 2 : async_result_cb (GObject *obj,
92 : : GAsyncResult *result,
93 : : gpointer user_data)
94 : : {
95 : 2 : GAsyncResult **result_out = (GAsyncResult **) user_data;
96 : :
97 [ - + ]: 2 : g_assert_null (*result_out);
98 : 2 : *result_out = g_object_ref (result);
99 : 2 : }
100 : :
101 : : /* Test that making two calls in series to a mock D-Bus service works. The
102 : : * @test_data is a boolean value indicating whether to do the calls
103 : : * synchronously (%FALSE) or asynchronously (%TRUE).
104 : : *
105 : : * The mock D-Bus replies are generated in series_server_cb(), which is
106 : : * used for both synchronous and asynchronous calls. */
107 : : static void series_server_cb (GtDBusQueue *queue,
108 : : gpointer user_data);
109 : :
110 : : static void
111 : 2 : test_dbus_queue_series (BusFixture *fixture,
112 : : gconstpointer test_data)
113 : : {
114 : 2 : g_autoptr(GVariant) reply = NULL;
115 : 2 : g_autoptr(GError) local_error = NULL;
116 : 2 : gboolean test_async = GPOINTER_TO_UINT (test_data);
117 : 2 : GDBusConnection *client_connection = gt_dbus_queue_get_client_connection (fixture->queue);
118 : 2 : g_autofree gchar *object_path = NULL;
119 : 2 : g_autoptr(GVariant) properties = NULL;
120 : : const gchar *some_str;
121 : : guint some_int;
122 : :
123 : 2 : gt_dbus_queue_set_server_func (fixture->queue, series_server_cb, fixture);
124 : :
125 [ + + ]: 2 : if (test_async)
126 : : {
127 : 2 : g_autoptr(GAsyncResult) result = NULL;
128 : :
129 : 1 : g_dbus_connection_call (client_connection,
130 : : "com.example.Test",
131 : : "/com/example/Test",
132 : : "com.example.Test.Manager",
133 : : "GetObjectPath",
134 : : g_variant_new ("(u)", 123),
135 : : G_VARIANT_TYPE ("(o)"),
136 : : G_DBUS_CALL_FLAGS_NONE,
137 : : -1, /* timeout (ms) */
138 : : NULL, /* cancellable */
139 : : async_result_cb,
140 : : &result);
141 : :
142 [ + + ]: 4 : while (result == NULL)
143 : 3 : g_main_context_iteration (NULL, TRUE);
144 : 1 : reply = g_dbus_connection_call_finish (client_connection, result, &local_error);
145 : : }
146 : : else
147 : : {
148 : 1 : reply = g_dbus_connection_call_sync (client_connection,
149 : : "com.example.Test",
150 : : "/com/example/Test",
151 : : "com.example.Test.Manager",
152 : : "GetObjectPath",
153 : : g_variant_new ("(u)", 123),
154 : : G_VARIANT_TYPE ("(o)"),
155 : : G_DBUS_CALL_FLAGS_NONE,
156 : : -1, /* timeout (ms) */
157 : : NULL, /* cancellable */
158 : : &local_error);
159 : : }
160 : :
161 [ - + ]: 2 : g_assert_no_error (local_error);
162 [ - + ]: 2 : g_assert_nonnull (reply);
163 : :
164 : 2 : g_variant_get (reply, "(o)", &object_path);
165 : :
166 [ + - ]: 2 : g_clear_pointer (&reply, g_variant_unref);
167 : :
168 : : /* Get and check the object properties. */
169 [ + + ]: 2 : if (test_async)
170 : : {
171 : 2 : g_autoptr(GAsyncResult) result = NULL;
172 : :
173 : 1 : g_dbus_connection_call (client_connection,
174 : : "com.example.Test",
175 : : object_path,
176 : : "org.freedesktop.DBus.Properties",
177 : : "GetAll",
178 : : g_variant_new ("(s)", "com.example.Test.Object"),
179 : : G_VARIANT_TYPE ("(a{sv})"),
180 : : G_DBUS_CALL_FLAGS_NONE,
181 : : -1, /* timeout (ms) */
182 : : NULL, /* cancellable */
183 : : async_result_cb,
184 : : &result);
185 : :
186 [ + + ]: 3 : while (result == NULL)
187 : 2 : g_main_context_iteration (NULL, TRUE);
188 : 1 : reply = g_dbus_connection_call_finish (client_connection, result, &local_error);
189 : : }
190 : : else
191 : : {
192 : 1 : reply = g_dbus_connection_call_sync (client_connection,
193 : : "com.example.Test",
194 : : object_path,
195 : : "org.freedesktop.DBus.Properties",
196 : : "GetAll",
197 : : g_variant_new ("(s)", "com.example.Test.Object"),
198 : : G_VARIANT_TYPE ("(a{sv})"),
199 : : G_DBUS_CALL_FLAGS_NONE,
200 : : -1, /* timeout (ms) */
201 : : NULL, /* cancellable */
202 : : &local_error);
203 : : }
204 : :
205 [ - + ]: 2 : g_assert_no_error (local_error);
206 [ - + ]: 2 : g_assert_nonnull (reply);
207 : :
208 : 2 : properties = g_variant_get_child_value (reply, 0);
209 : 2 : g_variant_lookup (properties, "some-str", "&s", &some_str);
210 [ - + ]: 2 : g_assert_cmpstr (some_str, ==, "hello");
211 : 2 : g_variant_lookup (properties, "some-int", "u", &some_int);
212 [ - + ]: 2 : g_assert_cmpuint (some_int, ==, 11);
213 : 2 : }
214 : :
215 : : /* This is run in a worker thread. */
216 : : static void
217 : 2 : series_server_cb (GtDBusQueue *queue,
218 : : gpointer user_data)
219 : : {
220 : 2 : BusFixture *fixture = user_data;
221 : 2 : g_autoptr(GDBusMethodInvocation) invocation1 = NULL;
222 : 2 : g_autoptr(GDBusMethodInvocation) invocation2 = NULL;
223 : 2 : g_autofree gchar *object_path = NULL;
224 : 2 : g_autofree gchar *reply1 = NULL;
225 : :
226 : : /* Handle the GetObjectPath() call. */
227 : : guint object_id;
228 : 2 : invocation1 =
229 : 2 : gt_dbus_queue_assert_pop_message (queue,
230 : : "/com/example/Test",
231 : : "com.example.Test.Manager",
232 : : "GetObjectPath", "(u)", &object_id);
233 [ - + ]: 2 : g_assert_cmpint (object_id, ==, fixture->valid_id);
234 : :
235 : 2 : object_path = g_strdup_printf ("/com/example/Test/Object%u", object_id);
236 : 2 : reply1 = g_strdup_printf ("(@o '%s',)", object_path);
237 : 2 : g_dbus_method_invocation_return_value (invocation1, g_variant_new_parsed (reply1));
238 : :
239 : : /* Handle the Properties.GetAll() call and return some arbitrary values for
240 : : * the given object. */
241 : : const gchar *property_interface;
242 : 2 : invocation2 =
243 : 2 : gt_dbus_queue_assert_pop_message (queue,
244 : : object_path,
245 : : "org.freedesktop.DBus.Properties",
246 : : "GetAll", "(&s)", &property_interface);
247 [ - + ]: 2 : g_assert_cmpstr (property_interface, ==, "com.example.Test.Object");
248 : :
249 : 2 : const gchar *reply2 =
250 : : "({"
251 : : "'some-str': <'hello'>,"
252 : : "'some-int': <@u 11>"
253 : : "},)";
254 : 2 : g_dbus_method_invocation_return_value (invocation2, g_variant_new_parsed (reply2));
255 : 2 : }
256 : :
257 : : int
258 : 2 : main (int argc,
259 : : char *argv[])
260 : : {
261 : 2 : setlocale (LC_ALL, "");
262 : :
263 : 2 : g_test_init (&argc, &argv, NULL);
264 : :
265 : 2 : g_test_add_func ("/dbus-queue/construction",
266 : : test_dbus_queue_construction);
267 : :
268 : 2 : g_test_add ("/dbus-queue/series-async", BusFixture, GUINT_TO_POINTER (TRUE),
269 : : bus_set_up, test_dbus_queue_series, bus_tear_down);
270 : 2 : g_test_add ("/dbus-queue/series-sync", BusFixture, GUINT_TO_POINTER (FALSE),
271 : : bus_set_up, test_dbus_queue_series, bus_tear_down);
272 : :
273 : 2 : return g_test_run ();
274 : : }
|