• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = &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