gkdbus: Fix underflow and unreachable code bug
[platform/upstream/glib.git] / 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 }