contenttype.c 12.7 KB
Newer Older
Matthias Clasen's avatar
Matthias Clasen committed
1
#include <gio/gio.h>
2
#include <string.h>
Matthias Clasen's avatar
Matthias Clasen committed
3

4 5 6 7 8 9 10 11 12 13 14 15
#define g_assert_content_type_equals(s1, s2) 			\
  do { 								\
    const char *__s1 = (s1), *__s2 = (s2); 			\
    if (g_content_type_equals (__s1, __s2)) ;		 	\
    else 							\
      g_assertion_message_cmpstr (G_LOG_DOMAIN, 		\
                                  __FILE__, __LINE__, 		\
                                  G_STRFUNC, 			\
                                  #s1 " == " #s2, 		\
                                  __s1, " == ", __s2); 		\
  } while (0)

Matthias Clasen's avatar
Matthias Clasen committed
16 17 18 19 20
static void
test_guess (void)
{
  gchar *res;
  gchar *expected;
21
  gchar *existing_directory;
Matthias Clasen's avatar
Matthias Clasen committed
22
  gboolean uncertain;
23
  guchar data[] =
24 25 26 27
    "[Desktop Entry]\n"
    "Type=Application\n"
    "Name=appinfo-test\n"
    "Exec=./appinfo-test --option\n";
Matthias Clasen's avatar
Matthias Clasen committed
28

29 30 31 32 33 34 35 36 37 38 39
#ifdef G_OS_WIN32
  existing_directory = (gchar *) g_getenv ("SYSTEMROOT");

  if (existing_directory)
    existing_directory = g_strdup_printf ("%s/", existing_directory);
#else
  existing_directory = g_strdup ("/etc/");
#endif

  res = g_content_type_guess (existing_directory, NULL, 0, &uncertain);
  g_free (existing_directory);
Matthias Clasen's avatar
Matthias Clasen committed
40
  expected = g_content_type_from_mime_type ("inode/directory");
41
  g_assert_content_type_equals (expected, res);
42
  g_assert_true (uncertain);
Matthias Clasen's avatar
Matthias Clasen committed
43 44 45 46 47
  g_free (res);
  g_free (expected);

  res = g_content_type_guess ("foo.txt", NULL, 0, &uncertain);
  expected = g_content_type_from_mime_type ("text/plain");
48
  g_assert_content_type_equals (expected, res);
49 50 51
  g_free (res);
  g_free (expected);

52 53
  res = g_content_type_guess ("foo.txt", data, sizeof (data) - 1, &uncertain);
  expected = g_content_type_from_mime_type ("text/plain");
54
  g_assert_content_type_equals (expected, res);
55
  g_assert_false (uncertain);
56 57 58
  g_free (res);
  g_free (expected);

59 60
  /* Sadly OSX just doesn't have as large and robust of a mime type database as Linux */
#ifndef __APPLE__
61
  res = g_content_type_guess ("foo", data, sizeof (data) - 1, &uncertain);
62
  expected = g_content_type_from_mime_type ("text/plain");
63
  g_assert_content_type_equals (expected, res);
64
  g_assert_false (uncertain);
65 66 67
  g_free (res);
  g_free (expected);

68 69
  res = g_content_type_guess ("foo.desktop", data, sizeof (data) - 1, &uncertain);
  expected = g_content_type_from_mime_type ("application/x-desktop");
70
  g_assert_content_type_equals (expected, res);
71
  g_assert_false (uncertain);
72 73 74
  g_free (res);
  g_free (expected);

75
  res = g_content_type_guess (NULL, data, sizeof (data) - 1, &uncertain);
76
  expected = g_content_type_from_mime_type ("application/x-desktop");
77
  g_assert_content_type_equals (expected, res);
78
  g_assert_false (uncertain);
79 80 81
  g_free (res);
  g_free (expected);

Martin Pitt's avatar
Martin Pitt committed
82 83
  /* this is potentially ambiguous: it does not match the PO template format,
   * but looks like text so it can't be Powerpoint */
84
  res = g_content_type_guess ("test.pot", (guchar *)"ABC abc", 7, &uncertain);
Martin Pitt's avatar
Martin Pitt committed
85
  expected = g_content_type_from_mime_type ("text/x-gettext-translation-template");
86
  g_assert_content_type_equals (expected, res);
87
  g_assert_false (uncertain);
Martin Pitt's avatar
Martin Pitt committed
88 89 90 91 92
  g_free (res);
  g_free (expected);

  res = g_content_type_guess ("test.pot", (guchar *)"msgid \"", 7, &uncertain);
  expected = g_content_type_from_mime_type ("text/x-gettext-translation-template");
93
  g_assert_content_type_equals (expected, res);
94
  g_assert_false (uncertain);
Martin Pitt's avatar
Martin Pitt committed
95 96 97 98
  g_free (res);
  g_free (expected);

  res = g_content_type_guess ("test.pot", (guchar *)"\xCF\xD0\xE0\x11", 4, &uncertain);
99
  expected = g_content_type_from_mime_type ("application/vnd.ms-powerpoint");
100
  g_assert_content_type_equals (expected, res);
Martin Pitt's avatar
Martin Pitt committed
101
  /* we cannot reliably detect binary powerpoint files as long as there is no
102 103
   * defined MIME magic, so do not check uncertain here
   */
104 105 106
  g_free (res);
  g_free (expected);

107
  res = g_content_type_guess ("test.otf", (guchar *)"OTTO", 4, &uncertain);
108
  expected = g_content_type_from_mime_type ("application/x-font-otf");
109
  g_assert_content_type_equals (expected, res);
110
  g_assert_false (uncertain);
Matthias Clasen's avatar
Matthias Clasen committed
111 112
  g_free (res);
  g_free (expected);
113
#endif
114 115 116 117

  res = g_content_type_guess (NULL, (guchar *)"%!PS-Adobe-2.0 EPSF-1.2", 23, &uncertain);
  expected = g_content_type_from_mime_type ("image/x-eps");
  g_assert_content_type_equals (expected, res);
118
  g_assert_false (uncertain);
119 120
  g_free (res);
  g_free (expected);
121 122 123 124 125 126 127 128

  /* The data below would be detected as a valid content type, but shouldn’t be read at all. */
  res = g_content_type_guess (NULL, (guchar *)"%!PS-Adobe-2.0 EPSF-1.2", 0, &uncertain);
  expected = g_content_type_from_mime_type ("application/x-zerosize");
  g_assert_content_type_equals (expected, res);
  g_assert_false (uncertain);
  g_free (res);
  g_free (expected);
Matthias Clasen's avatar
Matthias Clasen committed
129 130 131 132 133 134 135 136 137
}

