tizen: kdbus: make i explicitly positive in make_single_header_vector
[platform/upstream/glib.git] / gio / tests / gdbus-example-subtree.c
1 #include <gio/gio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 /* ---------------------------------------------------------------------------------------------------- */
6
7 static GDBusNodeInfo *introspection_data = NULL;
8 static GDBusInterfaceInfo *manager_interface_info = NULL;
9 static GDBusInterfaceInfo *block_interface_info = NULL;
10 static GDBusInterfaceInfo *partition_interface_info = NULL;
11
12 /* Introspection data for the service we are exporting */
13 static const gchar introspection_xml[] =
14   "<node>"
15   "  <interface name='org.gtk.GDBus.Example.Manager'>"
16   "    <method name='Hello'>"
17   "      <arg type='s' name='greeting' direction='in'/>"
18   "      <arg type='s' name='response' direction='out'/>"
19   "    </method>"
20   "  </interface>"
21   "  <interface name='org.gtk.GDBus.Example.Block'>"
22   "    <method name='Hello'>"
23   "      <arg type='s' name='greeting' direction='in'/>"
24   "      <arg type='s' name='response' direction='out'/>"
25   "    </method>"
26   "    <property type='i' name='Major' access='read'/>"
27   "    <property type='i' name='Minor' access='read'/>"
28   "    <property type='s' name='Notes' access='readwrite'/>"
29   "  </interface>"
30   "  <interface name='org.gtk.GDBus.Example.Partition'>"
31   "    <method name='Hello'>"
32   "      <arg type='s' name='greeting' direction='in'/>"
33   "      <arg type='s' name='response' direction='out'/>"
34   "    </method>"
35   "    <property type='i' name='PartitionNumber' access='read'/>"
36   "    <property type='s' name='Notes' access='readwrite'/>"
37   "  </interface>"
38   "</node>";
39
40 /* ---------------------------------------------------------------------------------------------------- */
41
42 static void
43 manager_method_call (GDBusConnection       *connection,
44                      const gchar           *sender,
45                      const gchar           *object_path,
46                      const gchar           *interface_name,
47                      const gchar           *method_name,
48                      GVariant              *parameters,
49                      GDBusMethodInvocation *invocation,
50                      gpointer               user_data)
51 {
52   const gchar *greeting;
53   gchar *response;
54
55   g_assert_cmpstr (interface_name, ==, "org.gtk.GDBus.Example.Manager");
56   g_assert_cmpstr (method_name, ==, "Hello");
57
58   g_variant_get (parameters, "(&s)", &greeting);
59
60   response = g_strdup_printf ("Method %s.%s with user_data '%s' on object path %s called with arg '%s'",
61                               interface_name,
62                               method_name,
63                               (const gchar *) user_data,
64                               object_path,
65                               greeting);
66   g_dbus_method_invocation_return_value (invocation,
67                                          g_variant_new ("(s)", response));
68   g_free (response);
69 }
70
71 const GDBusInterfaceVTable manager_vtable =
72 {
73   manager_method_call,
74   NULL,                 /* get_property */
75   NULL,                 /* set_property */
76   { 0 }
77 };
78
79 /* ---------------------------------------------------------------------------------------------------- */
80
81 static void
82 block_method_call (GDBusConnection       *connection,
83                    const gchar           *sender,
84                    const gchar           *object_path,
85                    const gchar           *interface_name,
86                    const gchar           *method_name,
87                    GVariant              *parameters,
88                    GDBusMethodInvocation *invocation,
89                    gpointer               user_data)
90 {
91   g_assert_cmpstr (interface_name, ==, "org.gtk.GDBus.Example.Block");
92
93   if (g_strcmp0 (method_name, "Hello") == 0)
94     {
95       const gchar *greeting;
96       gchar *response;
97
98       g_variant_get (parameters, "(&s)", &greeting);
99
100       response = g_strdup_printf ("Method %s.%s with user_data '%s' on object path %s called with arg '%s'",
101                                   interface_name,
102                                   method_name,
103                                   (const gchar *) user_data,
104                                   object_path,
105                                   greeting);
106       g_dbus_method_invocation_return_value (invocation,
107                                              g_variant_new ("(s)", response));
108       g_free (response);
109     }
110   else if (g_strcmp0 (method_name, "DoStuff") == 0)
111     {
112       g_dbus_method_invocation_return_dbus_error (invocation,
113                                                   "org.gtk.GDBus.TestSubtree.Error.Failed",
114                                                   "This method intentionally always fails");
115     }
116   else
117     {
118       g_assert_not_reached ();
119     }
120 }
121
122 static GVariant *
123 block_get_property (GDBusConnection  *connection,
124                     const gchar      *sender,
125                     const gchar      *object_path,
126                     const gchar      *interface_name,
127                     const gchar      *property_name,
128                     GError          **error,
129                     gpointer          user_data)
130 {
131   GVariant *ret;
132   const gchar *node;
133   gint major;
134   gint minor;
135
136   node = strrchr (object_path, '/') + 1;
137   if (g_str_has_prefix (node, "sda"))
138     major = 8;
139   else
140     major = 9;
141   if (strlen (node) == 4)
142     minor = node[3] - '0';
143   else
144     minor = 0;
145
146   ret = NULL;
147   if (g_strcmp0 (property_name, "Major") == 0)
148     {
149       ret = g_variant_new_int32 (major);
150     }
151   else if (g_strcmp0 (property_name, "Minor") == 0)
152     {
153       ret = g_variant_new_int32 (minor);
154     }
155   else if (g_strcmp0 (property_name, "Notes") == 0)
156     {
157       g_set_error (error,
158                    G_IO_ERROR,
159                    G_IO_ERROR_FAILED,
160                    "Hello %s. I thought I said reading this property "
161                    "always results in an error. kthxbye",
162                    sender);
163     }
164   else
165     {
166       g_assert_not_reached ();
167     }
168
169   return ret;
170 }
171
172 static gboolean
173 block_set_property (GDBusConnection  *connection,
174                     const gchar      *sender,
175                     const gchar      *object_path,
176                     const gchar      *interface_name,
177                     const gchar      *property_name,
178                     GVariant         *value,
179                     GError          **error,
180                     gpointer          user_data)
181 {
182   /* TODO */
183   g_assert_not_reached ();
184 }
185
186 const GDBusInterfaceVTable block_vtable =
187 {
188   block_method_call,
189   block_get_property,
190   block_set_property,
191   { 0 }
192 };
193
194 /* ---------------------------------------------------------------------------------------------------- */
195
196 static void
197 partition_method_call (GDBusConnection       *connection,
198                        const gchar           *sender,
199                        const gchar           *object_path,
200                        const gchar           *interface_name,
201                        const gchar           *method_name,
202                        GVariant              *parameters,
203                        GDBusMethodInvocation *invocation,
204                        gpointer               user_data)
205 {
206   const gchar *greeting;
207   gchar *response;
208
209   g_assert_cmpstr (interface_name, ==, "org.gtk.GDBus.Example.Partition");
210   g_assert_cmpstr (method_name, ==, "Hello");
211
212   g_variant_get (parameters, "(&s)", &greeting);
213
214   response = g_strdup_printf ("Method %s.%s with user_data '%s' on object path %s called with arg '%s'",
215                               interface_name,
216                               method_name,
217                               (const gchar *) user_data,
218                               object_path,
219                               greeting);
220   g_dbus_method_invocation_return_value (invocation,
221                                          g_variant_new ("(s)", response));
222   g_free (response);
223 }
224
225 const GDBusInterfaceVTable partition_vtable =
226 {
227   partition_method_call,
228   NULL,
229   NULL,
230   { 0 }
231 };
232
233 /* ---------------------------------------------------------------------------------------------------- */
234
235 static gchar **
236 subtree_enumerate (GDBusConnection       *connection,
237                    const gchar           *sender,
238                    const gchar           *object_path,
239                    gpointer               user_data)
240 {
241   gchar **nodes;
242   GPtrArray *p;
243
244   p = g_ptr_array_new ();
245   g_ptr_array_add (p, g_strdup ("sda"));
246   g_ptr_array_add (p, g_strdup ("sda1"));
247   g_ptr_array_add (p, g_strdup ("sda2"));
248   g_ptr_array_add (p, g_strdup ("sda3"));
249   g_ptr_array_add (p, g_strdup ("sdb"));
250   g_ptr_array_add (p, g_strdup ("sdb1"));
251   g_ptr_array_add (p, g_strdup ("sdc"));
252   g_ptr_array_add (p, g_strdup ("sdc1"));
253   g_ptr_array_add (p, NULL);
254   nodes = (gchar **) g_ptr_array_free (p, FALSE);
255
256   return nodes;
257 }
258
259 static GDBusInterfaceInfo **
260 subtree_introspect (GDBusConnection       *connection,
261                     const gchar           *sender,
262                     const gchar           *object_path,
263                     const gchar           *node,
264                     gpointer               user_data)
265 {
266   GPtrArray *p;
267
268   p = g_ptr_array_new ();
269   if (node == NULL)
270     {
271       g_ptr_array_add (p, g_dbus_interface_info_ref (manager_interface_info));
272     }
273   else
274     {
275       g_ptr_array_add (p, g_dbus_interface_info_ref (block_interface_info));
276       if (strlen (node) == 4)
277         g_ptr_array_add (p,
278                          g_dbus_interface_info_ref (partition_interface_info));
279     }
280
281   g_ptr_array_add (p, NULL);
282
283   return (GDBusInterfaceInfo **) g_ptr_array_free (p, FALSE);
284 }
285
286 static const GDBusInterfaceVTable *
287 subtree_dispatch (GDBusConnection             *connection,
288                   const gchar                 *sender,
289                   const gchar                 *object_path,
290                   const gchar                 *interface_name,
291                   const gchar                 *node,
292                   gpointer                    *out_user_data,
293                   gpointer                     user_data)
294 {
295   const GDBusInterfaceVTable *vtable_to_return;
296   gpointer user_data_to_return;
297
298   if (g_strcmp0 (interface_name, "org.gtk.GDBus.Example.Manager") == 0)
299     {
300       user_data_to_return = "The Root";
301       vtable_to_return = &manager_vtable;
302     }
303   else
304     {
305       if (strlen (node) == 4)
306         user_data_to_return = "A partition";
307       else
308         user_data_to_return = "A block device";
309
310       if (g_strcmp0 (interface_name, "org.gtk.GDBus.Example.Block") == 0)
311         vtable_to_return = &block_vtable;
312       else if (g_strcmp0 (interface_name, "org.gtk.GDBus.Example.Partition") == 0)
313         vtable_to_return = &partition_vtable;
314       else
315         g_assert_not_reached ();
316     }
317
318   *out_user_data = user_data_to_return;
319
320   return vtable_to_return;
321 }
322
323 const GDBusSubtreeVTable subtree_vtable =
324 {
325   subtree_enumerate,
326   subtree_introspect,
327   subtree_dispatch,
328   { 0 }
329 };
330
331 /* ---------------------------------------------------------------------------------------------------- */
332
333 static void
334 on_bus_acquired (GDBusConnection *connection,
335                  const gchar     *name,
336                  gpointer         user_data)
337 {
338   guint registration_id;
339
340   registration_id = g_dbus_connection_register_subtree (connection,
341                                                         "/org/gtk/GDBus/TestSubtree/Devices",
342                                                         &subtree_vtable,
343                                                         G_DBUS_SUBTREE_FLAGS_NONE,
344                                                         NULL,  /* user_data */
345                                                         NULL,  /* user_data_free_func */
346                                                         NULL); /* GError** */
347   g_assert (registration_id > 0);
348 }
349
350 static void
351 on_name_acquired (GDBusConnection *connection,
352                   const gchar     *name,
353                   gpointer         user_data)
354 {
355 }
356
357 static void
358 on_name_lost (GDBusConnection *connection,
359               const gchar     *name,
360               gpointer         user_data)
361 {
362   exit (1);
363 }
364
365 int
366 main (int argc, char *argv[])
367 {
368   guint owner_id;
369   GMainLoop *loop;
370
371   /* We are lazy here - we don't want to manually provide
372    * the introspection data structures - so we just build
373    * them from XML.
374    */
375   introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
376   g_assert (introspection_data != NULL);
377
378   manager_interface_info = g_dbus_node_info_lookup_interface (introspection_data, "org.gtk.GDBus.Example.Manager");
379   block_interface_info = g_dbus_node_info_lookup_interface (introspection_data, "org.gtk.GDBus.Example.Block");
380   partition_interface_info = g_dbus_node_info_lookup_interface (introspection_data, "org.gtk.GDBus.Example.Partition");
381   g_assert (manager_interface_info != NULL);
382   g_assert (block_interface_info != NULL);
383   g_assert (partition_interface_info != NULL);
384
385   owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
386                              "org.gtk.GDBus.TestSubtree",
387                              G_BUS_NAME_OWNER_FLAGS_NONE,
388                              on_bus_acquired,
389                              on_name_acquired,
390                              on_name_lost,
391                              NULL,
392                              NULL);
393
394   loop = g_main_loop_new (NULL, FALSE);
395   g_main_loop_run (loop);
396
397   g_bus_unown_name (owner_id);
398
399   g_dbus_node_info_unref (introspection_data);
400
401   return 0;
402 }