• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GLib testing framework examples and tests
2  *
3  * Copyright (C) 2012 Red Hat 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
16  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17  *
18  * Author: Stef Walter <stefw@gnome.org>
19  */
20 
21 #include "config.h"
22 
23 #include <gio/gio.h>
24 
25 #include <sys/socket.h>
26 
27 #include <errno.h>
28 #include <string.h>
29 #include <unistd.h>
30 
31 typedef struct {
32   GDBusInterfaceSkeleton parent;
33   gint number;
34 } MockInterface;
35 
36 typedef struct {
37   GDBusInterfaceSkeletonClass parent_class;
38 } MockInterfaceClass;
39 
40 static GType mock_interface_get_type (void);
G_DEFINE_TYPE(MockInterface,mock_interface,G_TYPE_DBUS_INTERFACE_SKELETON)41 G_DEFINE_TYPE (MockInterface, mock_interface, G_TYPE_DBUS_INTERFACE_SKELETON)
42 
43 static void
44 mock_interface_init (MockInterface *self)
45 {
46 
47 }
48 
49 static GDBusInterfaceInfo *
mock_interface_get_info(GDBusInterfaceSkeleton * skeleton)50 mock_interface_get_info (GDBusInterfaceSkeleton *skeleton)
51 {
52   static GDBusPropertyInfo path_info = {
53     -1,
54     "Path",
55     "o",
56     G_DBUS_PROPERTY_INFO_FLAGS_READABLE,
57     NULL,
58   };
59 
60   static GDBusPropertyInfo number_info = {
61     -1,
62     "Number",
63     "i",
64     G_DBUS_PROPERTY_INFO_FLAGS_READABLE,
65     NULL,
66   };
67 
68   static GDBusPropertyInfo *property_info[] = {
69     &path_info,
70     &number_info,
71     NULL
72   };
73 
74   static GDBusInterfaceInfo interface_info = {
75     -1,
76     (gchar *) "org.mock.Interface",
77     NULL,
78     NULL,
79     (GDBusPropertyInfo **) &property_info,
80     NULL
81   };
82 
83   return &interface_info;
84 }
85 
86 static GVariant *
mock_interface_get_property(GDBusConnection * connection,const gchar * sender,const gchar * object_path,const gchar * interface_name,const gchar * property_name,GError ** error,gpointer user_data)87 mock_interface_get_property (GDBusConnection *connection,
88                              const gchar *sender,
89                              const gchar *object_path,
90                              const gchar *interface_name,
91                              const gchar *property_name,
92                              GError **error,
93                              gpointer user_data)
94 {
95   MockInterface *self = user_data;
96   if (g_str_equal (property_name, "Path"))
97     return g_variant_new_object_path (object_path);
98   else if (g_str_equal (property_name, "Number"))
99     return g_variant_new_int32 (self->number);
100   else
101     return NULL;
102 }
103 
104 static GDBusInterfaceVTable *
mock_interface_get_vtable(GDBusInterfaceSkeleton * interface)105 mock_interface_get_vtable (GDBusInterfaceSkeleton *interface)
106 {
107   static GDBusInterfaceVTable vtable = {
108     NULL,
109     mock_interface_get_property,
110     NULL,
111   };
112 
113   return &vtable;
114 }
115 
116 static GVariant *
mock_interface_get_properties(GDBusInterfaceSkeleton * interface)117 mock_interface_get_properties (GDBusInterfaceSkeleton *interface)
118 {
119   GVariantBuilder builder;
120   GDBusInterfaceInfo *info;
121   GDBusInterfaceVTable *vtable;
122   guint n;
123 
124   /* Groan, this is completely generic code and should be in gdbus */
125 
126   info = g_dbus_interface_skeleton_get_info (interface);
127   vtable = g_dbus_interface_skeleton_get_vtable (interface);
128 
129   g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
130   for (n = 0; info->properties[n] != NULL; n++)
131     {
132       if (info->properties[n]->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
133         {
134           GVariant *value;
135           g_return_val_if_fail (vtable->get_property != NULL, NULL);
136           value = (vtable->get_property) (g_dbus_interface_skeleton_get_connection (interface), NULL,
137                                           g_dbus_interface_skeleton_get_object_path (interface),
138                                           info->name, info->properties[n]->name,
139                                           NULL, interface);
140           if (value != NULL)
141             {
142               g_variant_take_ref (value);
143               g_variant_builder_add (&builder, "{sv}", info->properties[n]->name, value);
144               g_variant_unref (value);
145             }
146         }
147     }
148 
149   return g_variant_builder_end (&builder);
150 }
151 
152 static void
mock_interface_flush(GDBusInterfaceSkeleton * skeleton)153 mock_interface_flush (GDBusInterfaceSkeleton *skeleton)
154 {
155 
156 }
157 
158 static void
mock_interface_class_init(MockInterfaceClass * klass)159 mock_interface_class_init (MockInterfaceClass *klass)
160 {
161   GDBusInterfaceSkeletonClass *skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass);
162   skeleton_class->get_info = mock_interface_get_info;
163   skeleton_class->get_properties = mock_interface_get_properties;
164   skeleton_class->flush = mock_interface_flush;
165   skeleton_class->get_vtable = mock_interface_get_vtable;
166 }
167 typedef struct {
168   GDBusConnection *server;
169   GDBusConnection *client;
170   GMainLoop *loop;
171   GAsyncResult *result;
172 } Test;
173 
174 static void
on_server_connection(GObject * source,GAsyncResult * result,gpointer user_data)175 on_server_connection (GObject *source,
176                       GAsyncResult *result,
177                       gpointer user_data)
178 {
179   Test *test = user_data;
180   GError *error = NULL;
181 
182   g_assert (test->server == NULL);
183   test->server = g_dbus_connection_new_finish (result, &error);
184   g_assert_no_error (error);
185   g_assert (test->server != NULL);
186 
187   if (test->server && test->client)
188     g_main_loop_quit (test->loop);
189 }
190 
191 static void
on_client_connection(GObject * source,GAsyncResult * result,gpointer user_data)192 on_client_connection (GObject *source,
193                       GAsyncResult *result,
194                       gpointer user_data)
195 {
196   Test *test = user_data;
197   GError *error = NULL;
198 
199   g_assert (test->client == NULL);
200   test->client = g_dbus_connection_new_finish (result, &error);
201   g_assert_no_error (error);
202   g_assert (test->client != NULL);
203 
204   if (test->server && test->client)
205     g_main_loop_quit (test->loop);
206 }
207 
208 static void
setup(Test * test,gconstpointer unused)209 setup (Test *test,
210        gconstpointer unused)
211 {
212   GError *error = NULL;
213   GSocket *socket;
214   GSocketConnection *stream;
215   gchar *guid;
216   int pair[2];
217 
218   test->loop = g_main_loop_new (NULL, FALSE);
219 
220   if (socketpair (AF_UNIX, SOCK_STREAM, 0, pair) < 0)
221     {
222       int errsv = errno;
223       g_set_error (&error, G_IO_ERROR, g_io_error_from_errno (errsv),
224                    "%s", g_strerror (errsv));
225       g_assert_no_error (error);
226     }
227 
228   /* Build up the server stuff */
229   socket = g_socket_new_from_fd (pair[1], &error);
230   g_assert_no_error (error);
231 
232   stream = g_socket_connection_factory_create_connection (socket);
233   g_assert (stream != NULL);
234   g_object_unref (socket);
235 
236   guid = g_dbus_generate_guid ();
237   g_dbus_connection_new (G_IO_STREAM (stream), guid,
238                          G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER |
239                          G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS,
240                          NULL, NULL, on_server_connection, test);
241   g_object_unref (stream);
242   g_free (guid);
243 
244   /* Build up the client stuff */
245   socket = g_socket_new_from_fd (pair[0], &error);
246   g_assert_no_error (error);
247 
248   stream = g_socket_connection_factory_create_connection (socket);
249   g_assert (stream != NULL);
250   g_object_unref (socket);
251 
252   g_dbus_connection_new (G_IO_STREAM (stream), NULL,
253                          G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
254                          G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS,
255                          NULL, NULL, on_client_connection, test);
256 
257   g_main_loop_run (test->loop);
258 
259   g_assert (test->server);
260   g_assert (test->client);
261 
262   g_object_unref (stream);
263 }
264 
265 static void
teardown(Test * test,gconstpointer unused)266 teardown (Test *test,
267           gconstpointer unused)
268 {
269   g_clear_object (&test->client);
270   g_clear_object (&test->server);
271   g_main_loop_unref (test->loop);
272 }
273 
274 static void
on_result(GObject * source,GAsyncResult * result,gpointer user_data)275 on_result (GObject *source,
276            GAsyncResult *result,
277            gpointer user_data)
278 {
279   Test *test = user_data;
280   g_assert (test->result == NULL);
281   test->result = g_object_ref (result);
282   g_main_loop_quit (test->loop);
283 
284 }
285 
286 static void
test_object_manager(Test * test,gconstpointer test_data)287 test_object_manager (Test *test,
288                      gconstpointer test_data)
289 {
290   GDBusObjectManager *client;
291   GDBusObjectManagerServer *server;
292   MockInterface *mock;
293   GDBusObjectSkeleton *skeleton;
294   const gchar *dbus_name;
295   GError *error = NULL;
296   GDBusInterface *proxy;
297   GVariant *prop;
298   const gchar *object_path = test_data;
299   gchar *number1_path = NULL, *number2_path = NULL;
300 
301   if (g_strcmp0 (object_path, "/") == 0)
302     {
303       number1_path = g_strdup ("/number_1");
304       number2_path = g_strdup ("/number_2");
305     }
306   else
307     {
308       number1_path = g_strdup_printf ("%s/number_1", object_path);
309       number2_path = g_strdup_printf ("%s/number_2", object_path);
310     }
311 
312   server = g_dbus_object_manager_server_new (object_path);
313 
314   mock = g_object_new (mock_interface_get_type (), NULL);
315   mock->number = 1;
316   skeleton = g_dbus_object_skeleton_new (number1_path);
317   g_dbus_object_skeleton_add_interface (skeleton, G_DBUS_INTERFACE_SKELETON (mock));
318   g_dbus_object_manager_server_export (server, skeleton);
319 
320   mock = g_object_new (mock_interface_get_type (), NULL);
321   mock->number = 2;
322   skeleton = g_dbus_object_skeleton_new (number2_path);
323   g_dbus_object_skeleton_add_interface (skeleton, G_DBUS_INTERFACE_SKELETON (mock));
324   g_dbus_object_manager_server_export (server, skeleton);
325 
326   g_dbus_object_manager_server_set_connection (server, test->server);
327 
328   dbus_name = NULL;
329 
330   g_dbus_object_manager_client_new (test->client, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START,
331                                     dbus_name, object_path, NULL, NULL, NULL, NULL, on_result, test);
332 
333   g_main_loop_run (test->loop);
334   client = g_dbus_object_manager_client_new_finish (test->result, &error);
335   g_assert_no_error (error);
336   g_clear_object (&test->result);
337 
338   proxy = g_dbus_object_manager_get_interface (client, number1_path, "org.mock.Interface");
339   g_assert (proxy != NULL);
340   prop = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Path");
341   g_assert (prop != NULL);
342   g_assert_cmpstr ((gchar *)g_variant_get_type (prop), ==, (gchar *)G_VARIANT_TYPE_OBJECT_PATH);
343   g_assert_cmpstr (g_variant_get_string (prop, NULL), ==, number1_path);
344   g_variant_unref (prop);
345   prop = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Number");
346   g_assert (prop != NULL);
347   g_assert_cmpstr ((gchar *)g_variant_get_type (prop), ==, (gchar *)G_VARIANT_TYPE_INT32);
348   g_assert_cmpint (g_variant_get_int32 (prop), ==, 1);
349   g_variant_unref (prop);
350   g_object_unref (proxy);
351 
352   proxy = g_dbus_object_manager_get_interface (client, number2_path, "org.mock.Interface");
353   g_assert (proxy != NULL);
354   prop = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Path");
355   g_assert (prop != NULL);
356   g_assert_cmpstr ((gchar *)g_variant_get_type (prop), ==, (gchar *)G_VARIANT_TYPE_OBJECT_PATH);
357   g_assert_cmpstr (g_variant_get_string (prop, NULL), ==, number2_path);
358   g_variant_unref (prop);
359   prop = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Number");
360   g_assert (prop != NULL);
361   g_assert_cmpstr ((gchar *)g_variant_get_type (prop), ==, (gchar *)G_VARIANT_TYPE_INT32);
362   g_assert_cmpint (g_variant_get_int32 (prop), ==, 2);
363   g_variant_unref (prop);
364   g_object_unref (proxy);
365 
366   g_object_unref (server);
367   g_object_unref (client);
368 
369   g_free (number2_path);
370   g_free (number1_path);
371 }
372 
373 int
main(int argc,char * argv[])374 main (int   argc,
375       char *argv[])
376 {
377   g_test_init (&argc, &argv, NULL);
378 
379   g_test_add ("/gdbus/peer-object-manager/normal", Test, "/objects",
380               setup, test_object_manager, teardown);
381   g_test_add ("/gdbus/peer-object-manager/root", Test, "/",
382               setup, test_object_manager, teardown);
383 
384   return g_test_run();
385 }
386