[kdbus] KDBUS_ITEM_PAYLOAD_OFF items are (once again) relative to msg header
[platform/upstream/glib.git] / gio / tests / dbus-appinfo.c
1 /*
2  * Copyright © 2013 Canonical Limited
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; either version 2 of the licence or (at
7  * your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General
15  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
16  *
17  * Authors: Ryan Lortie <desrt@desrt.ca>
18  */
19
20 #include <gio/gio.h>
21 #include <gio/gdesktopappinfo.h>
22
23 #include "gdbus-sessionbus.h"
24
25 static GDesktopAppInfo *appinfo;
26 static int current_state;
27 static gboolean saw_startup_id;
28 static gboolean requested_startup_id;
29
30
31 static GType test_app_launch_context_get_type (void);
32 typedef GAppLaunchContext TestAppLaunchContext;
33 typedef GAppLaunchContextClass TestAppLaunchContextClass;
34 G_DEFINE_TYPE (TestAppLaunchContext, test_app_launch_context, G_TYPE_APP_LAUNCH_CONTEXT)
35
36 static gchar *
37 test_app_launch_context_get_startup_notify_id (GAppLaunchContext *context,
38                                                GAppInfo          *info,
39                                                GList             *uris)
40 {
41   requested_startup_id = TRUE;
42   return g_strdup ("expected startup id");
43 }
44
45 static void
46 test_app_launch_context_init (TestAppLaunchContext *ctx)
47 {
48 }
49
50 static void
51 test_app_launch_context_class_init (GAppLaunchContextClass *class)
52 {
53   class->get_startup_notify_id = test_app_launch_context_get_startup_notify_id;
54 }
55
56 static GType test_application_get_type (void);
57 typedef GApplication TestApplication;
58 typedef GApplicationClass TestApplicationClass;
59 G_DEFINE_TYPE (TestApplication, test_application, G_TYPE_APPLICATION)
60
61 static void
62 saw_action (const gchar *action)
63 {
64   /* This is the main driver of the test.  It's a bit of a state
65    * machine.
66    *
67    * Each time some event arrives on the app, it calls here to report
68    * which event it was.  The initial activation of the app is what
69    * starts everything in motion (starting from state 0).  At each
70    * state, we assert that we receive the expected event, send the next
71    * event, then update the current_state variable so we do the correct
72    * thing next time.
73    */
74
75   switch (current_state)
76     {
77       case 0: g_assert_cmpstr (action, ==, "activate");
78
79       /* Let's try another activation... */
80       g_app_info_launch (G_APP_INFO (appinfo), NULL, NULL, NULL);
81       current_state = 1; return; case 1: g_assert_cmpstr (action, ==, "activate");
82
83
84       /* Now let's try opening some files... */
85       {
86         GList *files;
87
88         files = g_list_prepend (NULL, g_file_new_for_uri ("file:///a/b"));
89         files = g_list_append (files, g_file_new_for_uri ("file:///c/d"));
90         g_app_info_launch (G_APP_INFO (appinfo), files, NULL, NULL);
91         g_list_free_full (files, g_object_unref);
92       }
93       current_state = 2; return; case 2: g_assert_cmpstr (action, ==, "open");
94
95       /* Now action activations... */
96       g_desktop_app_info_launch_action (appinfo, "frob", NULL);
97       current_state = 3; return; case 3: g_assert_cmpstr (action, ==, "frob");
98
99       g_desktop_app_info_launch_action (appinfo, "tweak", NULL);
100       current_state = 4; return; case 4: g_assert_cmpstr (action, ==, "tweak");
101
102       g_desktop_app_info_launch_action (appinfo, "twiddle", NULL);
103       current_state = 5; return; case 5: g_assert_cmpstr (action, ==, "twiddle");
104
105       /* Now launch the app with startup notification */
106       {
107         GAppLaunchContext *ctx;
108
109         g_assert (saw_startup_id == FALSE);
110         ctx = g_object_new (test_app_launch_context_get_type (), NULL);
111         g_app_info_launch (G_APP_INFO (appinfo), NULL, ctx, NULL);
112         g_assert (requested_startup_id);
113         requested_startup_id = FALSE;
114         g_object_unref (ctx);
115       }
116       current_state = 6; return; case 6: g_assert_cmpstr (action, ==, "activate"); g_assert (saw_startup_id);
117       saw_startup_id = FALSE;
118
119       /* Now do the same for an action */
120       {
121         GAppLaunchContext *ctx;
122
123         g_assert (saw_startup_id == FALSE);
124         ctx = g_object_new (test_app_launch_context_get_type (), NULL);
125         g_desktop_app_info_launch_action (appinfo, "frob", ctx);
126         g_assert (requested_startup_id);
127         requested_startup_id = FALSE;
128         g_object_unref (ctx);
129       }
130       current_state = 7; return; case 7: g_assert_cmpstr (action, ==, "frob"); g_assert (saw_startup_id);
131       saw_startup_id = FALSE;
132
133       /* Now quit... */
134       g_desktop_app_info_launch_action (appinfo, "quit", NULL);
135       current_state = 8; return; case 8: g_assert_not_reached ();
136     }
137 }
138
139 static void
140 test_application_frob (GSimpleAction *action,
141                        GVariant      *parameter,
142                        gpointer       user_data)
143 {
144   g_assert (parameter == NULL);
145   saw_action ("frob");
146 }
147
148 static void
149 test_application_tweak (GSimpleAction *action,
150                         GVariant      *parameter,
151                         gpointer       user_data)
152 {
153   g_assert (parameter == NULL);
154   saw_action ("tweak");
155 }
156
157 static void
158 test_application_twiddle (GSimpleAction *action,
159                           GVariant      *parameter,
160                           gpointer       user_data)
161 {
162   g_assert (parameter == NULL);
163   saw_action ("twiddle");
164 }
165
166 static void
167 test_application_quit (GSimpleAction *action,
168                        GVariant      *parameter,
169                        gpointer       user_data)
170 {
171   GApplication *application = user_data;
172
173   g_application_quit (application);
174 }
175
176 static const GActionEntry app_actions[] = {
177   { "frob",         test_application_frob              },
178   { "tweak",        test_application_tweak             },
179   { "twiddle",      test_application_twiddle           },
180   { "quit",         test_application_quit              }
181 };
182
183 static void
184 test_application_activate (GApplication *application)
185 {
186   /* Unbalanced, but that's OK because we will quit() */
187   g_application_hold (application);
188
189   saw_action ("activate");
190 }
191
192 static void
193 test_application_open (GApplication  *application,
194                        GFile        **files,
195                        gint           n_files,
196                        const gchar   *hint)
197 {
198   GFile *f;
199
200   g_assert_cmpstr (hint, ==, "");
201
202   g_assert_cmpint (n_files, ==, 2);
203   f = g_file_new_for_uri ("file:///a/b");
204   g_assert (g_file_equal (files[0], f));
205   g_object_unref (f);
206   f = g_file_new_for_uri ("file:///c/d");
207   g_assert (g_file_equal (files[1], f));
208   g_object_unref (f);
209
210   saw_action ("open");
211 }
212
213 static void
214 test_application_startup (GApplication *application)
215 {
216   G_APPLICATION_CLASS (test_application_parent_class)
217     ->startup (application);
218
219   g_action_map_add_action_entries (G_ACTION_MAP (application), app_actions, G_N_ELEMENTS (app_actions), application);
220 }
221
222 static void
223 test_application_before_emit (GApplication *application,
224                               GVariant     *platform_data)
225 {
226   const gchar *startup_id;
227
228   g_assert (!saw_startup_id);
229
230   if (!g_variant_lookup (platform_data, "desktop-startup-id", "&s", &startup_id))
231     return;
232
233   g_assert_cmpstr (startup_id, ==, "expected startup id");
234   saw_startup_id = TRUE;
235 }
236
237 static void
238 test_application_init (TestApplication *app)
239 {
240 }
241
242 static void
243 test_application_class_init (GApplicationClass *class)
244 {
245   class->before_emit = test_application_before_emit;
246   class->startup = test_application_startup;
247   class->activate = test_application_activate;
248   class->open = test_application_open;
249 }
250
251 static void
252 test_dbus_appinfo (void)
253 {
254   const gchar *argv[] = { "myapp", NULL };
255   TestApplication *app;
256   int status;
257
258   appinfo = g_desktop_app_info_new_from_filename (g_test_build_filename (G_TEST_DIST,
259                                                                          "org.gtk.test.dbusappinfo.desktop",
260                                                                          NULL));
261   g_assert (appinfo != NULL);
262
263   app = g_object_new (test_application_get_type (),
264                       "application-id", "org.gtk.test.dbusappinfo",
265                       "flags", G_APPLICATION_HANDLES_OPEN,
266                       NULL);
267   status = g_application_run (app, 1, (gchar **) argv);
268
269   g_assert_cmpint (status, ==, 0);
270   g_assert_cmpint (current_state, ==, 8);
271
272   g_object_unref (appinfo);
273   g_object_unref (app);
274 }
275
276 int
277 main (int argc, char **argv)
278 {
279   g_test_init (&argc, &argv, NULL);
280
281   g_test_add_func ("/appinfo/dbusappinfo", test_dbus_appinfo);
282
283   return session_bus_run ();
284 }