tests/protocol: redo a bit
[glib.git] / gobject / tests / reference.c
blob0742339a1ac13a477225472dadebcfc1d82ac635
1 #include <glib-object.h>
3 static void
4 test_fundamentals (void)
6 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_NONE));
7 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_INTERFACE));
8 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_CHAR));
9 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_UCHAR));
10 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_BOOLEAN));
11 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_INT));
12 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_UINT));
13 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_LONG));
14 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_ULONG));
15 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_INT64));
16 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_UINT64));
17 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_ENUM));
18 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_FLAGS));
19 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_FLOAT));
20 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_DOUBLE));
21 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_STRING));
22 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_POINTER));
23 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_BOXED));
24 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_PARAM));
25 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_OBJECT));
26 g_assert (G_TYPE_OBJECT == g_object_get_type ());
27 g_assert (G_TYPE_IS_FUNDAMENTAL (G_TYPE_VARIANT));
28 g_assert (G_TYPE_IS_DERIVED (G_TYPE_INITIALLY_UNOWNED));
30 g_assert (g_type_fundamental_next () == G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_USER_FIRST));
33 static void
34 test_type_qdata (void)
36 gchar *data;
38 g_type_set_qdata (G_TYPE_ENUM, g_quark_from_string ("bla"), "bla");
39 data = g_type_get_qdata (G_TYPE_ENUM, g_quark_from_string ("bla"));
40 g_assert_cmpstr (data, ==, "bla");
43 static void
44 test_type_query (void)
46 GTypeQuery query;
48 g_type_query (G_TYPE_ENUM, &query);
49 g_assert_cmpint (query.type, ==, G_TYPE_ENUM);
50 g_assert_cmpstr (query.type_name, ==, "GEnum");
51 g_assert_cmpint (query.class_size, ==, sizeof (GEnumClass));
52 g_assert_cmpint (query.instance_size, ==, 0);
55 typedef struct _MyObject MyObject;
56 typedef struct _MyObjectClass MyObjectClass;
57 typedef struct _MyObjectClassPrivate MyObjectClassPrivate;
59 struct _MyObject
61 GObject parent_instance;
63 gint count;
66 struct _MyObjectClass
68 GObjectClass parent_class;
71 struct _MyObjectClassPrivate
73 gint secret_class_count;
76 static GType my_object_get_type (void);
77 G_DEFINE_TYPE_WITH_CODE (MyObject, my_object, G_TYPE_OBJECT,
78 g_type_add_class_private (g_define_type_id, sizeof (MyObjectClassPrivate)) );
80 static void
81 my_object_init (MyObject *obj)
83 obj->count = 42;
86 static void
87 my_object_class_init (MyObjectClass *klass)
91 static void
92 test_class_private (void)
94 GObject *obj;
95 MyObjectClass *class;
96 MyObjectClassPrivate *priv;
98 obj = g_object_new (my_object_get_type (), NULL);
100 class = g_type_class_ref (my_object_get_type ());
101 priv = G_TYPE_CLASS_GET_PRIVATE (class, my_object_get_type (), MyObjectClassPrivate);
102 priv->secret_class_count = 13;
103 g_type_class_unref (class);
105 g_object_unref (obj);
107 g_assert_cmpint (g_type_qname (my_object_get_type ()), ==, g_quark_from_string ("MyObject"));
110 static void
111 test_clear (void)
113 GObject *o = NULL;
114 GObject *tmp;
116 g_clear_object (&o);
117 g_assert (o == NULL);
119 tmp = g_object_new (G_TYPE_OBJECT, NULL);
120 g_assert_cmpint (tmp->ref_count, ==, 1);
121 o = g_object_ref (tmp);
122 g_assert (o != NULL);
124 g_assert_cmpint (tmp->ref_count, ==, 2);
125 g_clear_object (&o);
126 g_assert_cmpint (tmp->ref_count, ==, 1);
127 g_assert (o == NULL);
129 g_object_unref (tmp);
132 static void
133 test_clear_function (void)
135 volatile GObject *o = NULL;
136 GObject *tmp;
138 (g_clear_object) (&o);
139 g_assert (o == NULL);
141 tmp = g_object_new (G_TYPE_OBJECT, NULL);
142 g_assert_cmpint (tmp->ref_count, ==, 1);
143 o = g_object_ref (tmp);
144 g_assert (o != NULL);
146 g_assert_cmpint (tmp->ref_count, ==, 2);
147 (g_clear_object) (&o);
148 g_assert_cmpint (tmp->ref_count, ==, 1);
149 g_assert (o == NULL);
151 g_object_unref (tmp);
154 static void
155 toggle_cb (gpointer data, GObject *obj, gboolean is_last)
157 gboolean *b = data;
159 *b = TRUE;
162 static void
163 test_object_value (void)
165 GObject *v;
166 GObject *v2;
167 GValue value = G_VALUE_INIT;
168 gboolean toggled = FALSE;
170 g_value_init (&value, G_TYPE_OBJECT);
172 v = g_object_new (G_TYPE_OBJECT, NULL);
173 g_object_add_toggle_ref (v, toggle_cb, &toggled);
175 g_value_take_object (&value, v);
177 v2 = g_value_get_object (&value);
178 g_assert (v2 == v);
180 v2 = g_value_dup_object (&value);
181 g_assert (v2 == v); /* objects use ref/unref for copy/free */
182 g_object_unref (v2);
184 g_assert (!toggled);
185 g_value_unset (&value);
186 g_assert (toggled);
188 /* test the deprecated variant too */
189 g_value_init (&value, G_TYPE_OBJECT);
190 /* get a new reference */
191 g_object_ref (v);
193 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
194 g_value_set_object_take_ownership (&value, v);
195 G_GNUC_END_IGNORE_DEPRECATIONS
197 toggled = FALSE;
198 g_value_unset (&value);
199 g_assert (toggled);
201 g_object_remove_toggle_ref (v, toggle_cb, &toggled);
204 static void
205 test_initially_unowned (void)
207 GObject *obj;
209 obj = g_object_new (G_TYPE_INITIALLY_UNOWNED, NULL);
210 g_assert (g_object_is_floating (obj));
211 g_assert_cmpint (obj->ref_count, ==, 1);
213 g_object_ref_sink (obj);
214 g_assert (!g_object_is_floating (obj));
215 g_assert_cmpint (obj->ref_count, ==, 1);
217 g_object_ref_sink (obj);
218 g_assert (!g_object_is_floating (obj));
219 g_assert_cmpint (obj->ref_count, ==, 2);
221 g_object_unref (obj);
222 g_assert_cmpint (obj->ref_count, ==, 1);
224 g_object_force_floating (obj);
225 g_assert (g_object_is_floating (obj));
226 g_assert_cmpint (obj->ref_count, ==, 1);
228 g_object_ref_sink (obj);
229 g_object_unref (obj);
232 static void
233 test_weak_pointer (void)
235 GObject *obj;
236 gpointer weak;
237 gpointer weak2;
239 weak = weak2 = obj = g_object_new (G_TYPE_OBJECT, NULL);
240 g_assert_cmpint (obj->ref_count, ==, 1);
242 g_object_add_weak_pointer (obj, &weak);
243 g_object_add_weak_pointer (obj, &weak2);
244 g_assert_cmpint (obj->ref_count, ==, 1);
245 g_assert (weak == obj);
246 g_assert (weak2 == obj);
248 g_object_remove_weak_pointer (obj, &weak2);
249 g_assert_cmpint (obj->ref_count, ==, 1);
250 g_assert (weak == obj);
251 g_assert (weak2 == obj);
253 g_object_unref (obj);
254 g_assert (weak == NULL);
255 g_assert (weak2 == obj);
258 /* See gobject/tests/threadtests.c for the threaded version */
259 static void
260 test_weak_ref (void)
262 GObject *obj;
263 GObject *obj2;
264 GObject *tmp;
265 GWeakRef weak = { { GUINT_TO_POINTER (0xDEADBEEFU) } };
266 GWeakRef weak2 = { { GUINT_TO_POINTER (0xDEADBEEFU) } };
267 GWeakRef weak3 = { { GUINT_TO_POINTER (0xDEADBEEFU) } };
268 GWeakRef *dynamic_weak = g_new (GWeakRef, 1);
270 /* you can initialize to empty like this... */
271 g_weak_ref_init (&weak2, NULL);
272 g_assert (g_weak_ref_get (&weak2) == NULL);
274 /* ... or via an initializer */
275 g_weak_ref_init (&weak3, NULL);
276 g_assert (g_weak_ref_get (&weak3) == NULL);
278 obj = g_object_new (G_TYPE_OBJECT, NULL);
279 g_assert_cmpint (obj->ref_count, ==, 1);
281 obj2 = g_object_new (G_TYPE_OBJECT, NULL);
282 g_assert_cmpint (obj2->ref_count, ==, 1);
284 /* you can init with an object (even if uninitialized) */
285 g_weak_ref_init (&weak, obj);
286 g_weak_ref_init (dynamic_weak, obj);
287 /* or set to point at an object, if initialized (maybe to 0) */
288 g_weak_ref_set (&weak2, obj);
289 g_weak_ref_set (&weak3, obj);
290 /* none of this affects its refcount */
291 g_assert_cmpint (obj->ref_count, ==, 1);
293 /* getting the value takes a ref */
294 tmp = g_weak_ref_get (&weak);
295 g_assert (tmp == obj);
296 g_assert_cmpint (obj->ref_count, ==, 2);
297 g_object_unref (tmp);
298 g_assert_cmpint (obj->ref_count, ==, 1);
300 tmp = g_weak_ref_get (&weak2);
301 g_assert (tmp == obj);
302 g_assert_cmpint (obj->ref_count, ==, 2);
303 g_object_unref (tmp);
304 g_assert_cmpint (obj->ref_count, ==, 1);
306 tmp = g_weak_ref_get (&weak3);
307 g_assert (tmp == obj);
308 g_assert_cmpint (obj->ref_count, ==, 2);
309 g_object_unref (tmp);
310 g_assert_cmpint (obj->ref_count, ==, 1);
312 tmp = g_weak_ref_get (dynamic_weak);
313 g_assert (tmp == obj);
314 g_assert_cmpint (obj->ref_count, ==, 2);
315 g_object_unref (tmp);
316 g_assert_cmpint (obj->ref_count, ==, 1);
318 /* clearing a weak ref stops tracking */
319 g_weak_ref_clear (&weak);
321 /* setting a weak ref to NULL stops tracking too */
322 g_weak_ref_set (&weak2, NULL);
323 g_assert (g_weak_ref_get (&weak2) == NULL);
324 g_weak_ref_clear (&weak2);
326 /* setting a weak ref to a new object stops tracking the old one */
327 g_weak_ref_set (dynamic_weak, obj2);
328 tmp = g_weak_ref_get (dynamic_weak);
329 g_assert (tmp == obj2);
330 g_assert_cmpint (obj2->ref_count, ==, 2);
331 g_object_unref (tmp);
332 g_assert_cmpint (obj2->ref_count, ==, 1);
334 g_assert_cmpint (obj->ref_count, ==, 1);
336 /* free the object: weak3 is the only one left pointing there */
337 g_object_unref (obj);
338 g_assert (g_weak_ref_get (&weak3) == NULL);
340 /* setting a weak ref to a new object stops tracking the old one */
341 g_weak_ref_set (dynamic_weak, obj2);
342 tmp = g_weak_ref_get (dynamic_weak);
343 g_assert (tmp == obj2);
344 g_assert_cmpint (obj2->ref_count, ==, 2);
345 g_object_unref (tmp);
346 g_assert_cmpint (obj2->ref_count, ==, 1);
348 g_weak_ref_clear (&weak3);
350 /* clear and free dynamic_weak... */
351 g_weak_ref_clear (dynamic_weak);
353 /* ... to prove that doing so stops this from being a use-after-free */
354 g_object_unref (obj2);
355 g_free (dynamic_weak);
358 typedef struct
360 gboolean should_be_last;
361 gint count;
362 } Count;
364 static void
365 toggle_notify (gpointer data,
366 GObject *obj,
367 gboolean is_last)
369 Count *c = data;
371 g_assert (is_last == c->should_be_last);
373 c->count++;
376 static void
377 test_toggle_ref (void)
379 GObject *obj;
380 Count c, c2;
382 obj = g_object_new (G_TYPE_OBJECT, NULL);
384 g_object_add_toggle_ref (obj, toggle_notify, &c);
385 g_object_add_toggle_ref (obj, toggle_notify, &c2);
387 c.should_be_last = c2.should_be_last = TRUE;
388 c.count = c2.count = 0;
390 g_object_unref (obj);
392 g_assert_cmpint (c.count, ==, 0);
393 g_assert_cmpint (c2.count, ==, 0);
395 g_object_ref (obj);
397 g_assert_cmpint (c.count, ==, 0);
398 g_assert_cmpint (c2.count, ==, 0);
400 g_object_remove_toggle_ref (obj, toggle_notify, &c2);
402 g_object_unref (obj);
404 g_assert_cmpint (c.count, ==, 1);
406 c.should_be_last = FALSE;
408 g_object_ref (obj);
410 g_assert_cmpint (c.count, ==, 2);
412 c.should_be_last = TRUE;
414 g_object_unref (obj);
416 g_assert_cmpint (c.count, ==, 3);
418 g_object_remove_toggle_ref (obj, toggle_notify, &c);
421 static gboolean destroyed;
422 static gint value;
424 static void
425 data_destroy (gpointer data)
427 g_assert_cmpint (GPOINTER_TO_INT (data), ==, value);
429 destroyed = TRUE;
432 static void
433 test_object_qdata (void)
435 GObject *obj;
436 gpointer v;
437 GQuark quark;
439 obj = g_object_new (G_TYPE_OBJECT, NULL);
441 value = 1;
442 destroyed = FALSE;
443 g_object_set_data_full (obj, "test", GINT_TO_POINTER (1), data_destroy);
444 v = g_object_get_data (obj, "test");
445 g_assert_cmpint (GPOINTER_TO_INT (v), ==, 1);
446 g_object_set_data_full (obj, "test", GINT_TO_POINTER (2), data_destroy);
447 g_assert (destroyed);
448 value = 2;
449 destroyed = FALSE;
450 v = g_object_steal_data (obj, "test");
451 g_assert_cmpint (GPOINTER_TO_INT (v), ==, 2);
452 g_assert (!destroyed);
454 value = 1;
455 destroyed = FALSE;
456 quark = g_quark_from_string ("test");
457 g_object_set_qdata_full (obj, quark, GINT_TO_POINTER (1), data_destroy);
458 v = g_object_get_qdata (obj, quark);
459 g_assert_cmpint (GPOINTER_TO_INT (v), ==, 1);
460 g_object_set_qdata_full (obj, quark, GINT_TO_POINTER (2), data_destroy);
461 g_assert (destroyed);
462 value = 2;
463 destroyed = FALSE;
464 v = g_object_steal_qdata (obj, quark);
465 g_assert_cmpint (GPOINTER_TO_INT (v), ==, 2);
466 g_assert (!destroyed);
468 g_object_set_qdata_full (obj, quark, GINT_TO_POINTER (3), data_destroy);
469 value = 3;
470 destroyed = FALSE;
471 g_object_unref (obj);
473 g_assert (destroyed);
476 typedef struct {
477 const gchar *value;
478 gint refcount;
479 } Value;
481 static gpointer
482 ref_value (gpointer value, gpointer user_data)
484 Value *v = value;
485 Value **old_value_p = user_data;
487 if (old_value_p)
488 *old_value_p = v;
490 if (v)
491 v->refcount += 1;
493 return value;
496 static void
497 unref_value (gpointer value)
499 Value *v = value;
501 v->refcount -= 1;
502 if (v->refcount == 0)
503 g_free (value);
506 static
507 Value *
508 new_value (const gchar *s)
510 Value *v;
512 v = g_new (Value, 1);
513 v->value = s;
514 v->refcount = 1;
516 return v;
519 static void
520 test_object_qdata2 (void)
522 GObject *obj;
523 Value *v, *v1, *v2, *v3, *old_val;
524 GDestroyNotify old_destroy;
525 gboolean res;
527 obj = g_object_new (G_TYPE_OBJECT, NULL);
529 v1 = new_value ("bla");
531 g_object_set_data_full (obj, "test", v1, unref_value);
533 v = g_object_get_data (obj, "test");
534 g_assert_cmpstr (v->value, ==, "bla");
535 g_assert_cmpint (v->refcount, ==, 1);
537 v = g_object_dup_data (obj, "test", ref_value, &old_val);
538 g_assert (old_val == v1);
539 g_assert_cmpstr (v->value, ==, "bla");
540 g_assert_cmpint (v->refcount, ==, 2);
541 unref_value (v);
543 v = g_object_dup_data (obj, "nono", ref_value, &old_val);
544 g_assert (old_val == NULL);
545 g_assert (v == NULL);
547 v2 = new_value ("not");
549 res = g_object_replace_data (obj, "test", v1, v2, unref_value, &old_destroy);
550 g_assert (res == TRUE);
551 g_assert (old_destroy == unref_value);
552 g_assert_cmpstr (v1->value, ==, "bla");
553 g_assert_cmpint (v1->refcount, ==, 1);
555 v = g_object_get_data (obj, "test");
556 g_assert_cmpstr (v->value, ==, "not");
557 g_assert_cmpint (v->refcount, ==, 1);
559 v3 = new_value ("xyz");
560 res = g_object_replace_data (obj, "test", v1, v3, unref_value, &old_destroy);
561 g_assert (res == FALSE);
562 g_assert_cmpstr (v2->value, ==, "not");
563 g_assert_cmpint (v2->refcount, ==, 1);
565 unref_value (v1);
567 res = g_object_replace_data (obj, "test", NULL, v3, unref_value, &old_destroy);
568 g_assert (res == FALSE);
569 g_assert_cmpstr (v2->value, ==, "not");
570 g_assert_cmpint (v2->refcount, ==, 1);
572 res = g_object_replace_data (obj, "test", v2, NULL, unref_value, &old_destroy);
573 g_assert (res == TRUE);
574 g_assert (old_destroy == unref_value);
575 g_assert_cmpstr (v2->value, ==, "not");
576 g_assert_cmpint (v2->refcount, ==, 1);
578 unref_value (v2);
580 v = g_object_get_data (obj, "test");
581 g_assert (v == NULL);
583 res = g_object_replace_data (obj, "test", NULL, v3, unref_value, &old_destroy);
584 g_assert (res == TRUE);
586 v = g_object_get_data (obj, "test");
587 g_assert (v == v3);
589 ref_value (v3, NULL);
590 g_assert_cmpint (v3->refcount, ==, 2);
591 g_object_unref (obj);
592 g_assert_cmpint (v3->refcount, ==, 1);
593 unref_value (v3);
597 main (int argc, char **argv)
599 g_test_init (&argc, &argv, NULL);
601 g_test_add_func ("/type/fundamentals", test_fundamentals);
602 g_test_add_func ("/type/qdata", test_type_qdata);
603 g_test_add_func ("/type/query", test_type_query);
604 g_test_add_func ("/type/class-private", test_class_private);
605 g_test_add_func ("/object/clear", test_clear);
606 g_test_add_func ("/object/clear-function", test_clear_function);
607 g_test_add_func ("/object/value", test_object_value);
608 g_test_add_func ("/object/initially-unowned", test_initially_unowned);
609 g_test_add_func ("/object/weak-pointer", test_weak_pointer);
610 g_test_add_func ("/object/weak-ref", test_weak_ref);
611 g_test_add_func ("/object/toggle-ref", test_toggle_ref);
612 g_test_add_func ("/object/qdata", test_object_qdata);
613 g_test_add_func ("/object/qdata2", test_object_qdata2);
615 return g_test_run ();