1#include <glib.h>
2
3#include "glib-private.h"
4
5static void
6test_overwrite (void)
7{
8 GError *error, *dest, *src;
9
10 if (!g_test_undefined ())
11 return;
12
13 error = g_error_new_literal (G_MARKUP_ERROR, code: G_MARKUP_ERROR_EMPTY, message: "bla");
14
15 g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_WARNING,
16 pattern: "*set over the top*");
17 g_set_error_literal (err: &error, G_MARKUP_ERROR, code: G_MARKUP_ERROR_PARSE, message: "bla");
18 g_test_assert_expected_messages ();
19
20 g_assert_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_EMPTY);
21 g_error_free (error);
22
23
24 error = g_error_new_literal (G_MARKUP_ERROR, code: G_MARKUP_ERROR_EMPTY, message: "bla");
25
26 g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_WARNING,
27 pattern: "*set over the top*");
28 g_set_error (err: &error, G_MARKUP_ERROR, code: G_MARKUP_ERROR_PARSE, format: "bla");
29 g_test_assert_expected_messages ();
30
31 g_assert_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_EMPTY);
32 g_error_free (error);
33
34
35 dest = g_error_new_literal (G_MARKUP_ERROR, code: G_MARKUP_ERROR_EMPTY, message: "bla");
36 src = g_error_new_literal (G_MARKUP_ERROR, code: G_MARKUP_ERROR_PARSE, message: "bla");
37
38 g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_WARNING,
39 pattern: "*set over the top*");
40 g_propagate_error (dest: &dest, src);
41 g_test_assert_expected_messages ();
42
43 g_assert_error (dest, G_MARKUP_ERROR, G_MARKUP_ERROR_EMPTY);
44 g_error_free (error: dest);
45}
46
47static void
48test_prefix (void)
49{
50 GError *error;
51 GError *dest, *src;
52
53 error = NULL;
54 g_prefix_error (err: &error, format: "foo %d %s: ", 1, "two");
55 g_assert (error == NULL);
56
57 error = g_error_new_literal (G_MARKUP_ERROR, code: G_MARKUP_ERROR_EMPTY, message: "bla");
58 g_prefix_error (err: &error, format: "foo %d %s: ", 1, "two");
59 g_assert_cmpstr (error->message, ==, "foo 1 two: bla");
60 g_error_free (error);
61
62 dest = NULL;
63 src = g_error_new_literal (G_MARKUP_ERROR, code: G_MARKUP_ERROR_EMPTY, message: "bla");
64 g_propagate_prefixed_error (dest: &dest, src, format: "foo %d %s: ", 1, "two");
65 g_assert_cmpstr (dest->message, ==, "foo 1 two: bla");
66 g_error_free (error: dest);
67
68 src = g_error_new_literal (G_MARKUP_ERROR, code: G_MARKUP_ERROR_EMPTY, message: "bla");
69 g_propagate_prefixed_error (NULL, src, format: "foo %d %s: ", 1, "two");
70}
71
72static void
73test_literal (void)
74{
75 GError *error;
76
77 error = NULL;
78 g_set_error_literal (err: &error, G_MARKUP_ERROR, code: G_MARKUP_ERROR_EMPTY, message: "%s %d %x");
79 g_assert_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_EMPTY);
80 g_assert_cmpstr (error->message, ==, "%s %d %x");
81 g_error_free (error);
82}
83
84static void
85test_copy (void)
86{
87 GError *error;
88 GError *copy;
89
90 error = NULL;
91 g_set_error_literal (err: &error, G_MARKUP_ERROR, code: G_MARKUP_ERROR_EMPTY, message: "%s %d %x");
92 copy = g_error_copy (error);
93
94 g_assert_error (copy, G_MARKUP_ERROR, G_MARKUP_ERROR_EMPTY);
95 g_assert_cmpstr (copy->message, ==, "%s %d %x");
96
97 g_error_free (error);
98 g_error_free (error: copy);
99}
100
101static void
102test_new_valist_invalid_va (gpointer dummy,
103 ...)
104{
105#ifdef __linux__
106 /* Only worth testing this on Linux; if other platforms regress on this legacy
107 * behaviour, we don’t care. In particular, calling g_error_new_valist() with
108 * a %NULL format will crash on FreeBSD as its implementation of vasprintf()
109 * is less forgiving than Linux’s. That’s fine: it’s a programmer error in
110 * either case. */
111 const struct
112 {
113 GQuark domain;
114 const gchar *format;
115 }
116 tests[] =
117 {
118 { G_MARKUP_ERROR, NULL },
119 { 0, "Message" },
120 };
121 gsize i;
122
123 g_test_summary (summary: "Test that g_error_new_valist() rejects invalid input");
124
125 if (!g_test_undefined ())
126 {
127 g_test_skip (msg: "Not testing response to programmer error");
128 return;
129 }
130
131 for (i = 0; i < G_N_ELEMENTS (tests); i++)
132 {
133 GError *error = NULL, *error_copy = NULL;
134 va_list ap;
135
136 g_test_message (format: "Test %" G_GSIZE_FORMAT, i);
137
138 va_start (ap, dummy);
139
140#pragma GCC diagnostic push
141#pragma GCC diagnostic ignored "-Wformat-nonliteral"
142
143 g_test_expect_message (G_LOG_DOMAIN,
144 log_level: G_LOG_LEVEL_WARNING,
145 pattern: "*g_error_new_valist: runtime check failed*");
146 error = g_error_new_valist (domain: tests[i].domain, code: G_MARKUP_ERROR_EMPTY, format: tests[i].format, args: ap);
147 g_test_assert_expected_messages ();
148 g_assert_nonnull (error);
149
150#pragma GCC diagnostic pop
151
152 g_test_expect_message (G_LOG_DOMAIN,
153 log_level: G_LOG_LEVEL_WARNING,
154 pattern: "*g_error_copy: runtime check failed*");
155 error_copy = g_error_copy (error);
156 g_test_assert_expected_messages ();
157 g_assert_nonnull (error_copy);
158
159 g_clear_error (err: &error);
160 g_clear_error (err: &error_copy);
161
162 va_end (ap);
163 }
164#else /* if !__linux__ */
165 g_test_skip ("g_error_new_valist() programmer error handling is only relevant on Linux");
166#endif /* !__linux__ */
167}
168
169static void
170test_new_valist_invalid (void)
171{
172 /* We need a wrapper function so we can build a va_list */
173 test_new_valist_invalid_va (NULL);
174}
175
176static void
177test_matches (void)
178{
179 GError *error = NULL;
180
181 g_test_summary (summary: "Test g_error_matches()");
182
183 error = g_error_new (G_MARKUP_ERROR, code: G_MARKUP_ERROR_EMPTY, format: "Oh no!");
184
185 g_assert_true (g_error_matches (error, G_MARKUP_ERROR, G_MARKUP_ERROR_EMPTY));
186 g_assert_false (g_error_matches (NULL, G_MARKUP_ERROR, G_MARKUP_ERROR_EMPTY));
187 g_assert_false (g_error_matches (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE)); /* same numeric value as G_MARKUP_ERROR_EMPTY */
188 g_assert_false (g_error_matches (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED)); /* different numeric value from G_MARKUP_ERROR_EMPTY */
189 g_assert_false (g_error_matches (error, G_MARKUP_ERROR, G_MARKUP_ERROR_BAD_UTF8));
190
191 g_error_free (error);
192}
193
194static void
195test_clear (void)
196{
197 GError *error = NULL;
198
199 g_test_summary (summary: "Test g_error_clear()");
200
201 g_clear_error (err: &error);
202 g_assert_null (error);
203
204 g_clear_error (NULL);
205
206 error = g_error_new (G_MARKUP_ERROR, code: G_MARKUP_ERROR_EMPTY, format: "Oh no!");
207 g_clear_error (err: &error);
208 g_assert_null (error);
209}
210
211typedef struct
212{
213 int init_called;
214 int copy_called;
215 int free_called;
216} TestErrorCheck;
217
218static TestErrorCheck *init_check;
219
220GQuark test_error_quark (void);
221#define TEST_ERROR (test_error_quark ())
222
223typedef struct
224{
225 int foo;
226 TestErrorCheck *check;
227} TestErrorPrivate;
228
229static void
230test_error_private_init (TestErrorPrivate *priv)
231{
232 priv->foo = 13;
233 /* If that triggers, it's test bug.
234 */
235 g_assert_nonnull (init_check);
236 /* Using global init_check, because error->check is still nil at
237 * this point.
238 */
239 init_check->init_called++;
240}
241
242static void
243test_error_private_copy (const TestErrorPrivate *src_priv,
244 TestErrorPrivate *dest_priv)
245{
246 dest_priv->foo = src_priv->foo;
247 dest_priv->check = src_priv->check;
248
249 dest_priv->check->copy_called++;
250}
251
252static void
253test_error_private_clear (TestErrorPrivate *priv)
254{
255 priv->check->free_called++;
256}
257
258G_DEFINE_EXTENDED_ERROR (TestError, test_error)
259
260static TestErrorPrivate *
261fill_test_error (GError *error, TestErrorCheck *check)
262{
263 TestErrorPrivate *test_error = test_error_get_private (error);
264
265 test_error->check = check;
266
267 return test_error;
268}
269
270static void
271test_extended (void)
272{
273 TestErrorCheck check = { 0, 0, 0 };
274 GError *error;
275 TestErrorPrivate *test_priv;
276 GError *copy_error;
277 TestErrorPrivate *copy_test_priv;
278
279 init_check = &check;
280 error = g_error_new_literal (TEST_ERROR, code: 0, message: "foo");
281 test_priv = fill_test_error (error, check: &check);
282
283 g_assert_cmpint (check.init_called, ==, 1);
284 g_assert_cmpint (check.copy_called, ==, 0);
285 g_assert_cmpint (check.free_called, ==, 0);
286
287 g_assert_cmpuint (error->domain, ==, TEST_ERROR);
288 g_assert_cmpint (test_priv->foo, ==, 13);
289
290 copy_error = g_error_copy (error);
291 g_assert_cmpint (check.init_called, ==, 2);
292 g_assert_cmpint (check.copy_called, ==, 1);
293 g_assert_cmpint (check.free_called, ==, 0);
294
295 g_assert_cmpuint (error->domain, ==, copy_error->domain);
296 g_assert_cmpint (error->code, ==, copy_error->code);
297 g_assert_cmpstr (error->message, ==, copy_error->message);
298
299 copy_test_priv = test_error_get_private (error: copy_error);
300 g_assert_cmpint (test_priv->foo, ==, copy_test_priv->foo);
301
302 g_error_free (error);
303 g_error_free (error: copy_error);
304
305 g_assert_cmpint (check.init_called, ==, 2);
306 g_assert_cmpint (check.copy_called, ==, 1);
307 g_assert_cmpint (check.free_called, ==, 2);
308}
309
310static void
311test_extended_duplicate (void)
312{
313 g_test_summary (summary: "Test that registering a duplicate extended error domain doesn’t work");
314
315 if (!g_test_subprocess ())
316 {
317 /* Spawn a subprocess and expect it to fail. */
318 g_test_trap_subprocess (NULL, usec_timeout: 0, test_flags: 0);
319 g_test_trap_assert_failed ();
320 g_test_trap_assert_stderr ("*CRITICAL*Attempted to register an extended error domain for TestError more than once*");
321 }
322 else
323 {
324 GQuark q;
325 guint i;
326
327 for (i = 0; i < 2; i++)
328 {
329 q = g_error_domain_register_static (error_type_name: "TestError",
330 error_type_private_size: sizeof (TestErrorPrivate),
331 error_type_init: g_error_with_test_error_private_init,
332 error_type_copy: g_error_with_test_error_private_copy,
333 error_type_clear: g_error_with_test_error_private_clear);
334 g_assert_cmpstr (g_quark_to_string (q), ==, "TestError");
335 }
336 }
337}
338
339typedef struct
340{
341 int dummy;
342} TestErrorNonStaticPrivate;
343
344static void test_error_non_static_private_init (GError *error) {}
345static void test_error_non_static_private_copy (const GError *src_error, GError *dest_error) {}
346static void test_error_non_static_private_clear (GError *error) {}
347
348static void
349test_extended_non_static (void)
350{
351 gchar *domain_name = g_strdup (str: "TestErrorNonStatic");
352 GQuark q;
353 GError *error = NULL;
354
355 g_test_summary (summary: "Test registering an extended error domain with a non-static name");
356
357 q = g_error_domain_register (error_type_name: domain_name,
358 error_type_private_size: sizeof (TestErrorNonStaticPrivate),
359 error_type_init: test_error_non_static_private_init,
360 error_type_copy: test_error_non_static_private_copy,
361 error_type_clear: test_error_non_static_private_clear);
362 g_free (mem: domain_name);
363
364 error = g_error_new (domain: q, code: 0, format: "Test error: %s", "hello");
365 g_assert_true (g_error_matches (error, q, 0));
366 g_assert_cmpstr (g_quark_to_string (q), ==, "TestErrorNonStatic");
367 g_error_free (error);
368}
369
370int
371main (int argc, char *argv[])
372{
373 g_test_init (argc: &argc, argv: &argv, NULL);
374
375 g_test_add_func (testpath: "/error/overwrite", test_func: test_overwrite);
376 g_test_add_func (testpath: "/error/prefix", test_func: test_prefix);
377 g_test_add_func (testpath: "/error/literal", test_func: test_literal);
378 g_test_add_func (testpath: "/error/copy", test_func: test_copy);
379 g_test_add_func (testpath: "/error/matches", test_func: test_matches);
380 g_test_add_func (testpath: "/error/clear", test_func: test_clear);
381 g_test_add_func (testpath: "/error/new-valist/invalid", test_func: test_new_valist_invalid);
382 g_test_add_func (testpath: "/error/extended", test_func: test_extended);
383 g_test_add_func (testpath: "/error/extended/duplicate", test_func: test_extended_duplicate);
384 g_test_add_func (testpath: "/error/extended/non-static", test_func: test_extended_non_static);
385
386 return g_test_run ();
387}
388

source code of gtk/subprojects/glib/glib/tests/error.c