1 #include <glib-object.h>
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
));
34 test_type_qdata (void)
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");
44 test_type_query (void)
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
;
61 GObject parent_instance
;
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
)) );
81 my_object_init (MyObject
*obj
)
87 my_object_class_init (MyObjectClass
*klass
)
92 test_class_private (void)
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"));
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);
126 g_assert_cmpint (tmp
->ref_count
, ==, 1);
127 g_assert (o
== NULL
);
129 g_object_unref (tmp
);
133 test_clear_function (void)
135 volatile GObject
*o
= NULL
;
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
);
160 g_assert (!g_set_object (&o
, NULL
));
161 g_assert (o
== NULL
);
163 tmp
= g_object_new (G_TYPE_OBJECT
, NULL
);
164 g_assert_cmpint (tmp
->ref_count
, ==, 1);
166 g_assert (g_set_object (&o
, tmp
));
168 g_assert_cmpint (tmp
->ref_count
, ==, 2);
170 g_object_unref (tmp
);
171 g_assert_cmpint (tmp
->ref_count
, ==, 1);
173 /* Setting it again shouldn’t cause finalisation. */
174 g_assert (!g_set_object (&o
, tmp
));
176 g_assert_cmpint (tmp
->ref_count
, ==, 1);
178 g_assert (g_set_object (&o
, NULL
));
179 g_assert (o
== NULL
);
180 g_assert (!G_IS_OBJECT (tmp
)); /* finalised */
184 test_set_function (void)
189 g_assert (!(g_set_object
) (&o
, NULL
));
190 g_assert (o
== NULL
);
192 tmp
= g_object_new (G_TYPE_OBJECT
, NULL
);
193 g_assert_cmpint (tmp
->ref_count
, ==, 1);
195 g_assert ((g_set_object
) (&o
, tmp
));
197 g_assert_cmpint (tmp
->ref_count
, ==, 2);
199 g_object_unref (tmp
);
200 g_assert_cmpint (tmp
->ref_count
, ==, 1);
202 /* Setting it again shouldn’t cause finalisation. */
203 g_assert (!(g_set_object
) (&o
, tmp
));
205 g_assert_cmpint (tmp
->ref_count
, ==, 1);
207 g_assert ((g_set_object
) (&o
, NULL
));
208 g_assert (o
== NULL
);
209 g_assert (!G_IS_OBJECT (tmp
)); /* finalised */
213 toggle_cb (gpointer data
, GObject
*obj
, gboolean is_last
)
221 test_object_value (void)
225 GValue value
= G_VALUE_INIT
;
226 gboolean toggled
= FALSE
;
228 g_value_init (&value
, G_TYPE_OBJECT
);
230 v
= g_object_new (G_TYPE_OBJECT
, NULL
);
231 g_object_add_toggle_ref (v
, toggle_cb
, &toggled
);
233 g_value_take_object (&value
, v
);
235 v2
= g_value_get_object (&value
);
238 v2
= g_value_dup_object (&value
);
239 g_assert (v2
== v
); /* objects use ref/unref for copy/free */
243 g_value_unset (&value
);
246 /* test the deprecated variant too */
247 g_value_init (&value
, G_TYPE_OBJECT
);
248 /* get a new reference */
251 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
252 g_value_set_object_take_ownership (&value
, v
);
253 G_GNUC_END_IGNORE_DEPRECATIONS
256 g_value_unset (&value
);
259 g_object_remove_toggle_ref (v
, toggle_cb
, &toggled
);
263 test_initially_unowned (void)
267 obj
= g_object_new (G_TYPE_INITIALLY_UNOWNED
, NULL
);
268 g_assert (g_object_is_floating (obj
));
269 g_assert_cmpint (obj
->ref_count
, ==, 1);
271 g_object_ref_sink (obj
);
272 g_assert (!g_object_is_floating (obj
));
273 g_assert_cmpint (obj
->ref_count
, ==, 1);
275 g_object_ref_sink (obj
);
276 g_assert (!g_object_is_floating (obj
));
277 g_assert_cmpint (obj
->ref_count
, ==, 2);
279 g_object_unref (obj
);
280 g_assert_cmpint (obj
->ref_count
, ==, 1);
282 g_object_force_floating (obj
);
283 g_assert (g_object_is_floating (obj
));
284 g_assert_cmpint (obj
->ref_count
, ==, 1);
286 g_object_ref_sink (obj
);
287 g_object_unref (obj
);
291 test_weak_pointer (void)
297 weak
= weak2
= obj
= g_object_new (G_TYPE_OBJECT
, NULL
);
298 g_assert_cmpint (obj
->ref_count
, ==, 1);
300 g_object_add_weak_pointer (obj
, &weak
);
301 g_object_add_weak_pointer (obj
, &weak2
);
302 g_assert_cmpint (obj
->ref_count
, ==, 1);
303 g_assert (weak
== obj
);
304 g_assert (weak2
== obj
);
306 g_object_remove_weak_pointer (obj
, &weak2
);
307 g_assert_cmpint (obj
->ref_count
, ==, 1);
308 g_assert (weak
== obj
);
309 g_assert (weak2
== obj
);
311 g_object_unref (obj
);
312 g_assert (weak
== NULL
);
313 g_assert (weak2
== obj
);
316 /* See gobject/tests/threadtests.c for the threaded version */
323 GWeakRef weak
= { { GUINT_TO_POINTER (0xDEADBEEFU
) } };
324 GWeakRef weak2
= { { GUINT_TO_POINTER (0xDEADBEEFU
) } };
325 GWeakRef weak3
= { { GUINT_TO_POINTER (0xDEADBEEFU
) } };
326 GWeakRef
*dynamic_weak
= g_new (GWeakRef
, 1);
328 /* you can initialize to empty like this... */
329 g_weak_ref_init (&weak2
, NULL
);
330 g_assert (g_weak_ref_get (&weak2
) == NULL
);
332 /* ... or via an initializer */
333 g_weak_ref_init (&weak3
, NULL
);
334 g_assert (g_weak_ref_get (&weak3
) == NULL
);
336 obj
= g_object_new (G_TYPE_OBJECT
, NULL
);
337 g_assert_cmpint (obj
->ref_count
, ==, 1);
339 obj2
= g_object_new (G_TYPE_OBJECT
, NULL
);
340 g_assert_cmpint (obj2
->ref_count
, ==, 1);
342 /* you can init with an object (even if uninitialized) */
343 g_weak_ref_init (&weak
, obj
);
344 g_weak_ref_init (dynamic_weak
, obj
);
345 /* or set to point at an object, if initialized (maybe to 0) */
346 g_weak_ref_set (&weak2
, obj
);
347 g_weak_ref_set (&weak3
, obj
);
348 /* none of this affects its refcount */
349 g_assert_cmpint (obj
->ref_count
, ==, 1);
351 /* getting the value takes a ref */
352 tmp
= g_weak_ref_get (&weak
);
353 g_assert (tmp
== obj
);
354 g_assert_cmpint (obj
->ref_count
, ==, 2);
355 g_object_unref (tmp
);
356 g_assert_cmpint (obj
->ref_count
, ==, 1);
358 tmp
= g_weak_ref_get (&weak2
);
359 g_assert (tmp
== obj
);
360 g_assert_cmpint (obj
->ref_count
, ==, 2);
361 g_object_unref (tmp
);
362 g_assert_cmpint (obj
->ref_count
, ==, 1);
364 tmp
= g_weak_ref_get (&weak3
);
365 g_assert (tmp
== obj
);
366 g_assert_cmpint (obj
->ref_count
, ==, 2);
367 g_object_unref (tmp
);
368 g_assert_cmpint (obj
->ref_count
, ==, 1);
370 tmp
= g_weak_ref_get (dynamic_weak
);
371 g_assert (tmp
== obj
);
372 g_assert_cmpint (obj
->ref_count
, ==, 2);
373 g_object_unref (tmp
);
374 g_assert_cmpint (obj
->ref_count
, ==, 1);
376 /* clearing a weak ref stops tracking */
377 g_weak_ref_clear (&weak
);
379 /* setting a weak ref to NULL stops tracking too */
380 g_weak_ref_set (&weak2
, NULL
);
381 g_assert (g_weak_ref_get (&weak2
) == NULL
);
382 g_weak_ref_clear (&weak2
);
384 /* setting a weak ref to a new object stops tracking the old one */
385 g_weak_ref_set (dynamic_weak
, obj2
);
386 tmp
= g_weak_ref_get (dynamic_weak
);
387 g_assert (tmp
== obj2
);
388 g_assert_cmpint (obj2
->ref_count
, ==, 2);
389 g_object_unref (tmp
);
390 g_assert_cmpint (obj2
->ref_count
, ==, 1);
392 g_assert_cmpint (obj
->ref_count
, ==, 1);
394 /* free the object: weak3 is the only one left pointing there */
395 g_object_unref (obj
);
396 g_assert (g_weak_ref_get (&weak3
) == NULL
);
398 /* setting a weak ref to a new object stops tracking the old one */
399 g_weak_ref_set (dynamic_weak
, obj2
);
400 tmp
= g_weak_ref_get (dynamic_weak
);
401 g_assert (tmp
== obj2
);
402 g_assert_cmpint (obj2
->ref_count
, ==, 2);
403 g_object_unref (tmp
);
404 g_assert_cmpint (obj2
->ref_count
, ==, 1);
406 g_weak_ref_clear (&weak3
);
408 /* clear and free dynamic_weak... */
409 g_weak_ref_clear (dynamic_weak
);
411 /* ... to prove that doing so stops this from being a use-after-free */
412 g_object_unref (obj2
);
413 g_free (dynamic_weak
);
418 gboolean should_be_last
;
423 toggle_notify (gpointer data
,
429 g_assert (is_last
== c
->should_be_last
);
435 test_toggle_ref (void)
440 obj
= g_object_new (G_TYPE_OBJECT
, NULL
);
442 g_object_add_toggle_ref (obj
, toggle_notify
, &c
);
443 g_object_add_toggle_ref (obj
, toggle_notify
, &c2
);
445 c
.should_be_last
= c2
.should_be_last
= TRUE
;
446 c
.count
= c2
.count
= 0;
448 g_object_unref (obj
);
450 g_assert_cmpint (c
.count
, ==, 0);
451 g_assert_cmpint (c2
.count
, ==, 0);
455 g_assert_cmpint (c
.count
, ==, 0);
456 g_assert_cmpint (c2
.count
, ==, 0);
458 g_object_remove_toggle_ref (obj
, toggle_notify
, &c2
);
460 g_object_unref (obj
);
462 g_assert_cmpint (c
.count
, ==, 1);
464 c
.should_be_last
= FALSE
;
468 g_assert_cmpint (c
.count
, ==, 2);
470 c
.should_be_last
= TRUE
;
472 g_object_unref (obj
);
474 g_assert_cmpint (c
.count
, ==, 3);
476 g_object_remove_toggle_ref (obj
, toggle_notify
, &c
);
479 static gboolean destroyed
;
483 data_destroy (gpointer data
)
485 g_assert_cmpint (GPOINTER_TO_INT (data
), ==, value
);
491 test_object_qdata (void)
497 obj
= g_object_new (G_TYPE_OBJECT
, NULL
);
501 g_object_set_data_full (obj
, "test", GINT_TO_POINTER (1), data_destroy
);
502 v
= g_object_get_data (obj
, "test");
503 g_assert_cmpint (GPOINTER_TO_INT (v
), ==, 1);
504 g_object_set_data_full (obj
, "test", GINT_TO_POINTER (2), data_destroy
);
505 g_assert (destroyed
);
508 v
= g_object_steal_data (obj
, "test");
509 g_assert_cmpint (GPOINTER_TO_INT (v
), ==, 2);
510 g_assert (!destroyed
);
514 quark
= g_quark_from_string ("test");
515 g_object_set_qdata_full (obj
, quark
, GINT_TO_POINTER (1), data_destroy
);
516 v
= g_object_get_qdata (obj
, quark
);
517 g_assert_cmpint (GPOINTER_TO_INT (v
), ==, 1);
518 g_object_set_qdata_full (obj
, quark
, GINT_TO_POINTER (2), data_destroy
);
519 g_assert (destroyed
);
522 v
= g_object_steal_qdata (obj
, quark
);
523 g_assert_cmpint (GPOINTER_TO_INT (v
), ==, 2);
524 g_assert (!destroyed
);
526 g_object_set_qdata_full (obj
, quark
, GINT_TO_POINTER (3), data_destroy
);
529 g_object_unref (obj
);
531 g_assert (destroyed
);
540 ref_value (gpointer value
, gpointer user_data
)
543 Value
**old_value_p
= user_data
;
555 unref_value (gpointer value
)
560 if (v
->refcount
== 0)
566 new_value (const gchar
*s
)
570 v
= g_new (Value
, 1);
578 test_object_qdata2 (void)
581 Value
*v
, *v1
, *v2
, *v3
, *old_val
;
582 GDestroyNotify old_destroy
;
585 obj
= g_object_new (G_TYPE_OBJECT
, NULL
);
587 v1
= new_value ("bla");
589 g_object_set_data_full (obj
, "test", v1
, unref_value
);
591 v
= g_object_get_data (obj
, "test");
592 g_assert_cmpstr (v
->value
, ==, "bla");
593 g_assert_cmpint (v
->refcount
, ==, 1);
595 v
= g_object_dup_data (obj
, "test", ref_value
, &old_val
);
596 g_assert (old_val
== v1
);
597 g_assert_cmpstr (v
->value
, ==, "bla");
598 g_assert_cmpint (v
->refcount
, ==, 2);
601 v
= g_object_dup_data (obj
, "nono", ref_value
, &old_val
);
602 g_assert (old_val
== NULL
);
603 g_assert (v
== NULL
);
605 v2
= new_value ("not");
607 res
= g_object_replace_data (obj
, "test", v1
, v2
, unref_value
, &old_destroy
);
608 g_assert (res
== TRUE
);
609 g_assert (old_destroy
== unref_value
);
610 g_assert_cmpstr (v1
->value
, ==, "bla");
611 g_assert_cmpint (v1
->refcount
, ==, 1);
613 v
= g_object_get_data (obj
, "test");
614 g_assert_cmpstr (v
->value
, ==, "not");
615 g_assert_cmpint (v
->refcount
, ==, 1);
617 v3
= new_value ("xyz");
618 res
= g_object_replace_data (obj
, "test", v1
, v3
, unref_value
, &old_destroy
);
619 g_assert (res
== FALSE
);
620 g_assert_cmpstr (v2
->value
, ==, "not");
621 g_assert_cmpint (v2
->refcount
, ==, 1);
625 res
= g_object_replace_data (obj
, "test", NULL
, v3
, unref_value
, &old_destroy
);
626 g_assert (res
== FALSE
);
627 g_assert_cmpstr (v2
->value
, ==, "not");
628 g_assert_cmpint (v2
->refcount
, ==, 1);
630 res
= g_object_replace_data (obj
, "test", v2
, NULL
, unref_value
, &old_destroy
);
631 g_assert (res
== TRUE
);
632 g_assert (old_destroy
== unref_value
);
633 g_assert_cmpstr (v2
->value
, ==, "not");
634 g_assert_cmpint (v2
->refcount
, ==, 1);
638 v
= g_object_get_data (obj
, "test");
639 g_assert (v
== NULL
);
641 res
= g_object_replace_data (obj
, "test", NULL
, v3
, unref_value
, &old_destroy
);
642 g_assert (res
== TRUE
);
644 v
= g_object_get_data (obj
, "test");
647 ref_value (v3
, NULL
);
648 g_assert_cmpint (v3
->refcount
, ==, 2);
649 g_object_unref (obj
);
650 g_assert_cmpint (v3
->refcount
, ==, 1);
655 main (int argc
, char **argv
)
657 g_test_init (&argc
, &argv
, NULL
);
659 g_test_add_func ("/type/fundamentals", test_fundamentals
);
660 g_test_add_func ("/type/qdata", test_type_qdata
);
661 g_test_add_func ("/type/query", test_type_query
);
662 g_test_add_func ("/type/class-private", test_class_private
);
663 g_test_add_func ("/object/clear", test_clear
);
664 g_test_add_func ("/object/clear-function", test_clear_function
);
665 g_test_add_func ("/object/set", test_set
);
666 g_test_add_func ("/object/set-function", test_set_function
);
667 g_test_add_func ("/object/value", test_object_value
);
668 g_test_add_func ("/object/initially-unowned", test_initially_unowned
);
669 g_test_add_func ("/object/weak-pointer", test_weak_pointer
);
670 g_test_add_func ("/object/weak-ref", test_weak_ref
);
671 g_test_add_func ("/object/toggle-ref", test_toggle_ref
);
672 g_test_add_func ("/object/qdata", test_object_qdata
);
673 g_test_add_func ("/object/qdata2", test_object_qdata2
);
675 return g_test_run ();