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
);
155 toggle_cb (gpointer data
, GObject
*obj
, gboolean is_last
)
163 test_object_value (void)
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
);
180 v2
= g_value_dup_object (&value
);
181 g_assert (v2
== v
); /* objects use ref/unref for copy/free */
185 g_value_unset (&value
);
188 /* test the deprecated variant too */
189 g_value_init (&value
, G_TYPE_OBJECT
);
190 /* get a new reference */
193 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
194 g_value_set_object_take_ownership (&value
, v
);
195 G_GNUC_END_IGNORE_DEPRECATIONS
198 g_value_unset (&value
);
201 g_object_remove_toggle_ref (v
, toggle_cb
, &toggled
);
205 test_initially_unowned (void)
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
);
233 test_weak_pointer (void)
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 */
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
);
360 gboolean should_be_last
;
365 toggle_notify (gpointer data
,
371 g_assert (is_last
== c
->should_be_last
);
377 test_toggle_ref (void)
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);
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
;
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
;
425 data_destroy (gpointer data
)
427 g_assert_cmpint (GPOINTER_TO_INT (data
), ==, value
);
433 test_object_qdata (void)
439 obj
= g_object_new (G_TYPE_OBJECT
, NULL
);
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
);
450 v
= g_object_steal_data (obj
, "test");
451 g_assert_cmpint (GPOINTER_TO_INT (v
), ==, 2);
452 g_assert (!destroyed
);
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
);
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
);
471 g_object_unref (obj
);
473 g_assert (destroyed
);
482 ref_value (gpointer value
, gpointer user_data
)
485 Value
**old_value_p
= user_data
;
497 unref_value (gpointer value
)
502 if (v
->refcount
== 0)
508 new_value (const gchar
*s
)
512 v
= g_new (Value
, 1);
520 test_object_qdata2 (void)
523 Value
*v
, *v1
, *v2
, *v3
, *old_val
;
524 GDestroyNotify old_destroy
;
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);
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);
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);
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");
589 ref_value (v3
, NULL
);
590 g_assert_cmpint (v3
->refcount
, ==, 2);
591 g_object_unref (obj
);
592 g_assert_cmpint (v3
->refcount
, ==, 1);
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 ();