static void
test_unknown (void)
{
  gchar *unknown;
  gchar *str;

  unknown = g_content_type_from_mime_type ("application/octet-stream");
138
  g_assert_true (g_content_type_is_unknown (unknown));
Matthias Clasen's avatar
Matthias Clasen committed
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
  str = g_content_type_get_mime_type (unknown);
  g_assert_cmpstr (str, ==, "application/octet-stream");
  g_free (str);
  g_free (unknown);
}

static void
test_subtype (void)
{
  gchar *plain;
  gchar *xml;

  plain = g_content_type_from_mime_type ("text/plain");
  xml = g_content_type_from_mime_type ("application/xml");

154 155
  g_assert_true (g_content_type_is_a (xml, plain));
  g_assert_true (g_content_type_is_mime_type (xml, "text/plain"));
Matthias Clasen's avatar
Matthias Clasen committed
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175

  g_free (plain);
  g_free (xml);
}

static gint
find_mime (gconstpointer a, gconstpointer b)
{
  if (g_content_type_equals (a, b))
    return 0;
  return 1;
}

static void
test_list (void)
{
  GList *types;
  gchar *plain;
  gchar *xml;

176 177 178 179 180
#ifdef __APPLE__
  g_test_skip ("The OSX backend does not implement g_content_types_get_registered()");
  return;
#endif

Matthias Clasen's avatar
Matthias Clasen committed
181 182 183 184 185
  plain = g_content_type_from_mime_type ("text/plain");
  xml = g_content_type_from_mime_type ("application/xml");

  types = g_content_types_get_registered ();

186
  g_assert_cmpuint (g_list_length (types), >, 1);
Matthias Clasen's avatar
Matthias Clasen committed
187 188

  /* just check that some types are in the list */
189 190
  g_assert_nonnull (g_list_find_custom (types, plain, find_mime));
  g_assert_nonnull (g_list_find_custom (types, xml, find_mime));
Matthias Clasen's avatar
Matthias Clasen committed
191

192
  g_list_free_full (types, g_free);
Matthias Clasen's avatar
Matthias Clasen committed
193 194 195 196 197 198 199 200 201 202 203

  g_free (plain);
  g_free (xml);
}

