gkdbus: Fix underflow and unreachable code bug
[platform/upstream/glib.git] / gobject / tests / reference.c
1 #include <glib-object.h>
2
3 static 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
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
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
81 my_object_init (MyObject *obj)
82 {
83   obj->count = 42;
84 }
85
86 static void
87 my_object_class_init (MyObjectClass *klass)
88 {
89 }
90
91 static 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
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
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
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
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
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
250 toggle_cb (gpointer data, GObject *obj, gboolean is_last)
251 {
252   gboolean *b = data;
253
254   *b = TRUE;
255 }
256
257 static 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
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   obj = g_object_new (G_TYPE_INITIALLY_UNOWNED, NULL);
327   g_assert_true (g_object_is_floating (obj));
328   g_assert_cmpint (obj->ref_count, ==, 1);
329
330   g_object_take_ref (obj);
331   g_assert_false (g_object_is_floating (obj));
332   g_assert_cmpint (obj->ref_count, ==, 1);
333
334   g_object_take_ref (obj);
335   g_assert_false (g_object_is_floating (obj));
336   g_assert_cmpint (obj->ref_count, ==, 1);
337
338   g_object_unref (obj);
339
340   if (g_test_undefined ())
341     {
342       obj = g_object_new (G_TYPE_INITIALLY_UNOWNED, NULL);
343
344 #ifdef G_ENABLE_DEBUG
345       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
346                              "A floating object GInitiallyUnowned * was finalized*");
347 #endif
348       g_object_unref (obj);
349 #ifdef G_ENABLE_DEBUG
350       g_test_assert_expected_messages ();
351 #endif
352     }
353 }
354
355 static void
356 test_weak_pointer (void)
357 {
358   GObject *obj;
359   gpointer weak;
360   gpointer weak2;
361
362   weak = weak2 = 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_object_add_weak_pointer (obj, &weak2);
367   g_assert_cmpint (obj->ref_count, ==, 1);
368   g_assert (weak == obj);
369   g_assert (weak2 == obj);
370
371   g_object_remove_weak_pointer (obj, &weak2);
372   g_assert_cmpint (obj->ref_count, ==, 1);
373   g_assert (weak == obj);
374   g_assert (weak2 == obj);
375
376   g_object_unref (obj);
377   g_assert (weak == NULL);
378   g_assert (weak2 == obj);
379 }
380
381 static void
382 test_weak_pointer_clear (void)
383 {
384   GObject *obj;
385   gpointer weak = NULL;
386
387   g_clear_weak_pointer (&weak);
388   g_assert_null (weak);
389
390   weak = obj = g_object_new (G_TYPE_OBJECT, NULL);
391   g_assert_cmpint (obj->ref_count, ==, 1);
392
393   g_object_add_weak_pointer (obj, &weak);
394   g_assert_cmpint (obj->ref_count, ==, 1);
395   g_assert_true (weak == obj);
396
397   g_clear_weak_pointer (&weak);
398   g_assert_cmpint (obj->ref_count, ==, 1);
399   g_assert_null (weak);
400
401   g_object_unref (obj);
402 }
403
404 static void
405 test_weak_pointer_clear_function (void)
406 {
407   GObject *obj;
408   gpointer weak = NULL;
409
410   (g_clear_weak_pointer) (&weak);
411   g_assert_null (weak);
412
413   weak = obj = g_object_new (G_TYPE_OBJECT, NULL);
414   g_assert_cmpint (obj->ref_count, ==, 1);
415
416   g_object_add_weak_pointer (obj, &weak);
417   g_assert_cmpint (obj->ref_count, ==, 1);
418   g_assert_true (weak == obj);
419
420   (g_clear_weak_pointer) (&weak);
421   g_assert_cmpint (obj->ref_count, ==, 1);
422   g_assert_null (weak);
423
424   g_object_unref (obj);
425 }
426
427 static void
428 test_weak_pointer_set (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 static void
456 test_weak_pointer_set_function (void)
457 {
458   GObject *obj;
459   gpointer weak = NULL;
460
461   g_assert_false ((g_set_weak_pointer) (&weak, NULL));
462   g_assert_null (weak);
463
464   obj = g_object_new (G_TYPE_OBJECT, NULL);
465   g_assert_cmpint (obj->ref_count, ==, 1);
466
467   g_assert_true ((g_set_weak_pointer) (&weak, obj));
468   g_assert_cmpint (obj->ref_count, ==, 1);
469   g_assert_true (weak == obj);
470
471   g_assert_true ((g_set_weak_pointer) (&weak, NULL));
472   g_assert_cmpint (obj->ref_count, ==, 1);
473   g_assert_null (weak);
474
475   g_assert_true ((g_set_weak_pointer) (&weak, obj));
476   g_assert_cmpint (obj->ref_count, ==, 1);
477   g_assert_true (weak == obj);
478
479   g_object_unref (obj);
480   g_assert_null (weak);
481 }
482
483 /* See gobject/tests/threadtests.c for the threaded version */
484 static void
485 test_weak_ref (void)
486 {
487   GObject *obj;
488   GObject *obj2;
489   GObject *tmp;
490   GWeakRef weak = { { GUINT_TO_POINTER (0xDEADBEEFU) } };
491   GWeakRef weak2 = { { GUINT_TO_POINTER (0xDEADBEEFU) } };
492   GWeakRef weak3 = { { GUINT_TO_POINTER (0xDEADBEEFU) } };
493   GWeakRef *dynamic_weak = g_new (GWeakRef, 1);
494
495   /* you can initialize to empty like this... */
496   g_weak_ref_init (&weak2, NULL);
497   g_assert (g_weak_ref_get (&weak2) == NULL);
498
499   /* ... or via an initializer */
500   g_weak_ref_init (&weak3, NULL);
501   g_assert (g_weak_ref_get (&weak3) == NULL);
502
503   obj = g_object_new (G_TYPE_OBJECT, NULL);
504   g_assert_cmpint (obj->ref_count, ==, 1);
505
506   obj2 = g_object_new (G_TYPE_OBJECT, NULL);
507   g_assert_cmpint (obj2->ref_count, ==, 1);
508
509   /* you can init with an object (even if uninitialized) */
510   g_weak_ref_init (&weak, obj);
511   g_weak_ref_init (dynamic_weak, obj);
512   /* or set to point at an object, if initialized (maybe to 0) */
513   g_weak_ref_set (&weak2, obj);
514   g_weak_ref_set (&weak3, obj);
515   /* none of this affects its refcount */
516   g_assert_cmpint (obj->ref_count, ==, 1);
517
518   /* getting the value takes a ref */
519   tmp = g_weak_ref_get (&weak);
520   g_assert (tmp == obj);
521   g_assert_cmpint (obj->ref_count, ==, 2);
522   g_object_unref (tmp);
523   g_assert_cmpint (obj->ref_count, ==, 1);
524
525   tmp = g_weak_ref_get (&weak2);
526   g_assert (tmp == obj);
527   g_assert_cmpint (obj->ref_count, ==, 2);
528   g_object_unref (tmp);
529   g_assert_cmpint (obj->ref_count, ==, 1);
530
531   tmp = g_weak_ref_get (&weak3);
532   g_assert (tmp == obj);
533   g_assert_cmpint (obj->ref_count, ==, 2);
534   g_object_unref (tmp);
535   g_assert_cmpint (obj->ref_count, ==, 1);
536
537   tmp = g_weak_ref_get (dynamic_weak);
538   g_assert (tmp == obj);
539   g_assert_cmpint (obj->ref_count, ==, 2);
540   g_object_unref (tmp);
541   g_assert_cmpint (obj->ref_count, ==, 1);
542
543   /* clearing a weak ref stops tracking */
544   g_weak_ref_clear (&weak);
545
546   /* setting a weak ref to NULL stops tracking too */
547   g_weak_ref_set (&weak2, NULL);
548   g_assert (g_weak_ref_get (&weak2) == NULL);
549   g_weak_ref_clear (&weak2);
550
551   /* setting a weak ref to a new object stops tracking the old one */
552   g_weak_ref_set (dynamic_weak, obj2);
553   tmp = g_weak_ref_get (dynamic_weak);
554   g_assert (tmp == obj2);
555   g_assert_cmpint (obj2->ref_count, ==, 2);
556   g_object_unref (tmp);
557   g_assert_cmpint (obj2->ref_count, ==, 1);
558
559   g_assert_cmpint (obj->ref_count, ==, 1);
560
561   /* free the object: weak3 is the only one left pointing there */
562   g_object_unref (obj);
563   g_assert (g_weak_ref_get (&weak3) == NULL);
564
565   /* setting a weak ref to a new object stops tracking the old one */
566   g_weak_ref_set (dynamic_weak, obj2);
567   tmp = g_weak_ref_get (dynamic_weak);
568   g_assert (tmp == obj2);
569   g_assert_cmpint (obj2->ref_count, ==, 2);
570   g_object_unref (tmp);
571   g_assert_cmpint (obj2->ref_count, ==, 1);
572
573   g_weak_ref_clear (&weak3);
574
575   /* unset dynamic_weak... */
576   g_weak_ref_set (dynamic_weak, NULL);
577   g_assert_null (g_weak_ref_get (dynamic_weak));
578
579   /* initializing a weak reference to an object that had before works */
580   g_weak_ref_set (dynamic_weak, obj2);
581   tmp = g_weak_ref_get (dynamic_weak);
582   g_assert_true (tmp == obj2);
583   g_assert_cmpint (obj2->ref_count, ==, 2);
584   g_object_unref (tmp);
585   g_assert_cmpint (obj2->ref_count, ==, 1);
586
587   /* clear and free dynamic_weak... */
588   g_weak_ref_clear (dynamic_weak);
589
590   /* ... to prove that doing so stops this from being a use-after-free */
591   g_object_unref (obj2);
592   g_free (dynamic_weak);
593 }
594
595 G_DECLARE_FINAL_TYPE (WeakReffedObject, weak_reffed_object,
596                       WEAK, REFFED_OBJECT, GObject)
597
598 struct _WeakReffedObject
599 {
600   GObject parent;
601
602   GWeakRef *weak_ref;
603 };
604
605 G_DEFINE_TYPE (WeakReffedObject, weak_reffed_object, G_TYPE_OBJECT)
606
607 static void
608 weak_reffed_object_dispose (GObject *object)
609 {
610   WeakReffedObject *weak_reffed = WEAK_REFFED_OBJECT (object);
611
612   g_assert_cmpint (object->ref_count, ==, 1);
613
614   g_weak_ref_set (weak_reffed->weak_ref, object);
615
616   G_OBJECT_CLASS (weak_reffed_object_parent_class)->dispose (object);
617
618   g_assert_null (g_weak_ref_get (weak_reffed->weak_ref));
619 }
620
621 static void
622 weak_reffed_object_init (WeakReffedObject *connector)
623 {
624 }
625
626 static void
627 weak_reffed_object_class_init (WeakReffedObjectClass *klass)
628 {
629   GObjectClass *object_class = G_OBJECT_CLASS (klass);
630
631   object_class->dispose = weak_reffed_object_dispose;
632 }
633
634 static void
635 test_weak_ref_on_dispose (void)
636 {
637   WeakReffedObject *obj;
638   GWeakRef weak = { { GUINT_TO_POINTER (0xDEADBEEFU) } };
639
640   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2390");
641   g_test_summary ("Test that a weak ref set during dispose vfunc is cleared");
642
643   g_weak_ref_init (&weak, NULL);
644
645   obj = g_object_new (weak_reffed_object_get_type (), NULL);
646   obj->weak_ref = &weak;
647
648   g_assert_cmpint (G_OBJECT (obj)->ref_count, ==, 1);
649   g_clear_object (&obj);
650
651   g_assert_null (g_weak_ref_get (&weak));
652 }
653
654 static void
655 test_weak_ref_on_run_dispose (void)
656 {
657   GObject *obj;
658   GWeakRef weak = { { GUINT_TO_POINTER (0xDEADBEEFU) } };
659
660   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/865");
661   g_test_summary ("Test that a weak ref is cleared on g_object_run_dispose()");
662
663   obj = g_object_new (G_TYPE_OBJECT, NULL);
664   g_weak_ref_init (&weak, obj);
665
666   g_assert_true (obj == g_weak_ref_get (&weak));
667   g_object_unref (obj);
668
669   g_object_run_dispose (obj);
670   g_assert_null (g_weak_ref_get (&weak));
671
672   g_clear_object (&obj);
673   g_assert_null (g_weak_ref_get (&weak));
674 }
675
676 static void
677 on_weak_ref_toggle_notify (gpointer data,
678                            GObject *object,
679                            gboolean is_last_ref)
680 {
681   GWeakRef *weak = data;
682
683   if (is_last_ref)
684     g_weak_ref_set (weak, object);
685 }
686
687 static void
688 on_weak_ref_toggle_notify_disposed (gpointer data,
689                                     GObject *object)
690 {
691   g_assert_cmpint (object->ref_count, ==, 1);
692
693   g_object_ref (object);
694   g_object_unref (object);
695 }
696
697 static void
698 test_weak_ref_on_toggle_notify (void)
699 {
700   GObject *obj;
701   GWeakRef weak = { { GUINT_TO_POINTER (0xDEADBEEFU) } };
702
703   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2390");
704   g_test_summary ("Test that a weak ref set on toggle notify is cleared");
705
706   g_weak_ref_init (&weak, NULL);
707
708   obj = g_object_new (G_TYPE_OBJECT, NULL);
709   g_object_add_toggle_ref (obj, on_weak_ref_toggle_notify, &weak);
710   g_object_weak_ref (obj, on_weak_ref_toggle_notify_disposed, NULL);
711   g_object_unref (obj);
712
713   g_assert_cmpint (obj->ref_count, ==, 1);
714   g_clear_object (&obj);
715
716   g_assert_null (g_weak_ref_get (&weak));
717 }
718
719 typedef struct
720 {
721   gboolean should_be_last;
722   gint count;
723 } Count;
724
725 static void
726 toggle_notify (gpointer  data,
727                GObject  *obj,
728                gboolean  is_last)
729 {
730   Count *c = data;
731
732   g_assert (is_last == c->should_be_last);
733
734   if (is_last)
735     g_assert_cmpint (g_atomic_int_get (&obj->ref_count), ==, 1);
736   else
737     g_assert_cmpint (g_atomic_int_get (&obj->ref_count), ==, 2);
738
739   c->count++;
740 }
741
742 static void
743 test_toggle_ref (void)
744 {
745   GObject *obj;
746   Count c, c2;
747
748   obj = g_object_new (G_TYPE_OBJECT, NULL);
749
750   g_object_add_toggle_ref (obj, toggle_notify, &c);
751   g_object_add_toggle_ref (obj, toggle_notify, &c2);
752
753   c.should_be_last = c2.should_be_last = TRUE;
754   c.count = c2.count = 0;
755
756   g_object_unref (obj);
757
758   g_assert_cmpint (c.count, ==, 0);
759   g_assert_cmpint (c2.count, ==, 0);
760
761   g_object_ref (obj);
762
763   g_assert_cmpint (c.count, ==, 0);
764   g_assert_cmpint (c2.count, ==, 0);
765
766   g_object_remove_toggle_ref (obj, toggle_notify, &c2);
767
768   g_object_unref (obj);
769
770   g_assert_cmpint (c.count, ==, 1);
771
772   c.should_be_last = FALSE;
773
774   g_object_ref (obj);
775
776   g_assert_cmpint (c.count, ==, 2);
777
778   c.should_be_last = TRUE;
779
780   g_object_unref (obj);
781
782   g_assert_cmpint (c.count, ==, 3);
783
784   g_object_remove_toggle_ref (obj, toggle_notify, &c);
785 }
786
787 G_DECLARE_FINAL_TYPE (DisposeReffingObject, dispose_reffing_object,
788                       DISPOSE, REFFING_OBJECT, GObject)
789
790 typedef enum
791 {
792   PROP_INT_PROP = 1,
793   N_PROPS,
794 } DisposeReffingObjectProperty;
795
796 static GParamSpec *dispose_reffing_object_properties[N_PROPS] = {0};
797
798 struct _DisposeReffingObject
799 {
800   GObject parent;
801
802   GToggleNotify toggle_notify;
803   Count actual;
804   Count expected;
805   unsigned disposing_refs;
806   gboolean disposing_refs_all_normal;
807
808   GCallback notify_handler;
809   unsigned notify_called;
810
811   int int_prop;
812
813   GWeakRef *weak_ref;
814 };
815
816 G_DEFINE_TYPE (DisposeReffingObject, dispose_reffing_object, G_TYPE_OBJECT)
817
818 static void
819 on_object_notify (GObject    *object,
820                   GParamSpec *pspec,
821                   void       *data)
822 {
823   DisposeReffingObject *obj = DISPOSE_REFFING_OBJECT (object);
824
825   obj->notify_called++;
826 }
827
828 static void
829 dispose_reffing_object_dispose (GObject *object)
830 {
831   DisposeReffingObject *obj = DISPOSE_REFFING_OBJECT (object);
832
833   g_assert_cmpint (object->ref_count, ==, 1);
834   g_assert_cmpint (obj->actual.count, ==, obj->expected.count);
835
836   for (unsigned i = 0; i < obj->disposing_refs; ++i)
837     {
838       if (i == 0 && !obj->disposing_refs_all_normal)
839         {
840           g_object_add_toggle_ref (object, obj->toggle_notify, &obj->actual);
841         }
842       else
843         {
844           obj->actual.should_be_last = FALSE;
845           g_object_ref (obj);
846           g_assert_cmpint (obj->actual.count, ==, obj->expected.count);
847         }
848
849       obj->actual.should_be_last = TRUE;
850     }
851
852   G_OBJECT_CLASS (dispose_reffing_object_parent_class)->dispose (object);
853
854   if (obj->notify_handler)
855     {
856       unsigned old_notify_called = obj->notify_called;
857
858       g_assert_cmpuint (g_signal_handler_find (object, G_SIGNAL_MATCH_FUNC,
859                         0, 0, NULL, obj->notify_handler, NULL), ==, 0);
860
861       g_signal_connect (object, "notify", G_CALLBACK (obj->notify_handler), NULL);
862
863       /* This would trigger a toggle notification, but is not something we may
864        * want with https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2377
865        * so, we only test this in case we have more than one ref
866        */
867       if (obj->toggle_notify == toggle_notify)
868         g_assert_cmpint (obj->disposing_refs, >, 1);
869
870       g_object_notify (object, "int-prop");
871       g_assert_cmpuint (obj->notify_called, ==, old_notify_called);
872     }
873
874   g_assert_cmpint (obj->actual.count, ==, obj->expected.count);
875 }
876
877 static void
878 dispose_reffing_object_init (DisposeReffingObject *connector)
879 {
880 }
881
882 static void
883 dispose_reffing_object_set_property (GObject *object,
884                                      guint property_id,
885                                      const GValue *value,
886                                      GParamSpec *pspec)
887 {
888   DisposeReffingObject *obj = DISPOSE_REFFING_OBJECT (object);
889
890   switch ((DisposeReffingObjectProperty) property_id)
891     {
892     case PROP_INT_PROP:
893       obj->int_prop = g_value_get_int (value);
894       break;
895     default:
896       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
897       break;
898     }
899 }
900
901 static void
902 dispose_reffing_object_get_property (GObject *object,
903                                      guint property_id,
904                                      GValue *value,
905                                      GParamSpec *pspec)
906 {
907   DisposeReffingObject *obj = DISPOSE_REFFING_OBJECT (object);
908
909   switch ((DisposeReffingObjectProperty) property_id)
910     {
911     case PROP_INT_PROP:
912       g_value_set_int (value, obj->int_prop);
913       break;
914     default:
915       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
916       break;
917     }
918 }
919
920 static void
921 dispose_reffing_object_class_init (DisposeReffingObjectClass *klass)
922 {
923   GObjectClass *object_class = G_OBJECT_CLASS (klass);
924
925   dispose_reffing_object_properties[PROP_INT_PROP] =
926       g_param_spec_int ("int-prop", "int-prop", "int-prop",
927                         G_MININT, G_MAXINT,
928                         0,
929                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
930
931   object_class->dispose = dispose_reffing_object_dispose;
932   object_class->set_property = dispose_reffing_object_set_property;
933   object_class->get_property = dispose_reffing_object_get_property;
934
935   g_object_class_install_properties (object_class, N_PROPS,
936                                      dispose_reffing_object_properties);
937 }
938
939 static void
940 test_toggle_ref_on_dispose (void)
941 {
942   DisposeReffingObject *obj;
943   gpointer disposed_checker = &obj;
944
945   /* This tests wants to ensure that an object that gets re-referenced
946    * (one or multiple times) during its dispose virtual function:
947    *  - Notifies all the queued "notify" signal handlers
948    *  - Notifies toggle notifications if any
949    *  - It does not get finalized
950    */
951
952   obj = g_object_new (dispose_reffing_object_get_type (), NULL);
953   obj->toggle_notify = toggle_notify;
954   obj->notify_handler = G_CALLBACK (on_object_notify);
955   g_object_add_weak_pointer (G_OBJECT (obj), &disposed_checker);
956
957   /* Convert to toggle notification */
958   g_object_add_toggle_ref (G_OBJECT (obj), obj->toggle_notify, &obj->actual);
959   g_assert_cmpint (obj->actual.count, ==, 0);
960
961   obj->actual.should_be_last = TRUE;
962   obj->notify_handler = G_CALLBACK (on_object_notify);
963   g_object_unref (obj);
964   g_assert_cmpint (obj->actual.count, ==, 1);
965   g_assert_cmpuint (obj->notify_called, ==, 0);
966
967   /* Remove the toggle reference, making it to dispose and resurrect again */
968   obj->disposing_refs = 1;
969   obj->expected.count = 1;
970   obj->notify_handler = NULL; /* FIXME: enable it when !2377 is in */
971   g_object_remove_toggle_ref (G_OBJECT (obj), obj->toggle_notify, NULL);
972   g_assert_cmpint (obj->actual.count, ==, 2);
973   g_assert_cmpuint (obj->notify_called, ==, 0);
974
975   g_assert_null (disposed_checker);
976   g_assert_cmpint (g_atomic_int_get (&G_OBJECT (obj)->ref_count), ==,
977                    obj->disposing_refs);
978
979   /* Object has been disposed, but is still alive, so add another weak pointer */
980   disposed_checker = &obj;
981   g_object_add_weak_pointer (G_OBJECT (obj), &disposed_checker);
982
983   /* Remove the toggle reference, making it to dispose and resurrect with
984    * more references than before, so that no toggle notify is called
985    */
986   obj->disposing_refs = 3;
987   obj->expected.count = 2;
988   obj->notify_handler = G_CALLBACK (on_object_notify);
989   g_object_remove_toggle_ref (G_OBJECT (obj), obj->toggle_notify, NULL);
990   g_assert_cmpint (obj->actual.count, ==, 2);
991   g_assert_cmpint (obj->notify_called, ==, 1);
992   obj->expected.count = obj->actual.count;
993
994   g_assert_null (disposed_checker);
995   g_assert_cmpint (g_atomic_int_get (&G_OBJECT (obj)->ref_count), ==,
996                    obj->disposing_refs);
997
998   disposed_checker = &obj;
999   g_object_add_weak_pointer (G_OBJECT (obj), &disposed_checker);
1000
1001   /* Now remove the first added reference */
1002   obj->disposing_refs = 0;
1003   g_object_unref (obj);
1004   g_assert_nonnull (disposed_checker);
1005   g_assert_cmpint (g_atomic_int_get (&G_OBJECT (obj)->ref_count), ==, 2);
1006   g_assert_cmpint (obj->actual.count, ==, 2);
1007   g_assert_cmpint (obj->notify_called, ==, 1);
1008
1009   /* And the toggle one */
1010   obj->actual.should_be_last = TRUE;
1011   obj->notify_handler = NULL;
1012   g_object_remove_toggle_ref (G_OBJECT (obj), obj->toggle_notify, NULL);
1013   g_assert_nonnull (disposed_checker);
1014   g_assert_cmpint (g_atomic_int_get (&G_OBJECT (obj)->ref_count), ==, 1);
1015   g_assert_cmpint (obj->actual.count, ==, 2);
1016   obj->expected.count = obj->actual.count;
1017
1018   g_clear_object (&obj);
1019   g_assert_null (disposed_checker);
1020 }
1021
1022 static void
1023 toggle_notify_counter (gpointer  data,
1024                        GObject  *obj,
1025                        gboolean  is_last)
1026 {
1027   Count *c = data;
1028   c->count++;
1029
1030   if (is_last)
1031     g_assert_cmpint (g_atomic_int_get (&obj->ref_count), ==, 1);
1032   else
1033     g_assert_cmpint (g_atomic_int_get (&obj->ref_count), ==, 2);
1034 }
1035
1036 static void
1037 on_object_notify_switch_to_normal_ref (GObject    *object,
1038                                        GParamSpec *pspec,
1039                                        void       *data)
1040 {
1041   DisposeReffingObject *obj = DISPOSE_REFFING_OBJECT (object);
1042
1043   obj->notify_called++;
1044
1045   g_object_ref (object);
1046   g_object_remove_toggle_ref (object, obj->toggle_notify, NULL);
1047 }
1048
1049 static void
1050 on_object_notify_switch_to_toggle_ref (GObject    *object,
1051                                        GParamSpec *pspec,
1052                                        void       *data)
1053 {
1054   DisposeReffingObject *obj = DISPOSE_REFFING_OBJECT (object);
1055
1056   obj->notify_called++;
1057
1058   g_object_add_toggle_ref (object, obj->toggle_notify, &obj->actual);
1059   g_object_unref (object);
1060 }
1061
1062 static void
1063 on_object_notify_add_ref (GObject    *object,
1064                           GParamSpec *pspec,
1065                           void       *data)
1066 {
1067   DisposeReffingObject *obj = DISPOSE_REFFING_OBJECT (object);
1068   int old_toggle_cout = obj->actual.count;
1069
1070   obj->notify_called++;
1071
1072   g_object_ref (object);
1073   g_assert_cmpint (obj->actual.count, ==, old_toggle_cout);
1074 }
1075
1076 static void
1077 test_toggle_ref_and_notify_on_dispose (void)
1078 {
1079   DisposeReffingObject *obj;
1080   gpointer disposed_checker = &obj;
1081
1082   /* This tests wants to ensure that toggle signal emission during dispose
1083    * is properly working if the object is revitalized by adding new references.
1084    * It also wants to check that toggle notifications are not happening if a
1085    * notify handler is removing them at this phase.
1086    */
1087
1088   obj = g_object_new (dispose_reffing_object_get_type (), NULL);
1089   obj->toggle_notify = toggle_notify_counter;
1090   g_object_add_weak_pointer (G_OBJECT (obj), &disposed_checker);
1091
1092   /* Convert to toggle notification */
1093   g_object_add_toggle_ref (G_OBJECT (obj), obj->toggle_notify, &obj->actual);
1094   g_assert_cmpint (obj->actual.count, ==, 0);
1095
1096   obj->notify_handler = G_CALLBACK (on_object_notify);
1097   g_object_unref (obj);
1098   g_assert_cmpint (obj->actual.count, ==, 1);
1099   g_assert_cmpuint (obj->notify_called, ==, 0);
1100
1101   disposed_checker = &obj;
1102   g_object_add_weak_pointer (G_OBJECT (obj), &disposed_checker);
1103
1104   /* Check that notification is triggered after being queued */
1105   obj->disposing_refs = 1;
1106   obj->expected.count = 1;
1107   obj->notify_handler = G_CALLBACK (on_object_notify);
1108   g_object_remove_toggle_ref (G_OBJECT (obj), obj->toggle_notify, NULL);
1109    /* FIXME: adjust the count to 1 when !2377 is in */
1110   g_assert_cmpint (obj->actual.count, ==, 4);
1111   g_assert_cmpuint (obj->notify_called, ==, 1);
1112
1113   disposed_checker = &obj;
1114   g_object_add_weak_pointer (G_OBJECT (obj), &disposed_checker);
1115
1116   /* Check that notification is triggered after being queued, but no toggle
1117    * notification is happening if notify handler switches to normal reference
1118    */
1119   obj->disposing_refs = 1;
1120   obj->expected.count = 4;
1121   obj->notify_handler = G_CALLBACK (on_object_notify_switch_to_normal_ref);
1122   g_object_remove_toggle_ref (G_OBJECT (obj), obj->toggle_notify, NULL);
1123   g_assert_cmpint (obj->actual.count, ==, 5);
1124   g_assert_cmpuint (obj->notify_called, ==, 2);
1125
1126   disposed_checker = &obj;
1127   g_object_add_weak_pointer (G_OBJECT (obj), &disposed_checker);
1128
1129   /* Check that notification is triggered after being queued, but that toggle
1130    * is happening if notify handler switched to toggle reference
1131    */
1132   obj->disposing_refs = 1;
1133   obj->disposing_refs_all_normal = TRUE;
1134   obj->expected.count = 5;
1135   obj->notify_handler = G_CALLBACK (on_object_notify_switch_to_toggle_ref);
1136   g_object_unref (obj);
1137   g_assert_cmpint (obj->actual.count, ==, 7);
1138   g_assert_cmpuint (obj->notify_called, ==, 3);
1139
1140   disposed_checker = &obj;
1141   g_object_add_weak_pointer (G_OBJECT (obj), &disposed_checker);
1142
1143   /* Check that notification is triggered after being queued, but that toggle
1144    * is not happening if current refcount changed.
1145    */
1146   obj->disposing_refs = 1;
1147   obj->disposing_refs_all_normal = FALSE;
1148   obj->expected.count = 7;
1149   obj->notify_handler = G_CALLBACK (on_object_notify_add_ref);
1150   g_object_remove_toggle_ref (G_OBJECT (obj), obj->toggle_notify, NULL);
1151   g_assert_cmpint (obj->actual.count, ==, 8);
1152   g_assert_cmpuint (obj->notify_called, ==, 4);
1153   g_object_unref (obj);
1154
1155   disposed_checker = &obj;
1156   g_object_add_weak_pointer (G_OBJECT (obj), &disposed_checker);
1157
1158   obj->disposing_refs = 0;
1159   obj->expected.count = 9;
1160   g_clear_object (&obj);
1161   g_assert_null (disposed_checker);
1162 }
1163
1164 static gboolean global_destroyed;
1165 static gint global_value;
1166
1167 static void
1168 data_destroy (gpointer data)
1169 {
1170   g_assert_cmpint (GPOINTER_TO_INT (data), ==, global_value);
1171
1172   global_destroyed = TRUE;
1173 }
1174
1175 static void
1176 test_object_qdata (void)
1177 {
1178   GObject *obj;
1179   gpointer v;
1180   GQuark quark;
1181
1182   obj = g_object_new (G_TYPE_OBJECT, NULL);
1183
1184   global_value = 1;
1185   global_destroyed = FALSE;
1186   g_object_set_data_full (obj, "test", GINT_TO_POINTER (1), data_destroy);
1187   v = g_object_get_data (obj, "test");
1188   g_assert_cmpint (GPOINTER_TO_INT (v), ==, 1);
1189   g_object_set_data_full (obj, "test", GINT_TO_POINTER (2), data_destroy);
1190   g_assert (global_destroyed);
1191   global_value = 2;
1192   global_destroyed = FALSE;
1193   v = g_object_steal_data (obj, "test");
1194   g_assert_cmpint (GPOINTER_TO_INT (v), ==, 2);
1195   g_assert (!global_destroyed);
1196
1197   global_value = 1;
1198   global_destroyed = FALSE;
1199   quark = g_quark_from_string ("test");
1200   g_object_set_qdata_full (obj, quark, GINT_TO_POINTER (1), data_destroy);
1201   v = g_object_get_qdata (obj, quark);
1202   g_assert_cmpint (GPOINTER_TO_INT (v), ==, 1);
1203   g_object_set_qdata_full (obj, quark, GINT_TO_POINTER (2), data_destroy);
1204   g_assert (global_destroyed);
1205   global_value = 2;
1206   global_destroyed = FALSE;
1207   v = g_object_steal_qdata (obj, quark);
1208   g_assert_cmpint (GPOINTER_TO_INT (v), ==, 2);
1209   g_assert (!global_destroyed);
1210
1211   g_object_set_qdata_full (obj, quark, GINT_TO_POINTER (3), data_destroy);
1212   global_value = 3;
1213   global_destroyed = FALSE;
1214   g_object_unref (obj);
1215
1216   g_assert (global_destroyed);
1217 }
1218
1219 typedef struct {
1220   const gchar *value;
1221   gint refcount;
1222 } Value;
1223
1224 static gpointer
1225 ref_value (gpointer value, gpointer user_data)
1226 {
1227   Value *v = value;
1228   Value **old_value_p = user_data;
1229
1230   if (old_value_p)
1231     *old_value_p = v;
1232
1233   if (v)
1234     v->refcount += 1;
1235
1236   return value;
1237 }
1238
1239 static void
1240 unref_value (gpointer value)
1241 {
1242   Value *v = value;
1243
1244   v->refcount -= 1;
1245   if (v->refcount == 0)
1246     g_free (value);
1247 }
1248
1249 static
1250 Value *
1251 new_value (const gchar *s)
1252 {
1253   Value *v;
1254
1255   v = g_new (Value, 1);
1256   v->value = s;
1257   v->refcount = 1;
1258
1259   return v;
1260 }
1261
1262 static void
1263 test_object_qdata2 (void)
1264 {
1265   GObject *obj;
1266   Value *v, *v1, *v2, *v3, *old_val;
1267   GDestroyNotify old_destroy;
1268   gboolean res;
1269
1270   obj = g_object_new (G_TYPE_OBJECT, NULL);
1271
1272   v1 = new_value ("bla");
1273
1274   g_object_set_data_full (obj, "test", v1, unref_value);
1275
1276   v = g_object_get_data (obj, "test");
1277   g_assert_cmpstr (v->value, ==, "bla");
1278   g_assert_cmpint (v->refcount, ==, 1);
1279
1280   v = g_object_dup_data (obj, "test", ref_value, &old_val);
1281   g_assert (old_val == v1);
1282   g_assert_cmpstr (v->value, ==, "bla");
1283   g_assert_cmpint (v->refcount, ==, 2);
1284   unref_value (v);
1285
1286   v = g_object_dup_data (obj, "nono", ref_value, &old_val);
1287   g_assert (old_val == NULL);
1288   g_assert (v == NULL);
1289
1290   v2 = new_value ("not");
1291
1292   res = g_object_replace_data (obj, "test", v1, v2, unref_value, &old_destroy);
1293   g_assert (res == TRUE);
1294   g_assert (old_destroy == unref_value);
1295   g_assert_cmpstr (v1->value, ==, "bla");
1296   g_assert_cmpint (v1->refcount, ==, 1);
1297
1298   v = g_object_get_data (obj, "test");
1299   g_assert_cmpstr (v->value, ==, "not");
1300   g_assert_cmpint (v->refcount, ==, 1);
1301
1302   v3 = new_value ("xyz");
1303   res = g_object_replace_data (obj, "test", v1, v3, unref_value, &old_destroy);
1304   g_assert (res == FALSE);
1305   g_assert_cmpstr (v2->value, ==, "not");
1306   g_assert_cmpint (v2->refcount, ==, 1);
1307
1308   unref_value (v1);
1309
1310   res = g_object_replace_data (obj, "test", NULL, v3, unref_value, &old_destroy);
1311   g_assert (res == FALSE);
1312   g_assert_cmpstr (v2->value, ==, "not");
1313   g_assert_cmpint (v2->refcount, ==, 1);
1314
1315   res = g_object_replace_data (obj, "test", v2, NULL, unref_value, &old_destroy);
1316   g_assert (res == TRUE);
1317   g_assert (old_destroy == unref_value);
1318   g_assert_cmpstr (v2->value, ==, "not");
1319   g_assert_cmpint (v2->refcount, ==, 1);
1320
1321   unref_value (v2);
1322
1323   v = g_object_get_data (obj, "test");
1324   g_assert (v == NULL);
1325
1326   res = g_object_replace_data (obj, "test", NULL, v3, unref_value, &old_destroy);
1327   g_assert (res == TRUE);
1328
1329   v = g_object_get_data (obj, "test");
1330   g_assert (v == v3);
1331
1332   ref_value (v3, NULL);
1333   g_assert_cmpint (v3->refcount, ==, 2);
1334   g_object_unref (obj);
1335   g_assert_cmpint (v3->refcount, ==, 1);
1336   unref_value (v3);
1337 }
1338
1339 int
1340 main (int argc, char **argv)
1341 {
1342   g_test_init (&argc, &argv, NULL);
1343
1344   g_setenv ("G_ENABLE_DIAGNOSTIC", "1", TRUE);
1345
1346   g_test_add_func ("/type/fundamentals", test_fundamentals);
1347   g_test_add_func ("/type/qdata", test_type_qdata);
1348   g_test_add_func ("/type/query", test_type_query);
1349   g_test_add_func ("/type/class-private", test_class_private);
1350   g_test_add_func ("/object/clear", test_clear);
1351   g_test_add_func ("/object/clear-function", test_clear_function);
1352   g_test_add_func ("/object/set", test_set);
1353   g_test_add_func ("/object/set-function", test_set_function);
1354   g_test_add_func ("/object/set/derived-type", test_set_derived_type);
1355   g_test_add_func ("/object/value", test_object_value);
1356   g_test_add_func ("/object/initially-unowned", test_initially_unowned);
1357   g_test_add_func ("/object/weak-pointer", test_weak_pointer);
1358   g_test_add_func ("/object/weak-pointer/clear", test_weak_pointer_clear);
1359   g_test_add_func ("/object/weak-pointer/clear-function", test_weak_pointer_clear_function);
1360   g_test_add_func ("/object/weak-pointer/set", test_weak_pointer_set);
1361   g_test_add_func ("/object/weak-pointer/set-function", test_weak_pointer_set_function);
1362   g_test_add_func ("/object/weak-ref", test_weak_ref);
1363   g_test_add_func ("/object/weak-ref/on-dispose", test_weak_ref_on_dispose);
1364   g_test_add_func ("/object/weak-ref/on-run-dispose", test_weak_ref_on_run_dispose);
1365   g_test_add_func ("/object/weak-ref/on-toggle-notify", test_weak_ref_on_toggle_notify);
1366   g_test_add_func ("/object/toggle-ref", test_toggle_ref);
1367   g_test_add_func ("/object/toggle-ref/ref-on-dispose", test_toggle_ref_on_dispose);
1368   g_test_add_func ("/object/toggle-ref/ref-and-notify-on-dispose", test_toggle_ref_and_notify_on_dispose);
1369   g_test_add_func ("/object/qdata", test_object_qdata);
1370   g_test_add_func ("/object/qdata2", test_object_qdata2);
1371
1372   return g_test_run ();
1373 }