• 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
toggle_cb(gpointer data,GObject * obj,gboolean is_last)221 toggle_cb (gpointer data, GObject *obj, gboolean is_last)
222 {
223   gboolean *b = data;
224 
225   *b = TRUE;
226 }
227 
228 static void
test_object_value(void)229 test_object_value (void)
230 {
231   GObject *v;
232   GObject *v2;
233   GValue value = G_VALUE_INIT;
234   gboolean toggled = FALSE;
235 
236   g_value_init (&value, G_TYPE_OBJECT);
237 
238   v = g_object_new (G_TYPE_OBJECT, NULL);
239   g_object_add_toggle_ref (v, toggle_cb, &toggled);
240 
241   g_value_take_object (&value, v);
242 
243   v2 = g_value_get_object (&value);
244   g_assert (v2 == v);
245 
246   v2 = g_value_dup_object (&value);
247   g_assert (v2 == v);  /* objects use ref/unref for copy/free */
248   g_object_unref (v2);
249 
250   g_assert (!toggled);
251   g_value_unset (&value);
252   g_assert (toggled);
253 
254   /* test the deprecated variant too */
255   g_value_init (&value, G_TYPE_OBJECT);
256   /* get a new reference */
257   g_object_ref (v);
258 
259 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
260   g_value_set_object_take_ownership (&value, v);
261 G_GNUC_END_IGNORE_DEPRECATIONS
262 
263   toggled = FALSE;
264   g_value_unset (&value);
265   g_assert (toggled);
266 
267   g_object_remove_toggle_ref (v, toggle_cb, &toggled);
268 }
269 
270 static void
test_initially_unowned(void)271 test_initially_unowned (void)
272 {
273   GObject *obj;
274 
275   obj = g_object_new (G_TYPE_INITIALLY_UNOWNED, NULL);
276   g_assert (g_object_is_floating (obj));
277   g_assert_cmpint (obj->ref_count, ==, 1);
278 
279   g_object_ref_sink (obj);
280   g_assert (!g_object_is_floating (obj));
281   g_assert_cmpint (obj->ref_count, ==, 1);
282 
283   g_object_ref_sink (obj);
284   g_assert (!g_object_is_floating (obj));
285   g_assert_cmpint (obj->ref_count, ==, 2);
286 
287   g_object_unref (obj);
288   g_assert_cmpint (obj->ref_count, ==, 1);
289 
290   g_object_force_floating (obj);
291   g_assert (g_object_is_floating (obj));
292   g_assert_cmpint (obj->ref_count, ==, 1);
293 
294   g_object_ref_sink (obj);
295   g_object_unref (obj);
296 }
297 
298 static void
test_weak_pointer(void)299 test_weak_pointer (void)
300 {
301   GObject *obj;
302   gpointer weak;
303   gpointer weak2;
304 
305   weak = weak2 = obj = g_object_new (G_TYPE_OBJECT, NULL);
306   g_assert_cmpint (obj->ref_count, ==, 1);
307 
308   g_object_add_weak_pointer (obj, &weak);
309   g_object_add_weak_pointer (obj, &weak2);
310   g_assert_cmpint (obj->ref_count, ==, 1);
311   g_assert (weak == obj);
312   g_assert (weak2 == obj);
313 
314   g_object_remove_weak_pointer (obj, &weak2);
315   g_assert_cmpint (obj->ref_count, ==, 1);
316   g_assert (weak == obj);
317   g_assert (weak2 == obj);
318 
319   g_object_unref (obj);
320   g_assert (weak == NULL);
321   g_assert (weak2 == obj);
322 }
323 
324 static void
test_weak_pointer_clear(void)325 test_weak_pointer_clear (void)
326 {
327   GObject *obj;
328   gpointer weak = NULL;
329 
330   g_clear_weak_pointer (&weak);
331   g_assert_null (weak);
332 
333   weak = obj = g_object_new (G_TYPE_OBJECT, NULL);
334   g_assert_cmpint (obj->ref_count, ==, 1);
335 
336   g_object_add_weak_pointer (obj, &weak);
337   g_assert_cmpint (obj->ref_count, ==, 1);
338   g_assert_true (weak == obj);
339 
340   g_clear_weak_pointer (&weak);
341   g_assert_cmpint (obj->ref_count, ==, 1);
342   g_assert_null (weak);
343 
344   g_object_unref (obj);
345 }
346 
347 static void
test_weak_pointer_clear_function(void)348 test_weak_pointer_clear_function (void)
349 {
350   GObject *obj;
351   gpointer weak = NULL;
352 
353   (g_clear_weak_pointer) (&weak);
354   g_assert_null (weak);
355 
356   weak = obj = g_object_new (G_TYPE_OBJECT, NULL);
357   g_assert_cmpint (obj->ref_count, ==, 1);
358 
359   g_object_add_weak_pointer (obj, &weak);
360   g_assert_cmpint (obj->ref_count, ==, 1);
361   g_assert_true (weak == obj);
362 
363   (g_clear_weak_pointer) (&weak);
364   g_assert_cmpint (obj->ref_count, ==, 1);
365   g_assert_null (weak);
366 
367   g_object_unref (obj);
368 }
369 
370 static void
test_weak_pointer_set(void)371 test_weak_pointer_set (void)
372 {
373   GObject *obj;
374   gpointer weak = NULL;
375 
376   g_assert_false (g_set_weak_pointer (&weak, NULL));
377   g_assert_null (weak);
378 
379   obj = g_object_new (G_TYPE_OBJECT, NULL);
380   g_assert_cmpint (obj->ref_count, ==, 1);
381 
382   g_assert_true (g_set_weak_pointer (&weak, obj));
383   g_assert_cmpint (obj->ref_count, ==, 1);
384   g_assert_true (weak == obj);
385 
386   g_assert_true (g_set_weak_pointer (&weak, NULL));
387   g_assert_cmpint (obj->ref_count, ==, 1);
388   g_assert_null (weak);
389 
390   g_assert_true (g_set_weak_pointer (&weak, obj));
391   g_assert_cmpint (obj->ref_count, ==, 1);
392   g_assert_true (weak == obj);
393 
394   g_object_unref (obj);
395   g_assert_null (weak);
396 }
397 
398 static void
test_weak_pointer_set_function(void)399 test_weak_pointer_set_function (void)
400 {
401   GObject *obj;
402   gpointer weak = NULL;
403 
404   g_assert_false ((g_set_weak_pointer) (&weak, NULL));
405   g_assert_null (weak);
406 
407   obj = g_object_new (G_TYPE_OBJECT, NULL);
408   g_assert_cmpint (obj->ref_count, ==, 1);
409 
410   g_assert_true ((g_set_weak_pointer) (&weak, obj));
411   g_assert_cmpint (obj->ref_count, ==, 1);
412   g_assert_true (weak == obj);
413 
414   g_assert_true ((g_set_weak_pointer) (&weak, NULL));
415   g_assert_cmpint (obj->ref_count, ==, 1);
416   g_assert_null (weak);
417 
418   g_assert_true ((g_set_weak_pointer) (&weak, obj));
419   g_assert_cmpint (obj->ref_count, ==, 1);
420   g_assert_true (weak == obj);
421 
422   g_object_unref (obj);
423   g_assert_null (weak);
424 }
425 
426 /* See gobject/tests/threadtests.c for the threaded version */
427 static void
test_weak_ref(void)428 test_weak_ref (void)
429 {
430   GObject *obj;
431   GObject *obj2;
432   GObject *tmp;
433   GWeakRef weak = { { GUINT_TO_POINTER (0xDEADBEEFU) } };
434   GWeakRef weak2 = { { GUINT_TO_POINTER (0xDEADBEEFU) } };
435   GWeakRef weak3 = { { GUINT_TO_POINTER (0xDEADBEEFU) } };
436   GWeakRef *dynamic_weak = g_new (GWeakRef, 1);
437 
438   /* you can initialize to empty like this... */
439   g_weak_ref_init (&weak2, NULL);
440   g_assert (g_weak_ref_get (&weak2) == NULL);
441 
442   /* ... or via an initializer */
443   g_weak_ref_init (&weak3, NULL);
444   g_assert (g_weak_ref_get (&weak3) == NULL);
445 
446   obj = g_object_new (G_TYPE_OBJECT, NULL);
447   g_assert_cmpint (obj->ref_count, ==, 1);
448 
449   obj2 = g_object_new (G_TYPE_OBJECT, NULL);
450   g_assert_cmpint (obj2->ref_count, ==, 1);
451 
452   /* you can init with an object (even if uninitialized) */
453   g_weak_ref_init (&weak, obj);
454   g_weak_ref_init (dynamic_weak, obj);
455   /* or set to point at an object, if initialized (maybe to 0) */
456   g_weak_ref_set (&weak2, obj);
457   g_weak_ref_set (&weak3, obj);
458   /* none of this affects its refcount */
459   g_assert_cmpint (obj->ref_count, ==, 1);
460 
461   /* getting the value takes a ref */
462   tmp = g_weak_ref_get (&weak);
463   g_assert (tmp == obj);
464   g_assert_cmpint (obj->ref_count, ==, 2);
465   g_object_unref (tmp);
466   g_assert_cmpint (obj->ref_count, ==, 1);
467 
468   tmp = g_weak_ref_get (&weak2);
469   g_assert (tmp == obj);
470   g_assert_cmpint (obj->ref_count, ==, 2);
471   g_object_unref (tmp);
472   g_assert_cmpint (obj->ref_count, ==, 1);
473 
474   tmp = g_weak_ref_get (&weak3);
475   g_assert (tmp == obj);
476   g_assert_cmpint (obj->ref_count, ==, 2);
477   g_object_unref (tmp);
478   g_assert_cmpint (obj->ref_count, ==, 1);
479 
480   tmp = g_weak_ref_get (dynamic_weak);
481   g_assert (tmp == obj);
482   g_assert_cmpint (obj->ref_count, ==, 2);
483   g_object_unref (tmp);
484   g_assert_cmpint (obj->ref_count, ==, 1);
485 
486   /* clearing a weak ref stops tracking */
487   g_weak_ref_clear (&weak);
488 
489   /* setting a weak ref to NULL stops tracking too */
490   g_weak_ref_set (&weak2, NULL);
491   g_assert (g_weak_ref_get (&weak2) == NULL);
492   g_weak_ref_clear (&weak2);
493 
494   /* setting a weak ref to a new object stops tracking the old one */
495   g_weak_ref_set (dynamic_weak, obj2);
496   tmp = g_weak_ref_get (dynamic_weak);
497   g_assert (tmp == obj2);
498   g_assert_cmpint (obj2->ref_count, ==, 2);
499   g_object_unref (tmp);
500   g_assert_cmpint (obj2->ref_count, ==, 1);
501 
502   g_assert_cmpint (obj->ref_count, ==, 1);
503 
504   /* free the object: weak3 is the only one left pointing there */
505   g_object_unref (obj);
506   g_assert (g_weak_ref_get (&weak3) == NULL);
507 
508   /* setting a weak ref to a new object stops tracking the old one */
509   g_weak_ref_set (dynamic_weak, obj2);
510   tmp = g_weak_ref_get (dynamic_weak);
511   g_assert (tmp == obj2);
512   g_assert_cmpint (obj2->ref_count, ==, 2);
513   g_object_unref (tmp);
514   g_assert_cmpint (obj2->ref_count, ==, 1);
515 
516   g_weak_ref_clear (&weak3);
517 
518   /* clear and free dynamic_weak... */
519   g_weak_ref_clear (dynamic_weak);
520 
521   /* ... to prove that doing so stops this from being a use-after-free */
522   g_object_unref (obj2);
523   g_free (dynamic_weak);
524 }
525 
526 typedef struct
527 {
528   gboolean should_be_last;
529   gint count;
530 } Count;
531 
532 static void
toggle_notify(gpointer data,GObject * obj,gboolean is_last)533 toggle_notify (gpointer  data,
534                GObject  *obj,
535                gboolean  is_last)
536 {
537   Count *c = data;
538 
539   g_assert (is_last == c->should_be_last);
540 
541   c->count++;
542 }
543 
544 static void
test_toggle_ref(void)545 test_toggle_ref (void)
546 {
547   GObject *obj;
548   Count c, c2;
549 
550   obj = g_object_new (G_TYPE_OBJECT, NULL);
551 
552   g_object_add_toggle_ref (obj, toggle_notify, &c);
553   g_object_add_toggle_ref (obj, toggle_notify, &c2);
554 
555   c.should_be_last = c2.should_be_last = TRUE;
556   c.count = c2.count = 0;
557 
558   g_object_unref (obj);
559 
560   g_assert_cmpint (c.count, ==, 0);
561   g_assert_cmpint (c2.count, ==, 0);
562 
563   g_object_ref (obj);
564 
565   g_assert_cmpint (c.count, ==, 0);
566   g_assert_cmpint (c2.count, ==, 0);
567 
568   g_object_remove_toggle_ref (obj, toggle_notify, &c2);
569 
570   g_object_unref (obj);
571 
572   g_assert_cmpint (c.count, ==, 1);
573 
574   c.should_be_last = FALSE;
575 
576   g_object_ref (obj);
577 
578   g_assert_cmpint (c.count, ==, 2);
579 
580   c.should_be_last = TRUE;
581 
582   g_object_unref (obj);
583 
584   g_assert_cmpint (c.count, ==, 3);
585 
586   g_object_remove_toggle_ref (obj, toggle_notify, &c);
587 }
588 
589 static gboolean destroyed;
590 static gint value;
591 
592 static void
data_destroy(gpointer data)593 data_destroy (gpointer data)
594 {
595   g_assert_cmpint (GPOINTER_TO_INT (data), ==, value);
596 
597   destroyed = TRUE;
598 }
599 
600 static void
test_object_qdata(void)601 test_object_qdata (void)
602 {
603   GObject *obj;
604   gpointer v;
605   GQuark quark;
606 
607   obj = g_object_new (G_TYPE_OBJECT, NULL);
608 
609   value = 1;
610   destroyed = FALSE;
611   g_object_set_data_full (obj, "test", GINT_TO_POINTER (1), data_destroy);
612   v = g_object_get_data (obj, "test");
613   g_assert_cmpint (GPOINTER_TO_INT (v), ==, 1);
614   g_object_set_data_full (obj, "test", GINT_TO_POINTER (2), data_destroy);
615   g_assert (destroyed);
616   value = 2;
617   destroyed = FALSE;
618   v = g_object_steal_data (obj, "test");
619   g_assert_cmpint (GPOINTER_TO_INT (v), ==, 2);
620   g_assert (!destroyed);
621 
622   value = 1;
623   destroyed = FALSE;
624   quark = g_quark_from_string ("test");
625   g_object_set_qdata_full (obj, quark, GINT_TO_POINTER (1), data_destroy);
626   v = g_object_get_qdata (obj, quark);
627   g_assert_cmpint (GPOINTER_TO_INT (v), ==, 1);
628   g_object_set_qdata_full (obj, quark, GINT_TO_POINTER (2), data_destroy);
629   g_assert (destroyed);
630   value = 2;
631   destroyed = FALSE;
632   v = g_object_steal_qdata (obj, quark);
633   g_assert_cmpint (GPOINTER_TO_INT (v), ==, 2);
634   g_assert (!destroyed);
635 
636   g_object_set_qdata_full (obj, quark, GINT_TO_POINTER (3), data_destroy);
637   value = 3;
638   destroyed = FALSE;
639   g_object_unref (obj);
640 
641   g_assert (destroyed);
642 }
643 
644 typedef struct {
645   const gchar *value;
646   gint refcount;
647 } Value;
648 
649 static gpointer
ref_value(gpointer value,gpointer user_data)650 ref_value (gpointer value, gpointer user_data)
651 {
652   Value *v = value;
653   Value **old_value_p = user_data;
654 
655   if (old_value_p)
656     *old_value_p = v;
657 
658   if (v)
659     v->refcount += 1;
660 
661   return value;
662 }
663 
664 static void
unref_value(gpointer value)665 unref_value (gpointer value)
666 {
667   Value *v = value;
668 
669   v->refcount -= 1;
670   if (v->refcount == 0)
671     g_free (value);
672 }
673 
674 static
675 Value *
new_value(const gchar * s)676 new_value (const gchar *s)
677 {
678   Value *v;
679 
680   v = g_new (Value, 1);
681   v->value = s;
682   v->refcount = 1;
683 
684   return v;
685 }
686 
687 static void
test_object_qdata2(void)688 test_object_qdata2 (void)
689 {
690   GObject *obj;
691   Value *v, *v1, *v2, *v3, *old_val;
692   GDestroyNotify old_destroy;
693   gboolean res;
694 
695   obj = g_object_new (G_TYPE_OBJECT, NULL);
696 
697   v1 = new_value ("bla");
698 
699   g_object_set_data_full (obj, "test", v1, unref_value);
700 
701   v = g_object_get_data (obj, "test");
702   g_assert_cmpstr (v->value, ==, "bla");
703   g_assert_cmpint (v->refcount, ==, 1);
704 
705   v = g_object_dup_data (obj, "test", ref_value, &old_val);
706   g_assert (old_val == v1);
707   g_assert_cmpstr (v->value, ==, "bla");
708   g_assert_cmpint (v->refcount, ==, 2);
709   unref_value (v);
710 
711   v = g_object_dup_data (obj, "nono", ref_value, &old_val);
712   g_assert (old_val == NULL);
713   g_assert (v == NULL);
714 
715   v2 = new_value ("not");
716 
717   res = g_object_replace_data (obj, "test", v1, v2, unref_value, &old_destroy);
718   g_assert (res == TRUE);
719   g_assert (old_destroy == unref_value);
720   g_assert_cmpstr (v1->value, ==, "bla");
721   g_assert_cmpint (v1->refcount, ==, 1);
722 
723   v = g_object_get_data (obj, "test");
724   g_assert_cmpstr (v->value, ==, "not");
725   g_assert_cmpint (v->refcount, ==, 1);
726 
727   v3 = new_value ("xyz");
728   res = g_object_replace_data (obj, "test", v1, v3, unref_value, &old_destroy);
729   g_assert (res == FALSE);
730   g_assert_cmpstr (v2->value, ==, "not");
731   g_assert_cmpint (v2->refcount, ==, 1);
732 
733   unref_value (v1);
734 
735   res = g_object_replace_data (obj, "test", NULL, v3, unref_value, &old_destroy);
736   g_assert (res == FALSE);
737   g_assert_cmpstr (v2->value, ==, "not");
738   g_assert_cmpint (v2->refcount, ==, 1);
739 
740   res = g_object_replace_data (obj, "test", v2, NULL, unref_value, &old_destroy);
741   g_assert (res == TRUE);
742   g_assert (old_destroy == unref_value);
743   g_assert_cmpstr (v2->value, ==, "not");
744   g_assert_cmpint (v2->refcount, ==, 1);
745 
746   unref_value (v2);
747 
748   v = g_object_get_data (obj, "test");
749   g_assert (v == NULL);
750 
751   res = g_object_replace_data (obj, "test", NULL, v3, unref_value, &old_destroy);
752   g_assert (res == TRUE);
753 
754   v = g_object_get_data (obj, "test");
755   g_assert (v == v3);
756 
757   ref_value (v3, NULL);
758   g_assert_cmpint (v3->refcount, ==, 2);
759   g_object_unref (obj);
760   g_assert_cmpint (v3->refcount, ==, 1);
761   unref_value (v3);
762 }
763 
764 int
main(int argc,char ** argv)765 main (int argc, char **argv)
766 {
767   g_test_init (&argc, &argv, NULL);
768 
769   g_test_add_func ("/type/fundamentals", test_fundamentals);
770   g_test_add_func ("/type/qdata", test_type_qdata);
771   g_test_add_func ("/type/query", test_type_query);
772   g_test_add_func ("/type/class-private", test_class_private);
773   g_test_add_func ("/object/clear", test_clear);
774   g_test_add_func ("/object/clear-function", test_clear_function);
775   g_test_add_func ("/object/set", test_set);
776   g_test_add_func ("/object/set-function", test_set_function);
777   g_test_add_func ("/object/value", test_object_value);
778   g_test_add_func ("/object/initially-unowned", test_initially_unowned);
779   g_test_add_func ("/object/weak-pointer", test_weak_pointer);
780   g_test_add_func ("/object/weak-pointer/clear", test_weak_pointer_clear);
781   g_test_add_func ("/object/weak-pointer/clear-function", test_weak_pointer_clear_function);
782   g_test_add_func ("/object/weak-pointer/set", test_weak_pointer_set);
783   g_test_add_func ("/object/weak-pointer/set-function", test_weak_pointer_set_function);
784   g_test_add_func ("/object/weak-ref", test_weak_ref);
785   g_test_add_func ("/object/toggle-ref", test_toggle_ref);
786   g_test_add_func ("/object/qdata", test_object_qdata);
787   g_test_add_func ("/object/qdata2", test_object_qdata2);
788 
789   return g_test_run ();
790 }
791