static void
test_executable (void)
{
  gchar *type;

  type = g_content_type_from_mime_type ("application/x-executable");
204
  g_assert_true (g_content_type_can_be_executable (type));
Matthias Clasen's avatar
Matthias Clasen committed
205 206 207
  g_free (type);

  type = g_content_type_from_mime_type ("text/plain");
208
  g_assert_true (g_content_type_can_be_executable (type));
Matthias Clasen's avatar
Matthias Clasen committed
209
  g_free (type);
Matthias Clasen's avatar
Matthias Clasen committed
210 211

  type = g_content_type_from_mime_type ("image/png");
212
  g_assert_false (g_content_type_can_be_executable (type));
Matthias Clasen's avatar
Matthias Clasen committed
213
  g_free (type);
Matthias Clasen's avatar
Matthias Clasen committed
214 215
}

Matthias Clasen's avatar
Matthias Clasen committed
216 217 218 219 220 221 222 223
static void
test_description (void)
{
  gchar *type;
  gchar *desc;

  type = g_content_type_from_mime_type ("text/plain");
  desc = g_content_type_get_description (type);
224
  g_assert_nonnull (desc);
Matthias Clasen's avatar
Matthias Clasen committed
225 226 227 228 229

  g_free (desc);
  g_free (type);
}

230 231 232 233 234 235 236 237
static void
test_icon (void)
{
  gchar *type;
  GIcon *icon;

  type = g_content_type_from_mime_type ("text/plain");
  icon = g_content_type_get_icon (type);
238
  g_assert_true (G_IS_ICON (icon));
239 240 241 242 243
  if (G_IS_THEMED_ICON (icon))
    {
      const gchar *const *names;

      names = g_themed_icon_get_names (G_THEMED_ICON (icon));
244
#ifdef __APPLE__
245
      g_assert_true (g_strv_contains (names, "text-*"));
246
#else
247 248
      g_assert_true (g_strv_contains (names, "text-plain"));
      g_assert_true (g_strv_contains (names, "text-x-generic"));
249
#endif
250
    }
251 252 253 254 255
  g_object_unref (icon);
  g_free (type);

  type = g_content_type_from_mime_type ("application/rtf");
  icon = g_content_type_get_icon (type);
256
  g_assert_true (G_IS_ICON (icon));
257 258 259 260 261
  if (G_IS_THEMED_ICON (icon))
    {
      const gchar *const *names;

      names = g_themed_icon_get_names (G_THEMED_ICON (icon));
262
      g_assert_true (g_strv_contains (names, "application-rtf"));
263
#ifndef __APPLE__
264
      g_assert_true (g_strv_contains (names, "x-office-document"));
265
#endif
266 267 268 269 270 271 272 273
    }
  g_object_unref (icon);
  g_free (type);
}

static void
test_symbolic_icon (void)
{
274
#ifndef G_OS_WIN32
275 276 277 278 279
  gchar *type;
  GIcon *icon;

  type = g_content_type_from_mime_type ("text/plain");
  icon = g_content_type_get_symbolic_icon (type);
280
  g_assert_true (G_IS_ICON (icon));
281 282 283 284 285
  if (G_IS_THEMED_ICON (icon))
    {
      const gchar *const *names;

      names = g_themed_icon_get_names (G_THEMED_ICON (icon));
286
#ifdef __APPLE__
287 288
      g_assert_true (g_strv_contains (names, "text-*-symbolic"));
      g_assert_true (g_strv_contains (names, "text-*"));
289
#else
290 291 292 293
      g_assert_true (g_strv_contains (names, "text-plain-symbolic"));
      g_assert_true (g_strv_contains (names, "text-x-generic-symbolic"));
      g_assert_true (g_strv_contains (names, "text-plain"));
      g_assert_true (g_strv_contains (names, "text-x-generic"));
294
#endif
295 296 297 298 299 300
    }
  g_object_unref (icon);
  g_free (type);

  type = g_content_type_from_mime_type ("application/rtf");
  icon = g_content_type_get_symbolic_icon (type);
301
  g_assert_true (G_IS_ICON (icon));
302 303 304 305 306
  if (G_IS_THEMED_ICON (icon))
    {
      const gchar *const *names;

      names = g_themed_icon_get_names (G_THEMED_ICON (icon));
307 308
      g_assert_true (g_strv_contains (names, "application-rtf-symbolic"));
      g_assert_true (g_strv_contains (names, "application-rtf"));
309
#ifndef __APPLE__
310 311
      g_assert_true (g_strv_contains (names, "x-office-document-symbolic"));
      g_assert_true (g_strv_contains (names, "x-office-document"));
312
#endif
313
    }
314 315
  g_object_unref (icon);
  g_free (type);
316
#endif
317 318
}

