1 /* GObject - GLib Type, Object, Parameter and Signal Library
2 * Copyright (C) 2005 Red Hat, Inc.
4 * SPDX-License-Identifier: LGPL-2.1-or-later
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 #include <glib-object.h>
22 /* This test tests weak and toggle references */
24 static GObject *global_object;
26 static gboolean object_destroyed;
27 static gboolean weak_ref1_notified;
28 static gboolean weak_ref2_notified;
29 static gboolean toggle_ref1_weakened;
30 static gboolean toggle_ref1_strengthened;
31 static gboolean toggle_ref2_weakened;
32 static gboolean toggle_ref2_strengthened;
33 static gboolean toggle_ref3_weakened;
34 static gboolean toggle_ref3_strengthened;
36 /* TestObject, a parent class for TestObject */
37 static GType test_object_get_type (void);
38 #define TEST_TYPE_OBJECT (test_object_get_type ())
39 typedef struct _TestObject TestObject;
40 typedef struct _TestObjectClass TestObjectClass;
44 GObject parent_instance;
46 struct _TestObjectClass
48 GObjectClass parent_class;
51 G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT)
54 test_object_finalize (GObject *object)
56 object_destroyed = TRUE;
58 G_OBJECT_CLASS (test_object_parent_class)->finalize (object);
62 test_object_class_init (TestObjectClass *class)
64 GObjectClass *object_class = G_OBJECT_CLASS (class);
66 object_class->finalize = test_object_finalize;
70 test_object_init (TestObject *test_object)
77 object_destroyed = FALSE;
78 weak_ref1_notified = FALSE;
79 weak_ref2_notified = FALSE;
80 toggle_ref1_weakened = FALSE;
81 toggle_ref1_strengthened = FALSE;
82 toggle_ref2_weakened = FALSE;
83 toggle_ref2_strengthened = FALSE;
84 toggle_ref3_weakened = FALSE;
85 toggle_ref3_strengthened = FALSE;
89 weak_ref1 (gpointer data,
92 g_assert_true (object == global_object);
93 g_assert_cmpint (GPOINTER_TO_INT (data), ==, 42);
95 weak_ref1_notified = TRUE;
99 weak_ref2 (gpointer data,
102 g_assert_true (object == global_object);
103 g_assert_cmpint (GPOINTER_TO_INT (data), ==, 24);
105 weak_ref2_notified = TRUE;
109 toggle_ref1 (gpointer data,
111 gboolean is_last_ref)
113 g_assert_true (object == global_object);
114 g_assert_cmpint (GPOINTER_TO_INT (data), ==, 42);
117 toggle_ref1_weakened = TRUE;
119 toggle_ref1_strengthened = TRUE;
123 toggle_ref2 (gpointer data,
125 gboolean is_last_ref)
127 g_assert_true (object == global_object);
128 g_assert_cmpint (GPOINTER_TO_INT (data), ==, 24);
131 toggle_ref2_weakened = TRUE;
133 toggle_ref2_strengthened = TRUE;
137 toggle_ref3 (gpointer data,
139 gboolean is_last_ref)
141 g_assert_true (object == global_object);
142 g_assert_cmpint (GPOINTER_TO_INT (data), ==, 34);
146 toggle_ref3_weakened = TRUE;
147 g_object_remove_toggle_ref (object, toggle_ref3, GUINT_TO_POINTER (34));
150 toggle_ref3_strengthened = TRUE;
154 test_references (void)
158 /* Test basic weak reference operation */
159 global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
161 g_object_weak_ref (object, weak_ref1, GUINT_TO_POINTER (42));
164 g_object_unref (object);
165 g_assert_true (weak_ref1_notified);
166 g_assert_true (object_destroyed);
168 /* Test two weak references at once
170 global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
172 g_object_weak_ref (object, weak_ref1, GUINT_TO_POINTER (42));
173 g_object_weak_ref (object, weak_ref2, GUINT_TO_POINTER (24));
176 g_object_unref (object);
177 g_assert_true (weak_ref1_notified);
178 g_assert_true (weak_ref2_notified);
179 g_assert_true (object_destroyed);
181 /* Test remove weak references */
182 global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
184 g_object_weak_ref (object, weak_ref1, GUINT_TO_POINTER (42));
185 g_object_weak_ref (object, weak_ref2, GUINT_TO_POINTER (24));
186 g_object_weak_unref (object, weak_ref1, GUINT_TO_POINTER (42));
189 g_object_unref (object);
190 g_assert_false (weak_ref1_notified);
191 g_assert_true (weak_ref2_notified);
192 g_assert_true (object_destroyed);
194 /* Test basic toggle reference operation */
195 global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
197 g_object_add_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
200 g_object_unref (object);
201 g_assert_true (toggle_ref1_weakened);
202 g_assert_false (toggle_ref1_strengthened);
203 g_assert_false (object_destroyed);
206 g_object_ref (object);
207 g_assert_false (toggle_ref1_weakened);
208 g_assert_true (toggle_ref1_strengthened);
209 g_assert_false (object_destroyed);
211 g_object_unref (object);
214 g_object_remove_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
215 g_assert_false (toggle_ref1_weakened);
216 g_assert_false (toggle_ref1_strengthened);
217 g_assert_true (object_destroyed);
219 global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
221 /* Test two toggle references at once */
222 g_object_add_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
223 g_object_add_toggle_ref (object, toggle_ref2, GUINT_TO_POINTER (24));
226 g_object_unref (object);
227 g_assert_false (toggle_ref1_weakened);
228 g_assert_false (toggle_ref1_strengthened);
229 g_assert_false (toggle_ref2_weakened);
230 g_assert_false (toggle_ref2_strengthened);
231 g_assert_false (object_destroyed);
234 g_object_remove_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
235 g_assert_false (toggle_ref1_weakened);
236 g_assert_false (toggle_ref1_strengthened);
237 g_assert_true (toggle_ref2_weakened);
238 g_assert_false (toggle_ref2_strengthened);
239 g_assert_false (object_destroyed);
242 /* Check that removing a toggle ref with %NULL data works fine. */
243 g_object_remove_toggle_ref (object, toggle_ref2, NULL);
244 g_assert_false (toggle_ref1_weakened);
245 g_assert_false (toggle_ref1_strengthened);
246 g_assert_false (toggle_ref2_weakened);
247 g_assert_false (toggle_ref2_strengthened);
248 g_assert_true (object_destroyed);
250 /* Test a toggle reference that removes itself */
251 global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
253 g_object_add_toggle_ref (object, toggle_ref3, GUINT_TO_POINTER (34));
256 g_object_unref (object);
257 g_assert_true (toggle_ref3_weakened);
258 g_assert_false (toggle_ref3_strengthened);
259 g_assert_true (object_destroyed);
266 g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
267 G_LOG_LEVEL_WARNING |
268 G_LOG_LEVEL_CRITICAL);
270 g_test_init (&argc, &argv, NULL);
272 g_test_add_func ("/gobject/references", test_references);
274 return g_test_run ();