• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <glib-object.h>
2 
3 static void
test_fundamentals(void)4 test_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 
33 static void
test_type_qdata(void)34 test_type_qdata (void)
35 {
36   gchar *data;
37 
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");
41 }
42 
43 static void
test_type_query(void)44 test_type_query (void)
45 {
46   GTypeQuery query;
47 
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);
53 }
54 
55 typedef struct _MyObject MyObject;
56 typedef struct _MyObjectClass MyObjectClass;
57 typedef struct _MyObjectClassPrivate MyObjectClassPrivate;
58 
59 struct _MyObject
60 {
61   GObject parent_instance;
62 
63   gint count;
64 };
65 
66 struct _MyObjectClass
67 {
68   GObjectClass parent_class;
69 };
70 
71 struct _MyObjectClassPrivate
72 {
73   gint secret_class_count;
74 };
75 
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)) );
79 
80 static void
my_object_init(MyObject * obj)81 my_object_init (MyObject *obj)
82 {
83   obj->count = 42;
84 }
85 
86 static void
my_object_class_init(MyObjectClass * klass)87 my_object_class_init (MyObjectClass *klass)
88 {
89 }
90 
91 static void
test_class_private(void)92 test_class_private (void)
93 {
94   GObject *obj;
95   MyObjectClass *class;
96   MyObjectClassPrivate *priv;
97 
98   obj = g_object_new (my_object_get_type (), NULL);
99 
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);
104 
105   g_object_unref (obj);
106 
107   g_assert_cmpint (g_type_qname (my_object_get_type ()), ==, g_quark_from_string ("MyObject"));
108 }
109 
110 static void
test_clear(void)111 test_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 (tmp);
130 }
131 
132 static void
test_clear_function(void)133 test_clear_function (void)
134 {
135   GObject *o = NULL;
136   GObject *tmp;
137 
138   (g_clear_object) (&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) (&o);
148   g_assert_cmpint (tmp->ref_count, ==, 1);
149   g_assert (o == NULL);
150 
151   g_object_unref (tmp);
152 }
153 
154 static void
test_set(void)155 test_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 (tmp, &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 (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 
187 static void
test_set_function(void)188 test_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 (tmp, &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 (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 
220 static void
test_set_derived_type(void)221 test_set_derived_type (void)
222 {
223   GBinding *obj = NULL;
224   GObject *o = NULL;
225   GBinding *b = NULL;
226 
227   g_test_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 (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 (obj);
245   g_clear_object (&b);
246   g_clear_object (&o);
247 }
248 
249 static void
toggle_cb(gpointer data,GObject * obj,gboolean is_last)250 toggle_cb (gpointer data, GObject *obj, gboolean is_last)
251 {
252   gboolean *b = data;
253 
254   *b = TRUE;
255 }
256 
257 static void
test_object_value(void)258 test_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, G_TYPE_OBJECT);
266 
267   v = g_object_new (G_TYPE_OBJECT, NULL);
268   g_object_add_toggle_ref (v, toggle_cb, &toggled);
269 
270   g_value_take_object (&value, v);
271 
272   v2 = g_value_get_object (&value);
273   g_assert (v2 == v);
274 
275   v2 = g_value_dup_object (&value);
276   g_assert (v2 == v);  /* objects use ref/unref for copy/free */
277   g_object_unref (v2);
278 
279   g_assert (!toggled);
280   g_value_unset (&value);
281   g_assert (toggled);
282 
283   /* test the deprecated variant too */
284   g_value_init (&value, G_TYPE_OBJECT);
285   /* get a new reference */
286   g_object_ref (v);
287 
288 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
289   g_value_set_object_take_ownership (&value, v);
290 G_GNUC_END_IGNORE_DEPRECATIONS
291 
292   toggled = FALSE;
293   g_value_unset (&value);
294   g_assert (toggled);
295 
296   g_object_remove_toggle_ref (v, toggle_cb, &toggled);
297 }
298 
299 static void
test_initially_unowned(void)300 test_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 (obj);
317   g_assert_cmpint (obj->ref_count, ==, 1);
318 
319   g_object_force_floating (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 (obj);
325 }
326 
327 static void
test_weak_pointer(void)328 test_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 (obj, &weak);
338   g_object_add_weak_pointer (obj, &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 (obj, &weak2);
344   g_assert_cmpint (obj->ref_count, ==, 1);
345   g_assert (weak == obj);
346   g_assert (weak2 == obj);
347 
348   g_object_unref (obj);
349   g_assert (weak == NULL);
350   g_assert (weak2 == obj);
351 }
352 
353 static void
test_weak_pointer_clear(void)354 test_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 (obj, &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 (obj);
374 }
375 
376 static void
test_weak_pointer_clear_function(void)377 test_weak_pointer_clear_function (void)
378 {
379   GObject *obj;
380   gpointer weak = NULL;
381 
382   (g_clear_weak_pointer) (&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 (obj, &weak);
389   g_assert_cmpint (obj->ref_count, ==, 1);
390   g_assert_true (weak == obj);
391 
392   (g_clear_weak_pointer) (&weak);
393   g_assert_cmpint (obj->ref_count, ==, 1);
394   g_assert_null (weak);
395 
396   g_object_unref (obj);
397 }
398 
399 static void
test_weak_pointer_set(void)400 test_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 (obj);
424   g_assert_null (weak);
425 }
426 
427 static void
test_weak_pointer_set_function(void)428 test_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 (obj);
452   g_assert_null (weak);
453 }
454 
455 /* See gobject/tests/threadtests.c for the threaded version */
456 static void
test_weak_ref(void)457 test_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 (&weak2, NULL);
469   g_assert (g_weak_ref_get (&weak2) == NULL);
470 
471   /* ... or via an initializer */
472   g_weak_ref_init (&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, obj);
483   g_weak_ref_init (dynamic_weak, obj);
484   /* or set to point at an object, if initialized (maybe to 0) */
485   g_weak_ref_set (&weak2, obj);
486   g_weak_ref_set (&weak3, 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);
492   g_assert (tmp == obj);
493   g_assert_cmpint (obj->ref_count, ==, 2);
494   g_object_unref (tmp);
495   g_assert_cmpint (obj->ref_count, ==, 1);
496 
497   tmp = g_weak_ref_get (&weak2);
498   g_assert (tmp == obj);
499   g_assert_cmpint (obj->ref_count, ==, 2);
500   g_object_unref (tmp);
501   g_assert_cmpint (obj->ref_count, ==, 1);
502 
503   tmp = g_weak_ref_get (&weak3);
504   g_assert (tmp == obj);
505   g_assert_cmpint (obj->ref_count, ==, 2);
506   g_object_unref (tmp);
507   g_assert_cmpint (obj->ref_count, ==, 1);
508 
509   tmp = g_weak_ref_get (dynamic_weak);
510   g_assert (tmp == obj);
511   g_assert_cmpint (obj->ref_count, ==, 2);
512   g_object_unref (tmp);
513   g_assert_cmpint (obj->ref_count, ==, 1);
514 
515   /* clearing a weak ref stops tracking */
516   g_weak_ref_clear (&weak);
517 
518   /* setting a weak ref to NULL stops tracking too */
519   g_weak_ref_set (&weak2, NULL);
520   g_assert (g_weak_ref_get (&weak2) == NULL);
521   g_weak_ref_clear (&weak2);
522 
523   /* setting a weak ref to a new object stops tracking the old one */
524   g_weak_ref_set (dynamic_weak, obj2);
525   tmp = g_weak_ref_get (dynamic_weak);
526   g_assert (tmp == obj2);
527   g_assert_cmpint (obj2->ref_count, ==, 2);
528   g_object_unref (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 (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 (dynamic_weak, obj2);
539   tmp = g_weak_ref_get (dynamic_weak);
540   g_assert (tmp == obj2);
541   g_assert_cmpint (obj2->ref_count, ==, 2);
542   g_object_unref (tmp);
543   g_assert_cmpint (obj2->ref_count, ==, 1);
544 
545   g_weak_ref_clear (&weak3);
546 
547   /* clear and free dynamic_weak... */
548   g_weak_ref_clear (dynamic_weak);
549 
550   /* ... to prove that doing so stops this from being a use-after-free */
551   g_object_unref (obj2);
552   g_free (dynamic_weak);
553 }
554 
555 typedef struct
556 {
557   gboolean should_be_last;
558   gint count;
559 } Count;
560 
561 static void
toggle_notify(gpointer data,GObject * obj,gboolean is_last)562 toggle_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 
573 static void
test_toggle_ref(void)574 test_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 (obj, toggle_notify, &c);
582   g_object_add_toggle_ref (obj, toggle_notify, &c2);
583 
584   c.should_be_last = c2.should_be_last = TRUE;
585   c.count = c2.count = 0;
586 
587   g_object_unref (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 (obj, toggle_notify, &c2);
598 
599   g_object_unref (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 (obj);
612 
613   g_assert_cmpint (c.count, ==, 3);
614 
615   g_object_remove_toggle_ref (obj, toggle_notify, &c);
616 }
617 
618 static gboolean destroyed;
619 static gint value;
620 
621 static void
data_destroy(gpointer data)622 data_destroy (gpointer data)
623 {
624   g_assert_cmpint (GPOINTER_TO_INT (data), ==, value);
625 
626   destroyed = TRUE;
627 }
628 
629 static void
test_object_qdata(void)630 test_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 (obj, "test", GINT_TO_POINTER (1), data_destroy);
641   v = g_object_get_data (obj, "test");
642   g_assert_cmpint (GPOINTER_TO_INT (v), ==, 1);
643   g_object_set_data_full (obj, "test", GINT_TO_POINTER (2), data_destroy);
644   g_assert (destroyed);
645   value = 2;
646   destroyed = FALSE;
647   v = g_object_steal_data (obj, "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 ("test");
654   g_object_set_qdata_full (obj, quark, GINT_TO_POINTER (1), data_destroy);
655   v = g_object_get_qdata (obj, quark);
656   g_assert_cmpint (GPOINTER_TO_INT (v), ==, 1);
657   g_object_set_qdata_full (obj, quark, GINT_TO_POINTER (2), data_destroy);
658   g_assert (destroyed);
659   value = 2;
660   destroyed = FALSE;
661   v = g_object_steal_qdata (obj, quark);
662   g_assert_cmpint (GPOINTER_TO_INT (v), ==, 2);
663   g_assert (!destroyed);
664 
665   g_object_set_qdata_full (obj, quark, GINT_TO_POINTER (3), data_destroy);
666   value = 3;
667   destroyed = FALSE;
668   g_object_unref (obj);
669 
670   g_assert (destroyed);
671 }
672 
673 typedef struct {
674   const gchar *value;
675   gint refcount;
676 } Value;
677 
678 static gpointer
ref_value(gpointer value,gpointer user_data)679 ref_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 
693 static void
unref_value(gpointer value)694 unref_value (gpointer value)
695 {
696   Value *v = value;
697 
698   v->refcount -= 1;
699   if (v->refcount == 0)
700     g_free (value);
701 }
702 
703 static
704 Value *
new_value(const gchar * s)705 new_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 
716 static void
test_object_qdata2(void)717 test_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 ("bla");
727 
728   g_object_set_data_full (obj, "test", v1, unref_value);
729 
730   v = g_object_get_data (obj, "test");
731   g_assert_cmpstr (v->value, ==, "bla");
732   g_assert_cmpint (v->refcount, ==, 1);
733 
734   v = g_object_dup_data (obj, "test", ref_value, &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 (v);
739 
740   v = g_object_dup_data (obj, "nono", ref_value, &old_val);
741   g_assert (old_val == NULL);
742   g_assert (v == NULL);
743 
744   v2 = new_value ("not");
745 
746   res = g_object_replace_data (obj, "test", v1, v2, unref_value, &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 (obj, "test");
753   g_assert_cmpstr (v->value, ==, "not");
754   g_assert_cmpint (v->refcount, ==, 1);
755 
756   v3 = new_value ("xyz");
757   res = g_object_replace_data (obj, "test", v1, v3, unref_value, &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 (v1);
763 
764   res = g_object_replace_data (obj, "test", NULL, v3, unref_value, &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 (obj, "test", v2, NULL, unref_value, &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 (v2);
776 
777   v = g_object_get_data (obj, "test");
778   g_assert (v == NULL);
779 
780   res = g_object_replace_data (obj, "test", NULL, v3, unref_value, &old_destroy);
781   g_assert (res == TRUE);
782 
783   v = g_object_get_data (obj, "test");
784   g_assert (v == v3);
785 
786   ref_value (v3, NULL);
787   g_assert_cmpint (v3->refcount, ==, 2);
788   g_object_unref (obj);
789   g_assert_cmpint (v3->refcount, ==, 1);
790   unref_value (v3);
791 }
792 
793 int
main(int argc,char ** argv)794 main (int argc, char **argv)
795 {
796   g_test_init (&argc, &argv, NULL);
797 
798   g_test_add_func ("/type/fundamentals", test_fundamentals);
799   g_test_add_func ("/type/qdata", test_type_qdata);
800   g_test_add_func ("/type/query", test_type_query);
801   g_test_add_func ("/type/class-private", test_class_private);
802   g_test_add_func ("/object/clear", test_clear);
803   g_test_add_func ("/object/clear-function", test_clear_function);
804   g_test_add_func ("/object/set", test_set);
805   g_test_add_func ("/object/set-function", test_set_function);
806   g_test_add_func ("/object/set/derived-type", test_set_derived_type);
807   g_test_add_func ("/object/value", test_object_value);
808   g_test_add_func ("/object/initially-unowned", test_initially_unowned);
809   g_test_add_func ("/object/weak-pointer", test_weak_pointer);
810   g_test_add_func ("/object/weak-pointer/clear", test_weak_pointer_clear);
811   g_test_add_func ("/object/weak-pointer/clear-function", test_weak_pointer_clear_function);
812   g_test_add_func ("/object/weak-pointer/set", test_weak_pointer_set);
813   g_test_add_func ("/object/weak-pointer/set-function", test_weak_pointer_set_function);
814   g_test_add_func ("/object/weak-ref", test_weak_ref);
815   g_test_add_func ("/object/toggle-ref", test_toggle_ref);
816   g_test_add_func ("/object/qdata", test_object_qdata);
817   g_test_add_func ("/object/qdata2", test_object_qdata2);
818 
819   return g_test_run ();
820 }
821