1#include <glib-object.h>
2
3static void
4test_fundamentals (void)
5{
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));
29
30 g_assert (g_type_fundamental_next () == G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_USER_FIRST));
31}
32
33static void
34test_type_qdata (void)
35{
36 gchar *data;
37
38 g_type_set_qdata (G_TYPE_ENUM, quark: g_quark_from_string (string: "bla"), data: "bla");
39 data = g_type_get_qdata (G_TYPE_ENUM, quark: g_quark_from_string (string: "bla"));
40 g_assert_cmpstr (data, ==, "bla");
41}
42
43static void
44test_type_query (void)
45{
46 GTypeQuery query;
47
48 g_type_query (G_TYPE_ENUM, query: &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);
53}
54
55typedef struct _MyObject MyObject;
56typedef struct _MyObjectClass MyObjectClass;
57typedef struct _MyObjectClassPrivate MyObjectClassPrivate;
58
59struct _MyObject
60{
61 GObject parent_instance;
62
63 gint count;
64};
65
66struct _MyObjectClass
67{
68 GObjectClass parent_class;
69};
70
71struct _MyObjectClassPrivate
72{
73 gint secret_class_count;
74};
75
76static GType my_object_get_type (void);
77G_DEFINE_TYPE_WITH_CODE (MyObject, my_object, G_TYPE_OBJECT,
78 g_type_add_class_private (g_define_type_id, sizeof (MyObjectClassPrivate)) );
79
80static void
81my_object_init (MyObject *obj)
82{
83 obj->count = 42;
84}
85
86static void
87my_object_class_init (MyObjectClass *klass)
88{
89}
90
91static void
92test_class_private (void)
93{
94 GObject *obj;
95 MyObjectClass *class;
96 MyObjectClassPrivate *priv;
97
98 obj = g_object_new (object_type: my_object_get_type (), NULL);
99
100 class = g_type_class_ref (type: 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 (g_class: class);
104
105 g_object_unref (object: obj);
106
107 g_assert_cmpint (g_type_qname (my_object_get_type ()), ==, g_quark_from_string ("MyObject"));
108}
109
110static void
111test_clear (void)
112{
113 GObject *o = NULL;
114 GObject *tmp;
115
116 g_clear_object (&o);
117 g_assert (o == NULL);
118
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);
123
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);
128
129 g_object_unref (object: tmp);
130}
131
132static void
133test_clear_function (void)
134{
135 GObject *o = NULL;
136 GObject *tmp;
137
138 (g_clear_object) (object_ptr: &o);
139 g_assert (o == NULL);
140
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);
145
146 g_assert_cmpint (tmp->ref_count, ==, 2);
147 (g_clear_object) (object_ptr: &o);
148 g_assert_cmpint (tmp->ref_count, ==, 1);
149 g_assert (o == NULL);
150
151 g_object_unref (object: tmp);
152}
153
154static void
155test_set (void)
156{
157 GObject *o = NULL;
158 GObject *tmp;
159 gpointer tmp_weak = NULL;
160
161 g_assert (!g_set_object (&o, NULL));
162 g_assert (o == NULL);
163
164 tmp = g_object_new (G_TYPE_OBJECT, NULL);
165 tmp_weak = tmp;
166 g_object_add_weak_pointer (object: tmp, weak_pointer_location: &tmp_weak);
167 g_assert_cmpint (tmp->ref_count, ==, 1);
168
169 g_assert (g_set_object (&o, tmp));
170 g_assert (o == tmp);
171 g_assert_cmpint (tmp->ref_count, ==, 2);
172
173 g_object_unref (object: tmp);
174 g_assert_cmpint (tmp->ref_count, ==, 1);
175
176 /* Setting it again shouldn’t cause finalisation. */
177 g_assert (!g_set_object (&o, tmp));
178 g_assert (o == tmp);
179 g_assert_cmpint (tmp->ref_count, ==, 1);
180 g_assert_nonnull (tmp_weak);
181
182 g_assert (g_set_object (&o, NULL));
183 g_assert (o == NULL);
184 g_assert_null (tmp_weak);
185}
186
187static void
188test_set_function (void)
189{
190 GObject *o = NULL;
191 GObject *tmp;
192 gpointer tmp_weak = NULL;
193
194 g_assert (!(g_set_object) (&o, NULL));
195 g_assert (o == NULL);
196
197 tmp = g_object_new (G_TYPE_OBJECT, NULL);
198 tmp_weak = tmp;
199 g_object_add_weak_pointer (object: tmp, weak_pointer_location: &tmp_weak);
200 g_assert_cmpint (tmp->ref_count, ==, 1);
201
202 g_assert ((g_set_object) (&o, tmp));
203 g_assert (o == tmp);
204 g_assert_cmpint (tmp->ref_count, ==, 2);
205
206 g_object_unref (object: tmp);
207 g_assert_cmpint (tmp->ref_count, ==, 1);
208
209 /* Setting it again shouldn’t cause finalisation. */
210 g_assert (!(g_set_object) (&o, tmp));
211 g_assert (o == tmp);
212 g_assert_cmpint (tmp->ref_count, ==, 1);
213 g_assert_nonnull (tmp_weak);
214
215 g_assert ((g_set_object) (&o, NULL));
216 g_assert (o == NULL);
217 g_assert_null (tmp_weak);
218}
219
220static void
221test_set_derived_type (void)
222{
223 GBinding *obj = NULL;
224 GObject *o = NULL;
225 GBinding *b = NULL;
226
227 g_test_summary (summary: "Check that g_set_object() doesn’t give strict aliasing "
228 "warnings when used on types derived from GObject");
229
230 g_assert_false (g_set_object (&o, NULL));
231 g_assert_null (o);
232
233 g_assert_false (g_set_object (&b, NULL));
234 g_assert_null (b);
235
236 obj = g_object_new (object_type: my_object_get_type (), NULL);
237
238 g_assert_true (g_set_object (&o, G_OBJECT (obj)));
239 g_assert_true (o == G_OBJECT (obj));
240
241 g_assert_true (g_set_object (&b, obj));
242 g_assert_true (b == obj);
243
244 g_object_unref (object: obj);
245 g_clear_object (&b);
246 g_clear_object (&o);
247}
248
249static void
250toggle_cb (gpointer data, GObject *obj, gboolean is_last)
251{
252 gboolean *b = data;
253
254 *b = TRUE;
255}
256
257static void
258test_object_value (void)
259{
260 GObject *v;
261 GObject *v2;
262 GValue value = G_VALUE_INIT;
263 gboolean toggled = FALSE;
264
265 g_value_init (value: &value, G_TYPE_OBJECT);
266
267 v = g_object_new (G_TYPE_OBJECT, NULL);
268 g_object_add_toggle_ref (object: v, notify: toggle_cb, data: &toggled);
269
270 g_value_take_object (value: &value, v_object: v);
271
272 v2 = g_value_get_object (value: &value);
273 g_assert (v2 == v);
274
275 v2 = g_value_dup_object (value: &value);
276 g_assert (v2 == v); /* objects use ref/unref for copy/free */
277 g_object_unref (object: v2);
278
279 g_assert (!toggled);
280 g_value_unset (value: &value);
281 g_assert (toggled);
282
283 /* test the deprecated variant too */
284 g_value_init (value: &value, G_TYPE_OBJECT);
285 /* get a new reference */
286 g_object_ref (v);
287
288G_GNUC_BEGIN_IGNORE_DEPRECATIONS
289 g_value_set_object_take_ownership (value: &value, v_object: v);
290G_GNUC_END_IGNORE_DEPRECATIONS
291
292 toggled = FALSE;
293 g_value_unset (value: &value);
294 g_assert (toggled);
295
296 g_object_remove_toggle_ref (object: v, notify: toggle_cb, data: &toggled);
297}
298
299static void
300test_initially_unowned (void)
301{
302 GObject *obj;
303
304 obj = g_object_new (G_TYPE_INITIALLY_UNOWNED, NULL);
305 g_assert (g_object_is_floating (obj));
306 g_assert_cmpint (obj->ref_count, ==, 1);
307
308 g_object_ref_sink (obj);
309 g_assert (!g_object_is_floating (obj));
310 g_assert_cmpint (obj->ref_count, ==, 1);
311
312 g_object_ref_sink (obj);
313 g_assert (!g_object_is_floating (obj));
314 g_assert_cmpint (obj->ref_count, ==, 2);
315
316 g_object_unref (object: obj);
317 g_assert_cmpint (obj->ref_count, ==, 1);
318
319 g_object_force_floating (object: obj);
320 g_assert (g_object_is_floating (obj));
321 g_assert_cmpint (obj->ref_count, ==, 1);
322
323 g_object_ref_sink (obj);
324 g_object_unref (object: obj);
325}
326
327static void
328test_weak_pointer (void)
329{
330 GObject *obj;
331 gpointer weak;
332 gpointer weak2;
333
334 weak = weak2 = obj = g_object_new (G_TYPE_OBJECT, NULL);
335 g_assert_cmpint (obj->ref_count, ==, 1);
336
337 g_object_add_weak_pointer (object: obj, weak_pointer_location: &weak);
338 g_object_add_weak_pointer (object: obj, weak_pointer_location: &weak2);
339 g_assert_cmpint (obj->ref_count, ==, 1);
340 g_assert (weak == obj);
341 g_assert (weak2 == obj);
342
343 g_object_remove_weak_pointer (object: obj, weak_pointer_location: &weak2);
344 g_assert_cmpint (obj->ref_count, ==, 1);
345 g_assert (weak == obj);
346 g_assert (weak2 == obj);
347
348 g_object_unref (object: obj);
349 g_assert (weak == NULL);
350 g_assert (weak2 == obj);
351}
352
353static void
354test_weak_pointer_clear (void)
355{
356 GObject *obj;
357 gpointer weak = NULL;
358
359 g_clear_weak_pointer (&weak);
360 g_assert_null (weak);
361
362 weak = obj = g_object_new (G_TYPE_OBJECT, NULL);
363 g_assert_cmpint (obj->ref_count, ==, 1);
364
365 g_object_add_weak_pointer (object: obj, weak_pointer_location: &weak);
366 g_assert_cmpint (obj->ref_count, ==, 1);
367 g_assert_true (weak == obj);
368
369 g_clear_weak_pointer (&weak);
370 g_assert_cmpint (obj->ref_count, ==, 1);
371 g_assert_null (weak);
372
373 g_object_unref (object: obj);
374}
375
376static void
377test_weak_pointer_clear_function (void)
378{
379 GObject *obj;
380 gpointer weak = NULL;
381
382 (g_clear_weak_pointer) (weak_pointer_location: &weak);
383 g_assert_null (weak);
384
385 weak = obj = g_object_new (G_TYPE_OBJECT, NULL);
386 g_assert_cmpint (obj->ref_count, ==, 1);
387
388 g_object_add_weak_pointer (object: obj, weak_pointer_location: &weak);
389 g_assert_cmpint (obj->ref_count, ==, 1);
390 g_assert_true (weak == obj);
391
392 (g_clear_weak_pointer) (weak_pointer_location: &weak);
393 g_assert_cmpint (obj->ref_count, ==, 1);
394 g_assert_null (weak);
395
396 g_object_unref (object: obj);
397}
398
399static void
400test_weak_pointer_set (void)
401{
402 GObject *obj;
403 gpointer weak = NULL;
404
405 g_assert_false (g_set_weak_pointer (&weak, NULL));
406 g_assert_null (weak);
407
408 obj = g_object_new (G_TYPE_OBJECT, NULL);
409 g_assert_cmpint (obj->ref_count, ==, 1);
410
411 g_assert_true (g_set_weak_pointer (&weak, obj));
412 g_assert_cmpint (obj->ref_count, ==, 1);
413 g_assert_true (weak == obj);
414
415 g_assert_true (g_set_weak_pointer (&weak, NULL));
416 g_assert_cmpint (obj->ref_count, ==, 1);
417 g_assert_null (weak);
418
419 g_assert_true (g_set_weak_pointer (&weak, obj));
420 g_assert_cmpint (obj->ref_count, ==, 1);
421 g_assert_true (weak == obj);
422
423 g_object_unref (object: obj);
424 g_assert_null (weak);
425}
426
427static void
428test_weak_pointer_set_function (void)
429{
430 GObject *obj;
431 gpointer weak = NULL;
432
433 g_assert_false ((g_set_weak_pointer) (&weak, NULL));
434 g_assert_null (weak);
435
436 obj = g_object_new (G_TYPE_OBJECT, NULL);
437 g_assert_cmpint (obj->ref_count, ==, 1);
438
439 g_assert_true ((g_set_weak_pointer) (&weak, obj));
440 g_assert_cmpint (obj->ref_count, ==, 1);
441 g_assert_true (weak == obj);
442
443 g_assert_true ((g_set_weak_pointer) (&weak, NULL));
444 g_assert_cmpint (obj->ref_count, ==, 1);
445 g_assert_null (weak);
446
447 g_assert_true ((g_set_weak_pointer) (&weak, obj));
448 g_assert_cmpint (obj->ref_count, ==, 1);
449 g_assert_true (weak == obj);
450
451 g_object_unref (object: obj);
452 g_assert_null (weak);
453}
454
455/* See gobject/tests/threadtests.c for the threaded version */
456static void
457test_weak_ref (void)
458{
459 GObject *obj;
460 GObject *obj2;
461 GObject *tmp;
462 GWeakRef weak = { { GUINT_TO_POINTER (0xDEADBEEFU) } };
463 GWeakRef weak2 = { { GUINT_TO_POINTER (0xDEADBEEFU) } };
464 GWeakRef weak3 = { { GUINT_TO_POINTER (0xDEADBEEFU) } };
465 GWeakRef *dynamic_weak = g_new (GWeakRef, 1);
466
467 /* you can initialize to empty like this... */
468 g_weak_ref_init (weak_ref: &weak2, NULL);
469 g_assert (g_weak_ref_get (&weak2) == NULL);
470
471 /* ... or via an initializer */
472 g_weak_ref_init (weak_ref: &weak3, NULL);
473 g_assert (g_weak_ref_get (&weak3) == NULL);
474
475 obj = g_object_new (G_TYPE_OBJECT, NULL);
476 g_assert_cmpint (obj->ref_count, ==, 1);
477
478 obj2 = g_object_new (G_TYPE_OBJECT, NULL);
479 g_assert_cmpint (obj2->ref_count, ==, 1);
480
481 /* you can init with an object (even if uninitialized) */
482 g_weak_ref_init (weak_ref: &weak, object: obj);
483 g_weak_ref_init (weak_ref: dynamic_weak, object: obj);
484 /* or set to point at an object, if initialized (maybe to 0) */
485 g_weak_ref_set (weak_ref: &weak2, object: obj);
486 g_weak_ref_set (weak_ref: &weak3, object: obj);
487 /* none of this affects its refcount */
488 g_assert_cmpint (obj->ref_count, ==, 1);
489
490 /* getting the value takes a ref */
491 tmp = g_weak_ref_get (weak_ref: &weak);
492 g_assert (tmp == obj);
493 g_assert_cmpint (obj->ref_count, ==, 2);
494 g_object_unref (object: tmp);
495 g_assert_cmpint (obj->ref_count, ==, 1);
496
497 tmp = g_weak_ref_get (weak_ref: &weak2);
498 g_assert (tmp == obj);
499 g_assert_cmpint (obj->ref_count, ==, 2);
500 g_object_unref (object: tmp);
501 g_assert_cmpint (obj->ref_count, ==, 1);
502
503 tmp = g_weak_ref_get (weak_ref: &weak3);
504 g_assert (tmp == obj);
505 g_assert_cmpint (obj->ref_count, ==, 2);
506 g_object_unref (object: tmp);
507 g_assert_cmpint (obj->ref_count, ==, 1);
508
509 tmp = g_weak_ref_get (weak_ref: dynamic_weak);
510 g_assert (tmp == obj);
511 g_assert_cmpint (obj->ref_count, ==, 2);
512 g_object_unref (object: tmp);
513 g_assert_cmpint (obj->ref_count, ==, 1);
514
515 /* clearing a weak ref stops tracking */
516 g_weak_ref_clear (weak_ref: &weak);
517
518 /* setting a weak ref to NULL stops tracking too */
519 g_weak_ref_set (weak_ref: &weak2, NULL);
520 g_assert (g_weak_ref_get (&weak2) == NULL);
521 g_weak_ref_clear (weak_ref: &weak2);
522
523 /* setting a weak ref to a new object stops tracking the old one */
524 g_weak_ref_set (weak_ref: dynamic_weak, object: obj2);
525 tmp = g_weak_ref_get (weak_ref: dynamic_weak);
526 g_assert (tmp == obj2);
527 g_assert_cmpint (obj2->ref_count, ==, 2);
528 g_object_unref (object: tmp);
529 g_assert_cmpint (obj2->ref_count, ==, 1);
530
531 g_assert_cmpint (obj->ref_count, ==, 1);
532
533 /* free the object: weak3 is the only one left pointing there */
534 g_object_unref (object: obj);
535 g_assert (g_weak_ref_get (&weak3) == NULL);
536
537 /* setting a weak ref to a new object stops tracking the old one */
538 g_weak_ref_set (weak_ref: dynamic_weak, object: obj2);
539 tmp = g_weak_ref_get (weak_ref: dynamic_weak);
540 g_assert (tmp == obj2);
541 g_assert_cmpint (obj2->ref_count, ==, 2);
542 g_object_unref (object: tmp);
543 g_assert_cmpint (obj2->ref_count, ==, 1);
544
545 g_weak_ref_clear (weak_ref: &weak3);
546
547 /* clear and free dynamic_weak... */
548 g_weak_ref_clear (weak_ref: dynamic_weak);
549
550 /* ... to prove that doing so stops this from being a use-after-free */
551 g_object_unref (object: obj2);
552 g_free (mem: dynamic_weak);
553}
554
555typedef struct
556{
557 gboolean should_be_last;
558 gint count;
559} Count;
560
561static void
562toggle_notify (gpointer data,
563 GObject *obj,
564 gboolean is_last)
565{
566 Count *c = data;
567
568 g_assert (is_last == c->should_be_last);
569
570 c->count++;
571}
572
573static void
574test_toggle_ref (void)
575{
576 GObject *obj;
577 Count c, c2;
578
579 obj = g_object_new (G_TYPE_OBJECT, NULL);
580
581 g_object_add_toggle_ref (object: obj, notify: toggle_notify, data: &c);
582 g_object_add_toggle_ref (object: obj, notify: toggle_notify, data: &c2);
583
584 c.should_be_last = c2.should_be_last = TRUE;
585 c.count = c2.count = 0;
586
587 g_object_unref (object: obj);
588
589 g_assert_cmpint (c.count, ==, 0);
590 g_assert_cmpint (c2.count, ==, 0);
591
592 g_object_ref (obj);
593
594 g_assert_cmpint (c.count, ==, 0);
595 g_assert_cmpint (c2.count, ==, 0);
596
597 g_object_remove_toggle_ref (object: obj, notify: toggle_notify, data: &c2);
598
599 g_object_unref (object: obj);
600
601 g_assert_cmpint (c.count, ==, 1);
602
603 c.should_be_last = FALSE;
604
605 g_object_ref (obj);
606
607 g_assert_cmpint (c.count, ==, 2);
608
609 c.should_be_last = TRUE;
610
611 g_object_unref (object: obj);
612
613 g_assert_cmpint (c.count, ==, 3);
614
615 g_object_remove_toggle_ref (object: obj, notify: toggle_notify, data: &c);
616}
617
618static gboolean destroyed;
619static gint value;
620
621static void
622data_destroy (gpointer data)
623{
624 g_assert_cmpint (GPOINTER_TO_INT (data), ==, value);
625
626 destroyed = TRUE;
627}
628
629static void
630test_object_qdata (void)
631{
632 GObject *obj;
633 gpointer v;
634 GQuark quark;
635
636 obj = g_object_new (G_TYPE_OBJECT, NULL);
637
638 value = 1;
639 destroyed = FALSE;
640 g_object_set_data_full (object: obj, key: "test", GINT_TO_POINTER (1), destroy: data_destroy);
641 v = g_object_get_data (object: obj, key: "test");
642 g_assert_cmpint (GPOINTER_TO_INT (v), ==, 1);
643 g_object_set_data_full (object: obj, key: "test", GINT_TO_POINTER (2), destroy: data_destroy);
644 g_assert (destroyed);
645 value = 2;
646 destroyed = FALSE;
647 v = g_object_steal_data (object: obj, key: "test");
648 g_assert_cmpint (GPOINTER_TO_INT (v), ==, 2);
649 g_assert (!destroyed);
650
651 value = 1;
652 destroyed = FALSE;
653 quark = g_quark_from_string (string: "test");
654 g_object_set_qdata_full (object: obj, quark, GINT_TO_POINTER (1), destroy: data_destroy);
655 v = g_object_get_qdata (object: obj, quark);
656 g_assert_cmpint (GPOINTER_TO_INT (v), ==, 1);
657 g_object_set_qdata_full (object: obj, quark, GINT_TO_POINTER (2), destroy: data_destroy);
658 g_assert (destroyed);
659 value = 2;
660 destroyed = FALSE;
661 v = g_object_steal_qdata (object: obj, quark);
662 g_assert_cmpint (GPOINTER_TO_INT (v), ==, 2);
663 g_assert (!destroyed);
664
665 g_object_set_qdata_full (object: obj, quark, GINT_TO_POINTER (3), destroy: data_destroy);
666 value = 3;
667 destroyed = FALSE;
668 g_object_unref (object: obj);
669
670 g_assert (destroyed);
671}
672
673typedef struct {
674 const gchar *value;
675 gint refcount;
676} Value;
677
678static gpointer
679ref_value (gpointer value, gpointer user_data)
680{
681 Value *v = value;
682 Value **old_value_p = user_data;
683
684 if (old_value_p)
685 *old_value_p = v;
686
687 if (v)
688 v->refcount += 1;
689
690 return value;
691}
692
693static void
694unref_value (gpointer value)
695{
696 Value *v = value;
697
698 v->refcount -= 1;
699 if (v->refcount == 0)
700 g_free (mem: value);
701}
702
703static
704Value *
705new_value (const gchar *s)
706{
707 Value *v;
708
709 v = g_new (Value, 1);
710 v->value = s;
711 v->refcount = 1;
712
713 return v;
714}
715
716static void
717test_object_qdata2 (void)
718{
719 GObject *obj;
720 Value *v, *v1, *v2, *v3, *old_val;
721 GDestroyNotify old_destroy;
722 gboolean res;
723
724 obj = g_object_new (G_TYPE_OBJECT, NULL);
725
726 v1 = new_value (s: "bla");
727
728 g_object_set_data_full (object: obj, key: "test", data: v1, destroy: unref_value);
729
730 v = g_object_get_data (object: obj, key: "test");
731 g_assert_cmpstr (v->value, ==, "bla");
732 g_assert_cmpint (v->refcount, ==, 1);
733
734 v = g_object_dup_data (object: obj, key: "test", dup_func: ref_value, user_data: &old_val);
735 g_assert (old_val == v1);
736 g_assert_cmpstr (v->value, ==, "bla");
737 g_assert_cmpint (v->refcount, ==, 2);
738 unref_value (value: v);
739
740 v = g_object_dup_data (object: obj, key: "nono", dup_func: ref_value, user_data: &old_val);
741 g_assert (old_val == NULL);
742 g_assert (v == NULL);
743
744 v2 = new_value (s: "not");
745
746 res = g_object_replace_data (object: obj, key: "test", oldval: v1, newval: v2, destroy: unref_value, old_destroy: &old_destroy);
747 g_assert (res == TRUE);
748 g_assert (old_destroy == unref_value);
749 g_assert_cmpstr (v1->value, ==, "bla");
750 g_assert_cmpint (v1->refcount, ==, 1);
751
752 v = g_object_get_data (object: obj, key: "test");
753 g_assert_cmpstr (v->value, ==, "not");
754 g_assert_cmpint (v->refcount, ==, 1);
755
756 v3 = new_value (s: "xyz");
757 res = g_object_replace_data (object: obj, key: "test", oldval: v1, newval: v3, destroy: unref_value, old_destroy: &old_destroy);
758 g_assert (res == FALSE);
759 g_assert_cmpstr (v2->value, ==, "not");
760 g_assert_cmpint (v2->refcount, ==, 1);
761
762 unref_value (value: v1);
763
764 res = g_object_replace_data (object: obj, key: "test", NULL, newval: v3, destroy: unref_value, old_destroy: &old_destroy);
765 g_assert (res == FALSE);
766 g_assert_cmpstr (v2->value, ==, "not");
767 g_assert_cmpint (v2->refcount, ==, 1);
768
769 res = g_object_replace_data (object: obj, key: "test", oldval: v2, NULL, destroy: unref_value, old_destroy: &old_destroy);
770 g_assert (res == TRUE);
771 g_assert (old_destroy == unref_value);
772 g_assert_cmpstr (v2->value, ==, "not");
773 g_assert_cmpint (v2->refcount, ==, 1);
774
775 unref_value (value: v2);
776
777 v = g_object_get_data (object: obj, key: "test");
778 g_assert (v == NULL);
779
780 res = g_object_replace_data (object: obj, key: "test", NULL, newval: v3, destroy: unref_value, old_destroy: &old_destroy);
781 g_assert (res == TRUE);
782
783 v = g_object_get_data (object: obj, key: "test");
784 g_assert (v == v3);
785
786 ref_value (value: v3, NULL);
787 g_assert_cmpint (v3->refcount, ==, 2);
788 g_object_unref (object: obj);
789 g_assert_cmpint (v3->refcount, ==, 1);
790 unref_value (value: v3);
791}
792
793int
794main (int argc, char **argv)
795{
796 g_test_init (argc: &argc, argv: &argv, NULL);
797
798 g_test_add_func (testpath: "/type/fundamentals", test_func: test_fundamentals);
799 g_test_add_func (testpath: "/type/qdata", test_func: test_type_qdata);
800 g_test_add_func (testpath: "/type/query", test_func: test_type_query);
801 g_test_add_func (testpath: "/type/class-private", test_func: test_class_private);
802 g_test_add_func (testpath: "/object/clear", test_func: test_clear);
803 g_test_add_func (testpath: "/object/clear-function", test_func: test_clear_function);
804 g_test_add_func (testpath: "/object/set", test_func: test_set);
805 g_test_add_func (testpath: "/object/set-function", test_func: test_set_function);
806 g_test_add_func (testpath: "/object/set/derived-type", test_func: test_set_derived_type);
807 g_test_add_func (testpath: "/object/value", test_func: test_object_value);
808 g_test_add_func (testpath: "/object/initially-unowned", test_func: test_initially_unowned);
809 g_test_add_func (testpath: "/object/weak-pointer", test_func: test_weak_pointer);
810 g_test_add_func (testpath: "/object/weak-pointer/clear", test_func: test_weak_pointer_clear);
811 g_test_add_func (testpath: "/object/weak-pointer/clear-function", test_func: test_weak_pointer_clear_function);
812 g_test_add_func (testpath: "/object/weak-pointer/set", test_func: test_weak_pointer_set);
813 g_test_add_func (testpath: "/object/weak-pointer/set-function", test_func: test_weak_pointer_set_function);
814 g_test_add_func (testpath: "/object/weak-ref", test_func: test_weak_ref);
815 g_test_add_func (testpath: "/object/toggle-ref", test_func: test_toggle_ref);
816 g_test_add_func (testpath: "/object/qdata", test_func: test_object_qdata);
817 g_test_add_func (testpath: "/object/qdata2", test_func: test_object_qdata2);
818
819 return g_test_run ();
820}
821

source code of gtk/subprojects/glib/gobject/tests/reference.c