(root)/
glib-2.79.0/
gio/
tests/
file-thumbnail.c
       1  /* Unit tests for GFile thumbnails
       2   * GIO - GLib Input, Output and Streaming Library
       3   *
       4   * Copyright (C) 2022 Marco Trevisan
       5   *
       6   * SPDX-License-Identifier: LGPL-2.1-or-later
       7   *
       8   * This library is free software; you can redistribute it and/or
       9   * modify it under the terms of the GNU Lesser General Public
      10   * License as published by the Free Software Foundation; either
      11   * version 2.1 of the License, or (at your option) any later version.
      12   *
      13   * This library is distributed in the hope that it will be useful,
      14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16   * Lesser General Public License for more details.
      17   *
      18   * You should have received a copy of the GNU Lesser General
      19   * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      20   *
      21   * Author: Marco Trevisan <marco.trevisan@canonical.com>
      22   */
      23  
      24  #include <gio/gio.h>
      25  
      26  #define THUMBNAIL_FAIL_SIZE "fail"
      27  
      28  #define THUMBNAILS_ATTRIBS ( \
      29    G_FILE_ATTRIBUTE_THUMBNAIL_PATH "," \
      30    G_FILE_ATTRIBUTE_THUMBNAILING_FAILED "," \
      31    G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID "," \
      32    G_FILE_ATTRIBUTE_THUMBNAIL_PATH_NORMAL "," \
      33    G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_NORMAL "," \
      34    G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_NORMAL "," \
      35    G_FILE_ATTRIBUTE_THUMBNAIL_PATH_LARGE "," \
      36    G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_LARGE "," \
      37    G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_LARGE "," \
      38    G_FILE_ATTRIBUTE_THUMBNAIL_PATH_XLARGE "," \
      39    G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_XLARGE "," \
      40    G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XLARGE "," \
      41    G_FILE_ATTRIBUTE_THUMBNAIL_PATH_XXLARGE "," \
      42    G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_XXLARGE "," \
      43    G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XXLARGE "," \
      44  )
      45  
      46  /* Must be kept in order, for priority */
      47  static const char * SIZES_NAMES[] = {
      48    "normal",
      49    "large",
      50    "x-large",
      51    "xx-large",
      52  };
      53  
      54  static GFile *
      55  get_thumbnail_src_file (const gchar *name)
      56  {
      57    const gchar *thumbnail_path;
      58    thumbnail_path = g_test_get_filename (G_TEST_DIST, "thumbnails",
      59                                          name, NULL);
      60  
      61    g_assert_true (g_file_test (thumbnail_path, G_FILE_TEST_IS_REGULAR));
      62  
      63    return g_file_new_for_path (thumbnail_path);
      64  }
      65  
      66  static gchar *
      67  get_thumbnail_basename (GFile *source)
      68  {
      69    GChecksum *checksum;
      70    gchar *uri = g_file_get_uri (source);
      71    gchar *basename;
      72  
      73    checksum = g_checksum_new (G_CHECKSUM_MD5);
      74    g_checksum_update (checksum, (const guchar *) uri, strlen (uri));
      75  
      76    basename = g_strconcat (g_checksum_get_string (checksum), ".png", NULL);
      77  
      78    g_checksum_free (checksum);
      79    g_free (uri);
      80  
      81    return basename;
      82  }
      83  
      84  static GFile *
      85  get_expected_thumbnail_file (GFile       *source,
      86                               const gchar *size)
      87  {
      88    GFile *file;
      89    gchar *basename;
      90  
      91    basename = get_thumbnail_basename (source);
      92    file = g_file_new_build_filename (g_get_user_cache_dir (),
      93                                      "thumbnails",
      94                                      size,
      95                                      basename,
      96                                      NULL);
      97    g_free (basename);
      98    return file;
      99  }
     100  
     101  static GFile *
     102  get_failed_thumbnail_file (GFile *source)
     103  {
     104    GFile *file;
     105    gchar *basename;
     106  
     107    basename = get_thumbnail_basename (source);
     108    file = g_file_new_build_filename (g_get_user_cache_dir (),
     109                                      "thumbnails", THUMBNAIL_FAIL_SIZE,
     110                                      "gnome-thumbnail-factory",
     111                                      basename,
     112                                      NULL);
     113    g_free (basename);
     114    return file;
     115  }
     116  
     117  static gboolean
     118  check_thumbnail_exists (GFile       *source,
     119                           const gchar *size)
     120  {
     121    GFile *thumbnail;
     122    gboolean ret;
     123  
     124    thumbnail = get_expected_thumbnail_file (source, size);
     125    g_assert_nonnull (thumbnail);
     126  
     127    ret = g_file_query_exists (thumbnail, NULL);
     128    g_clear_object (&thumbnail);
     129  
     130    return ret;
     131  }
     132  
     133  static gboolean
     134  check_failed_thumbnail_exists (GFile *source)
     135  {
     136    GFile *thumbnail;
     137    gboolean ret;
     138  
     139    thumbnail = get_failed_thumbnail_file (source);
     140    g_assert_nonnull (thumbnail);
     141  
     142    ret = g_file_query_exists (thumbnail, NULL);
     143    g_clear_object (&thumbnail);
     144  
     145    return ret;
     146  }
     147  
     148  static GFile *
     149  create_thumbnail (GFile       *source,
     150                    const gchar *size)
     151  {
     152    GFile *thumbnail;
     153    GFile *thumbnail_dir;
     154    GError *error = NULL;
     155    gchar *thumbnail_path;
     156  
     157    /* TODO: This is just a stub implementation to create a fake thumbnail file
     158     * We should implement a real thumbnail generator, but we don't care here.
     159     */
     160  
     161    if (!size || g_strcmp0 (size, THUMBNAIL_FAIL_SIZE) == 0)
     162      thumbnail = get_failed_thumbnail_file (source);
     163    else
     164      thumbnail = get_expected_thumbnail_file (source, size);
     165  
     166    thumbnail_dir = g_file_get_parent (thumbnail);
     167  
     168    if (!g_file_query_exists (thumbnail_dir, NULL))
     169      {
     170        g_file_make_directory_with_parents (thumbnail_dir, NULL, &error);
     171        g_assert_no_error (error);
     172        g_clear_error (&error);
     173      }
     174  
     175    g_file_copy (source, thumbnail, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error);
     176    g_assert_no_error (error);
     177  
     178    g_assert_true (g_file_query_exists (thumbnail, NULL));
     179    thumbnail_path = g_file_get_path (thumbnail);
     180    g_test_message ("Created test thumbnail at %s", thumbnail_path);
     181  
     182    g_clear_object (&thumbnail_dir);
     183    g_clear_error (&error);
     184    g_free (thumbnail_path);
     185  
     186    return thumbnail;
     187  }
     188  
     189  static GFile *
     190  create_thumbnail_from_test_file (const gchar  *source_name,
     191                                   const gchar  *size,
     192                                   GFile       **out_source)
     193  {
     194    GFile *thumbnail;
     195    GFile *source = get_thumbnail_src_file (source_name);
     196  
     197    thumbnail = create_thumbnail (source, size);
     198  
     199    if (!size || g_strcmp0 (size, THUMBNAIL_FAIL_SIZE) == 0)
     200      {
     201        g_assert_true (check_failed_thumbnail_exists (source));
     202      }
     203    else
     204      {
     205        g_assert_false (check_failed_thumbnail_exists (source));
     206        g_assert_true (check_thumbnail_exists (source, size));
     207      }
     208  
     209    if (out_source)
     210      *out_source = g_steal_pointer (&source);
     211  
     212    g_clear_object (&source);
     213  
     214    return thumbnail;
     215  }
     216  
     217  static gboolean
     218  get_size_attributes (const char   *size,
     219                       const gchar **path,
     220                       const gchar **is_valid,
     221                       const gchar **failed)
     222  {
     223    if (g_str_equal (size, "normal"))
     224      {
     225        *path = G_FILE_ATTRIBUTE_THUMBNAIL_PATH_NORMAL;
     226        *is_valid = G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_NORMAL;
     227        *failed = G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_NORMAL;
     228        return TRUE;
     229      }
     230    else if (g_str_equal (size, "large"))
     231      {
     232        *path = G_FILE_ATTRIBUTE_THUMBNAIL_PATH_LARGE;
     233        *is_valid = G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_LARGE;
     234        *failed = G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_LARGE;
     235        return TRUE;
     236      }
     237    else if (g_str_equal (size, "x-large"))
     238      {
     239        *path = G_FILE_ATTRIBUTE_THUMBNAIL_PATH_XLARGE;
     240        *is_valid = G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XLARGE;
     241        *failed = G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_XLARGE;
     242        return TRUE;
     243      }
     244    else if (g_str_equal (size, "xx-large"))
     245      {
     246        *path = G_FILE_ATTRIBUTE_THUMBNAIL_PATH_XXLARGE;
     247        *is_valid = G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XXLARGE;
     248        *failed = G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_XXLARGE;
     249        return TRUE;
     250      }
     251  
     252    *path = NULL;
     253    *is_valid = NULL;
     254    *failed = NULL;
     255  
     256    return FALSE;
     257  }
     258  
     259  static void
     260  test_valid_thumbnail_size (gconstpointer data)
     261  {
     262    GFile *source;
     263    GFile *thumbnail;
     264    GFile *f;
     265    GError *error = NULL;
     266    GFileInfo *info;
     267    const gchar *size = data;
     268    const gchar *path_attr, *failed_attr, *is_valid_attr;
     269  
     270    thumbnail = create_thumbnail_from_test_file ("valid.png", size, &source);
     271    info = g_file_query_info (source, THUMBNAILS_ATTRIBS, G_FILE_QUERY_INFO_NONE,
     272                              NULL, &error);
     273    g_assert_no_error (error);
     274  
     275    g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH));
     276    g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID));
     277    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED));
     278  
     279    f = g_file_new_for_path (g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH));
     280    g_assert_cmpstr (
     281      g_file_peek_path (f),
     282      ==,
     283      g_file_peek_path (thumbnail)
     284    );
     285    g_clear_object (&f);
     286  
     287    /* TODO: We can't really test this without having a proper thumbnail created
     288    g_assert_true (
     289       g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID));
     290    */
     291  
     292    g_assert_true (get_size_attributes (size, &path_attr, &is_valid_attr, &failed_attr));
     293  
     294    g_assert_true (g_file_info_has_attribute (info, path_attr));
     295    g_assert_true (g_file_info_has_attribute (info, is_valid_attr));
     296    g_assert_false (g_file_info_has_attribute (info, failed_attr));
     297  
     298    f = g_file_new_for_path (g_file_info_get_attribute_byte_string (info, path_attr));
     299    g_assert_cmpstr (
     300      g_file_info_get_attribute_byte_string (info, path_attr),
     301      ==,
     302      g_file_peek_path (thumbnail)
     303    );
     304    g_clear_object (&f);
     305  
     306    /* TODO: We can't really test this without having a proper thumbnail created
     307    g_assert_true (g_file_info_get_attribute_boolean (info, is_valid_attr));
     308    */
     309  
     310    g_clear_object (&source);
     311    g_clear_object (&thumbnail);
     312    g_clear_error (&error);
     313    g_clear_object (&info);
     314    g_clear_object (&f);
     315  }
     316  
     317  static void
     318  test_unknown_thumbnail_size (gconstpointer data)
     319  {
     320    GFile *source;
     321    GFile *thumbnail;
     322    GError *error = NULL;
     323    GFileInfo *info;
     324    const gchar *size = data;
     325  
     326    thumbnail = create_thumbnail_from_test_file ("valid.png", size, &source);
     327    info = g_file_query_info (source, THUMBNAILS_ATTRIBS, G_FILE_QUERY_INFO_NONE,
     328                              NULL, &error);
     329    g_assert_no_error (error);
     330  
     331    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH));
     332    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID));
     333    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED));
     334  
     335    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH_NORMAL));
     336    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_NORMAL));
     337    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_NORMAL));
     338  
     339    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH_LARGE));
     340    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_LARGE));
     341    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_LARGE));
     342  
     343    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH_XLARGE));
     344    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XLARGE));
     345    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED_XLARGE));
     346  
     347    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH_XXLARGE));
     348    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XXLARGE));
     349    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID_XXLARGE));
     350  
     351    g_clear_object (&source);
     352    g_clear_object (&thumbnail);
     353    g_clear_error (&error);
     354    g_clear_object (&info);
     355  }
     356  
     357  static void
     358  test_failed_thumbnail (void)
     359  {
     360    GFile *source;
     361    GFile *thumbnail;
     362    GError *error = NULL;
     363    GFileInfo *info;
     364  
     365    thumbnail = create_thumbnail_from_test_file ("valid.png", NULL, &source);
     366    info = g_file_query_info (source, THUMBNAILS_ATTRIBS, G_FILE_QUERY_INFO_NONE,
     367                              NULL, &error);
     368    g_assert_no_error (error);
     369  
     370    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH));
     371    g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID));
     372    g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED));
     373  
     374    g_assert_false (
     375       g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID));
     376    g_assert_true (
     377       g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED));
     378  
     379    g_clear_object (&source);
     380    g_clear_object (&thumbnail);
     381    g_clear_error (&error);
     382    g_clear_object (&info);
     383  }
     384  
     385  static void
     386  test_thumbnails_size_priority (void)
     387  {
     388    GPtrArray *sized_thumbnails;
     389    GError *error = NULL;
     390    GFileInfo *info;
     391    GFile *source;
     392    GFile *failed_thumbnail;
     393    gsize i;
     394  
     395    failed_thumbnail = create_thumbnail_from_test_file ("valid.png", NULL, &source);
     396    sized_thumbnails = g_ptr_array_new_with_free_func (g_object_unref);
     397  
     398    /* Checking that each thumbnail with higher priority override the previous */
     399    for (i = 0; i < G_N_ELEMENTS (SIZES_NAMES); i++)
     400      {
     401        GFile *thumbnail = create_thumbnail (source, SIZES_NAMES[i]);
     402        const gchar *path_attr, *failed_attr, *is_valid_attr;
     403        GFile *f;
     404  
     405        g_ptr_array_add (sized_thumbnails, thumbnail);
     406  
     407        info = g_file_query_info (source, THUMBNAILS_ATTRIBS,
     408                                 G_FILE_QUERY_INFO_NONE, NULL, &error);
     409        g_assert_no_error (error);
     410  
     411        g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH));
     412        g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID));
     413        g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED));
     414  
     415        f = g_file_new_for_path (g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH));
     416        g_assert_cmpstr (
     417          g_file_peek_path (f),
     418          ==,
     419          g_file_peek_path (thumbnail)
     420        );
     421        g_clear_object (&f);
     422  
     423        g_assert_true (get_size_attributes (SIZES_NAMES[i],
     424                       &path_attr, &is_valid_attr, &failed_attr));
     425  
     426        g_assert_true (g_file_info_has_attribute (info, path_attr));
     427        g_assert_true (g_file_info_has_attribute (info, is_valid_attr));
     428        g_assert_false (g_file_info_has_attribute (info, failed_attr));
     429  
     430        f = g_file_new_for_path (g_file_info_get_attribute_byte_string (info, path_attr));
     431        g_assert_cmpstr (
     432          g_file_peek_path (f),
     433          ==,
     434          g_file_peek_path (thumbnail)
     435        );
     436  
     437        g_clear_object (&info);
     438        g_clear_object (&f);
     439      }
     440  
     441    g_assert_cmpuint (sized_thumbnails->len, ==, G_N_ELEMENTS (SIZES_NAMES));
     442  
     443    /* Ensuring we can access to all the thumbnails by explicit size request */
     444    for (i = 0; i < G_N_ELEMENTS (SIZES_NAMES); i++)
     445      {
     446        GFile *thumbnail = g_ptr_array_index (sized_thumbnails, i);
     447        const gchar *path_attr, *failed_attr, *is_valid_attr;
     448        GFile *f;
     449  
     450        info = g_file_query_info (source, THUMBNAILS_ATTRIBS,
     451                                  G_FILE_QUERY_INFO_NONE, NULL, &error);
     452        g_assert_no_error (error);
     453  
     454        g_assert_true (get_size_attributes (SIZES_NAMES[i],
     455                       &path_attr, &is_valid_attr, &failed_attr));
     456  
     457        g_assert_true (g_file_info_has_attribute (info, path_attr));
     458        g_assert_true (g_file_info_has_attribute (info, is_valid_attr));
     459        g_assert_false (g_file_info_has_attribute (info, failed_attr));
     460  
     461        f = g_file_new_for_path (g_file_info_get_attribute_byte_string (info, path_attr));
     462        g_assert_cmpstr (
     463          g_file_peek_path (f),
     464          ==,
     465          g_file_peek_path (thumbnail)
     466        );
     467        g_clear_object (&f);
     468  
     469        g_clear_object (&info);
     470      }
     471  
     472    /* Now removing them in the inverse order, to check this again */
     473    for (i = G_N_ELEMENTS (SIZES_NAMES); i > 1; i--)
     474      {
     475        GFile *thumbnail = g_ptr_array_index (sized_thumbnails, i - 1);
     476        GFile *less_priority_thumbnail = g_ptr_array_index (sized_thumbnails, i - 2);
     477        const gchar *path_attr, *failed_attr, *is_valid_attr;
     478        GFile *f;
     479  
     480        g_file_delete (thumbnail, NULL, &error);
     481        g_assert_no_error (error);
     482  
     483        info = g_file_query_info (source, THUMBNAILS_ATTRIBS,
     484                                  G_FILE_QUERY_INFO_NONE, NULL, &error);
     485        g_assert_no_error (error);
     486  
     487        g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH));
     488        g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID));
     489        g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED));
     490  
     491        f = g_file_new_for_path (g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH));
     492        g_assert_cmpstr (
     493          g_file_peek_path (f),
     494          ==,
     495          g_file_peek_path (less_priority_thumbnail)
     496        );
     497        g_clear_object (&f);
     498  
     499        g_assert_true (get_size_attributes (SIZES_NAMES[i-2],
     500                       &path_attr, &is_valid_attr, &failed_attr));
     501  
     502        g_assert_true (g_file_info_has_attribute (info, path_attr));
     503        g_assert_true (g_file_info_has_attribute (info, is_valid_attr));
     504        g_assert_false (g_file_info_has_attribute (info, failed_attr));
     505  
     506        f = g_file_new_for_path (g_file_info_get_attribute_byte_string (info, path_attr));
     507        g_assert_cmpstr (
     508          g_file_peek_path (f),
     509          ==,
     510          g_file_peek_path (less_priority_thumbnail)
     511        );
     512  
     513        g_clear_object (&info);
     514        g_clear_object (&f);
     515      }
     516  
     517    /* And now let's remove the last valid one, so that failed should have priority */
     518    g_file_delete (G_FILE (g_ptr_array_index (sized_thumbnails, 0)), NULL, &error);
     519    g_assert_no_error (error);
     520  
     521    info = g_file_query_info (source, THUMBNAILS_ATTRIBS, G_FILE_QUERY_INFO_NONE,
     522                              NULL, &error);
     523    g_assert_no_error (error);
     524  
     525    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH));
     526    g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID));
     527    g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED));
     528  
     529    g_assert_false (
     530       g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID));
     531    g_assert_true (
     532       g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED));
     533  
     534    g_clear_object (&info);
     535  
     536    /* And check if we get the failed state for all explicit requests */
     537    for (i = 0; i < G_N_ELEMENTS (SIZES_NAMES); i++)
     538      {
     539        const gchar *path_attr, *failed_attr, *is_valid_attr;
     540  
     541        info = g_file_query_info (source, THUMBNAILS_ATTRIBS,
     542                                  G_FILE_QUERY_INFO_NONE, NULL, &error);
     543        g_assert_no_error (error);
     544  
     545        g_assert_true (get_size_attributes (SIZES_NAMES[i],
     546                       &path_attr, &is_valid_attr, &failed_attr));
     547  
     548        g_assert_false (g_file_info_has_attribute (info, path_attr));
     549        g_assert_true (g_file_info_has_attribute (info, is_valid_attr));
     550        g_assert_true (g_file_info_has_attribute (info, failed_attr));
     551  
     552        g_assert_false (g_file_info_get_attribute_boolean (info, is_valid_attr));
     553        g_assert_true (g_file_info_get_attribute_boolean (info, failed_attr));
     554  
     555        g_clear_object (&info);
     556      }
     557  
     558    /* Removing the failed thumbnail too, so no thumbnail should be available */
     559    g_file_delete (failed_thumbnail, NULL, &error);
     560    g_assert_no_error (error);
     561  
     562    info = g_file_query_info (source, THUMBNAILS_ATTRIBS, G_FILE_QUERY_INFO_NONE,
     563                              NULL, &error);
     564    g_assert_no_error (error);
     565  
     566    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH));
     567    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID));
     568    g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED));
     569  
     570    g_clear_object (&info);
     571  
     572    for (i = 0; i < G_N_ELEMENTS (SIZES_NAMES); i++)
     573      {
     574        const gchar *path_attr, *failed_attr, *is_valid_attr;
     575  
     576        info = g_file_query_info (source, THUMBNAILS_ATTRIBS,
     577                                  G_FILE_QUERY_INFO_NONE, NULL, &error);
     578        g_assert_no_error (error);
     579  
     580        g_assert_true (get_size_attributes (SIZES_NAMES[i],
     581                       &path_attr, &is_valid_attr, &failed_attr));
     582  
     583        g_assert_false (g_file_info_has_attribute (info, path_attr));
     584        g_assert_false (g_file_info_has_attribute (info, is_valid_attr));
     585        g_assert_false (g_file_info_has_attribute (info, failed_attr));
     586  
     587        g_clear_object (&info);
     588      }
     589  
     590    g_clear_object (&source);
     591    g_clear_pointer (&sized_thumbnails, g_ptr_array_unref);
     592    g_clear_object (&failed_thumbnail);
     593    g_clear_error (&error);
     594    g_clear_object (&info);
     595  }
     596  
     597  
     598  int
     599  main (int   argc,
     600        char *argv[])
     601  {
     602    gsize i;
     603  
     604    g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
     605  
     606    for (i = 0; i < G_N_ELEMENTS (SIZES_NAMES); i++)
     607      {
     608        gchar *test_path;
     609  
     610        test_path = g_strconcat ("/file-thumbnail/valid/", SIZES_NAMES[i], NULL);
     611        g_test_add_data_func (test_path, SIZES_NAMES[i], test_valid_thumbnail_size);
     612        g_free (test_path);
     613      }
     614  
     615    g_test_add_data_func ("/file-thumbnail/unknown/super-large", "super-large", test_unknown_thumbnail_size);
     616    g_test_add_func ("/file-thumbnail/fail", test_failed_thumbnail);
     617    g_test_add_func ("/file-thumbnail/size-priority", test_thumbnails_size_priority);
     618  
     619    return g_test_run ();
     620  }