319 320 321 322 323 324 325 326 327 328 329 330 331
static void
test_tree (void)
{
  const gchar *tests[] = {
    "x-content/image-dcf",
    "x-content/unix-software",
    "x-content/win32-software"
  };
  const gchar *path;
  GFile *file;
  gchar **types;
  gint i;

332 333 334 335 336
#ifdef __APPLE__
  g_test_skip ("The OSX backend does not implement g_content_type_guess_for_tree()");
  return;
#endif

337 338 339 340 341 342 343 344 345 346
  for (i = 0; i < G_N_ELEMENTS (tests); i++)
    {
      path = g_test_get_filename (G_TEST_DIST, tests[i], NULL);
      file = g_file_new_for_path (path);
      types = g_content_type_guess_for_tree (file);
      g_assert_content_type_equals (types[0], tests[i]);
      g_strfreev (types);
      g_object_unref (file);
   }
}
347

348 349 350 351 352 353 354 355 356 357
static void
test_type_is_a_special_case (void)
{
  gboolean res;

  g_test_bug ("782311");

  /* Everything but the inode type is application/octet-stream */
  res = g_content_type_is_a ("inode/directory", "application/octet-stream");
  g_assert_false (res);
358
#ifndef __APPLE__
359 360
  res = g_content_type_is_a ("anything", "application/octet-stream");
  g_assert_true (res);
361
#endif
362 363
}

364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
static void
test_guess_svg_from_data (void)
{
  const gchar svgfilecontent[] = "<svg  xmlns=\"http://www.w3.org/2000/svg\"\
      xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n\
    <rect x=\"10\" y=\"10\" height=\"100\" width=\"100\"\n\
          style=\"stroke:#ff0000; fill: #0000ff\"/>\n\
</svg>\n";

  gboolean uncertain = TRUE;
  gchar *res = g_content_type_guess (NULL, (guchar *)svgfilecontent,
                                     sizeof (svgfilecontent) - 1, &uncertain);
#ifdef __APPLE__
  g_assert_cmpstr (res, ==, "public.svg-image");
#elif defined(G_OS_WIN32)
  g_test_skip ("svg type detection from content is not implemented on WIN32");
#else
  g_assert_cmpstr (res, ==, "image/svg+xml");
#endif
  g_assert_false (uncertain);
  g_free (res);
}

387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
static void
test_mime_from_content (void)
{
#ifdef __APPLE__
  gchar *mime_type;
  mime_type = g_content_type_get_mime_type ("com.microsoft.bmp");
  g_assert_cmpstr (mime_type, ==, "image/bmp");
  g_free (mime_type);
  mime_type = g_content_type_get_mime_type ("com.compuserve.gif");
  g_assert_cmpstr (mime_type, ==, "image/gif");
  g_free (mime_type);
  mime_type = g_content_type_get_mime_type ("public.png");
  g_assert_cmpstr (mime_type, ==, "image/png");
  g_free (mime_type);
  mime_type = g_content_type_get_mime_type ("public.text");
  g_assert_cmpstr (mime_type, ==, "text/*");
  g_free (mime_type);
  mime_type = g_content_type_get_mime_type ("public.svg-image");
  g_assert_cmpstr (mime_type, ==, "image/svg+xml");
  g_free (mime_type);
#elif defined(G_OS_WIN32)
  g_test_skip ("mime from content type test not implemented on WIN32");
#else
  g_test_skip ("mime from content type test not implemented on UNIX");
#endif
}

Matthias Clasen's avatar
Matthias Clasen committed
414 415 416 417 418
int
main (int argc, char *argv[])
{
  g_test_init (&argc, &argv, NULL);

419 420
  g_test_bug_base ("http://bugzilla.gnome.org/");

Matthias Clasen's avatar
Matthias Clasen committed
421
  g_test_add_func ("/contenttype/guess", test_guess);
422
  g_test_add_func ("/contenttype/guess_svg_from_data", test_guess_svg_from_data);
423
  g_test_add_func ("/contenttype/mime_from_content", test_mime_from_content);
Matthias Clasen's avatar
Matthias Clasen committed
424 425 426 427
  g_test_add_func ("/contenttype/unknown", test_unknown);
  g_test_add_func ("/contenttype/subtype", test_subtype);
  g_test_add_func ("/contenttype/list", test_list);
  g_test_add_func ("/contenttype/executable", test_executable);
Matthias Clasen's avatar
Matthias Clasen committed
428
  g_test_add_func ("/contenttype/description", test_description);
429
  g_test_add_func ("/contenttype/icon", test_icon);
430
  g_test_add_func ("/contenttype/symbolic-icon", test_symbolic_icon);
431
  g_test_add_func ("/contenttype/tree", test_tree);
432 433
  g_test_add_func ("/contenttype/test_type_is_a_special_case",
                   test_type_is_a_special_case);
Matthias Clasen's avatar
Matthias Clasen committed
434 435 436

  return g_test_run ();
}