1 /* GObject - GLib Type, Object, Parameter and Signal Library
2 * Copyright (C) 2005 Red Hat, Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General
15 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #undef G_LOG_DOMAIN
19 #define G_LOG_DOMAIN "TestReferences"
20
21 #undef G_DISABLE_ASSERT
22 #undef G_DISABLE_CHECKS
23 #undef G_DISABLE_CAST_CHECKS
24
25 #include <glib-object.h>
26
27 /* This test tests weak and toggle references
28 */
29
30 static GObject *global_object;
31
32 static gboolean object_destroyed;
33 static gboolean weak_ref1_notified;
34 static gboolean weak_ref2_notified;
35 static gboolean toggle_ref1_weakened;
36 static gboolean toggle_ref1_strengthened;
37 static gboolean toggle_ref2_weakened;
38 static gboolean toggle_ref2_strengthened;
39 static gboolean toggle_ref3_weakened;
40 static gboolean toggle_ref3_strengthened;
41
42 /*
43 * TestObject, a parent class for TestObject
44 */
45 static GType test_object_get_type (void);
46 #define TEST_TYPE_OBJECT (test_object_get_type ())
47 typedef struct _TestObject TestObject;
48 typedef struct _TestObjectClass TestObjectClass;
49
50 struct _TestObject
51 {
52 GObject parent_instance;
53 };
54 struct _TestObjectClass
55 {
56 GObjectClass parent_class;
57 };
58
G_DEFINE_TYPE(TestObject,test_object,G_TYPE_OBJECT)59 G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT)
60
61 static void
62 test_object_finalize (GObject *object)
63 {
64 object_destroyed = TRUE;
65
66 G_OBJECT_CLASS (test_object_parent_class)->finalize (object);
67 }
68
69 static void
test_object_class_init(TestObjectClass * class)70 test_object_class_init (TestObjectClass *class)
71 {
72 GObjectClass *object_class = G_OBJECT_CLASS (class);
73
74 object_class->finalize = test_object_finalize;
75 }
76
77 static void
test_object_init(TestObject * test_object)78 test_object_init (TestObject *test_object)
79 {
80 }
81
82 static void
clear_flags(void)83 clear_flags (void)
84 {
85 object_destroyed = FALSE;
86 weak_ref1_notified = FALSE;
87 weak_ref2_notified = FALSE;
88 toggle_ref1_weakened = FALSE;
89 toggle_ref1_strengthened = FALSE;
90 toggle_ref2_weakened = FALSE;
91 toggle_ref2_strengthened = FALSE;
92 toggle_ref3_weakened = FALSE;
93 toggle_ref3_strengthened = FALSE;
94 }
95
96 static void
weak_ref1(gpointer data,GObject * object)97 weak_ref1 (gpointer data,
98 GObject *object)
99 {
100 g_assert (object == global_object);
101 g_assert (data == GUINT_TO_POINTER (42));
102
103 weak_ref1_notified = TRUE;
104 }
105
106 static void
weak_ref2(gpointer data,GObject * object)107 weak_ref2 (gpointer data,
108 GObject *object)
109 {
110 g_assert (object == global_object);
111 g_assert (data == GUINT_TO_POINTER (24));
112
113 weak_ref2_notified = TRUE;
114 }
115
116 static void
toggle_ref1(gpointer data,GObject * object,gboolean is_last_ref)117 toggle_ref1 (gpointer data,
118 GObject *object,
119 gboolean is_last_ref)
120 {
121 g_assert (object == global_object);
122 g_assert (data == GUINT_TO_POINTER (42));
123
124 if (is_last_ref)
125 toggle_ref1_weakened = TRUE;
126 else
127 toggle_ref1_strengthened = TRUE;
128 }
129
130 static void
toggle_ref2(gpointer data,GObject * object,gboolean is_last_ref)131 toggle_ref2 (gpointer data,
132 GObject *object,
133 gboolean is_last_ref)
134 {
135 g_assert (object == global_object);
136 g_assert (data == GUINT_TO_POINTER (24));
137
138 if (is_last_ref)
139 toggle_ref2_weakened = TRUE;
140 else
141 toggle_ref2_strengthened = TRUE;
142 }
143
144 static void
toggle_ref3(gpointer data,GObject * object,gboolean is_last_ref)145 toggle_ref3 (gpointer data,
146 GObject *object,
147 gboolean is_last_ref)
148 {
149 g_assert (object == global_object);
150 g_assert (data == GUINT_TO_POINTER (34));
151
152 if (is_last_ref)
153 {
154 toggle_ref3_weakened = TRUE;
155 g_object_remove_toggle_ref (object, toggle_ref3, GUINT_TO_POINTER (34));
156 }
157 else
158 toggle_ref3_strengthened = TRUE;
159 }
160
161 int
main(int argc,char * argv[])162 main (int argc,
163 char *argv[])
164 {
165 GObject *object;
166
167 g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
168 G_LOG_LEVEL_WARNING |
169 G_LOG_LEVEL_CRITICAL);
170
171 /* Test basic weak reference operation
172 */
173 global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
174
175 g_object_weak_ref (object, weak_ref1, GUINT_TO_POINTER (42));
176
177 clear_flags ();
178 g_object_unref (object);
179 g_assert (weak_ref1_notified == TRUE);
180 g_assert (object_destroyed == TRUE);
181
182 /* Test two weak references at once
183 */
184 global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
185
186 g_object_weak_ref (object, weak_ref1, GUINT_TO_POINTER (42));
187 g_object_weak_ref (object, weak_ref2, GUINT_TO_POINTER (24));
188
189 clear_flags ();
190 g_object_unref (object);
191 g_assert (weak_ref1_notified == TRUE);
192 g_assert (weak_ref2_notified == TRUE);
193 g_assert (object_destroyed == TRUE);
194
195 /* Test remove weak references
196 */
197 global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
198
199 g_object_weak_ref (object, weak_ref1, GUINT_TO_POINTER (42));
200 g_object_weak_ref (object, weak_ref2, GUINT_TO_POINTER (24));
201 g_object_weak_unref (object, weak_ref1, GUINT_TO_POINTER (42));
202
203 clear_flags ();
204 g_object_unref (object);
205 g_assert (weak_ref1_notified == FALSE);
206 g_assert (weak_ref2_notified == TRUE);
207 g_assert (object_destroyed == TRUE);
208
209 /* Test basic toggle reference operation
210 */
211 global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
212
213 g_object_add_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
214
215 clear_flags ();
216 g_object_unref (object);
217 g_assert (toggle_ref1_weakened == TRUE);
218 g_assert (toggle_ref1_strengthened == FALSE);
219 g_assert (object_destroyed == FALSE);
220
221 clear_flags ();
222 g_object_ref (object);
223 g_assert (toggle_ref1_weakened == FALSE);
224 g_assert (toggle_ref1_strengthened == TRUE);
225 g_assert (object_destroyed == FALSE);
226
227 g_object_unref (object);
228
229 clear_flags ();
230 g_object_remove_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
231 g_assert (toggle_ref1_weakened == FALSE);
232 g_assert (toggle_ref1_strengthened == FALSE);
233 g_assert (object_destroyed == TRUE);
234
235 global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
236
237 /* Test two toggle references at once
238 */
239 g_object_add_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
240 g_object_add_toggle_ref (object, toggle_ref2, GUINT_TO_POINTER (24));
241
242 clear_flags ();
243 g_object_unref (object);
244 g_assert (toggle_ref1_weakened == FALSE);
245 g_assert (toggle_ref1_strengthened == FALSE);
246 g_assert (toggle_ref2_weakened == FALSE);
247 g_assert (toggle_ref2_strengthened == FALSE);
248 g_assert (object_destroyed == FALSE);
249
250 clear_flags ();
251 g_object_remove_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
252 g_assert (toggle_ref1_weakened == FALSE);
253 g_assert (toggle_ref1_strengthened == FALSE);
254 g_assert (toggle_ref2_weakened == TRUE);
255 g_assert (toggle_ref2_strengthened == FALSE);
256 g_assert (object_destroyed == FALSE);
257
258 clear_flags ();
259 g_object_remove_toggle_ref (object, toggle_ref2, GUINT_TO_POINTER (24));
260 g_assert (toggle_ref1_weakened == FALSE);
261 g_assert (toggle_ref1_strengthened == FALSE);
262 g_assert (toggle_ref2_weakened == FALSE);
263 g_assert (toggle_ref2_strengthened == FALSE);
264 g_assert (object_destroyed == TRUE);
265
266 /* Test a toggle reference that removes itself
267 */
268 global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
269
270 g_object_add_toggle_ref (object, toggle_ref3, GUINT_TO_POINTER (34));
271
272 clear_flags ();
273 g_object_unref (object);
274 g_assert (toggle_ref3_weakened == TRUE);
275 g_assert (toggle_ref3_strengthened == FALSE);
276 g_assert (object_destroyed == TRUE);
277
278 return 0;
279 }
280