(root)/
glib-2.79.0/
gio/
tests/
gdbus-error.c
       1  /* GLib testing framework examples and tests
       2   *
       3   * Copyright (C) 2008-2010 Red Hat, Inc.
       4   *
       5   * SPDX-License-Identifier: LGPL-2.1-or-later
       6   *
       7   * This library is free software; you can redistribute it and/or
       8   * modify it under the terms of the GNU Lesser General Public
       9   * License as published by the Free Software Foundation; either
      10   * version 2.1 of the License, or (at your option) any later version.
      11   *
      12   * This library is distributed in the hope that it will be useful,
      13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15   * Lesser General Public License for more details.
      16   *
      17   * You should have received a copy of the GNU Lesser General
      18   * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      19   *
      20   * Author: David Zeuthen <davidz@redhat.com>
      21   */
      22  
      23  #include <gio/gio.h>
      24  #include <unistd.h>
      25  #include <string.h>
      26  
      27  /* ---------------------------------------------------------------------------------------------------- */
      28  /* Test that registered errors are properly mapped */
      29  /* ---------------------------------------------------------------------------------------------------- */
      30  
      31  static void
      32  check_registered_error (const gchar *given_dbus_error_name,
      33                          GQuark       error_domain,
      34                          gint         error_code)
      35  {
      36    GError *error;
      37    gchar *dbus_error_name;
      38  
      39    error = g_dbus_error_new_for_dbus_error (given_dbus_error_name, "test message");
      40    g_assert_error (error, error_domain, error_code);
      41    g_assert (g_dbus_error_is_remote_error (error));
      42    g_assert (g_dbus_error_strip_remote_error (error));
      43    g_assert_cmpstr (error->message, ==, "test message");
      44    dbus_error_name = g_dbus_error_get_remote_error (error);
      45    g_assert_cmpstr (dbus_error_name, ==, given_dbus_error_name);
      46    g_free (dbus_error_name);
      47    g_error_free (error);
      48  }
      49  
      50  static void
      51  test_registered_errors (void)
      52  {
      53    /* Here we check that we are able to map to GError and back for registered
      54     * errors.
      55     *
      56     * For example, if "org.freedesktop.DBus.Error.AddressInUse" is
      57     * associated with (G_DBUS_ERROR, G_DBUS_ERROR_DBUS_FAILED), check
      58     * that
      59     *
      60     *  - Creating a GError for e.g. "org.freedesktop.DBus.Error.AddressInUse"
      61     *    has (error_domain, code) == (G_DBUS_ERROR, G_DBUS_ERROR_DBUS_FAILED)
      62     *
      63     *  - That it is possible to recover e.g. "org.freedesktop.DBus.Error.AddressInUse"
      64     *    as the D-Bus error name when dealing with an error with (error_domain, code) ==
      65     *    (G_DBUS_ERROR, G_DBUS_ERROR_DBUS_FAILED)
      66     *
      67     * We just check a couple of well-known errors.
      68     */
      69    check_registered_error ("org.freedesktop.DBus.Error.Failed",
      70                            G_DBUS_ERROR,
      71                            G_DBUS_ERROR_FAILED);
      72    check_registered_error ("org.freedesktop.DBus.Error.AddressInUse",
      73                            G_DBUS_ERROR,
      74                            G_DBUS_ERROR_ADDRESS_IN_USE);
      75    check_registered_error ("org.freedesktop.DBus.Error.UnknownMethod",
      76                            G_DBUS_ERROR,
      77                            G_DBUS_ERROR_UNKNOWN_METHOD);
      78    check_registered_error ("org.freedesktop.DBus.Error.UnknownObject",
      79                            G_DBUS_ERROR,
      80                            G_DBUS_ERROR_UNKNOWN_OBJECT);
      81  }
      82  
      83  /* ---------------------------------------------------------------------------------------------------- */
      84  
      85  static void
      86  check_unregistered_error (const gchar *given_dbus_error_name)
      87  {
      88    GError *error;
      89    gchar *dbus_error_name;
      90  
      91    error = g_dbus_error_new_for_dbus_error (given_dbus_error_name, "test message");
      92    g_assert_error (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR);
      93    g_assert (g_dbus_error_is_remote_error (error));
      94    dbus_error_name = g_dbus_error_get_remote_error (error);
      95    g_assert_cmpstr (dbus_error_name, ==, given_dbus_error_name);
      96    g_free (dbus_error_name);
      97  
      98    /* strip the message */
      99    g_assert (g_dbus_error_strip_remote_error (error));
     100    g_assert_cmpstr (error->message, ==, "test message");
     101  
     102    /* check that we can no longer recover the D-Bus error name */
     103    g_assert (g_dbus_error_get_remote_error (error) == NULL);
     104  
     105    g_error_free (error);
     106  
     107  }
     108  
     109  static void
     110  test_unregistered_errors (void)
     111  {
     112    /* Here we check that we are able to map to GError and back for unregistered
     113     * errors.
     114     *
     115     * For example, if "com.example.Error.Failed" is not registered, then check
     116     *
     117     *  - Creating a GError for e.g. "com.example.Error.Failed" has (error_domain, code) ==
     118     *    (G_IO_ERROR, G_IO_ERROR_DBUS_ERROR)
     119     *
     120     *  - That it is possible to recover e.g. "com.example.Error.Failed" from that
     121     *    GError.
     122     *
     123     * We just check a couple of random errors.
     124     */
     125  
     126    check_unregistered_error ("com.example.Error.Failed");
     127    check_unregistered_error ("foobar.buh");
     128  }
     129  
     130  /* ---------------------------------------------------------------------------------------------------- */
     131  
     132  static void
     133  check_transparent_gerror (GQuark error_domain,
     134                            gint   error_code)
     135  {
     136    GError *error;
     137    gchar *given_dbus_error_name;
     138    gchar *dbus_error_name;
     139  
     140    error = g_error_new (error_domain, error_code, "test message");
     141    given_dbus_error_name = g_dbus_error_encode_gerror (error);
     142    g_assert (g_str_has_prefix (given_dbus_error_name, "org.gtk.GDBus.UnmappedGError.Quark"));
     143    g_error_free (error);
     144  
     145    error = g_dbus_error_new_for_dbus_error (given_dbus_error_name, "test message");
     146    g_assert_error (error, error_domain, error_code);
     147    g_assert (g_dbus_error_is_remote_error (error));
     148    dbus_error_name = g_dbus_error_get_remote_error (error);
     149    g_assert_cmpstr (dbus_error_name, ==, given_dbus_error_name);
     150    g_free (dbus_error_name);
     151    g_free (given_dbus_error_name);
     152  
     153    /* strip the message */
     154    g_assert (g_dbus_error_strip_remote_error (error));
     155    g_assert_cmpstr (error->message, ==, "test message");
     156  
     157    /* check that we can no longer recover the D-Bus error name */
     158    g_assert (g_dbus_error_get_remote_error (error) == NULL);
     159  
     160    g_error_free (error);
     161  }
     162  
     163  static void
     164  test_transparent_gerror (void)
     165  {
     166    /* Here we check that we are able to transparent pass unregistered GError's
     167     * over the wire.
     168     *
     169     * For example, if G_IO_ERROR_FAILED is not registered, then check
     170     *
     171     *  - g_dbus_error_encode_gerror() returns something of the form
     172     *    org.gtk.GDBus.UnmappedGError.Quark_HEXENCODED_QUARK_NAME_.Code_ERROR_CODE
     173     *
     174     *  - mapping back the D-Bus error name gives us G_IO_ERROR_FAILED
     175     *
     176     *  - That it is possible to recover the D-Bus error name from the
     177     *    GError.
     178     *
     179     * We just check a couple of random errors.
     180     */
     181  
     182    check_transparent_gerror (G_IO_ERROR, G_IO_ERROR_FAILED);
     183    check_transparent_gerror (G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE);
     184  }
     185  
     186  typedef enum
     187  {
     188    TEST_ERROR_FAILED,
     189    TEST_ERROR_BLA
     190  } TestError;
     191  
     192  GDBusErrorEntry test_error_entries[] =
     193  {
     194    { TEST_ERROR_FAILED, "org.gtk.test.Error.Failed" },
     195    { TEST_ERROR_BLA,    "org.gtk.test.Error.Bla"    }
     196  };
     197  
     198  static void
     199  test_register_error (void)
     200  {
     201    gsize test_error_quark = 0;
     202    gboolean res;
     203    gchar *msg;
     204    GError *error;
     205  
     206    g_dbus_error_register_error_domain ("test-error-quark",
     207                                        &test_error_quark,
     208                                        test_error_entries,
     209                                        G_N_ELEMENTS (test_error_entries));
     210    g_assert_cmpint (test_error_quark, !=, 0);
     211  
     212    error = g_dbus_error_new_for_dbus_error ("org.gtk.test.Error.Failed", "Failed");
     213    g_assert_error (error, test_error_quark, TEST_ERROR_FAILED);
     214    res = g_dbus_error_is_remote_error (error);
     215    msg = g_dbus_error_get_remote_error (error);
     216    g_assert (res);
     217    g_assert_cmpstr (msg, ==, "org.gtk.test.Error.Failed");
     218    res = g_dbus_error_strip_remote_error (error);
     219    g_assert (res);
     220    g_assert_cmpstr (error->message, ==, "Failed");
     221    g_clear_error (&error);
     222    g_free (msg);
     223  
     224    g_dbus_error_set_dbus_error (&error, "org.gtk.test.Error.Failed", "Failed again", "Prefix %d", 1);
     225    res = g_dbus_error_is_remote_error (error);
     226    msg = g_dbus_error_get_remote_error (error);
     227    g_assert (res);
     228    g_assert_cmpstr (msg, ==, "org.gtk.test.Error.Failed");
     229    res = g_dbus_error_strip_remote_error (error);
     230    g_assert (res);
     231    g_assert_cmpstr (error->message, ==, "Prefix 1: Failed again");
     232    g_clear_error (&error);
     233    g_free (msg);
     234  
     235    error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_NOT_EMPTY, "Not Empty");
     236    res = g_dbus_error_is_remote_error (error);
     237    msg = g_dbus_error_get_remote_error (error);
     238    g_assert (!res);
     239    g_assert_cmpstr (msg, ==, NULL);
     240    res = g_dbus_error_strip_remote_error (error);
     241    g_assert (!res);
     242    g_assert_cmpstr (error->message, ==, "Not Empty");
     243    g_clear_error (&error);
     244  
     245    error = g_error_new_literal (test_error_quark, TEST_ERROR_BLA, "Bla");
     246    msg = g_dbus_error_encode_gerror (error);
     247    g_assert_cmpstr (msg, ==, "org.gtk.test.Error.Bla");
     248    g_free (msg);
     249    g_clear_error (&error);
     250  
     251    res = g_dbus_error_unregister_error (test_error_quark,
     252                                         TEST_ERROR_BLA, "org.gtk.test.Error.Bla");
     253    g_assert (res);
     254  }
     255  
     256  
     257  /* ---------------------------------------------------------------------------------------------------- */
     258  
     259  int
     260  main (int   argc,
     261        char *argv[])
     262  {
     263    g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
     264  
     265    g_test_add_func ("/gdbus/registered-errors", test_registered_errors);
     266    g_test_add_func ("/gdbus/unregistered-errors", test_unregistered_errors);
     267    g_test_add_func ("/gdbus/transparent-gerror", test_transparent_gerror);
     268    g_test_add_func ("/gdbus/register-error", test_register_error);
     269  
     270    return g_test_run();
     271  }