1 #include <glib/gstdio.h>
3 #include <gio/gdesktopappinfo.h>
6 strv_equal (gchar **strv, ...)
15 va_start (list, strv);
18 str = va_arg (list, const gchar *);
21 if (g_strcmp0 (str, strv[count]) != 0)
31 res = g_strv_length (strv) == count;
36 const gchar *myapp_data =
44 const gchar *myapp2_data =
52 const gchar *myapp3_data =
60 const gchar *myapp4_data =
67 "MimeType=image/bmp;";
69 const gchar *myapp5_data =
76 "MimeType=image/bmp;";
78 const gchar *defaults_data =
79 "[Default Applications]\n"
80 "image/bmp=myapp4.desktop;\n"
81 "image/png=myapp3.desktop;\n";
83 const gchar *mimecache_data =
85 "image/bmp=myapp4.desktop;myapp5.desktop;\n";
87 /* Set up XDG_DATA_HOME and XDG_DATA_DIRS.
88 * XDG_DATA_DIRS/applications will contain defaults.list
89 * XDG_DATA_HOME/applications will contain myapp.desktop
90 * and myapp2.desktop, and no mimeapps.list
103 GError *error = NULL;
105 dir = g_get_current_dir ();
106 xdgdatahome = g_build_filename (dir, "xdgdatahome", NULL);
107 xdgdatadir = g_build_filename (dir, "xdgdatadir", NULL);
108 g_test_message ("setting XDG_DATA_HOME to '%s'\n", xdgdatahome);
109 g_setenv ("XDG_DATA_HOME", xdgdatahome, TRUE);
110 g_test_message ("setting XDG_DATA_DIRS to '%s'\n", xdgdatadir);
111 g_setenv ("XDG_DATA_DIRS", xdgdatadir, TRUE);
113 appdir = g_build_filename (xdgdatadir, "applications", NULL);
114 g_test_message ("creating '%s'\n", appdir);
115 res = g_mkdir_with_parents (appdir, 0700);
118 name = g_build_filename (appdir, "defaults.list", NULL);
119 g_test_message ("creating '%s'\n", name);
120 g_file_set_contents (name, defaults_data, -1, &error);
121 g_assert_no_error (error);
124 apphome = g_build_filename (xdgdatahome, "applications", NULL);
125 g_test_message ("creating '%s'\n", apphome);
126 res = g_mkdir_with_parents (apphome, 0700);
129 name = g_build_filename (apphome, "myapp.desktop", NULL);
130 g_test_message ("creating '%s'\n", name);
131 g_file_set_contents (name, myapp_data, -1, &error);
132 g_assert_no_error (error);
135 name = g_build_filename (apphome, "myapp2.desktop", NULL);
136 g_test_message ("creating '%s'\n", name);
137 g_file_set_contents (name, myapp2_data, -1, &error);
138 g_assert_no_error (error);
141 name = g_build_filename (apphome, "myapp3.desktop", NULL);
142 g_test_message ("creating '%s'\n", name);
143 g_file_set_contents (name, myapp3_data, -1, &error);
144 g_assert_no_error (error);
147 name = g_build_filename (apphome, "myapp4.desktop", NULL);
148 g_test_message ("creating '%s'\n", name);
149 g_file_set_contents (name, myapp4_data, -1, &error);
150 g_assert_no_error (error);
153 name = g_build_filename (apphome, "myapp5.desktop", NULL);
154 g_test_message ("creating '%s'\n", name);
155 g_file_set_contents (name, myapp5_data, -1, &error);
156 g_assert_no_error (error);
159 mimeapps = g_build_filename (apphome, "mimeapps.list", NULL);
160 g_test_message ("removing '%s'\n", mimeapps);
163 name = g_build_filename (apphome, "mimeinfo.cache", NULL);
164 g_test_message ("creating '%s'\n", name);
165 g_file_set_contents (name, mimecache_data, -1, &error);
166 g_assert_no_error (error);
170 g_free (xdgdatahome);
182 GError *error = NULL;
185 const gchar *contenttype = "application/pdf";
187 /* clear things out */
188 g_app_info_reset_type_associations (contenttype);
190 appinfo = (GAppInfo*)g_desktop_app_info_new ("myapp.desktop");
191 appinfo2 = (GAppInfo*)g_desktop_app_info_new ("myapp2.desktop");
193 def = g_app_info_get_default_for_type (contenttype, FALSE);
194 list = g_app_info_get_recommended_for_type (contenttype);
195 g_assert (def == NULL);
196 g_assert (list == NULL);
198 /* 1. add a non-default association */
199 g_app_info_add_supports_type (appinfo, contenttype, &error);
200 g_assert_no_error (error);
202 def = g_app_info_get_default_for_type (contenttype, FALSE);
203 list = g_app_info_get_recommended_for_type (contenttype);
204 g_assert (g_app_info_equal (def, appinfo));
205 g_assert_cmpint (g_list_length (list), ==, 1);
206 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
207 g_object_unref (def);
208 g_list_free_full (list, g_object_unref);
210 /* 2. add another non-default association */
211 g_app_info_add_supports_type (appinfo2, contenttype, &error);
212 g_assert_no_error (error);
214 def = g_app_info_get_default_for_type (contenttype, FALSE);
215 list = g_app_info_get_recommended_for_type (contenttype);
216 g_assert (g_app_info_equal (def, appinfo));
217 g_assert_cmpint (g_list_length (list), ==, 2);
218 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
219 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
220 g_object_unref (def);
221 g_list_free_full (list, g_object_unref);
223 /* 3. make the first app the default */
224 g_app_info_set_as_default_for_type (appinfo, contenttype, &error);
225 g_assert_no_error (error);
227 def = g_app_info_get_default_for_type (contenttype, FALSE);
228 list = g_app_info_get_recommended_for_type (contenttype);
229 g_assert (g_app_info_equal (def, appinfo));
230 g_assert_cmpint (g_list_length (list), ==, 2);
231 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
232 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
233 g_object_unref (def);
234 g_list_free_full (list, g_object_unref);
236 /* 4. make the second app the last used one */
237 g_app_info_set_as_last_used_for_type (appinfo2, contenttype, &error);
238 g_assert_no_error (error);
240 def = g_app_info_get_default_for_type (contenttype, FALSE);
241 list = g_app_info_get_recommended_for_type (contenttype);
242 g_assert (g_app_info_equal (def, appinfo));
243 g_assert_cmpint (g_list_length (list), ==, 2);
244 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo2));
245 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo));
246 g_object_unref (def);
247 g_list_free_full (list, g_object_unref);
249 /* 5. reset everything */
250 g_app_info_reset_type_associations (contenttype);
252 def = g_app_info_get_default_for_type (contenttype, FALSE);
253 list = g_app_info_get_recommended_for_type (contenttype);
254 g_assert (def == NULL);
255 g_assert (list == NULL);
257 g_object_unref (appinfo);
258 g_object_unref (appinfo2);
261 /* Repeat the same tests, this time checking that we handle
262 * mimeapps.list as expected. These tests are different from
263 * the ones in test_mime_api() in that we directly parse
264 * mimeapps.list to verify the results.
267 test_mime_file (void)
272 GError *error = NULL;
280 const gchar *contenttype = "application/pdf";
282 dir = g_get_current_dir ();
283 mimeapps = g_build_filename (dir, "xdgdatahome", "applications", "mimeapps.list", NULL);
285 /* clear things out */
286 g_app_info_reset_type_associations (contenttype);
288 appinfo = (GAppInfo*)g_desktop_app_info_new ("myapp.desktop");
289 appinfo2 = (GAppInfo*)g_desktop_app_info_new ("myapp2.desktop");
291 def = g_app_info_get_default_for_type (contenttype, FALSE);
292 list = g_app_info_get_recommended_for_type (contenttype);
293 g_assert (def == NULL);
294 g_assert (list == NULL);
296 /* 1. add a non-default association */
297 g_app_info_add_supports_type (appinfo, contenttype, &error);
298 g_assert_no_error (error);
300 keyfile = g_key_file_new ();
301 g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
302 g_assert_no_error (error);
304 assoc = g_key_file_get_string_list (keyfile, "Added Associations", contenttype, NULL, &error);
305 g_assert_no_error (error);
306 g_assert (strv_equal (assoc, "myapp.desktop", NULL));
309 /* we've unset XDG_DATA_DIRS so there should be no default */
310 assoc = g_key_file_get_string_list (keyfile, "Default Applications", contenttype, NULL, &error);
311 g_assert (error != NULL);
312 g_clear_error (&error);
314 g_key_file_free (keyfile);
316 /* 2. add another non-default association */
317 g_app_info_add_supports_type (appinfo2, contenttype, &error);
318 g_assert_no_error (error);
320 keyfile = g_key_file_new ();
321 g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
322 g_assert_no_error (error);
324 assoc = g_key_file_get_string_list (keyfile, "Added Associations", contenttype, NULL, &error);
325 g_assert_no_error (error);
326 g_assert (strv_equal (assoc, "myapp.desktop", "myapp2.desktop", NULL));
329 assoc = g_key_file_get_string_list (keyfile, "Default Applications", contenttype, NULL, &error);
330 g_assert (error != NULL);
331 g_clear_error (&error);
333 g_key_file_free (keyfile);
335 /* 3. make the first app the default */
336 g_app_info_set_as_default_for_type (appinfo, contenttype, &error);
337 g_assert_no_error (error);
339 keyfile = g_key_file_new ();
340 g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
341 g_assert_no_error (error);
343 assoc = g_key_file_get_string_list (keyfile, "Added Associations", contenttype, NULL, &error);
344 g_assert_no_error (error);
345 g_assert (strv_equal (assoc, "myapp.desktop", "myapp2.desktop", NULL));
348 str = g_key_file_get_string (keyfile, "Default Applications", contenttype, &error);
349 g_assert_no_error (error);
350 g_assert_cmpstr (str, ==, "myapp.desktop");
352 g_key_file_free (keyfile);
354 /* 4. make the second app the last used one */
355 g_app_info_set_as_last_used_for_type (appinfo2, contenttype, &error);
356 g_assert_no_error (error);
358 keyfile = g_key_file_new ();
359 g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
360 g_assert_no_error (error);
362 assoc = g_key_file_get_string_list (keyfile, "Added Associations", contenttype, NULL, &error);
363 g_assert_no_error (error);
364 g_assert (strv_equal (assoc, "myapp2.desktop", "myapp.desktop", NULL));
367 g_key_file_free (keyfile);
369 /* 5. reset everything */
370 g_app_info_reset_type_associations (contenttype);
372 keyfile = g_key_file_new ();
373 g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
374 g_assert_no_error (error);
376 res = g_key_file_has_key (keyfile, "Added Associations", contenttype, NULL);
379 res = g_key_file_has_key (keyfile, "Default Applications", contenttype, NULL);
382 g_key_file_free (keyfile);
384 g_object_unref (appinfo);
385 g_object_unref (appinfo2);
391 /* test interaction between defaults.list and mimeapps.list */
393 test_mime_default (void)
398 GError *error = NULL;
401 const gchar *contenttype = "image/png";
403 /* clear things out */
404 g_app_info_reset_type_associations (contenttype);
406 appinfo = (GAppInfo*)g_desktop_app_info_new ("myapp.desktop");
407 appinfo2 = (GAppInfo*)g_desktop_app_info_new ("myapp2.desktop");
408 appinfo3 = (GAppInfo*)g_desktop_app_info_new ("myapp3.desktop");
410 /* myapp3 is set as the default in defaults.list */
411 def = g_app_info_get_default_for_type (contenttype, FALSE);
412 list = g_app_info_get_recommended_for_type (contenttype);
413 g_assert (g_app_info_equal (def, appinfo3));
414 g_assert_cmpint (g_list_length (list), ==, 1);
415 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo3));
416 g_object_unref (def);
417 g_list_free_full (list, g_object_unref);
419 /* 1. add a non-default association */
420 g_app_info_add_supports_type (appinfo, contenttype, &error);
421 g_assert_no_error (error);
423 def = g_app_info_get_default_for_type (contenttype, FALSE);
424 list = g_app_info_get_recommended_for_type (contenttype);
425 g_assert (g_app_info_equal (def, appinfo3)); /* default is unaffected */
426 g_assert_cmpint (g_list_length (list), ==, 2);
427 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
428 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo3));
429 g_object_unref (def);
430 g_list_free_full (list, g_object_unref);
432 /* 2. add another non-default association */
433 g_app_info_add_supports_type (appinfo2, contenttype, &error);
434 g_assert_no_error (error);
436 def = g_app_info_get_default_for_type (contenttype, FALSE);
437 list = g_app_info_get_recommended_for_type (contenttype);
438 g_assert (g_app_info_equal (def, appinfo3));
439 g_assert_cmpint (g_list_length (list), ==, 3);
440 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
441 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
442 g_assert (g_app_info_equal ((GAppInfo*)list->next->next->data, appinfo3));
443 g_object_unref (def);
444 g_list_free_full (list, g_object_unref);
446 /* 3. make the first app the default */
447 g_app_info_set_as_default_for_type (appinfo, contenttype, &error);
448 g_assert_no_error (error);
450 def = g_app_info_get_default_for_type (contenttype, FALSE);
451 list = g_app_info_get_recommended_for_type (contenttype);
452 g_assert (g_app_info_equal (def, appinfo));
453 g_assert_cmpint (g_list_length (list), ==, 3);
454 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
455 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
456 g_assert (g_app_info_equal ((GAppInfo*)list->next->next->data, appinfo3));
457 g_object_unref (def);
458 g_list_free_full (list, g_object_unref);
460 g_object_unref (appinfo);
461 g_object_unref (appinfo2);
462 g_object_unref (appinfo3);
465 /* test interaction between mimeinfo.cache, defaults.list and mimeapps.list
466 * to ensure g_app_info_set_as_last_used_for_type doesn't incorrectly
470 test_mime_default_last_used (void)
474 GError *error = NULL;
477 const gchar *contenttype = "image/bmp";
479 /* clear things out */
480 g_app_info_reset_type_associations (contenttype);
482 appinfo4 = (GAppInfo*)g_desktop_app_info_new ("myapp4.desktop");
483 appinfo5 = (GAppInfo*)g_desktop_app_info_new ("myapp5.desktop");
485 /* myapp4 is set as the default in defaults.list */
486 /* myapp4 and myapp5 can both handle image/bmp */
487 def = g_app_info_get_default_for_type (contenttype, FALSE);
488 list = g_app_info_get_recommended_for_type (contenttype);
489 g_assert (g_app_info_equal (def, appinfo4));
490 g_assert_cmpint (g_list_length (list), ==, 2);
491 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo4));
492 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo5));
493 g_object_unref (def);
494 g_list_free_full (list, g_object_unref);
496 /* 1. set default (myapp4) as last used */
497 g_app_info_set_as_last_used_for_type (appinfo4, contenttype, &error);
498 g_assert_no_error (error);
500 def = g_app_info_get_default_for_type (contenttype, FALSE);
501 list = g_app_info_get_recommended_for_type (contenttype);
502 g_assert (g_app_info_equal (def, appinfo4)); /* default is unaffected */
503 g_assert_cmpint (g_list_length (list), ==, 2);
504 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo4));
505 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo5));
506 g_object_unref (def);
507 g_list_free_full (list, g_object_unref);
509 /* 2. set other (myapp5) as last used */
510 g_app_info_set_as_last_used_for_type (appinfo5, contenttype, &error);
511 g_assert_no_error (error);
513 def = g_app_info_get_default_for_type (contenttype, FALSE);
514 list = g_app_info_get_recommended_for_type (contenttype);
515 g_assert (g_app_info_equal (def, appinfo4));
516 g_assert_cmpint (g_list_length (list), ==, 2);
517 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo5));
518 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo4));
519 g_object_unref (def);
520 g_list_free_full (list, g_object_unref);
522 /* 3. change the default to myapp5 */
523 g_app_info_set_as_default_for_type (appinfo5, contenttype, &error);
524 g_assert_no_error (error);
526 def = g_app_info_get_default_for_type (contenttype, FALSE);
527 list = g_app_info_get_recommended_for_type (contenttype);
528 g_assert (g_app_info_equal (def, appinfo5));
529 g_assert_cmpint (g_list_length (list), ==, 2);
530 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo5));
531 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo4));
532 g_object_unref (def);
533 g_list_free_full (list, g_object_unref);
535 /* 4. set myapp4 as last used */
536 g_app_info_set_as_last_used_for_type (appinfo4, contenttype, &error);
537 g_assert_no_error (error);
539 def = g_app_info_get_default_for_type (contenttype, FALSE);
540 list = g_app_info_get_recommended_for_type (contenttype);
541 g_assert (g_app_info_equal (def, appinfo5));
542 g_assert_cmpint (g_list_length (list), ==, 2);
543 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo4));
544 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo5));
545 g_object_unref (def);
546 g_list_free_full (list, g_object_unref);
548 /* 5. set myapp5 as last used again */
549 g_app_info_set_as_last_used_for_type (appinfo5, contenttype, &error);
550 g_assert_no_error (error);
552 def = g_app_info_get_default_for_type (contenttype, FALSE);
553 list = g_app_info_get_recommended_for_type (contenttype);
554 g_assert (g_app_info_equal (def, appinfo5));
555 g_assert_cmpint (g_list_length (list), ==, 2);
556 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo5));
557 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo4));
558 g_object_unref (def);
559 g_list_free_full (list, g_object_unref);
561 g_object_unref (appinfo4);
562 g_object_unref (appinfo5);
566 main (int argc, char *argv[])
569 g_test_init (&argc, &argv, NULL);
573 g_test_add_func ("/appinfo/mime/api", test_mime_api);
574 g_test_add_func ("/appinfo/mime/default", test_mime_default);
575 g_test_add_func ("/appinfo/mime/file", test_mime_file);
576 g_test_add_func ("/appinfo/mime/default_last_used", test_mime_default_last_used);
578 return g_test_run ();