1 #include <glib.h>
2
3 #include "glib-private.h"
4
5 static void
test_overwrite(void)6 test_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, G_MARKUP_ERROR_EMPTY, "bla");
14
15 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
16 "*set over the top*");
17 g_set_error_literal (&error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, "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, G_MARKUP_ERROR_EMPTY, "bla");
25
26 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
27 "*set over the top*");
28 g_set_error (&error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, "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, G_MARKUP_ERROR_EMPTY, "bla");
36 src = g_error_new_literal (G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, "bla");
37
38 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
39 "*set over the top*");
40 g_propagate_error (&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 (dest);
45 }
46
47 static void
test_prefix(void)48 test_prefix (void)
49 {
50 GError *error;
51 GError *dest, *src;
52
53 error = NULL;
54 g_prefix_error (&error, "foo %d %s: ", 1, "two");
55 g_assert (error == NULL);
56
57 error = g_error_new_literal (G_MARKUP_ERROR, G_MARKUP_ERROR_EMPTY, "bla");
58 g_prefix_error (&error, "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, G_MARKUP_ERROR_EMPTY, "bla");
64 g_propagate_prefixed_error (&dest, src, "foo %d %s: ", 1, "two");
65 g_assert_cmpstr (dest->message, ==, "foo 1 two: bla");
66 g_error_free (dest);
67
68 src = g_error_new_literal (G_MARKUP_ERROR, G_MARKUP_ERROR_EMPTY, "bla");
69 g_propagate_prefixed_error (NULL, src, "foo %d %s: ", 1, "two");
70 }
71
72 static void
test_literal(void)73 test_literal (void)
74 {
75 GError *error;
76
77 error = NULL;
78 g_set_error_literal (&error, G_MARKUP_ERROR, G_MARKUP_ERROR_EMPTY, "%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
84 static void
test_copy(void)85 test_copy (void)
86 {
87 GError *error;
88 GError *copy;
89
90 error = NULL;
91 g_set_error_literal (&error, G_MARKUP_ERROR, G_MARKUP_ERROR_EMPTY, "%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 (copy);
99 }
100
101 static void
test_new_valist_invalid_va(gpointer dummy,...)102 test_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 ("Test that g_error_new_valist() rejects invalid input");
124
125 if (!g_test_undefined ())
126 {
127 g_test_skip ("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 ("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 G_LOG_LEVEL_WARNING,
145 "*g_error_new_valist: runtime check failed*");
146 error = g_error_new_valist (tests[i].domain, G_MARKUP_ERROR_EMPTY, tests[i].format, 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 G_LOG_LEVEL_WARNING,
154 "*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 (&error);
160 g_clear_error (&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
169 static void
test_new_valist_invalid(void)170 test_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
176 static void
test_matches(void)177 test_matches (void)
178 {
179 GError *error = NULL;
180
181 g_test_summary ("Test g_error_matches()");
182
183 error = g_error_new (G_MARKUP_ERROR, G_MARKUP_ERROR_EMPTY, "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
194 static void
test_clear(void)195 test_clear (void)
196 {
197 GError *error = NULL;
198
199 g_test_summary ("Test g_error_clear()");
200
201 g_clear_error (&error);
202 g_assert_null (error);
203
204 g_clear_error (NULL);
205
206 error = g_error_new (G_MARKUP_ERROR, G_MARKUP_ERROR_EMPTY, "Oh no!");
207 g_clear_error (&error);
208 g_assert_null (error);
209 }
210
211 typedef struct
212 {
213 int init_called;
214 int copy_called;
215 int free_called;
216 } TestErrorCheck;
217
218 static TestErrorCheck *init_check;
219
220 GQuark test_error_quark (void);
221 #define TEST_ERROR (test_error_quark ())
222
223 typedef struct
224 {
225 int foo;
226 TestErrorCheck *check;
227 } TestErrorPrivate;
228
229 static void
test_error_private_init(TestErrorPrivate * priv)230 test_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
242 static void
test_error_private_copy(const TestErrorPrivate * src_priv,TestErrorPrivate * dest_priv)243 test_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
252 static void
test_error_private_clear(TestErrorPrivate * priv)253 test_error_private_clear (TestErrorPrivate *priv)
254 {
255 priv->check->free_called++;
256 }
257
G_DEFINE_EXTENDED_ERROR(TestError,test_error)258 G_DEFINE_EXTENDED_ERROR (TestError, test_error)
259
260 static TestErrorPrivate *
261 fill_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
270 static void
test_extended(void)271 test_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 = ✓
280 error = g_error_new_literal (TEST_ERROR, 0, "foo");
281 test_priv = fill_test_error (error, &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 (copy_error);
300 g_assert_cmpint (test_priv->foo, ==, copy_test_priv->foo);
301
302 g_error_free (error);
303 g_error_free (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
310 static void
test_extended_duplicate(void)311 test_extended_duplicate (void)
312 {
313 g_test_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, 0, 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 ("TestError",
330 sizeof (TestErrorPrivate),
331 g_error_with_test_error_private_init,
332 g_error_with_test_error_private_copy,
333 g_error_with_test_error_private_clear);
334 g_assert_cmpstr (g_quark_to_string (q), ==, "TestError");
335 }
336 }
337 }
338
339 typedef struct
340 {
341 int dummy;
342 } TestErrorNonStaticPrivate;
343
test_error_non_static_private_init(GError * error)344 static void test_error_non_static_private_init (GError *error) {}
test_error_non_static_private_copy(const GError * src_error,GError * dest_error)345 static void test_error_non_static_private_copy (const GError *src_error, GError *dest_error) {}
test_error_non_static_private_clear(GError * error)346 static void test_error_non_static_private_clear (GError *error) {}
347
348 static void
test_extended_non_static(void)349 test_extended_non_static (void)
350 {
351 gchar *domain_name = g_strdup ("TestErrorNonStatic");
352 GQuark q;
353 GError *error = NULL;
354
355 g_test_summary ("Test registering an extended error domain with a non-static name");
356
357 q = g_error_domain_register (domain_name,
358 sizeof (TestErrorNonStaticPrivate),
359 test_error_non_static_private_init,
360 test_error_non_static_private_copy,
361 test_error_non_static_private_clear);
362 g_free (domain_name);
363
364 error = g_error_new (q, 0, "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
370 int
main(int argc,char * argv[])371 main (int argc, char *argv[])
372 {
373 g_test_init (&argc, &argv, NULL);
374
375 g_test_add_func ("/error/overwrite", test_overwrite);
376 g_test_add_func ("/error/prefix", test_prefix);
377 g_test_add_func ("/error/literal", test_literal);
378 g_test_add_func ("/error/copy", test_copy);
379 g_test_add_func ("/error/matches", test_matches);
380 g_test_add_func ("/error/clear", test_clear);
381 g_test_add_func ("/error/new-valist/invalid", test_new_valist_invalid);
382 g_test_add_func ("/error/extended", test_extended);
383 g_test_add_func ("/error/extended/duplicate", test_extended_duplicate);
384 g_test_add_func ("/error/extended/non-static", test_extended_non_static);
385
386 return g_test_run ();
387 }
388