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