Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2008 Red Hat, Inc
3 : : *
4 : : * SPDX-License-Identifier: LGPL-2.1-or-later
5 : : *
6 : : * This library is free software; you can redistribute it and/or
7 : : * modify it under the terms of the GNU Lesser General Public
8 : : * License as published by the Free Software Foundation; either
9 : : * version 2.1 of the License, or (at your option) any later version.
10 : : *
11 : : * This library is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : : * Lesser General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU Lesser General
17 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 : : *
19 : : * Author: Matthias Clasen
20 : : */
21 : :
22 : : #include <locale.h>
23 : :
24 : : #include <glib/glib.h>
25 : : #include <glib/gstdio.h>
26 : : #include <gio/gio.h>
27 : : #include <gio/gdesktopappinfo.h>
28 : : #include <gio/gunixinputstream.h>
29 : : #include <glib-unix.h>
30 : : #include <stdlib.h>
31 : : #include <string.h>
32 : : #include <unistd.h>
33 : : #include <sys/types.h>
34 : : #include <sys/stat.h>
35 : :
36 : : #include "fake-document-portal.h"
37 : : #include "gdbus-sessionbus.h"
38 : :
39 : 55 : G_DECLARE_FINAL_TYPE (TestLaunchContext, test_launch_context, TEST,
40 : : LAUNCH_CONTEXT, GAppLaunchContext);
41 : :
42 : : struct _TestLaunchContext {
43 : : GAppLaunchContext parent;
44 : :
45 : : char *overriden_startup_notify_id;
46 : : };
47 : :
48 : : struct _TestLaunchContextClass {
49 : : GAppLaunchContextClass parent;
50 : : };
51 : :
52 : 97 : G_DEFINE_FINAL_TYPE (TestLaunchContext, test_launch_context,
53 : : G_TYPE_APP_LAUNCH_CONTEXT);
54 : :
55 : : static void
56 : 40 : test_launch_context_init (TestLaunchContext *test_context)
57 : : {
58 : 40 : }
59 : :
60 : : static char *
61 : 10 : test_launch_context_get_startup_notify_id (GAppLaunchContext *context,
62 : : GAppInfo *app_info,
63 : : GList *files)
64 : : {
65 : 10 : TestLaunchContext *test_context = TEST_LAUNCH_CONTEXT (context);
66 : :
67 : 10 : if (test_context->overriden_startup_notify_id)
68 : 0 : return g_strdup (test_context->overriden_startup_notify_id);
69 : :
70 : 10 : if (g_app_info_get_id (app_info))
71 : 16 : return g_strdup (g_app_info_get_id (app_info));
72 : :
73 : 2 : if (g_app_info_get_display_name (app_info))
74 : 4 : return g_strdup (g_app_info_get_display_name (app_info));
75 : :
76 : 0 : return g_strdup (g_app_info_get_commandline (app_info));
77 : : }
78 : :
79 : : static void
80 : 40 : test_launch_context_get_startup_notify_dispose (GObject *object)
81 : : {
82 : 40 : TestLaunchContext *test_context = TEST_LAUNCH_CONTEXT (object);
83 : :
84 : 40 : g_clear_pointer (&test_context->overriden_startup_notify_id, g_free);
85 : 40 : G_OBJECT_CLASS (test_launch_context_parent_class)->dispose (object);
86 : 40 : }
87 : :
88 : : static void
89 : 1 : test_launch_context_class_init (TestLaunchContextClass *klass)
90 : : {
91 : 1 : G_APP_LAUNCH_CONTEXT_CLASS (klass)->get_startup_notify_id = test_launch_context_get_startup_notify_id;
92 : 1 : G_OBJECT_CLASS (klass)->dispose = test_launch_context_get_startup_notify_dispose;
93 : 1 : }
94 : :
95 : : static GAppInfo *
96 : 13 : create_command_line_app_info (const char *name,
97 : : const char *command_line,
98 : : const char *default_for_type)
99 : : {
100 : : GAppInfo *info;
101 : 13 : GError *error = NULL;
102 : :
103 : 13 : info = g_app_info_create_from_commandline (command_line,
104 : : name,
105 : : G_APP_INFO_CREATE_NONE,
106 : : &error);
107 : 13 : g_assert_no_error (error);
108 : :
109 : 13 : g_app_info_set_as_default_for_type (info, default_for_type, &error);
110 : 13 : g_assert_no_error (error);
111 : :
112 : 13 : return g_steal_pointer (&info);
113 : : }
114 : :
115 : : static GAppInfo *
116 : 11 : create_app_info (const char *name)
117 : : {
118 : 11 : GError *error = NULL;
119 : : GAppInfo *info;
120 : :
121 : 11 : info = create_command_line_app_info (name, "true blah", "application/x-blah");
122 : :
123 : : /* this is necessary to ensure that the info is saved */
124 : 11 : g_app_info_remove_supports_type (info, "application/x-blah", &error);
125 : 11 : g_assert_no_error (error);
126 : 11 : g_app_info_reset_type_associations ("application/x-blah");
127 : :
128 : 11 : return info;
129 : : }
130 : :
131 : : static gboolean
132 : 7 : skip_missing_update_desktop_database (void)
133 : : {
134 : 7 : gchar *path = g_find_program_in_path ("update-desktop-database");
135 : :
136 : 7 : if (path == NULL)
137 : : {
138 : 0 : g_test_skip ("update-desktop-database is required to run this test");
139 : 0 : return TRUE;
140 : : }
141 : 7 : g_free (path);
142 : 7 : return FALSE;
143 : : }
144 : :
145 : : static void
146 : 1 : test_delete (void)
147 : : {
148 : : GAppInfo *info;
149 : :
150 : : const char *id;
151 : : char *filename;
152 : : gboolean res;
153 : :
154 : 1 : if (skip_missing_update_desktop_database ())
155 : 0 : return;
156 : :
157 : 1 : info = create_app_info ("Blah");
158 : :
159 : 1 : id = g_app_info_get_id (info);
160 : 1 : g_assert_nonnull (id);
161 : :
162 : 1 : filename = g_build_filename (g_get_user_data_dir (), "applications", id, NULL);
163 : :
164 : 1 : res = g_file_test (filename, G_FILE_TEST_EXISTS);
165 : 1 : g_assert_true (res);
166 : :
167 : 1 : res = g_app_info_can_delete (info);
168 : 1 : g_assert_true (res);
169 : :
170 : 1 : res = g_app_info_delete (info);
171 : 1 : g_assert_true (res);
172 : :
173 : 1 : res = g_file_test (filename, G_FILE_TEST_EXISTS);
174 : 1 : g_assert_false (res);
175 : :
176 : 1 : g_object_unref (info);
177 : :
178 : 1 : if (g_file_test ("/usr/share/applications/gedit.desktop", G_FILE_TEST_EXISTS))
179 : : {
180 : 0 : info = (GAppInfo*)g_desktop_app_info_new_from_filename ("/usr/share/applications/gedit.desktop");
181 : 0 : g_assert_nonnull (info);
182 : :
183 : 0 : res = g_app_info_can_delete (info);
184 : 0 : g_assert_false (res);
185 : :
186 : 0 : res = g_app_info_delete (info);
187 : 0 : g_assert_false (res);
188 : : }
189 : :
190 : 1 : g_free (filename);
191 : : }
192 : :
193 : : static void
194 : 1 : test_default (void)
195 : : {
196 : : GAppInfo *info, *info1, *info2, *info3;
197 : : GList *list;
198 : 1 : GError *error = NULL;
199 : :
200 : 1 : if (skip_missing_update_desktop_database ())
201 : 0 : return;
202 : :
203 : 1 : info1 = create_app_info ("Blah1");
204 : 1 : info2 = create_app_info ("Blah2");
205 : 1 : info3 = create_app_info ("Blah3");
206 : :
207 : 1 : g_app_info_set_as_default_for_type (info1, "application/x-test", &error);
208 : 1 : g_assert_no_error (error);
209 : :
210 : 1 : g_app_info_set_as_default_for_type (info2, "application/x-test", &error);
211 : 1 : g_assert_no_error (error);
212 : :
213 : 1 : info = g_app_info_get_default_for_type ("application/x-test", FALSE);
214 : 1 : g_assert_nonnull (info);
215 : 1 : g_assert_cmpstr (g_app_info_get_id (info), ==, g_app_info_get_id (info2));
216 : 1 : g_object_unref (info);
217 : :
218 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
219 : : "*assertion*uri_scheme*failed*");
220 : 1 : g_assert_null (g_app_info_get_default_for_uri_scheme (NULL));
221 : 1 : g_test_assert_expected_messages ();
222 : :
223 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
224 : : "*assertion*uri_scheme*failed*");
225 : 1 : g_assert_null (g_app_info_get_default_for_uri_scheme (""));
226 : 1 : g_test_assert_expected_messages ();
227 : :
228 : 1 : g_app_info_set_as_default_for_type (info3, "x-scheme-handler/glib", &error);
229 : 1 : g_assert_no_error (error);
230 : 1 : info = g_app_info_get_default_for_uri_scheme ("glib");
231 : 1 : g_assert_nonnull (info);
232 : 1 : g_assert_true (g_app_info_equal (info, info3));
233 : 1 : g_object_unref (info);
234 : :
235 : : /* now try adding something, but not setting as default */
236 : 1 : g_app_info_add_supports_type (info3, "application/x-test", &error);
237 : 1 : g_assert_no_error (error);
238 : :
239 : : /* check that info2 is still default */
240 : 1 : info = g_app_info_get_default_for_type ("application/x-test", FALSE);
241 : 1 : g_assert_nonnull (info);
242 : 1 : g_assert_cmpstr (g_app_info_get_id (info), ==, g_app_info_get_id (info2));
243 : 1 : g_object_unref (info);
244 : :
245 : : /* now remove info1 again */
246 : 1 : g_app_info_remove_supports_type (info1, "application/x-test", &error);
247 : 1 : g_assert_no_error (error);
248 : :
249 : : /* and make sure info2 is still default */
250 : 1 : info = g_app_info_get_default_for_type ("application/x-test", FALSE);
251 : 1 : g_assert_nonnull (info);
252 : 1 : g_assert_cmpstr (g_app_info_get_id (info), ==, g_app_info_get_id (info2));
253 : 1 : g_object_unref (info);
254 : :
255 : : /* now clean it all up */
256 : 1 : g_app_info_reset_type_associations ("application/x-test");
257 : 1 : g_app_info_reset_type_associations ("x-scheme-handler/glib");
258 : :
259 : 1 : list = g_app_info_get_all_for_type ("application/x-test");
260 : 1 : g_assert_null (list);
261 : :
262 : 1 : list = g_app_info_get_all_for_type ("x-scheme-handler/glib");
263 : 1 : g_assert_null (list);
264 : :
265 : 1 : g_app_info_delete (info1);
266 : 1 : g_app_info_delete (info2);
267 : 1 : g_app_info_delete (info3);
268 : :
269 : 1 : g_object_unref (info1);
270 : 1 : g_object_unref (info2);
271 : 1 : g_object_unref (info3);
272 : : }
273 : :
274 : : typedef struct
275 : : {
276 : : GAppInfo *expected_info;
277 : : GMainLoop *loop;
278 : : } DefaultForTypeData;
279 : :
280 : : static void
281 : 6 : ensure_default_type_result (GAppInfo *info,
282 : : DefaultForTypeData *data,
283 : : GError *error)
284 : : {
285 : 6 : if (data->expected_info)
286 : : {
287 : 4 : g_assert_nonnull (info);
288 : 4 : g_assert_no_error (error);
289 : 4 : g_assert_true (g_app_info_equal (info, data->expected_info));
290 : : }
291 : : else
292 : : {
293 : 2 : g_assert_null (info);
294 : 2 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND);
295 : : }
296 : :
297 : 6 : g_main_loop_quit (data->loop);
298 : 6 : g_clear_object (&info);
299 : 6 : g_clear_error (&error);
300 : 6 : }
301 : :
302 : : static void
303 : 4 : on_default_for_type_cb (GObject *object,
304 : : GAsyncResult *result,
305 : : gpointer user_data)
306 : : {
307 : : GAppInfo *info;
308 : 4 : GError *error = NULL;
309 : 4 : DefaultForTypeData *data = user_data;
310 : :
311 : 4 : g_assert_null (object);
312 : :
313 : 4 : info = g_app_info_get_default_for_type_finish (result, &error);
314 : :
315 : 4 : ensure_default_type_result (info, data, error);
316 : 4 : }
317 : :
318 : : static void
319 : 2 : on_default_for_uri_cb (GObject *object,
320 : : GAsyncResult *result,
321 : : gpointer user_data)
322 : : {
323 : : GAppInfo *info;
324 : 2 : GError *error = NULL;
325 : 2 : DefaultForTypeData *data = user_data;
326 : :
327 : 2 : g_assert_null (object);
328 : :
329 : 2 : info = g_app_info_get_default_for_uri_scheme_finish (result, &error);
330 : :
331 : 2 : ensure_default_type_result (info, data, error);
332 : 2 : }
333 : :
334 : : static void
335 : 1 : test_default_async (void)
336 : : {
337 : : DefaultForTypeData data;
338 : : GAppInfo *info1, *info2, *info3;
339 : : GList *list;
340 : 1 : GError *error = NULL;
341 : :
342 : 1 : if (skip_missing_update_desktop_database ())
343 : 0 : return;
344 : :
345 : 1 : data.loop = g_main_loop_new (NULL, TRUE);
346 : :
347 : 1 : info1 = create_app_info ("Blah1");
348 : 1 : info2 = create_app_info ("Blah2");
349 : 1 : info3 = create_app_info ("Blah3");
350 : :
351 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
352 : : "*assertion*content_type*failed*");
353 : 1 : g_app_info_get_default_for_type_async (NULL, FALSE, NULL, NULL, NULL);
354 : 1 : g_test_assert_expected_messages ();
355 : :
356 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
357 : : "*assertion*content_type*failed*");
358 : 1 : g_app_info_get_default_for_type_async ("", FALSE, NULL, NULL, NULL);
359 : 1 : g_test_assert_expected_messages ();
360 : :
361 : 1 : g_app_info_set_as_default_for_type (info1, "application/x-test", &error);
362 : 1 : g_assert_no_error (error);
363 : :
364 : 1 : g_app_info_set_as_default_for_type (info2, "application/x-test", &error);
365 : 1 : g_assert_no_error (error);
366 : :
367 : 1 : data.expected_info = info2;
368 : 1 : g_app_info_get_default_for_type_async ("application/x-test", FALSE,
369 : : NULL, on_default_for_type_cb, &data);
370 : 1 : g_main_loop_run (data.loop);
371 : :
372 : : /* now try adding something, but not setting as default */
373 : 1 : g_app_info_add_supports_type (info3, "application/x-test", &error);
374 : 1 : g_assert_no_error (error);
375 : :
376 : : /* check that info2 is still default */
377 : 1 : data.expected_info = info2;
378 : 1 : g_app_info_get_default_for_type_async ("application/x-test", FALSE,
379 : : NULL, on_default_for_type_cb, &data);
380 : 1 : g_main_loop_run (data.loop);
381 : :
382 : : /* now remove info1 again */
383 : 1 : g_app_info_remove_supports_type (info1, "application/x-test", &error);
384 : 1 : g_assert_no_error (error);
385 : :
386 : : /* and make sure info2 is still default */
387 : 1 : data.expected_info = info2;
388 : 1 : g_app_info_get_default_for_type_async ("application/x-test", FALSE,
389 : : NULL, on_default_for_type_cb, &data);
390 : 1 : g_main_loop_run (data.loop);
391 : :
392 : 1 : g_app_info_set_as_default_for_type (info3, "x-scheme-handler/glib-async", &error);
393 : 1 : g_assert_no_error (error);
394 : :
395 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
396 : : "*assertion*uri_scheme*failed*");
397 : 1 : g_assert_null (g_app_info_get_default_for_uri_scheme (NULL));
398 : 1 : g_test_assert_expected_messages ();
399 : :
400 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
401 : : "*assertion*uri_scheme*failed*");
402 : 1 : g_assert_null (g_app_info_get_default_for_uri_scheme (""));
403 : 1 : g_test_assert_expected_messages ();
404 : :
405 : 1 : data.expected_info = info3;
406 : 1 : g_app_info_get_default_for_uri_scheme_async ("glib-async", NULL,
407 : : on_default_for_uri_cb, &data);
408 : 1 : g_main_loop_run (data.loop);
409 : :
410 : : /* now clean it all up */
411 : 1 : g_app_info_reset_type_associations ("application/x-test");
412 : :
413 : 1 : data.expected_info = NULL;
414 : 1 : g_app_info_get_default_for_type_async ("application/x-test", FALSE,
415 : : NULL, on_default_for_type_cb, &data);
416 : 1 : g_main_loop_run (data.loop);
417 : :
418 : 1 : g_app_info_reset_type_associations ("x-scheme-handler/glib-async");
419 : :
420 : 1 : data.expected_info = NULL;
421 : 1 : g_app_info_get_default_for_uri_scheme_async ("glib-async", NULL,
422 : : on_default_for_uri_cb, &data);
423 : 1 : g_main_loop_run (data.loop);
424 : :
425 : 1 : list = g_app_info_get_all_for_type ("application/x-test");
426 : 1 : g_assert_null (list);
427 : :
428 : 1 : g_app_info_delete (info1);
429 : 1 : g_app_info_delete (info2);
430 : 1 : g_app_info_delete (info3);
431 : :
432 : 1 : g_object_unref (info1);
433 : 1 : g_object_unref (info2);
434 : 1 : g_object_unref (info3);
435 : :
436 : 1 : g_main_loop_unref (data.loop);
437 : : }
438 : :
439 : : static void
440 : 1 : test_fallback (void)
441 : : {
442 : 1 : GAppInfo *info1, *info2, *app = NULL;
443 : : GList *apps, *recomm, *fallback, *list, *l, *m;
444 : 1 : GError *error = NULL;
445 : : gint old_length;
446 : :
447 : 1 : if (skip_missing_update_desktop_database ())
448 : 0 : return;
449 : :
450 : 1 : info1 = create_app_info ("Test1");
451 : 1 : info2 = create_app_info ("Test2");
452 : :
453 : 1 : g_assert_true (g_content_type_is_a ("text/x-python", "text/plain"));
454 : :
455 : 1 : apps = g_app_info_get_all_for_type ("text/x-python");
456 : 1 : old_length = g_list_length (apps);
457 : 1 : g_list_free_full (apps, g_object_unref);
458 : :
459 : 1 : g_app_info_add_supports_type (info1, "text/x-python", &error);
460 : 1 : g_assert_no_error (error);
461 : :
462 : 1 : g_app_info_add_supports_type (info2, "text/plain", &error);
463 : 1 : g_assert_no_error (error);
464 : :
465 : : /* check that both apps are registered */
466 : 1 : apps = g_app_info_get_all_for_type ("text/x-python");
467 : 1 : g_assert_cmpint (g_list_length (apps), ==, old_length + 2);
468 : :
469 : : /* check that Test1 is among the recommended apps */
470 : 1 : recomm = g_app_info_get_recommended_for_type ("text/x-python");
471 : 1 : g_assert_nonnull (recomm);
472 : 1 : for (l = recomm; l; l = l->next)
473 : : {
474 : 1 : app = l->data;
475 : 1 : if (g_app_info_equal (info1, app))
476 : 1 : break;
477 : : }
478 : 1 : g_assert_nonnull (app);
479 : 1 : g_assert_true (g_app_info_equal (info1, app));
480 : :
481 : : /* and that Test2 is among the fallback apps */
482 : 1 : fallback = g_app_info_get_fallback_for_type ("text/x-python");
483 : 1 : g_assert_nonnull (fallback);
484 : 1 : for (l = fallback; l; l = l->next)
485 : : {
486 : 1 : app = l->data;
487 : 1 : if (g_app_info_equal (info2, app))
488 : 1 : break;
489 : : }
490 : 1 : g_assert_cmpstr (g_app_info_get_name (app), ==, "Test2");
491 : :
492 : : /* check that recomm + fallback = all applications */
493 : 1 : list = g_list_concat (g_list_copy (recomm), g_list_copy (fallback));
494 : 1 : g_assert_cmpuint (g_list_length (list), ==, g_list_length (apps));
495 : :
496 : 3 : for (l = list, m = apps; l != NULL && m != NULL; l = l->next, m = m->next)
497 : : {
498 : 2 : g_assert_true (g_app_info_equal (l->data, m->data));
499 : : }
500 : :
501 : 1 : g_list_free (list);
502 : :
503 : 1 : g_list_free_full (apps, g_object_unref);
504 : 1 : g_list_free_full (recomm, g_object_unref);
505 : 1 : g_list_free_full (fallback, g_object_unref);
506 : :
507 : 1 : g_app_info_reset_type_associations ("text/x-python");
508 : 1 : g_app_info_reset_type_associations ("text/plain");
509 : :
510 : 1 : g_app_info_delete (info1);
511 : 1 : g_app_info_delete (info2);
512 : :
513 : 1 : g_object_unref (info1);
514 : 1 : g_object_unref (info2);
515 : : }
516 : :
517 : : static void
518 : 1 : test_last_used (void)
519 : : {
520 : : GList *applications;
521 : : GAppInfo *info1, *info2, *default_app;
522 : 1 : GError *error = NULL;
523 : :
524 : 1 : if (skip_missing_update_desktop_database ())
525 : 0 : return;
526 : :
527 : 1 : info1 = create_app_info ("Test1");
528 : 1 : info2 = create_app_info ("Test2");
529 : :
530 : 1 : g_app_info_set_as_default_for_type (info1, "application/x-test", &error);
531 : 1 : g_assert_no_error (error);
532 : :
533 : 1 : g_app_info_add_supports_type (info2, "application/x-test", &error);
534 : 1 : g_assert_no_error (error);
535 : :
536 : 1 : applications = g_app_info_get_recommended_for_type ("application/x-test");
537 : 1 : g_assert_cmpuint (g_list_length (applications), ==, 2);
538 : :
539 : : /* the first should be the default app now */
540 : 1 : g_assert_true (g_app_info_equal (g_list_nth_data (applications, 0), info1));
541 : 1 : g_assert_true (g_app_info_equal (g_list_nth_data (applications, 1), info2));
542 : :
543 : 1 : g_list_free_full (applications, g_object_unref);
544 : :
545 : 1 : g_app_info_set_as_last_used_for_type (info2, "application/x-test", &error);
546 : 1 : g_assert_no_error (error);
547 : :
548 : 1 : applications = g_app_info_get_recommended_for_type ("application/x-test");
549 : 1 : g_assert_cmpuint (g_list_length (applications), ==, 2);
550 : :
551 : 1 : default_app = g_app_info_get_default_for_type ("application/x-test", FALSE);
552 : 1 : g_assert_true (g_app_info_equal (default_app, info1));
553 : :
554 : : /* the first should be the other app now */
555 : 1 : g_assert_true (g_app_info_equal (g_list_nth_data (applications, 0), info2));
556 : 1 : g_assert_true (g_app_info_equal (g_list_nth_data (applications, 1), info1));
557 : :
558 : 1 : g_list_free_full (applications, g_object_unref);
559 : :
560 : 1 : g_app_info_reset_type_associations ("application/x-test");
561 : :
562 : 1 : g_app_info_delete (info1);
563 : 1 : g_app_info_delete (info2);
564 : :
565 : 1 : g_object_unref (info1);
566 : 1 : g_object_unref (info2);
567 : 1 : g_object_unref (default_app);
568 : : }
569 : :
570 : : static void
571 : 1 : test_extra_getters (void)
572 : : {
573 : : GDesktopAppInfo *appinfo;
574 : : const gchar *lang;
575 : : gchar *s;
576 : : gboolean b;
577 : :
578 : 1 : lang = setlocale (LC_ALL, NULL);
579 : 1 : g_setenv ("LANGUAGE", "de_DE.UTF8", TRUE);
580 : 1 : setlocale (LC_ALL, "");
581 : :
582 : 1 : appinfo = g_desktop_app_info_new_from_filename (g_test_get_filename (G_TEST_DIST, "appinfo-test-static.desktop", NULL));
583 : 1 : g_assert_nonnull (appinfo);
584 : :
585 : 1 : g_assert_true (g_desktop_app_info_has_key (appinfo, "Terminal"));
586 : 1 : g_assert_false (g_desktop_app_info_has_key (appinfo, "Bratwurst"));
587 : :
588 : 1 : s = g_desktop_app_info_get_string (appinfo, "StartupWMClass");
589 : 1 : g_assert_cmpstr (s, ==, "appinfo-class");
590 : 1 : g_free (s);
591 : :
592 : 1 : s = g_desktop_app_info_get_locale_string (appinfo, "X-JunkFood");
593 : 1 : g_assert_cmpstr (s, ==, "Bratwurst");
594 : 1 : g_free (s);
595 : :
596 : 1 : g_setenv ("LANGUAGE", "sv_SE.UTF8", TRUE);
597 : 1 : setlocale (LC_ALL, "");
598 : :
599 : 1 : s = g_desktop_app_info_get_locale_string (appinfo, "X-JunkFood");
600 : 1 : g_assert_cmpstr (s, ==, "Burger"); /* fallback */
601 : 1 : g_free (s);
602 : :
603 : 1 : b = g_desktop_app_info_get_boolean (appinfo, "Terminal");
604 : 1 : g_assert_true (b);
605 : :
606 : 1 : g_object_unref (appinfo);
607 : :
608 : 1 : g_setenv ("LANGUAGE", lang, TRUE);
609 : 1 : setlocale (LC_ALL, "");
610 : 1 : }
611 : :
612 : : static void
613 : 3 : wait_for_file (const gchar *want_this,
614 : : const gchar *but_not_this,
615 : : const gchar *or_this)
616 : : {
617 : 6 : while (access (want_this, F_OK) != 0)
618 : 3 : g_usleep (100000); /* 100ms */
619 : :
620 : 3 : g_assert_cmpuint (access (but_not_this, F_OK), !=, 0);
621 : 3 : g_assert_cmpuint (access (or_this, F_OK), !=, 0);
622 : :
623 : 3 : unlink (want_this);
624 : 3 : unlink (but_not_this);
625 : 3 : unlink (or_this);
626 : 3 : }
627 : :
628 : : static gboolean
629 : 2 : skip_missing_dbus_daemon (void)
630 : : {
631 : 2 : gchar *path = g_find_program_in_path ("dbus-daemon");
632 : 2 : if (path == NULL)
633 : : {
634 : 0 : g_test_skip ("dbus-daemon is required to run this test");
635 : 0 : return TRUE;
636 : : }
637 : 2 : g_free (path);
638 : 2 : return FALSE;
639 : : }
640 : :
641 : : static void
642 : 1 : test_actions (void)
643 : : {
644 : 1 : GTestDBus *bus = NULL;
645 : 1 : const char *expected[] = { "frob", "tweak", "twiddle", "broken", NULL };
646 : : const gchar * const *actions;
647 : : GDesktopAppInfo *appinfo;
648 : : const gchar *tmpdir;
649 : : gchar *name;
650 : : gchar *frob_path;
651 : : gchar *tweak_path;
652 : : gchar *twiddle_path;
653 : :
654 : 1 : if (skip_missing_dbus_daemon ())
655 : 0 : return;
656 : :
657 : : /* Set up a test session bus to keep D-Bus traffic off the real session bus. */
658 : 1 : bus = g_test_dbus_new (G_TEST_DBUS_NONE);
659 : 1 : g_test_dbus_up (bus);
660 : :
661 : 1 : appinfo = g_desktop_app_info_new_from_filename (g_test_get_filename (G_TEST_DIST, "appinfo-test-actions.desktop", NULL));
662 : 1 : g_assert_nonnull (appinfo);
663 : :
664 : 1 : actions = g_desktop_app_info_list_actions (appinfo);
665 : 5 : g_assert_cmpstrv (actions, expected);
666 : :
667 : 1 : name = g_desktop_app_info_get_action_name (appinfo, "frob");
668 : 1 : g_assert_cmpstr (name, ==, "Frobnicate");
669 : 1 : g_free (name);
670 : :
671 : 1 : name = g_desktop_app_info_get_action_name (appinfo, "tweak");
672 : 1 : g_assert_cmpstr (name, ==, "Tweak");
673 : 1 : g_free (name);
674 : :
675 : 1 : name = g_desktop_app_info_get_action_name (appinfo, "twiddle");
676 : 1 : g_assert_cmpstr (name, ==, "Twiddle");
677 : 1 : g_free (name);
678 : :
679 : 1 : name = g_desktop_app_info_get_action_name (appinfo, "broken");
680 : 1 : g_assert_nonnull (name);
681 : 1 : g_assert_true (g_utf8_validate (name, -1, NULL));
682 : 1 : g_free (name);
683 : :
684 : 1 : tmpdir = g_getenv ("G_TEST_TMPDIR");
685 : 1 : g_assert_nonnull (tmpdir);
686 : 1 : frob_path = g_build_filename (tmpdir, "frob", NULL);
687 : 1 : tweak_path = g_build_filename (tmpdir, "tweak", NULL);
688 : 1 : twiddle_path = g_build_filename (tmpdir, "twiddle", NULL);
689 : :
690 : 1 : g_assert_false (g_file_test (frob_path, G_FILE_TEST_EXISTS));
691 : 1 : g_assert_false (g_file_test (tweak_path, G_FILE_TEST_EXISTS));
692 : 1 : g_assert_false (g_file_test (twiddle_path, G_FILE_TEST_EXISTS));
693 : :
694 : 1 : g_desktop_app_info_launch_action (appinfo, "frob", NULL);
695 : 1 : wait_for_file (frob_path, tweak_path, twiddle_path);
696 : :
697 : 1 : g_desktop_app_info_launch_action (appinfo, "tweak", NULL);
698 : 1 : wait_for_file (tweak_path, frob_path, twiddle_path);
699 : :
700 : 1 : g_desktop_app_info_launch_action (appinfo, "twiddle", NULL);
701 : 1 : wait_for_file (twiddle_path, frob_path, tweak_path);
702 : :
703 : 1 : g_free (frob_path);
704 : 1 : g_free (tweak_path);
705 : 1 : g_free (twiddle_path);
706 : 1 : g_object_unref (appinfo);
707 : :
708 : 1 : g_test_dbus_down (bus);
709 : 1 : g_clear_object (&bus);
710 : : }
711 : :
712 : : static gchar *
713 : 50 : run_apps (const gchar *command,
714 : : const gchar *arg,
715 : : gboolean with_usr,
716 : : gboolean with_home,
717 : : const gchar *locale_name,
718 : : const gchar *language,
719 : : const gchar *xdg_current_desktop)
720 : : {
721 : : gboolean success;
722 : : gchar **envp;
723 : : gchar **argv;
724 : : gint status;
725 : : gchar *out;
726 : 50 : gchar *argv_str = NULL;
727 : :
728 : 50 : argv = g_new (gchar *, 4);
729 : 50 : argv[0] = g_test_build_filename (G_TEST_BUILT, "apps", NULL);
730 : 50 : argv[1] = g_strdup (command);
731 : 50 : argv[2] = g_strdup (arg);
732 : 50 : argv[3] = NULL;
733 : :
734 : 50 : g_assert_true (g_file_test (argv[0], G_FILE_TEST_IS_EXECUTABLE));
735 : 50 : envp = g_get_environ ();
736 : :
737 : 50 : if (with_usr)
738 : : {
739 : 41 : gchar *tmp = g_test_build_filename (G_TEST_DIST, "desktop-files", "usr", NULL);
740 : 41 : envp = g_environ_setenv (envp, "XDG_DATA_DIRS", tmp, TRUE);
741 : 41 : g_free (tmp);
742 : : }
743 : : else
744 : 9 : envp = g_environ_setenv (envp, "XDG_DATA_DIRS", "/does-not-exist", TRUE);
745 : :
746 : 50 : if (with_home)
747 : : {
748 : 34 : gchar *tmp = g_test_build_filename (G_TEST_DIST, "desktop-files", "home", NULL);
749 : 34 : envp = g_environ_setenv (envp, "XDG_DATA_HOME", tmp, TRUE);
750 : 34 : g_free (tmp);
751 : : }
752 : : else
753 : 16 : envp = g_environ_setenv (envp, "XDG_DATA_HOME", "/does-not-exist", TRUE);
754 : :
755 : 50 : if (locale_name)
756 : 2 : envp = g_environ_setenv (envp, "LC_ALL", locale_name, TRUE);
757 : : else
758 : 48 : envp = g_environ_setenv (envp, "LC_ALL", "C", TRUE);
759 : :
760 : 50 : if (language)
761 : 2 : envp = g_environ_setenv (envp, "LANGUAGE", language, TRUE);
762 : : else
763 : 48 : envp = g_environ_unsetenv (envp, "LANGUAGE");
764 : :
765 : 50 : if (xdg_current_desktop)
766 : 10 : envp = g_environ_setenv (envp, "XDG_CURRENT_DESKTOP", xdg_current_desktop, TRUE);
767 : : else
768 : 40 : envp = g_environ_unsetenv (envp, "XDG_CURRENT_DESKTOP");
769 : :
770 : 50 : envp = g_environ_setenv (envp, "G_MESSAGES_DEBUG", "", TRUE);
771 : :
772 : 50 : success = g_spawn_sync (NULL, argv, envp, 0, NULL, NULL, &out, NULL, &status, NULL);
773 : 50 : g_assert_true (success);
774 : 50 : g_assert_cmpuint (status, ==, 0);
775 : :
776 : 50 : argv_str = g_strjoinv (" ", argv);
777 : 50 : g_test_message ("%s: `%s` returned: %s", G_STRFUNC, argv_str, out);
778 : 50 : g_free (argv_str);
779 : :
780 : 50 : g_strfreev (envp);
781 : 50 : g_strfreev (argv);
782 : :
783 : 50 : return out;
784 : : }
785 : :
786 : : static void
787 : 59 : assert_strings_equivalent (const gchar *expected,
788 : : const gchar *result)
789 : 101 : {
790 : : gchar **expected_words;
791 : : gchar **result_words;
792 : : gint i, j;
793 : :
794 : 59 : expected_words = g_strsplit (expected, " ", 0);
795 : 59 : result_words = g_strsplit_set (result, " \n", 0);
796 : :
797 : 160 : for (i = 0; expected_words[i]; i++)
798 : : {
799 : 1007 : for (j = 0; result_words[j]; j++)
800 : 1007 : if (g_str_equal (expected_words[i], result_words[j]))
801 : 101 : goto got_it;
802 : :
803 : 0 : g_test_fail_printf ("Unable to find expected string '%s' in result '%s'", expected_words[i], result);
804 : :
805 : 101 : got_it:
806 : 101 : continue;
807 : : }
808 : :
809 : 59 : g_assert_cmpint (g_strv_length (expected_words), ==, g_strv_length (result_words));
810 : 59 : g_strfreev (expected_words);
811 : 59 : g_strfreev (result_words);
812 : 59 : }
813 : :
814 : : static void
815 : 4 : assert_list (const gchar *expected,
816 : : gboolean with_usr,
817 : : gboolean with_home,
818 : : const gchar *locale_name,
819 : : const gchar *language)
820 : : {
821 : : gchar *result;
822 : :
823 : 4 : result = run_apps ("list", NULL, with_usr, with_home, locale_name, language, NULL);
824 : 4 : g_strchomp (result);
825 : 4 : assert_strings_equivalent (expected, result);
826 : 4 : g_free (result);
827 : 4 : }
828 : :
829 : : static void
830 : 2 : assert_info (const gchar *desktop_id,
831 : : const gchar *expected,
832 : : gboolean with_usr,
833 : : gboolean with_home,
834 : : const gchar *locale_name,
835 : : const gchar *language)
836 : : {
837 : : gchar *result;
838 : :
839 : 2 : result = run_apps ("show-info", desktop_id, with_usr, with_home, locale_name, language, NULL);
840 : 2 : g_assert_cmpstr (result, ==, expected);
841 : 2 : g_free (result);
842 : 2 : }
843 : :
844 : : static void
845 : 28 : assert_search (const gchar *search_string,
846 : : const gchar *expected,
847 : : gboolean with_usr,
848 : : gboolean with_home,
849 : : const gchar *locale_name,
850 : : const gchar *language)
851 : : {
852 : : gchar **expected_lines;
853 : : gchar **result_lines;
854 : : gchar *result;
855 : : gint i;
856 : :
857 : 28 : expected_lines = g_strsplit (expected, "\n", -1);
858 : 28 : result = run_apps ("search", search_string, with_usr, with_home, locale_name, language, NULL);
859 : 28 : result_lines = g_strsplit (result, "\n", -1);
860 : 28 : g_assert_cmpint (g_strv_length (expected_lines), ==, g_strv_length (result_lines));
861 : 79 : for (i = 0; expected_lines[i]; i++)
862 : 51 : assert_strings_equivalent (expected_lines[i], result_lines[i]);
863 : 28 : g_strfreev (expected_lines);
864 : 28 : g_strfreev (result_lines);
865 : 28 : g_free (result);
866 : 28 : }
867 : :
868 : : static void
869 : 4 : assert_implementations (const gchar *interface,
870 : : const gchar *expected,
871 : : gboolean with_usr,
872 : : gboolean with_home)
873 : : {
874 : : gchar *result;
875 : :
876 : 4 : result = run_apps ("implementations", interface, with_usr, with_home, NULL, NULL, NULL);
877 : 4 : g_strchomp (result);
878 : 4 : assert_strings_equivalent (expected, result);
879 : 4 : g_free (result);
880 : 4 : }
881 : :
882 : : #define ALL_USR_APPS "evince-previewer.desktop nautilus-classic.desktop gnome-font-viewer.desktop " \
883 : : "baobab.desktop yelp.desktop eog.desktop cheese.desktop org.gnome.clocks.desktop " \
884 : : "gnome-contacts.desktop kde4-kate.desktop gcr-prompter.desktop totem.desktop " \
885 : : "gnome-terminal.desktop nautilus-autorun-software.desktop gcr-viewer.desktop " \
886 : : "nautilus-connect-server.desktop kde4-dolphin.desktop gnome-music.desktop " \
887 : : "kde4-konqbrowser.desktop gucharmap.desktop kde4-okular.desktop nautilus.desktop " \
888 : : "gedit.desktop evince.desktop file-roller.desktop dconf-editor.desktop glade.desktop " \
889 : : "invalid-desktop.desktop org.gnome.Calculator.desktop libreoffice-calc.desktop"
890 : : #define HOME_APPS "epiphany-weather-for-toronto-island-9c6a4e022b17686306243dada811d550d25eb1fb.desktop"
891 : : #define ALL_HOME_APPS HOME_APPS " eog.desktop"
892 : :
893 : : static void
894 : 1 : test_search (void)
895 : : {
896 : 1 : assert_list ("", FALSE, FALSE, NULL, NULL);
897 : 1 : assert_list (ALL_USR_APPS, TRUE, FALSE, NULL, NULL);
898 : 1 : assert_list (ALL_HOME_APPS, FALSE, TRUE, NULL, NULL);
899 : 1 : assert_list (ALL_USR_APPS " " HOME_APPS, TRUE, TRUE, NULL, NULL);
900 : :
901 : : /* The user has "installed" their own version of eog.desktop which
902 : : * calls it "Eye of GNOME". Do some testing based on that.
903 : : *
904 : : * We should always find "Pictures" keyword no matter where we look.
905 : : */
906 : 1 : assert_search ("Picture", "eog.desktop\n", TRUE, TRUE, NULL, NULL);
907 : 1 : assert_search ("Picture", "eog.desktop\n", TRUE, FALSE, NULL, NULL);
908 : 1 : assert_search ("Picture", "eog.desktop\n", FALSE, TRUE, NULL, NULL);
909 : 1 : assert_search ("Picture", "", FALSE, FALSE, NULL, NULL);
910 : :
911 : : /* We should only find it called "eye of gnome" when using the user's
912 : : * directory.
913 : : */
914 : 1 : assert_search ("eye gnome", "", TRUE, FALSE, NULL, NULL);
915 : 1 : assert_search ("eye gnome", "eog.desktop\n", FALSE, TRUE, NULL, NULL);
916 : 1 : assert_search ("eye gnome", "eog.desktop\n", TRUE, TRUE, NULL, NULL);
917 : :
918 : : /* We should only find it called "image viewer" when _not_ using the
919 : : * user's directory.
920 : : */
921 : 1 : assert_search ("image viewer", "eog.desktop\n", TRUE, FALSE, NULL, NULL);
922 : 1 : assert_search ("image viewer", "", FALSE, TRUE, NULL, NULL);
923 : 1 : assert_search ("image viewer", "", TRUE, TRUE, NULL, NULL);
924 : :
925 : : /* There're "flatpak" apps (clocks) installed as well - they should *not*
926 : : * match the prefix command ("/bin/sh") in the Exec= line though. Then with
927 : : * substring matching, Image Viewer (eog) should be in next group because it
928 : : * contains "Slideshow" in its keywords.
929 : : *
930 : : * Finally we have LibreOffice Calc, which contains "OpenDocument Spreadsheet".
931 : : * It is sorted last because its match ("sh" in "Spreadsheet") occurs in a
932 : : * later token.
933 : : */
934 : 1 : assert_search ("sh", "gnome-terminal.desktop\n"
935 : : "eog.desktop\n"
936 : : "libreoffice-calc.desktop\n", TRUE, FALSE, NULL, NULL);
937 : :
938 : : /* "frobnicator.desktop" is ignored by get_all() because the binary is
939 : : * missing, but search should still find it (to avoid either stale results
940 : : * from the cache or expensive stat() calls for each potential result)
941 : : */
942 : 1 : assert_search ("frobni", "frobnicator.desktop\n", TRUE, FALSE, NULL, NULL);
943 : :
944 : : /* Obvious multi-word search */
945 : 1 : assert_search ("doc hel", "yelp.desktop\n", TRUE, TRUE, NULL, NULL);
946 : :
947 : : /* Repeated search terms should do nothing... */
948 : 1 : assert_search ("files file fil fi f", "nautilus.desktop\n", TRUE, TRUE, NULL, NULL);
949 : :
950 : : /* "con" will match "connect" and "contacts" on name with prefix match in
951 : : * first group, then second group is a Keyword prefix match for "configuration" in dconf-editor.desktop
952 : : * and third group is a substring match for "Desktop Icons" in Name of nautilus-classic.desktop.
953 : : */
954 : 1 : assert_search ("con", "gnome-contacts.desktop nautilus-connect-server.desktop\n"
955 : : "dconf-editor.desktop\n"
956 : : "nautilus-classic.desktop\n", TRUE, TRUE, NULL, NULL);
957 : :
958 : : /* We prefer matches of tokens that come earlier in a string. In this case
959 : : * "LibreOffice Calc" and "Calculator" both have a name that contains a prefix
960 : : * match "cal", but the one in Calculator occurs in the first token.
961 : : */
962 : 1 : assert_search ("cal", "org.gnome.Calculator.desktop\nlibreoffice-calc.desktop\n", TRUE, TRUE, NULL, NULL);
963 : :
964 : : /* Same as above, but ensure that substring matches are sorted after prefix matches */
965 : 1 : assert_search ("ca", "org.gnome.Calculator.desktop\n"
966 : : "libreoffice-calc.desktop\n"
967 : : "frobnicator.desktop\n"
968 : : "cheese.desktop\n", TRUE, TRUE, NULL, NULL);
969 : :
970 : : /* "gnome" will match "eye of gnome" from the user's directory, plus
971 : : * matching "GNOME Clocks" X-GNOME-FullName.
972 : : */
973 : 1 : assert_search ("gnome", "eog.desktop\n"
974 : : "org.gnome.clocks.desktop\n", TRUE, TRUE, NULL, NULL);
975 : :
976 : : /* eog has exec name 'false' in usr only */
977 : 1 : assert_search ("false", "eog.desktop\n", TRUE, FALSE, NULL, NULL);
978 : 1 : assert_search ("false", "", FALSE, TRUE, NULL, NULL);
979 : 1 : assert_search ("false", "", TRUE, TRUE, NULL, NULL);
980 : 1 : assert_search ("false", "", FALSE, FALSE, NULL, NULL);
981 : :
982 : : /* make sure we only search the first component */
983 : 1 : assert_search ("nonsearchable", "", TRUE, FALSE, NULL, NULL);
984 : :
985 : : /* "gnome con" will match only gnome contacts; via the name for
986 : : * "contacts" and keywords for "friend"
987 : : */
988 : 1 : assert_search ("friend con", "gnome-contacts.desktop\n", TRUE, TRUE, NULL, NULL);
989 : :
990 : : /* make sure we get the correct kde4- prefix on the application IDs
991 : : * from subdirectories
992 : : */
993 : 1 : assert_search ("konq", "kde4-konqbrowser.desktop\n", TRUE, TRUE, NULL, NULL);
994 : 1 : assert_search ("kate", "kde4-kate.desktop\n", TRUE, TRUE, NULL, NULL);
995 : :
996 : : /* make sure we can look up apps by name properly */
997 : 1 : assert_info ("kde4-kate.desktop",
998 : : "kde4-kate.desktop\n"
999 : : "Kate\n"
1000 : : "Kate\n"
1001 : : "nil\n", TRUE, TRUE, NULL, NULL);
1002 : :
1003 : 1 : assert_info ("nautilus.desktop",
1004 : : "nautilus.desktop\n"
1005 : : "Files\n"
1006 : : "Files\n"
1007 : : "Access and organize files\n", TRUE, TRUE, NULL, NULL);
1008 : :
1009 : : /* make sure localised searching works properly */
1010 : 1 : assert_search ("foliumi", "nautilus.desktop\n"
1011 : : "kde4-konqbrowser.desktop\n", TRUE, FALSE, "en_US.UTF-8", "eo");
1012 : : /* the user's eog.desktop has no translations... */
1013 : 1 : assert_search ("foliumi", "nautilus.desktop\n"
1014 : : "kde4-konqbrowser.desktop\n", TRUE, TRUE, "en_US.UTF-8", "eo");
1015 : 1 : }
1016 : :
1017 : : static void
1018 : 1 : test_implements (void)
1019 : : {
1020 : : /* Make sure we can find our search providers... */
1021 : 1 : assert_implementations ("org.gnome.Shell.SearchProvider2",
1022 : : "gnome-music.desktop gnome-contacts.desktop eog.desktop",
1023 : : TRUE, FALSE);
1024 : :
1025 : : /* And our image acquisition possibilities... */
1026 : 1 : assert_implementations ("org.freedesktop.ImageProvider",
1027 : : "cheese.desktop",
1028 : : TRUE, FALSE);
1029 : :
1030 : : /* Make sure the user's eog is properly masking the system one */
1031 : 1 : assert_implementations ("org.gnome.Shell.SearchProvider2",
1032 : : "gnome-music.desktop gnome-contacts.desktop",
1033 : : TRUE, TRUE);
1034 : :
1035 : : /* Make sure we get nothing if we have nothing */
1036 : 1 : assert_implementations ("org.gnome.Shell.SearchProvider2", "", FALSE, FALSE);
1037 : 1 : }
1038 : :
1039 : : static void
1040 : 11 : assert_shown (const gchar *desktop_id,
1041 : : gboolean expected,
1042 : : const gchar *xdg_current_desktop)
1043 : : {
1044 : : gchar *result;
1045 : :
1046 : 11 : result = run_apps ("should-show", desktop_id, TRUE, TRUE, NULL, NULL, xdg_current_desktop);
1047 : 11 : g_assert_cmpstr (result, ==, expected ? "true\n" : "false\n");
1048 : 11 : g_free (result);
1049 : 11 : }
1050 : :
1051 : : static void
1052 : 1 : test_show_in (void)
1053 : : {
1054 : 1 : assert_shown ("gcr-prompter.desktop", FALSE, NULL);
1055 : 1 : assert_shown ("gcr-prompter.desktop", FALSE, "GNOME");
1056 : 1 : assert_shown ("gcr-prompter.desktop", FALSE, "KDE");
1057 : 1 : assert_shown ("gcr-prompter.desktop", FALSE, "GNOME:GNOME-Classic");
1058 : 1 : assert_shown ("gcr-prompter.desktop", TRUE, "GNOME-Classic:GNOME");
1059 : 1 : assert_shown ("gcr-prompter.desktop", TRUE, "GNOME-Classic");
1060 : 1 : assert_shown ("gcr-prompter.desktop", TRUE, "GNOME-Classic:KDE");
1061 : 1 : assert_shown ("gcr-prompter.desktop", TRUE, "KDE:GNOME-Classic");
1062 : 1 : assert_shown ("invalid-desktop.desktop", TRUE, "GNOME");
1063 : 1 : assert_shown ("invalid-desktop.desktop", FALSE, "../invalid/desktop");
1064 : 1 : assert_shown ("invalid-desktop.desktop", FALSE, "../invalid/desktop:../invalid/desktop");
1065 : 1 : }
1066 : :
1067 : : static void
1068 : 5 : on_launch_started (GAppLaunchContext *context, GAppInfo *info, GVariant *platform_data, gpointer data)
1069 : : {
1070 : 5 : gboolean *invoked = data;
1071 : :
1072 : 5 : g_assert_true (G_IS_APP_LAUNCH_CONTEXT (context));
1073 : :
1074 : 5 : if (TEST_IS_LAUNCH_CONTEXT (context))
1075 : : {
1076 : : GVariantDict dict;
1077 : : const char *sni;
1078 : : char *expected_sni;
1079 : :
1080 : 5 : g_assert_nonnull (platform_data);
1081 : 5 : g_variant_dict_init (&dict, platform_data);
1082 : 5 : g_assert_true (
1083 : : g_variant_dict_lookup (&dict, "startup-notification-id", "&s", &sni));
1084 : 5 : expected_sni = g_app_launch_context_get_startup_notify_id (context, info, NULL);
1085 : 5 : g_assert_cmpstr (sni, ==, expected_sni);
1086 : :
1087 : 5 : g_free (expected_sni);
1088 : 5 : g_variant_dict_clear (&dict);
1089 : : }
1090 : : else
1091 : : {
1092 : : /* Our default context doesn't fill in any platform data */
1093 : 0 : g_assert_null (platform_data);
1094 : : }
1095 : :
1096 : 5 : g_assert_false (*invoked);
1097 : 5 : *invoked = TRUE;
1098 : 5 : }
1099 : :
1100 : : static void
1101 : 3 : on_launched (GAppLaunchContext *context, GAppInfo *info, GVariant *platform_data, gpointer data)
1102 : : {
1103 : 3 : gboolean *launched = data;
1104 : : GVariantDict dict;
1105 : : int pid;
1106 : :
1107 : 3 : g_assert_true (G_IS_APP_LAUNCH_CONTEXT (context));
1108 : 3 : g_assert_true (G_IS_APP_INFO (info));
1109 : 3 : g_assert_nonnull (platform_data);
1110 : 3 : g_variant_dict_init (&dict, platform_data);
1111 : 3 : g_assert_true (g_variant_dict_lookup (&dict, "pid", "i", &pid, NULL));
1112 : 3 : g_assert_cmpint (pid, >, 1);
1113 : :
1114 : 3 : g_assert_false (*launched);
1115 : 3 : *launched = TRUE;
1116 : :
1117 : 3 : g_variant_dict_clear (&dict);
1118 : 3 : }
1119 : :
1120 : : static void
1121 : 2 : on_launch_failed (GAppLaunchContext *context, const char *startup_notify_id, gpointer data)
1122 : : {
1123 : 2 : gboolean *invoked = data;
1124 : :
1125 : 2 : g_assert_true (G_IS_APP_LAUNCH_CONTEXT (context));
1126 : 2 : g_assert_nonnull (startup_notify_id);
1127 : 2 : g_test_message ("Application launch failed: %s", startup_notify_id);
1128 : :
1129 : 2 : g_assert_false (*invoked);
1130 : 2 : *invoked = TRUE;
1131 : 2 : }
1132 : :
1133 : : static void
1134 : 3 : wait_child_completed (GDesktopAppInfo *appinfo,
1135 : : GPid pid,
1136 : : gpointer user_data)
1137 : : {
1138 : 3 : gboolean *child_waited = user_data;
1139 : 3 : int wait_status = 0;
1140 : 3 : GError *error = NULL;
1141 : :
1142 : 3 : while (waitpid (pid, &wait_status, 0) != pid);
1143 : 3 : g_spawn_check_wait_status (wait_status, &error);
1144 : 3 : g_assert_no_error (error);
1145 : 3 : g_clear_error (&error);
1146 : 3 : *child_waited = TRUE;
1147 : 3 : }
1148 : :
1149 : : /* Test g_desktop_app_info_launch_uris_as_manager() and
1150 : : * g_desktop_app_info_launch_uris_as_manager_with_fds()
1151 : : */
1152 : : static void
1153 : 1 : test_launch_as_manager (void)
1154 : : {
1155 : : GDesktopAppInfo *appinfo;
1156 : 1 : GError *error = NULL;
1157 : : gboolean retval;
1158 : : const gchar *path;
1159 : 1 : gboolean invoked = FALSE;
1160 : 1 : gboolean launched = FALSE;
1161 : 1 : gboolean failed = FALSE;
1162 : 1 : gboolean child_waited = FALSE;
1163 : : GAppLaunchContext *context;
1164 : :
1165 : 1 : path = g_test_get_filename (G_TEST_BUILT, "appinfo-test.desktop", NULL);
1166 : 1 : appinfo = g_desktop_app_info_new_from_filename (path);
1167 : 1 : g_assert_true (G_IS_APP_INFO (appinfo));
1168 : :
1169 : 1 : context = g_object_new (test_launch_context_get_type (), NULL);
1170 : 1 : g_signal_connect (context, "launch-started",
1171 : : G_CALLBACK (on_launch_started),
1172 : : &invoked);
1173 : 1 : g_signal_connect (context, "launched",
1174 : : G_CALLBACK (on_launched),
1175 : : &launched);
1176 : 1 : g_signal_connect (context, "launch-failed",
1177 : : G_CALLBACK (on_launch_failed),
1178 : : &failed);
1179 : 1 : retval = g_desktop_app_info_launch_uris_as_manager (appinfo, NULL, context,
1180 : : G_SPAWN_DO_NOT_REAP_CHILD,
1181 : : NULL,
1182 : : NULL,
1183 : : wait_child_completed,
1184 : : &child_waited,
1185 : : &error);
1186 : 1 : g_assert_no_error (error);
1187 : 1 : g_assert_true (retval);
1188 : 1 : g_assert_true (invoked);
1189 : 1 : g_assert_true (launched);
1190 : 1 : g_assert_true (child_waited);
1191 : 1 : g_assert_false (failed);
1192 : :
1193 : 1 : invoked = FALSE;
1194 : 1 : launched = FALSE;
1195 : 1 : failed = FALSE;
1196 : 1 : child_waited = FALSE;
1197 : 1 : retval = g_desktop_app_info_launch_uris_as_manager_with_fds (appinfo,
1198 : : NULL, context,
1199 : : G_SPAWN_DO_NOT_REAP_CHILD,
1200 : : NULL,
1201 : : NULL,
1202 : : wait_child_completed,
1203 : : &child_waited,
1204 : : -1, -1, -1,
1205 : : &error);
1206 : 1 : g_assert_no_error (error);
1207 : 1 : g_assert_true (retval);
1208 : 1 : g_assert_true (invoked);
1209 : 1 : g_assert_true (launched);
1210 : 1 : g_assert_true (child_waited);
1211 : 1 : g_assert_false (failed);
1212 : :
1213 : 1 : g_object_unref (appinfo);
1214 : 1 : g_assert_finalize_object (context);
1215 : 1 : }
1216 : :
1217 : : static void
1218 : 1 : test_launch_as_manager_fail (void)
1219 : : {
1220 : : GAppLaunchContext *context;
1221 : : GDesktopAppInfo *appinfo;
1222 : 1 : GError *error = NULL;
1223 : : gboolean retval;
1224 : : const gchar *path;
1225 : 1 : gboolean launch_started = FALSE;
1226 : 1 : gboolean launched = FALSE;
1227 : 1 : gboolean failed = FALSE;
1228 : 1 : gboolean child_waited = FALSE;
1229 : :
1230 : 1 : g_test_summary ("Tests that launch-errors are properly handled, we force " \
1231 : : "this by using invalid FD's values when launching as manager");
1232 : :
1233 : 1 : path = g_test_get_filename (G_TEST_BUILT, "appinfo-test.desktop", NULL);
1234 : 1 : appinfo = g_desktop_app_info_new_from_filename (path);
1235 : 1 : g_assert_true (G_IS_APP_INFO (appinfo));
1236 : :
1237 : 1 : context = g_object_new (test_launch_context_get_type (), NULL);
1238 : 1 : g_signal_connect (context, "launch-started",
1239 : : G_CALLBACK (on_launch_started),
1240 : : &launch_started);
1241 : 1 : g_signal_connect (context, "launched",
1242 : : G_CALLBACK (on_launched),
1243 : : &launched);
1244 : 1 : g_signal_connect (context, "launch-failed",
1245 : : G_CALLBACK (on_launch_failed),
1246 : : &failed);
1247 : :
1248 : 1 : retval = g_desktop_app_info_launch_uris_as_manager_with_fds (appinfo,
1249 : : NULL, context,
1250 : : G_SPAWN_DO_NOT_REAP_CHILD,
1251 : : NULL,
1252 : : NULL,
1253 : : wait_child_completed,
1254 : : &child_waited,
1255 : : 3000, 3001, 3002,
1256 : : &error);
1257 : 1 : g_assert_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED);
1258 : 1 : g_assert_false (retval);
1259 : 1 : g_assert_true (launch_started);
1260 : 1 : g_assert_false (launched);
1261 : 1 : g_assert_false (child_waited);
1262 : 1 : g_assert_true (failed);
1263 : :
1264 : 1 : g_clear_error (&error);
1265 : 1 : g_object_unref (appinfo);
1266 : 1 : g_assert_finalize_object (context);
1267 : 1 : }
1268 : :
1269 : : static GAppInfo *
1270 : 2 : create_app_info_toucher (const char *name,
1271 : : const char *touched_file_name,
1272 : : const char *handled_type,
1273 : : char **out_file_path)
1274 : : {
1275 : 2 : GError *error = NULL;
1276 : : GAppInfo *info;
1277 : : gchar *command_line;
1278 : : gchar *file_path;
1279 : : gchar *tmpdir;
1280 : :
1281 : 2 : g_assert_nonnull (out_file_path);
1282 : :
1283 : 2 : tmpdir = g_dir_make_tmp ("desktop-app-info-launch-XXXXXX", &error);
1284 : 2 : g_assert_no_error (error);
1285 : :
1286 : 2 : file_path = g_build_filename (tmpdir, touched_file_name, NULL);
1287 : 2 : command_line = g_strdup_printf ("touch %s", file_path);
1288 : :
1289 : 2 : info = create_command_line_app_info (name, command_line, handled_type);
1290 : 2 : *out_file_path = g_steal_pointer (&file_path);
1291 : :
1292 : 2 : g_free (tmpdir);
1293 : 2 : g_free (command_line);
1294 : :
1295 : 2 : return info;
1296 : : }
1297 : :
1298 : : static void
1299 : 1 : test_default_uri_handler (void)
1300 : : {
1301 : 1 : GError *error = NULL;
1302 : 1 : gchar *file_path = NULL;
1303 : : GAppInfo *info;
1304 : :
1305 : 1 : if (skip_missing_update_desktop_database ())
1306 : 0 : return;
1307 : :
1308 : 1 : info = create_app_info_toucher ("Touch Handled", "handled",
1309 : : "x-scheme-handler/glib-touch",
1310 : : &file_path);
1311 : 1 : g_assert_true (G_IS_APP_INFO (info));
1312 : 1 : g_assert_nonnull (file_path);
1313 : :
1314 : 1 : g_assert_true (g_app_info_launch_default_for_uri ("glib-touch://touch-me",
1315 : : NULL, &error));
1316 : 1 : g_assert_no_error (error);
1317 : :
1318 : 1254 : while (!g_file_test (file_path, G_FILE_TEST_IS_REGULAR));
1319 : 1 : g_assert_true (g_file_test (file_path, G_FILE_TEST_IS_REGULAR));
1320 : :
1321 : 1 : g_assert_false (g_app_info_launch_default_for_uri ("glib-INVALID-touch://touch-me",
1322 : : NULL, &error));
1323 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1324 : 1 : g_clear_error (&error);
1325 : :
1326 : 1 : g_object_unref (info);
1327 : 1 : g_free (file_path);
1328 : : }
1329 : :
1330 : : static void
1331 : 1 : on_launch_default_for_uri_success_cb (GObject *object,
1332 : : GAsyncResult *result,
1333 : : gpointer user_data)
1334 : : {
1335 : 1 : GError *error = NULL;
1336 : 1 : gboolean *called = user_data;
1337 : :
1338 : 1 : g_assert_true (g_app_info_launch_default_for_uri_finish (result, &error));
1339 : 1 : g_assert_no_error (error);
1340 : :
1341 : 1 : *called = TRUE;
1342 : 1 : }
1343 : :
1344 : : static void
1345 : 1 : on_launch_default_for_uri_not_found_cb (GObject *object,
1346 : : GAsyncResult *result,
1347 : : gpointer user_data)
1348 : : {
1349 : 1 : GError *error = NULL;
1350 : 1 : GMainLoop *loop = user_data;
1351 : :
1352 : 1 : g_assert_false (g_app_info_launch_default_for_uri_finish (result, &error));
1353 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
1354 : 1 : g_clear_error (&error);
1355 : :
1356 : 1 : g_main_loop_quit (loop);
1357 : 1 : }
1358 : :
1359 : : static void
1360 : 1 : on_launch_default_for_uri_cancelled_cb (GObject *object,
1361 : : GAsyncResult *result,
1362 : : gpointer user_data)
1363 : : {
1364 : 1 : GError *error = NULL;
1365 : 1 : GMainLoop *loop = user_data;
1366 : :
1367 : 1 : g_assert_false (g_app_info_launch_default_for_uri_finish (result, &error));
1368 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1369 : 1 : g_clear_error (&error);
1370 : :
1371 : 1 : g_main_loop_quit (loop);
1372 : 1 : }
1373 : :
1374 : : static void
1375 : 1 : test_default_uri_handler_async (void)
1376 : : {
1377 : : GCancellable *cancellable;
1378 : 1 : gchar *file_path = NULL;
1379 : : GAppInfo *info;
1380 : : GMainLoop *loop;
1381 : 1 : gboolean called = FALSE;
1382 : : gint64 start_time, touch_time;
1383 : :
1384 : 1 : if (skip_missing_update_desktop_database ())
1385 : 0 : return;
1386 : :
1387 : 1 : loop = g_main_loop_new (NULL, FALSE);
1388 : 1 : info = create_app_info_toucher ("Touch Handled", "handled-async",
1389 : : "x-scheme-handler/glib-async-touch",
1390 : : &file_path);
1391 : 1 : g_assert_true (G_IS_APP_INFO (info));
1392 : 1 : g_assert_nonnull (file_path);
1393 : :
1394 : 1 : start_time = g_get_real_time ();
1395 : 1 : g_app_info_launch_default_for_uri_async ("glib-async-touch://touch-me", NULL,
1396 : : NULL,
1397 : : on_launch_default_for_uri_success_cb,
1398 : : &called);
1399 : :
1400 : 585 : while (!g_file_test (file_path, G_FILE_TEST_IS_REGULAR) || !called)
1401 : 584 : g_main_context_iteration (NULL, FALSE);
1402 : :
1403 : 1 : touch_time = g_get_real_time () - start_time;
1404 : 1 : g_assert_true (called);
1405 : 1 : g_assert_true (g_file_test (file_path, G_FILE_TEST_IS_REGULAR));
1406 : :
1407 : 1 : g_unlink (file_path);
1408 : 1 : g_assert_false (g_file_test (file_path, G_FILE_TEST_IS_REGULAR));
1409 : :
1410 : 1 : g_app_info_launch_default_for_uri_async ("glib-async-INVALID-touch://touch-me",
1411 : : NULL, NULL,
1412 : : on_launch_default_for_uri_not_found_cb,
1413 : : loop);
1414 : 1 : g_main_loop_run (loop);
1415 : :
1416 : 1 : cancellable = g_cancellable_new ();
1417 : 1 : g_app_info_launch_default_for_uri_async ("glib-async-touch://touch-me", NULL,
1418 : : cancellable,
1419 : : on_launch_default_for_uri_cancelled_cb,
1420 : : loop);
1421 : 1 : g_cancellable_cancel (cancellable);
1422 : 1 : g_main_loop_run (loop);
1423 : :
1424 : : /* If started, our touch app would take some time to actually write the
1425 : : * file to disk, so let's wait a bit here to ensure that the file isn't
1426 : : * inadvertently getting created when a launch operation is canceled up
1427 : : * front. Give it 3× as long as the successful case took, to allow for
1428 : : * some variance.
1429 : : */
1430 : 1 : g_usleep (touch_time * 3);
1431 : 1 : g_assert_false (g_file_test (file_path, G_FILE_TEST_IS_REGULAR));
1432 : :
1433 : 1 : g_object_unref (info);
1434 : 1 : g_main_loop_unref (loop);
1435 : 1 : g_free (file_path);
1436 : : }
1437 : :
1438 : : static void
1439 : 1 : launch_snap_uris_with_portal (void)
1440 : : {
1441 : : GDesktopAppInfo *appinfo;
1442 : 1 : GError *error = NULL;
1443 : : gboolean retval;
1444 : : const gchar *path;
1445 : : const gchar *path2;
1446 : 1 : gboolean invoked = FALSE;
1447 : 1 : gboolean launched = FALSE;
1448 : 1 : gboolean failed = FALSE;
1449 : 1 : gboolean child_waited = FALSE;
1450 : : GAppLaunchContext *context;
1451 : 1 : GList *uris = NULL;
1452 : 1 : GFakeDocumentPortalThread *thread = NULL;
1453 : :
1454 : : /* Run a fake-document-portal */
1455 : 1 : session_bus_up ();
1456 : 1 : thread = g_fake_document_portal_thread_new (session_bus_get_address (),
1457 : : "snap.snap-app");
1458 : 1 : g_fake_document_portal_thread_run (thread);
1459 : :
1460 : 1 : path = g_test_get_filename (G_TEST_BUILT, "snap-app_appinfo-test.desktop", NULL);
1461 : 1 : appinfo = g_desktop_app_info_new_from_filename (path);
1462 : 1 : g_assert_true (G_IS_APP_INFO (appinfo));
1463 : :
1464 : 1 : path2 = g_test_get_filename (G_TEST_BUILT, "appinfo-test.desktop", NULL);
1465 : 1 : g_assert_true (g_file_test (path2, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR));
1466 : :
1467 : 1 : context = g_object_new (test_launch_context_get_type (), NULL);
1468 : 1 : g_signal_connect (context, "launch-started",
1469 : : G_CALLBACK (on_launch_started),
1470 : : &invoked);
1471 : 1 : g_signal_connect (context, "launched",
1472 : : G_CALLBACK (on_launched),
1473 : : &launched);
1474 : 1 : g_signal_connect (context, "launch-failed",
1475 : : G_CALLBACK (on_launch_failed),
1476 : : &failed);
1477 : 1 : g_app_launch_context_setenv (context, "DOCUMENT_PORTAL_MOUNT_POINT",
1478 : : g_fake_document_portal_thread_get_mount_point (thread));
1479 : :
1480 : 1 : uris = g_list_append (uris, g_strconcat ("file://", path, NULL));
1481 : 1 : uris = g_list_append (uris, g_strconcat ("file://", path2, NULL));
1482 : :
1483 : 1 : retval = g_desktop_app_info_launch_uris_as_manager (appinfo, uris,
1484 : : context,
1485 : : G_SPAWN_DO_NOT_REAP_CHILD,
1486 : : NULL,
1487 : : NULL,
1488 : : wait_child_completed,
1489 : : &child_waited,
1490 : : &error);
1491 : :
1492 : 1 : g_assert_no_error (error);
1493 : 1 : g_assert_true (retval);
1494 : 1 : g_assert_true (invoked);
1495 : 1 : g_assert_true (launched);
1496 : 1 : g_assert_true (child_waited);
1497 : 1 : g_assert_false (failed);
1498 : :
1499 : 1 : g_clear_list (&uris, g_free);
1500 : 1 : g_object_unref (appinfo);
1501 : 1 : g_assert_finalize_object (context);
1502 : :
1503 : 1 : g_fake_document_portal_thread_stop (thread);
1504 : 1 : g_clear_object (&thread);
1505 : 1 : session_bus_down ();
1506 : 1 : }
1507 : :
1508 : : /* Test if Desktop-File Id is correctly formed */
1509 : : static void
1510 : 1 : test_id (void)
1511 : : {
1512 : : gchar *result;
1513 : :
1514 : 1 : result = run_apps ("default-for-type", "application/vnd.kde.okular-archive",
1515 : : TRUE, FALSE, NULL, NULL, NULL);
1516 : 1 : g_assert_cmpstr (result, ==, "kde4-okular.desktop\n");
1517 : 1 : g_free (result);
1518 : 1 : }
1519 : :
1520 : : static const char *
1521 : 102 : get_terminal_divider (const char *terminal_name)
1522 : : {
1523 : 102 : if (g_str_equal (terminal_name, "xdg-terminal-exec"))
1524 : 3 : return NULL;
1525 : 99 : if (g_str_equal (terminal_name, "kgx"))
1526 : 9 : return "-e";
1527 : 90 : if (g_str_equal (terminal_name, "gnome-terminal"))
1528 : 9 : return "--";
1529 : 81 : if (g_str_equal (terminal_name, "tilix"))
1530 : 9 : return "-e";
1531 : 72 : if (g_str_equal (terminal_name, "konsole"))
1532 : 9 : return "-e";
1533 : 63 : if (g_str_equal (terminal_name, "nxterm"))
1534 : 9 : return "-e";
1535 : 54 : if (g_str_equal (terminal_name, "color-xterm"))
1536 : 9 : return "-e";
1537 : 45 : if (g_str_equal (terminal_name, "rxvt"))
1538 : 9 : return "-e";
1539 : 36 : if (g_str_equal (terminal_name, "dtterm"))
1540 : 9 : return "-e";
1541 : 27 : if (g_str_equal (terminal_name, "xterm"))
1542 : 9 : return "-e";
1543 : 18 : if (g_str_equal (terminal_name, "mate-terminal"))
1544 : 9 : return "-x";
1545 : 9 : if (g_str_equal (terminal_name, "xfce4-terminal"))
1546 : 9 : return "-x";
1547 : :
1548 : : g_return_val_if_reached (NULL);
1549 : : }
1550 : :
1551 : : typedef enum {
1552 : : TERMINAL_LAUNCH_TYPE_COMMAND_LINE_WITH_PATH_OVERRIDE,
1553 : : TERMINAL_LAUNCH_TYPE_COMMAND_LINE_WITH_CONTEXT,
1554 : : TERMINAL_LAUNCH_TYPE_KEY_FILE_WITH_PATH,
1555 : : } TerminalLaunchType;
1556 : :
1557 : : typedef struct {
1558 : : const char *exec;
1559 : : TerminalLaunchType type;
1560 : : } TerminalLaunchData;
1561 : :
1562 : : static TerminalLaunchData *
1563 : 36 : terminal_launch_data_new (const char *exec, TerminalLaunchType type)
1564 : : {
1565 : 36 : TerminalLaunchData *d = NULL;
1566 : :
1567 : 36 : d = g_new0 (TerminalLaunchData, 1);
1568 : 36 : d->exec = exec;
1569 : 36 : d->type = type;
1570 : :
1571 : 36 : return d;
1572 : : }
1573 : :
1574 : : static void
1575 : 36 : test_launch_uris_with_terminal (gconstpointer data)
1576 : : {
1577 : : int fd;
1578 : : int ret;
1579 : : int flags;
1580 : : int terminal_divider_arg_length;
1581 : 36 : const TerminalLaunchData *launch_data = data;
1582 : 36 : const char *terminal_exec = launch_data->exec;
1583 : 36 : char *old_path = NULL;
1584 : : char *command_line;
1585 : : char *bin_path;
1586 : : char *terminal_path;
1587 : : char *output_fd_path;
1588 : : char *script_contents;
1589 : 36 : char *output_contents = NULL;
1590 : : char *sh;
1591 : : GAppInfo *app_info;
1592 : : GList *uris;
1593 : : GList *paths;
1594 : : GStrv output_args;
1595 : 36 : GError *error = NULL;
1596 : : GInputStream *input_stream;
1597 : : GDataInputStream *data_input_stream;
1598 : : GAppLaunchContext *launch_context;
1599 : :
1600 : 36 : sh = g_find_program_in_path ("sh");
1601 : 36 : g_assert_nonnull (sh);
1602 : :
1603 : 36 : bin_path = g_dir_make_tmp ("bin-path-XXXXXX", &error);
1604 : 36 : g_assert_no_error (error);
1605 : :
1606 : 36 : launch_context = g_object_new (test_launch_context_get_type (), NULL);
1607 : :
1608 : 36 : switch (launch_data->type)
1609 : : {
1610 : 12 : case TERMINAL_LAUNCH_TYPE_COMMAND_LINE_WITH_PATH_OVERRIDE:
1611 : 12 : old_path = g_strdup (g_getenv ("PATH"));
1612 : 12 : g_assert_true (g_setenv ("PATH", bin_path, TRUE));
1613 : 12 : break;
1614 : :
1615 : 12 : case TERMINAL_LAUNCH_TYPE_COMMAND_LINE_WITH_CONTEXT:
1616 : 12 : g_app_launch_context_setenv (launch_context, "PATH", bin_path);
1617 : 12 : break;
1618 : :
1619 : 12 : case TERMINAL_LAUNCH_TYPE_KEY_FILE_WITH_PATH:
1620 : 12 : g_app_launch_context_setenv (launch_context, "PATH", "/not/valid");
1621 : 12 : break;
1622 : :
1623 : 0 : default:
1624 : : g_assert_not_reached ();
1625 : : }
1626 : :
1627 : 36 : terminal_path = g_build_filename (bin_path, terminal_exec, NULL);
1628 : 36 : output_fd_path = g_build_filename (bin_path, "fifo", NULL);
1629 : :
1630 : 36 : ret = mkfifo (output_fd_path, 0600);
1631 : 36 : g_assert_cmpint (ret, ==, 0);
1632 : :
1633 : 36 : fd = g_open (output_fd_path, O_RDONLY | O_CLOEXEC | O_NONBLOCK, 0);
1634 : 36 : g_assert_cmpint (fd, >=, 0);
1635 : :
1636 : 36 : flags = fcntl (fd, F_GETFL);
1637 : 36 : g_assert_cmpint (flags, >=, 0);
1638 : :
1639 : 36 : ret = fcntl (fd, F_SETFL, flags & ~O_NONBLOCK);
1640 : 36 : g_assert_cmpint (ret, ==, 0);
1641 : :
1642 : 36 : input_stream = g_unix_input_stream_new (fd, TRUE);
1643 : 36 : data_input_stream = g_data_input_stream_new (input_stream);
1644 : 36 : script_contents = g_strdup_printf ("#!%s\n" \
1645 : : "out='%s'\n"
1646 : : "printf '%%s\\n' \"$*\" > \"$out\"\n",
1647 : : sh,
1648 : : output_fd_path);
1649 : 36 : g_file_set_contents (terminal_path, script_contents, -1, &error);
1650 : 36 : g_assert_no_error (error);
1651 : 36 : g_assert_cmpint (g_chmod (terminal_path, 0500), ==, 0);
1652 : :
1653 : 36 : g_test_message ("Fake '%s' terminal created as: %s", terminal_exec, terminal_path);
1654 : :
1655 : 36 : command_line = g_strdup_printf ("true %s-argument", terminal_exec);
1656 : :
1657 : 36 : if (launch_data->type == TERMINAL_LAUNCH_TYPE_KEY_FILE_WITH_PATH)
1658 : : {
1659 : : GKeyFile *key_file;
1660 : : char *key_file_contents;
1661 : 12 : const char base_file[] =
1662 : : "[Desktop Entry]\n"
1663 : : "Type=Application\n"
1664 : : "Name=terminal launched app\n"
1665 : : "Terminal=true\n"
1666 : : "Path=%s\n"
1667 : : "Exec=%s\n";
1668 : :
1669 : 12 : key_file = g_key_file_new ();
1670 : 12 : key_file_contents = g_strdup_printf (base_file, bin_path, command_line);
1671 : :
1672 : 12 : g_assert_true (
1673 : : g_key_file_load_from_data (key_file, key_file_contents, -1,
1674 : : G_KEY_FILE_NONE, NULL));
1675 : :
1676 : 12 : app_info = (GAppInfo*) g_desktop_app_info_new_from_keyfile (key_file);
1677 : 12 : g_assert_true (G_IS_DESKTOP_APP_INFO (app_info));
1678 : 12 : g_assert_true (
1679 : : g_desktop_app_info_get_boolean (G_DESKTOP_APP_INFO (app_info), "Terminal"));
1680 : :
1681 : 12 : g_key_file_unref (key_file);
1682 : 12 : g_free (key_file_contents);
1683 : : }
1684 : : else
1685 : : {
1686 : 24 : app_info = g_app_info_create_from_commandline (command_line,
1687 : : "Test App on Terminal",
1688 : : G_APP_INFO_CREATE_NEEDS_TERMINAL |
1689 : : G_APP_INFO_CREATE_SUPPORTS_URIS,
1690 : : &error);
1691 : 24 : g_assert_no_error (error);
1692 : : }
1693 : :
1694 : 36 : paths = g_list_prepend (NULL, bin_path);
1695 : 36 : uris = g_list_prepend (NULL, g_filename_to_uri (bin_path, NULL, &error));
1696 : 36 : g_assert_no_error (error);
1697 : :
1698 : 36 : paths = g_list_prepend (paths, (gpointer) g_get_user_data_dir ());
1699 : 36 : uris = g_list_append (uris, g_filename_to_uri (g_get_user_data_dir (), NULL, &error));
1700 : 36 : g_assert_no_error (error);
1701 : :
1702 : 36 : g_assert_cmpint (g_list_length (paths), ==, 2);
1703 : 36 : g_app_info_launch_uris (app_info, uris, launch_context, &error);
1704 : 36 : g_assert_no_error (error);
1705 : :
1706 : 108 : while (output_contents == NULL)
1707 : : {
1708 : 36 : output_contents =
1709 : 36 : g_data_input_stream_read_upto (data_input_stream, "\n", 1, NULL, NULL, &error);
1710 : 36 : g_assert_no_error (error);
1711 : :
1712 : 36 : if (output_contents == NULL)
1713 : 0 : g_usleep (G_USEC_PER_SEC / 10);
1714 : : }
1715 : 36 : g_test_message ("'%s' called with arguments: '%s'", terminal_exec, output_contents);
1716 : :
1717 : 36 : g_data_input_stream_read_byte (data_input_stream, NULL, &error);
1718 : 36 : g_assert_no_error (error);
1719 : :
1720 : 36 : output_args = g_strsplit (output_contents, " ", -1);
1721 : 36 : g_clear_pointer (&output_contents, g_free);
1722 : :
1723 : 36 : terminal_divider_arg_length = (get_terminal_divider (terminal_exec) != NULL) ? 1 : 0;
1724 : 36 : g_assert_cmpuint (g_strv_length (output_args), ==, 3 + terminal_divider_arg_length);
1725 : 36 : if (terminal_divider_arg_length == 1)
1726 : : {
1727 : 33 : g_assert_cmpstr (output_args[0], ==, get_terminal_divider (terminal_exec));
1728 : 33 : g_assert_cmpstr (output_args[1], ==, "true");
1729 : 33 : g_assert_cmpstr (output_args[2], ==, command_line + 5);
1730 : : }
1731 : : else
1732 : : {
1733 : 3 : g_assert_cmpstr (output_args[0], ==, "true");
1734 : 3 : g_assert_cmpstr (output_args[1], ==, command_line + 5);
1735 : : }
1736 : 36 : paths = g_list_delete_link (paths,
1737 : 36 : g_list_find_custom (paths, output_args[2 + terminal_divider_arg_length], g_str_equal));
1738 : 36 : g_assert_cmpint (g_list_length (paths), ==, 1);
1739 : 36 : g_clear_pointer (&output_args, g_strfreev);
1740 : :
1741 : 144 : while (output_contents == NULL)
1742 : : {
1743 : 72 : output_contents =
1744 : 72 : g_data_input_stream_read_upto (data_input_stream, "\n", 1, NULL, NULL, &error);
1745 : 72 : g_assert_no_error (error);
1746 : :
1747 : 72 : if (output_contents == NULL)
1748 : 36 : g_usleep (G_USEC_PER_SEC / 10);
1749 : : }
1750 : 36 : g_test_message ("'%s' called with arguments: '%s'", terminal_exec, output_contents);
1751 : :
1752 : 36 : g_data_input_stream_read_byte (data_input_stream, NULL, &error);
1753 : 36 : g_assert_no_error (error);
1754 : :
1755 : 36 : output_args = g_strsplit (output_contents, " ", -1);
1756 : 36 : g_clear_pointer (&output_contents, g_free);
1757 : 36 : g_assert_cmpuint (g_strv_length (output_args), ==, 3 + terminal_divider_arg_length);
1758 : 36 : if (terminal_divider_arg_length > 0)
1759 : : {
1760 : 33 : g_assert_cmpstr (output_args[0], ==, get_terminal_divider (terminal_exec));
1761 : 33 : g_assert_cmpstr (output_args[1], ==, "true");
1762 : 33 : g_assert_cmpstr (output_args[2], ==, command_line + 5);
1763 : : }
1764 : : else
1765 : : {
1766 : 3 : g_assert_cmpstr (output_args[0], ==, "true");
1767 : 3 : g_assert_cmpstr (output_args[1], ==, command_line + 5);
1768 : : }
1769 : 36 : paths = g_list_delete_link (paths,
1770 : 36 : g_list_find_custom (paths, output_args[2 + terminal_divider_arg_length], g_str_equal));
1771 : 36 : g_assert_cmpint (g_list_length (paths), ==, 0);
1772 : 36 : g_clear_pointer (&output_args, g_strfreev);
1773 : :
1774 : 36 : g_assert_null (paths);
1775 : :
1776 : 36 : if (launch_data->type == TERMINAL_LAUNCH_TYPE_COMMAND_LINE_WITH_PATH_OVERRIDE)
1777 : 12 : g_assert_true (g_setenv ("PATH", old_path, TRUE));
1778 : :
1779 : 36 : g_close (fd, &error);
1780 : 36 : g_assert_no_error (error);
1781 : :
1782 : 36 : g_free (sh);
1783 : 36 : g_free (command_line);
1784 : 36 : g_free (bin_path);
1785 : 36 : g_free (terminal_path);
1786 : 36 : g_free (output_fd_path);
1787 : 36 : g_free (script_contents);
1788 : 36 : g_free (old_path);
1789 : 36 : g_clear_pointer (&output_args, g_strfreev);
1790 : 36 : g_clear_pointer (&output_contents, g_free);
1791 : 36 : g_clear_object (&data_input_stream);
1792 : 36 : g_clear_object (&input_stream);
1793 : 36 : g_clear_object (&app_info);
1794 : 36 : g_clear_object (&launch_context);
1795 : 36 : g_clear_error (&error);
1796 : 36 : g_clear_list (&paths, NULL);
1797 : 36 : g_clear_list (&uris, g_free);
1798 : 36 : }
1799 : :
1800 : : static void
1801 : 1 : test_launch_uris_with_invalid_terminal (void)
1802 : : {
1803 : : char *old_path;
1804 : : char *bin_path;
1805 : : GAppInfo *app_info;
1806 : 1 : GError *error = NULL;
1807 : :
1808 : 1 : bin_path = g_dir_make_tmp ("bin-path-XXXXXX", &error);
1809 : 1 : g_assert_no_error (error);
1810 : :
1811 : 1 : old_path = g_strdup (g_getenv ("PATH"));
1812 : 1 : g_assert_true (g_setenv ("PATH", bin_path, TRUE));
1813 : :
1814 : 1 : app_info = g_app_info_create_from_commandline ("true invalid-glib-terminal",
1815 : : "Test App on Invalid Terminal",
1816 : : G_APP_INFO_CREATE_NEEDS_TERMINAL |
1817 : : G_APP_INFO_CREATE_SUPPORTS_URIS,
1818 : : &error);
1819 : 1 : g_assert_no_error (error);
1820 : :
1821 : 1 : g_app_info_launch_uris (app_info, NULL, NULL, &error);
1822 : 1 : g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
1823 : 1 : g_clear_error (&error);
1824 : :
1825 : 1 : g_assert_true (g_setenv ("PATH", old_path, TRUE));
1826 : :
1827 : 1 : g_clear_object (&app_info);
1828 : 1 : g_clear_error (&error);
1829 : 1 : g_free (bin_path);
1830 : 1 : g_free (old_path);
1831 : 1 : }
1832 : :
1833 : : static void
1834 : 1 : test_app_path (void)
1835 : : {
1836 : : GDesktopAppInfo *appinfo;
1837 : : const char *desktop_path;
1838 : :
1839 : 1 : desktop_path = g_test_get_filename (G_TEST_BUILT, "appinfo-test-path.desktop", NULL);
1840 : 1 : appinfo = g_desktop_app_info_new_from_filename (desktop_path);
1841 : :
1842 : 1 : g_assert_true (G_IS_DESKTOP_APP_INFO (appinfo));
1843 : :
1844 : 1 : g_clear_object (&appinfo);
1845 : 1 : }
1846 : :
1847 : : static void
1848 : 1 : test_app_path_wrong (void)
1849 : : {
1850 : : GKeyFile *key_file;
1851 : : GDesktopAppInfo *appinfo;
1852 : 1 : const gchar bad_try_exec_file_contents[] =
1853 : : "[Desktop Entry]\n"
1854 : : "Type=Application\n"
1855 : : "Name=appinfo-test\n"
1856 : : "TryExec=appinfo-test\n"
1857 : : "Path=this-must-not-exist‼\n"
1858 : : "Exec=true\n";
1859 : 1 : const gchar bad_exec_file_contents[] =
1860 : : "[Desktop Entry]\n"
1861 : : "Type=Application\n"
1862 : : "Name=appinfo-test\n"
1863 : : "TryExec=true\n"
1864 : : "Path=this-must-not-exist‼\n"
1865 : : "Exec=appinfo-test\n";
1866 : :
1867 : 1 : g_assert_true (
1868 : : g_file_test (g_test_get_filename (G_TEST_BUILT, "appinfo-test", NULL),
1869 : : G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_EXECUTABLE));
1870 : :
1871 : 1 : key_file = g_key_file_new ();
1872 : :
1873 : 1 : g_assert_true (
1874 : : g_key_file_load_from_data (key_file, bad_try_exec_file_contents, -1,
1875 : : G_KEY_FILE_NONE, NULL));
1876 : :
1877 : 1 : appinfo = g_desktop_app_info_new_from_keyfile (key_file);
1878 : 1 : g_assert_false (G_IS_DESKTOP_APP_INFO (appinfo));
1879 : :
1880 : 1 : g_assert_true (
1881 : : g_key_file_load_from_data (key_file, bad_exec_file_contents, -1,
1882 : : G_KEY_FILE_NONE, NULL));
1883 : :
1884 : 1 : appinfo = g_desktop_app_info_new_from_keyfile (key_file);
1885 : 1 : g_assert_false (G_IS_DESKTOP_APP_INFO (appinfo));
1886 : :
1887 : 1 : g_clear_pointer (&key_file, g_key_file_unref);
1888 : 1 : g_clear_object (&appinfo);
1889 : 1 : }
1890 : :
1891 : : static void
1892 : 1 : test_invalid_key_file (void)
1893 : : {
1894 : 1 : const char *vectors[] =
1895 : : {
1896 : : /* This .desktop file has invalid escaping in its Exec= line; `\"` is an
1897 : : * invalid escape sequence in the Desktop Entry Spec
1898 : : * (https://specifications.freedesktop.org/desktop-entry-spec/latest/value-types.html): */
1899 : : "[Desktop Entry]\n"
1900 : : "Type=Application\n"
1901 : : "Name=Example2\n"
1902 : : "Exec=gedit \"/home/dkondor/program/file with \\\"weird\\\" name\"\n",
1903 : : /* This one has invalid escaping at the end of its Path= line: */
1904 : : "[Desktop Entry]\n"
1905 : : "Type=Application\n"
1906 : : "Name=Example2\n"
1907 : : "Path=some/path\\\n"
1908 : : "Exec=gedit",
1909 : : /* This one has invalid UTF-8 in its TryExec= line: */
1910 : : "[Desktop Entry]\n"
1911 : : "Type=Application\n"
1912 : : "Name=Example2\n"
1913 : : "TryExec=gedit \"\xc3\x28\"\n",
1914 : : };
1915 : :
1916 : 1 : g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3771");
1917 : 1 : g_test_summary ("Test that loading invalid key files does not succeed");
1918 : :
1919 : 4 : for (size_t i = 0; i < G_N_ELEMENTS (vectors); i++)
1920 : : {
1921 : 3 : int fd = -1;
1922 : 3 : char *tmp_filename = NULL;
1923 : 3 : GError *local_error = NULL;
1924 : :
1925 : : /* Create a temp desktop file containing the invalid key file data */
1926 : 3 : fd = g_file_open_tmp ("desktop-app-info-test-XXXXXX.desktop", &tmp_filename, NULL);
1927 : 3 : g_assert_cmpint (fd, >, -1);
1928 : 3 : g_close (fd, NULL);
1929 : :
1930 : 3 : g_file_set_contents (tmp_filename, vectors[i], -1, &local_error);
1931 : 3 : g_assert_no_error (local_error);
1932 : :
1933 : : /* Try loading the desktop file; it should fail */
1934 : 3 : g_assert_null (g_desktop_app_info_new_from_filename (tmp_filename));
1935 : :
1936 : 3 : g_unlink (tmp_filename);
1937 : 3 : g_free (tmp_filename);
1938 : : }
1939 : 1 : }
1940 : :
1941 : : static void
1942 : 1 : test_launch_startup_notify_fail (void)
1943 : : {
1944 : : GAppInfo *app_info;
1945 : : GAppLaunchContext *context;
1946 : 1 : GError *error = NULL;
1947 : : gboolean launch_started;
1948 : : gboolean launch_failed;
1949 : : gboolean launched;
1950 : : GList *uris;
1951 : :
1952 : 1 : app_info = g_app_info_create_from_commandline ("this-must-not-exist‼",
1953 : : "failing app",
1954 : : G_APP_INFO_CREATE_NONE |
1955 : : G_APP_INFO_CREATE_SUPPORTS_STARTUP_NOTIFICATION,
1956 : : &error);
1957 : 1 : g_assert_no_error (error);
1958 : :
1959 : 1 : context = g_object_new (test_launch_context_get_type (), NULL);
1960 : 1 : g_signal_connect (context, "launch-started",
1961 : : G_CALLBACK (on_launch_started),
1962 : : &launch_started);
1963 : 1 : g_signal_connect (context, "launched",
1964 : : G_CALLBACK (on_launch_started),
1965 : : &launched);
1966 : 1 : g_signal_connect (context, "launch-failed",
1967 : : G_CALLBACK (on_launch_failed),
1968 : : &launch_failed);
1969 : :
1970 : 1 : launch_started = FALSE;
1971 : 1 : launch_failed = FALSE;
1972 : 1 : launched = FALSE;
1973 : 1 : uris = g_list_prepend (NULL, g_file_new_for_uri ("foo://bar"));
1974 : 1 : uris = g_list_prepend (uris, g_file_new_for_uri ("bar://foo"));
1975 : 1 : g_assert_false (g_app_info_launch (app_info, uris, context, &error));
1976 : 1 : g_assert_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_NOENT);
1977 : 1 : g_assert_true (launch_started);
1978 : 1 : g_assert_true (launch_failed);
1979 : 1 : g_assert_false (launched);
1980 : :
1981 : 1 : g_clear_error (&error);
1982 : 1 : g_clear_object (&app_info);
1983 : 1 : g_clear_object (&context);
1984 : 1 : g_clear_list (&uris, g_object_unref);
1985 : 1 : }
1986 : :
1987 : : static void
1988 : 1 : test_launch_fail (void)
1989 : : {
1990 : : GAppInfo *app_info;
1991 : 1 : GError *error = NULL;
1992 : :
1993 : 1 : app_info = g_app_info_create_from_commandline ("this-must-not-exist‼",
1994 : : "failing app",
1995 : : G_APP_INFO_CREATE_NONE,
1996 : : &error);
1997 : 1 : g_assert_no_error (error);
1998 : :
1999 : 1 : g_assert_false (g_app_info_launch (app_info, NULL, NULL, &error));
2000 : 1 : g_assert_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_NOENT);
2001 : :
2002 : 1 : g_clear_error (&error);
2003 : 1 : g_clear_object (&app_info);
2004 : 1 : }
2005 : :
2006 : : static void
2007 : 1 : test_launch_fail_absolute_path (void)
2008 : : {
2009 : : GAppInfo *app_info;
2010 : 1 : GError *error = NULL;
2011 : :
2012 : 1 : app_info = g_app_info_create_from_commandline ("/nothing/of/this-must-exist‼",
2013 : : NULL,
2014 : : G_APP_INFO_CREATE_NONE,
2015 : : &error);
2016 : 1 : g_assert_no_error (error);
2017 : :
2018 : 1 : g_assert_false (g_app_info_launch (app_info, NULL, NULL, &error));
2019 : 1 : g_assert_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_NOENT);
2020 : :
2021 : 1 : g_clear_error (&error);
2022 : 1 : g_clear_object (&app_info);
2023 : :
2024 : 1 : app_info = g_app_info_create_from_commandline ("/",
2025 : : NULL,
2026 : : G_APP_INFO_CREATE_NONE,
2027 : : &error);
2028 : 1 : g_assert_no_error (error);
2029 : :
2030 : 1 : g_assert_false (g_app_info_launch (app_info, NULL, NULL, &error));
2031 : 1 : g_assert_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_NOENT);
2032 : :
2033 : 1 : g_clear_error (&error);
2034 : 1 : g_clear_object (&app_info);
2035 : 1 : }
2036 : :
2037 : : static void
2038 : 1 : async_result_cb (GObject *source_object,
2039 : : GAsyncResult *result,
2040 : : gpointer user_data)
2041 : : {
2042 : 1 : GAsyncResult **result_out = user_data;
2043 : :
2044 : 1 : g_assert (*result_out == NULL);
2045 : 1 : *result_out = g_object_ref (result);
2046 : 1 : g_main_context_wakeup (g_main_context_get_thread_default ());
2047 : 1 : }
2048 : :
2049 : : static void
2050 : 1 : test_launch_fail_dbus (void)
2051 : : {
2052 : 1 : GTestDBus *bus = NULL;
2053 : 1 : GDesktopAppInfo *app_info = NULL;
2054 : 1 : GAppLaunchContext *context = NULL;
2055 : 1 : GAsyncResult *result = NULL;
2056 : 1 : GError *error = NULL;
2057 : :
2058 : 1 : if (skip_missing_dbus_daemon ())
2059 : 0 : return;
2060 : :
2061 : : /* Set up a test session bus to ensure that launching the app happens using
2062 : : * D-Bus rather than spawning. */
2063 : 1 : bus = g_test_dbus_new (G_TEST_DBUS_NONE);
2064 : 1 : g_test_dbus_up (bus);
2065 : :
2066 : 1 : app_info = g_desktop_app_info_new_from_filename (g_test_get_filename (G_TEST_DIST, "org.gtk.test.dbusappinfo.desktop", NULL));
2067 : 1 : g_assert_nonnull (app_info);
2068 : :
2069 : 1 : g_assert_true (g_desktop_app_info_has_key (app_info, "DBusActivatable"));
2070 : :
2071 : 1 : context = g_app_launch_context_new ();
2072 : :
2073 : 1 : g_app_info_launch_uris_async (G_APP_INFO (app_info), NULL, context, NULL, async_result_cb, &result);
2074 : :
2075 : 4 : while (result == NULL)
2076 : 3 : g_main_context_iteration (NULL, TRUE);
2077 : :
2078 : 1 : g_assert_false (g_app_info_launch_uris_finish (G_APP_INFO (app_info), result, &error));
2079 : 1 : g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN);
2080 : :
2081 : 1 : g_test_dbus_down (bus);
2082 : 1 : g_clear_object (&bus);
2083 : :
2084 : 1 : g_clear_error (&error);
2085 : 1 : g_clear_object (&result);
2086 : 1 : g_clear_object (&context);
2087 : 1 : g_clear_object (&app_info);
2088 : : }
2089 : :
2090 : : int
2091 : 1 : main (int argc,
2092 : : char *argv[])
2093 : : {
2094 : : guint i;
2095 : 1 : const gchar *supported_terminals[] = {
2096 : : "xdg-terminal-exec",
2097 : : "kgx",
2098 : : "gnome-terminal",
2099 : : "mate-terminal",
2100 : : "xfce4-terminal",
2101 : : "tilix",
2102 : : "konsole",
2103 : : "nxterm",
2104 : : "color-xterm",
2105 : : "rxvt",
2106 : : "dtterm",
2107 : : "xterm",
2108 : : };
2109 : :
2110 : : /* While we use %G_TEST_OPTION_ISOLATE_DIRS to create temporary directories
2111 : : * for each of the tests, we want to use the system MIME registry, assuming
2112 : : * that it exists and correctly has shared-mime-info installed. */
2113 : 1 : g_content_type_set_mime_dirs (NULL);
2114 : :
2115 : 1 : g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
2116 : :
2117 : 1 : g_test_add_func ("/desktop-app-info/delete", test_delete);
2118 : 1 : g_test_add_func ("/desktop-app-info/default", test_default);
2119 : 1 : g_test_add_func ("/desktop-app-info/default-async", test_default_async);
2120 : 1 : g_test_add_func ("/desktop-app-info/fallback", test_fallback);
2121 : 1 : g_test_add_func ("/desktop-app-info/lastused", test_last_used);
2122 : 1 : g_test_add_func ("/desktop-app-info/extra-getters", test_extra_getters);
2123 : 1 : g_test_add_func ("/desktop-app-info/actions", test_actions);
2124 : 1 : g_test_add_func ("/desktop-app-info/search", test_search);
2125 : 1 : g_test_add_func ("/desktop-app-info/implements", test_implements);
2126 : 1 : g_test_add_func ("/desktop-app-info/show-in", test_show_in);
2127 : 1 : g_test_add_func ("/desktop-app-info/app-path", test_app_path);
2128 : 1 : g_test_add_func ("/desktop-app-info/app-path/wrong", test_app_path_wrong);
2129 : 1 : g_test_add_func ("/desktop-app-info/invalid-key-file", test_invalid_key_file);
2130 : 1 : g_test_add_func ("/desktop-app-info/launch/fail", test_launch_fail);
2131 : 1 : g_test_add_func ("/desktop-app-info/launch/fail-absolute-path", test_launch_fail_absolute_path);
2132 : 1 : g_test_add_func ("/desktop-app-info/launch/fail-startup-notify", test_launch_startup_notify_fail);
2133 : 1 : g_test_add_func ("/desktop-app-info/launch/fail-dbus", test_launch_fail_dbus);
2134 : 1 : g_test_add_func ("/desktop-app-info/launch-as-manager", test_launch_as_manager);
2135 : 1 : g_test_add_func ("/desktop-app-info/launch-as-manager/fail", test_launch_as_manager_fail);
2136 : 1 : g_test_add_func ("/desktop-app-info/launch-default-uri-handler", test_default_uri_handler);
2137 : 1 : g_test_add_func ("/desktop-app-info/launch-default-uri-handler-async", test_default_uri_handler_async);
2138 : 1 : g_test_add_func ("/desktop-app-info/launch-snap-uri-with-portal", launch_snap_uris_with_portal);
2139 : 1 : g_test_add_func ("/desktop-app-info/id", test_id);
2140 : :
2141 : 13 : for (i = 0; i < G_N_ELEMENTS (supported_terminals); i++)
2142 : : {
2143 : : char *path;
2144 : :
2145 : 12 : path = g_strdup_printf ("/desktop-app-info/launch-uris-with-terminal/with-path/%s",
2146 : : supported_terminals[i]);
2147 : 12 : g_test_add_data_func_full (path,
2148 : 12 : terminal_launch_data_new (supported_terminals[i],
2149 : : TERMINAL_LAUNCH_TYPE_COMMAND_LINE_WITH_PATH_OVERRIDE),
2150 : : test_launch_uris_with_terminal, g_free);
2151 : 12 : g_clear_pointer (&path, g_free);
2152 : :
2153 : 12 : path = g_strdup_printf ("/desktop-app-info/launch-uris-with-terminal/with-context/%s",
2154 : : supported_terminals[i]);
2155 : 12 : g_test_add_data_func_full (path,
2156 : 12 : terminal_launch_data_new (supported_terminals[i],
2157 : : TERMINAL_LAUNCH_TYPE_COMMAND_LINE_WITH_CONTEXT),
2158 : : test_launch_uris_with_terminal, g_free);
2159 : 12 : g_clear_pointer (&path, g_free);
2160 : :
2161 : 12 : path = g_strdup_printf ("/desktop-app-info/launch-uris-with-terminal/with-desktop-path/%s",
2162 : : supported_terminals[i]);
2163 : 12 : g_test_add_data_func_full (path,
2164 : 12 : terminal_launch_data_new (supported_terminals[i],
2165 : : TERMINAL_LAUNCH_TYPE_KEY_FILE_WITH_PATH),
2166 : : test_launch_uris_with_terminal, g_free);
2167 : 12 : g_clear_pointer (&path, g_free);
2168 : : }
2169 : :
2170 : 1 : g_test_add_func ("/desktop-app-info/launch-uris-with-terminal/invalid-glib-terminal",
2171 : : test_launch_uris_with_invalid_terminal);
2172 : :
2173 : 1 : return g_test_run ();
2174 : : }
|