1#include <gio/gio.h>
2#include <string.h>
3
4#include "glib/glib-private.h"
5
6#define g_assert_content_type_equals(s1, s2) \
7 do { \
8 const char *__s1 = (s1), *__s2 = (s2); \
9 if (g_content_type_equals (__s1, __s2)) ; \
10 else \
11 g_assertion_message_cmpstr (G_LOG_DOMAIN, \
12 __FILE__, __LINE__, \
13 G_STRFUNC, \
14 #s1 " == " #s2, \
15 __s1, " == ", __s2); \
16 } while (0)
17
18static void
19test_guess (void)
20{
21#ifdef _GLIB_ADDRESS_SANITIZER
22 g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310");
23#else
24 gchar *res;
25 gchar *expected;
26 gchar *existing_directory;
27 gboolean uncertain;
28 guchar data[] =
29 "[Desktop Entry]\n"
30 "Type=Application\n"
31 "Name=appinfo-test\n"
32 "Exec=./appinfo-test --option\n";
33
34#ifdef G_OS_WIN32
35 existing_directory = (gchar *) g_getenv ("SYSTEMROOT");
36
37 if (existing_directory)
38 existing_directory = g_strdup_printf ("%s/", existing_directory);
39#else
40 existing_directory = g_strdup (str: "/etc/");
41#endif
42
43 res = g_content_type_guess (filename: existing_directory, NULL, data_size: 0, result_uncertain: &uncertain);
44 g_free (mem: existing_directory);
45 expected = g_content_type_from_mime_type (mime_type: "inode/directory");
46 g_assert_content_type_equals (expected, res);
47 g_assert_true (uncertain);
48 g_free (mem: res);
49 g_free (mem: expected);
50
51 res = g_content_type_guess (filename: "foo.txt", NULL, data_size: 0, result_uncertain: &uncertain);
52 expected = g_content_type_from_mime_type (mime_type: "text/plain");
53 g_assert_content_type_equals (expected, res);
54 g_free (mem: res);
55 g_free (mem: expected);
56
57 res = g_content_type_guess (filename: "foo.txt", data, data_size: sizeof (data) - 1, result_uncertain: &uncertain);
58 expected = g_content_type_from_mime_type (mime_type: "text/plain");
59 g_assert_content_type_equals (expected, res);
60 g_assert_false (uncertain);
61 g_free (mem: res);
62 g_free (mem: expected);
63
64 /* Sadly OSX just doesn't have as large and robust of a mime type database as Linux */
65#ifndef __APPLE__
66 res = g_content_type_guess (filename: "foo", data, data_size: sizeof (data) - 1, result_uncertain: &uncertain);
67 expected = g_content_type_from_mime_type (mime_type: "text/plain");
68 g_assert_content_type_equals (expected, res);
69 g_assert_false (uncertain);
70 g_free (mem: res);
71 g_free (mem: expected);
72
73 res = g_content_type_guess (filename: "foo.desktop", data, data_size: sizeof (data) - 1, result_uncertain: &uncertain);
74 expected = g_content_type_from_mime_type (mime_type: "application/x-desktop");
75 g_assert_content_type_equals (expected, res);
76 g_assert_false (uncertain);
77 g_free (mem: res);
78 g_free (mem: expected);
79
80 res = g_content_type_guess (NULL, data, data_size: sizeof (data) - 1, result_uncertain: &uncertain);
81 expected = g_content_type_from_mime_type (mime_type: "application/x-desktop");
82 g_assert_content_type_equals (expected, res);
83 g_assert_false (uncertain);
84 g_free (mem: res);
85 g_free (mem: expected);
86
87 /* this is potentially ambiguous: it does not match the PO template format,
88 * but looks like text so it can't be Powerpoint */
89 res = g_content_type_guess (filename: "test.pot", data: (guchar *)"ABC abc", data_size: 7, result_uncertain: &uncertain);
90 expected = g_content_type_from_mime_type (mime_type: "text/x-gettext-translation-template");
91 g_assert_content_type_equals (expected, res);
92 g_assert_false (uncertain);
93 g_free (mem: res);
94 g_free (mem: expected);
95
96 res = g_content_type_guess (filename: "test.pot", data: (guchar *)"msgid \"", data_size: 7, result_uncertain: &uncertain);
97 expected = g_content_type_from_mime_type (mime_type: "text/x-gettext-translation-template");
98 g_assert_content_type_equals (expected, res);
99 g_assert_false (uncertain);
100 g_free (mem: res);
101 g_free (mem: expected);
102
103 res = g_content_type_guess (filename: "test.pot", data: (guchar *)"\xCF\xD0\xE0\x11", data_size: 4, result_uncertain: &uncertain);
104 expected = g_content_type_from_mime_type (mime_type: "application/vnd.ms-powerpoint");
105 g_assert_content_type_equals (expected, res);
106 /* we cannot reliably detect binary powerpoint files as long as there is no
107 * defined MIME magic, so do not check uncertain here
108 */
109 g_free (mem: res);
110 g_free (mem: expected);
111
112 res = g_content_type_guess (filename: "test.otf", data: (guchar *)"OTTO", data_size: 4, result_uncertain: &uncertain);
113 expected = g_content_type_from_mime_type (mime_type: "application/x-font-otf");
114 g_assert_content_type_equals (expected, res);
115 g_assert_false (uncertain);
116 g_free (mem: res);
117 g_free (mem: expected);
118#endif
119
120 res = g_content_type_guess (NULL, data: (guchar *)"%!PS-Adobe-2.0 EPSF-1.2", data_size: 23, result_uncertain: &uncertain);
121 expected = g_content_type_from_mime_type (mime_type: "image/x-eps");
122 g_assert_content_type_equals (expected, res);
123 g_assert_false (uncertain);
124 g_free (mem: res);
125 g_free (mem: expected);
126
127 /* The data below would be detected as a valid content type, but shouldn’t be read at all. */
128 res = g_content_type_guess (NULL, data: (guchar *)"%!PS-Adobe-2.0 EPSF-1.2", data_size: 0, result_uncertain: &uncertain);
129 expected = g_content_type_from_mime_type (mime_type: "application/x-zerosize");
130 g_assert_content_type_equals (expected, res);
131 g_assert_false (uncertain);
132 g_free (mem: res);
133 g_free (mem: expected);
134#endif
135}
136
137static void
138test_unknown (void)
139{
140#ifdef _GLIB_ADDRESS_SANITIZER
141 g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310");
142#else
143 gchar *unknown;
144 gchar *str;
145
146 unknown = g_content_type_from_mime_type (mime_type: "application/octet-stream");
147 g_assert_true (g_content_type_is_unknown (unknown));
148 str = g_content_type_get_mime_type (type: unknown);
149 g_assert_cmpstr (str, ==, "application/octet-stream");
150 g_free (mem: str);
151 g_free (mem: unknown);
152#endif
153}
154
155static void
156test_subtype (void)
157{
158#ifdef _GLIB_ADDRESS_SANITIZER
159 g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310");
160#else
161 gchar *plain;
162 gchar *xml;
163
164 plain = g_content_type_from_mime_type (mime_type: "text/plain");
165 xml = g_content_type_from_mime_type (mime_type: "application/xml");
166
167 g_assert_true (g_content_type_is_a (xml, plain));
168 g_assert_true (g_content_type_is_mime_type (xml, "text/plain"));
169
170 g_free (mem: plain);
171 g_free (mem: xml);
172#endif
173}
174
175static gint
176find_mime (gconstpointer a, gconstpointer b)
177{
178 if (g_content_type_equals (type1: a, type2: b))
179 return 0;
180 return 1;
181}
182
183static void
184test_list (void)
185{
186#ifdef _GLIB_ADDRESS_SANITIZER
187 g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310");
188 (void) find_mime;
189#else
190 GList *types;
191 gchar *plain;
192 gchar *xml;
193
194#ifdef __APPLE__
195 g_test_skip ("The OSX backend does not implement g_content_types_get_registered()");
196 return;
197#endif
198
199 plain = g_content_type_from_mime_type (mime_type: "text/plain");
200 xml = g_content_type_from_mime_type (mime_type: "application/xml");
201
202 types = g_content_types_get_registered ();
203
204 g_assert_cmpuint (g_list_length (types), >, 1);
205
206 /* just check that some types are in the list */
207 g_assert_nonnull (g_list_find_custom (types, plain, find_mime));
208 g_assert_nonnull (g_list_find_custom (types, xml, find_mime));
209
210 g_list_free_full (list: types, free_func: g_free);
211
212 g_free (mem: plain);
213 g_free (mem: xml);
214#endif
215}
216
217static void
218test_executable (void)
219{
220#ifdef _GLIB_ADDRESS_SANITIZER
221 g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310");
222#else
223 gchar *type;
224
225 type = g_content_type_from_mime_type (mime_type: "application/x-executable");
226 g_assert_true (g_content_type_can_be_executable (type));
227 g_free (mem: type);
228
229 type = g_content_type_from_mime_type (mime_type: "text/plain");
230 g_assert_true (g_content_type_can_be_executable (type));
231 g_free (mem: type);
232
233 type = g_content_type_from_mime_type (mime_type: "image/png");
234 g_assert_false (g_content_type_can_be_executable (type));
235 g_free (mem: type);
236#endif
237}
238
239static void
240test_description (void)
241{
242#ifdef _GLIB_ADDRESS_SANITIZER
243 g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310");
244#else
245 gchar *type;
246 gchar *desc;
247
248 type = g_content_type_from_mime_type (mime_type: "text/plain");
249 desc = g_content_type_get_description (type);
250 g_assert_nonnull (desc);
251
252 g_free (mem: desc);
253 g_free (mem: type);
254#endif
255}
256
257static void
258test_icon (void)
259{
260#ifdef _GLIB_ADDRESS_SANITIZER
261 g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310");
262#else
263 gchar *type;
264 GIcon *icon;
265
266 type = g_content_type_from_mime_type (mime_type: "text/plain");
267 icon = g_content_type_get_icon (type);
268 g_assert_true (G_IS_ICON (icon));
269 if (G_IS_THEMED_ICON (icon))
270 {
271 const gchar *const *names;
272
273 names = g_themed_icon_get_names (G_THEMED_ICON (icon));
274#ifdef __APPLE__
275 g_assert_true (g_strv_contains (names, "text-*"));
276#else
277 g_assert_true (g_strv_contains (names, "text-plain"));
278 g_assert_true (g_strv_contains (names, "text-x-generic"));
279#endif
280 }
281 g_object_unref (object: icon);
282 g_free (mem: type);
283
284 type = g_content_type_from_mime_type (mime_type: "application/rtf");
285 icon = g_content_type_get_icon (type);
286 g_assert_true (G_IS_ICON (icon));
287 if (G_IS_THEMED_ICON (icon))
288 {
289 const gchar *const *names;
290
291 names = g_themed_icon_get_names (G_THEMED_ICON (icon));
292 g_assert_true (g_strv_contains (names, "application-rtf"));
293#ifndef __APPLE__
294 g_assert_true (g_strv_contains (names, "x-office-document"));
295#endif
296 }
297 g_object_unref (object: icon);
298 g_free (mem: type);
299#endif
300}
301
302static void
303test_symbolic_icon (void)
304{
305#ifdef _GLIB_ADDRESS_SANITIZER
306 g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310");
307#elif !defined(G_OS_WIN32)
308 gchar *type;
309 GIcon *icon;
310
311 type = g_content_type_from_mime_type (mime_type: "text/plain");
312 icon = g_content_type_get_symbolic_icon (type);
313 g_assert_true (G_IS_ICON (icon));
314 if (G_IS_THEMED_ICON (icon))
315 {
316 const gchar *const *names;
317
318 names = g_themed_icon_get_names (G_THEMED_ICON (icon));
319#ifdef __APPLE__
320 g_assert_true (g_strv_contains (names, "text-*-symbolic"));
321 g_assert_true (g_strv_contains (names, "text-*"));
322#else
323 g_assert_true (g_strv_contains (names, "text-plain-symbolic"));
324 g_assert_true (g_strv_contains (names, "text-x-generic-symbolic"));
325 g_assert_true (g_strv_contains (names, "text-plain"));
326 g_assert_true (g_strv_contains (names, "text-x-generic"));
327#endif
328 }
329 g_object_unref (object: icon);
330 g_free (mem: type);
331
332 type = g_content_type_from_mime_type (mime_type: "application/rtf");
333 icon = g_content_type_get_symbolic_icon (type);
334 g_assert_true (G_IS_ICON (icon));
335 if (G_IS_THEMED_ICON (icon))
336 {
337 const gchar *const *names;
338
339 names = g_themed_icon_get_names (G_THEMED_ICON (icon));
340 g_assert_true (g_strv_contains (names, "application-rtf-symbolic"));
341 g_assert_true (g_strv_contains (names, "application-rtf"));
342#ifndef __APPLE__
343 g_assert_true (g_strv_contains (names, "x-office-document-symbolic"));
344 g_assert_true (g_strv_contains (names, "x-office-document"));
345#endif
346 }
347 g_object_unref (object: icon);
348 g_free (mem: type);
349#endif
350}
351
352static void
353test_tree (void)
354{
355#ifdef _GLIB_ADDRESS_SANITIZER
356 g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310");
357#else
358 const gchar *tests[] = {
359 "x-content/image-dcf",
360 "x-content/unix-software",
361 "x-content/win32-software"
362 };
363 const gchar *path;
364 GFile *file;
365 gchar **types;
366 gint i;
367
368#ifdef __APPLE__
369 g_test_skip ("The OSX backend does not implement g_content_type_guess_for_tree()");
370 return;
371#endif
372
373 for (i = 0; i < G_N_ELEMENTS (tests); i++)
374 {
375 path = g_test_get_filename (file_type: G_TEST_DIST, first_path: tests[i], NULL);
376 file = g_file_new_for_path (path);
377 types = g_content_type_guess_for_tree (root: file);
378 g_assert_content_type_equals (types[0], tests[i]);
379 g_strfreev (str_array: types);
380 g_object_unref (object: file);
381 }
382#endif
383}
384
385static void
386test_type_is_a_special_case (void)
387{
388#ifdef _GLIB_ADDRESS_SANITIZER
389 g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310");
390#else
391 gboolean res;
392
393 g_test_bug (bug_uri_snippet: "782311");
394
395 /* Everything but the inode type is application/octet-stream */
396 res = g_content_type_is_a (type: "inode/directory", supertype: "application/octet-stream");
397 g_assert_false (res);
398#ifndef __APPLE__
399 res = g_content_type_is_a (type: "anything", supertype: "application/octet-stream");
400 g_assert_true (res);
401#endif
402#endif
403}
404
405static void
406test_guess_svg_from_data (void)
407{
408#ifdef _GLIB_ADDRESS_SANITIZER
409 g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310");
410#else
411 const gchar svgfilecontent[] = "<svg xmlns=\"http://www.w3.org/2000/svg\"\
412 xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n\
413 <rect x=\"10\" y=\"10\" height=\"100\" width=\"100\"\n\
414 style=\"stroke:#ff0000; fill: #0000ff\"/>\n\
415</svg>\n";
416
417 gboolean uncertain = TRUE;
418 gchar *res = g_content_type_guess (NULL, data: (guchar *)svgfilecontent,
419 data_size: sizeof (svgfilecontent) - 1, result_uncertain: &uncertain);
420#ifdef __APPLE__
421 g_assert_cmpstr (res, ==, "public.svg-image");
422#elif defined(G_OS_WIN32)
423 g_test_skip ("svg type detection from content is not implemented on WIN32");
424#else
425 g_assert_cmpstr (res, ==, "image/svg+xml");
426#endif
427 g_assert_false (uncertain);
428 g_free (mem: res);
429#endif
430}
431
432static void
433test_mime_from_content (void)
434{
435#ifdef _GLIB_ADDRESS_SANITIZER
436 g_test_incomplete ("FIXME: Leaks xdgmime internal data, see glib#2310");
437#elif defined(__APPLE__)
438 gchar *mime_type;
439 mime_type = g_content_type_get_mime_type ("com.microsoft.bmp");
440 g_assert_cmpstr (mime_type, ==, "image/bmp");
441 g_free (mime_type);
442 mime_type = g_content_type_get_mime_type ("com.compuserve.gif");
443 g_assert_cmpstr (mime_type, ==, "image/gif");
444 g_free (mime_type);
445 mime_type = g_content_type_get_mime_type ("public.png");
446 g_assert_cmpstr (mime_type, ==, "image/png");
447 g_free (mime_type);
448 mime_type = g_content_type_get_mime_type ("public.text");
449 g_assert_cmpstr (mime_type, ==, "text/*");
450 g_free (mime_type);
451 mime_type = g_content_type_get_mime_type ("public.svg-image");
452 g_assert_cmpstr (mime_type, ==, "image/svg+xml");
453 g_free (mime_type);
454#elif defined(G_OS_WIN32)
455 g_test_skip ("mime from content type test not implemented on WIN32");
456#else
457 g_test_skip (msg: "mime from content type test not implemented on UNIX");
458#endif
459}
460
461int
462main (int argc, char *argv[])
463{
464 g_test_init (argc: &argc, argv: &argv, NULL);
465
466 g_test_bug_base (uri_pattern: "http://bugzilla.gnome.org/");
467
468 g_test_add_func (testpath: "/contenttype/guess", test_func: test_guess);
469 g_test_add_func (testpath: "/contenttype/guess_svg_from_data", test_func: test_guess_svg_from_data);
470 g_test_add_func (testpath: "/contenttype/mime_from_content", test_func: test_mime_from_content);
471 g_test_add_func (testpath: "/contenttype/unknown", test_func: test_unknown);
472 g_test_add_func (testpath: "/contenttype/subtype", test_func: test_subtype);
473 g_test_add_func (testpath: "/contenttype/list", test_func: test_list);
474 g_test_add_func (testpath: "/contenttype/executable", test_func: test_executable);
475 g_test_add_func (testpath: "/contenttype/description", test_func: test_description);
476 g_test_add_func (testpath: "/contenttype/icon", test_func: test_icon);
477 g_test_add_func (testpath: "/contenttype/symbolic-icon", test_func: test_symbolic_icon);
478 g_test_add_func (testpath: "/contenttype/tree", test_func: test_tree);
479 g_test_add_func (testpath: "/contenttype/test_type_is_a_special_case",
480 test_func: test_type_is_a_special_case);
481
482 return g_test_run ();
483}
484

source code of gtk/subprojects/glib/gio/tests/contenttype.c