Branch data Line data Source code
1 : : /* GLib testing framework examples and tests
2 : : * Copyright (C) 2008 Imendio AB
3 : : * Authors: Tim Janik
4 : : *
5 : : * SPDX-License-Identifier: LicenseRef-old-glib-tests
6 : : *
7 : : * This work is provided "as is"; redistribution and modification
8 : : * in whole or in part, in any medium, physical or electronic is
9 : : * permitted without restriction.
10 : : *
11 : : * This work 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.
14 : : *
15 : : * In no event shall the authors or contributors be liable for any
16 : : * direct, indirect, incidental, special, exemplary, or consequential
17 : : * damages (including, but not limited to, procurement of substitute
18 : : * goods or services; loss of use, data, or profits; or business
19 : : * interruption) however caused and on any theory of liability, whether
20 : : * in contract, strict liability, or tort (including negligence or
21 : : * otherwise) arising in any way out of the use of this software, even
22 : : * if advised of the possibility of such damage.
23 : : */
24 : : #include <glib.h>
25 : : #include <glib-object.h>
26 : :
27 : : /* This test tests the macros for defining dynamic types.
28 : : */
29 : :
30 : : static GMutex sync_mutex;
31 : : static gboolean loaded = FALSE;
32 : :
33 : : /* MODULE */
34 : : typedef struct _TestModule TestModule;
35 : : typedef struct _TestModuleClass TestModuleClass;
36 : :
37 : : #define TEST_TYPE_MODULE (test_module_get_type ())
38 : : #define TEST_MODULE(module) (G_TYPE_CHECK_INSTANCE_CAST ((module), TEST_TYPE_MODULE, TestModule))
39 : : #define TEST_MODULE_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), TEST_TYPE_MODULE, TestModuleClass))
40 : : #define TEST_IS_MODULE(module) (G_TYPE_CHECK_INSTANCE_TYPE ((module), TEST_TYPE_MODULE))
41 : : #define TEST_IS_MODULE_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), TEST_TYPE_MODULE))
42 : : #define TEST_MODULE_GET_CLASS(module) (G_TYPE_INSTANCE_GET_CLASS ((module), TEST_TYPE_MODULE, TestModuleClass))
43 : : typedef void (*TestModuleRegisterFunc) (GTypeModule *module);
44 : :
45 : : struct _TestModule
46 : : {
47 : : GTypeModule parent_instance;
48 : :
49 : : TestModuleRegisterFunc register_func;
50 : : };
51 : :
52 : : struct _TestModuleClass
53 : : {
54 : : GTypeModuleClass parent_class;
55 : : };
56 : :
57 : : static GType test_module_get_type (void);
58 : :
59 : : static gboolean
60 : 4 : test_module_load (GTypeModule *module)
61 : : {
62 : 4 : TestModule *test_module = TEST_MODULE (module);
63 : :
64 : 4 : test_module->register_func (module);
65 : :
66 : 4 : return TRUE;
67 : : }
68 : :
69 : : static void
70 : 2 : test_module_unload (GTypeModule *module)
71 : : {
72 : 2 : }
73 : :
74 : : static void
75 : 1 : test_module_class_init (TestModuleClass *class)
76 : : {
77 : 1 : GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
78 : :
79 : 1 : module_class->load = test_module_load;
80 : 1 : module_class->unload = test_module_unload;
81 : 1 : }
82 : :
83 : 6 : static GType test_module_get_type (void)
84 : : {
85 : : static GType object_type = 0;
86 : :
87 : 6 : if (!object_type) {
88 : : static const GTypeInfo object_info =
89 : : {
90 : : sizeof (TestModuleClass),
91 : : (GBaseInitFunc) NULL,
92 : : (GBaseFinalizeFunc) NULL,
93 : : (GClassInitFunc) test_module_class_init,
94 : : (GClassFinalizeFunc) NULL,
95 : : NULL,
96 : : sizeof (TestModule),
97 : : 0,
98 : : (GInstanceInitFunc)NULL,
99 : : NULL,
100 : : };
101 : 1 : object_type = g_type_register_static (G_TYPE_TYPE_MODULE, "TestModule", &object_info, 0);
102 : : }
103 : 6 : return object_type;
104 : : }
105 : :
106 : :
107 : : static GTypeModule *
108 : 2 : test_module_new (TestModuleRegisterFunc register_func)
109 : : {
110 : 2 : TestModule *test_module = g_object_new (TEST_TYPE_MODULE, NULL);
111 : 2 : GTypeModule *module = G_TYPE_MODULE (test_module);
112 : :
113 : 2 : test_module->register_func = register_func;
114 : :
115 : : /* Register the types initially */
116 : 2 : g_type_module_use (module);
117 : 2 : g_type_module_unuse (module);
118 : :
119 : 2 : return G_TYPE_MODULE (module);
120 : : }
121 : :
122 : :
123 : :
124 : : #define DYNAMIC_OBJECT_TYPE (dynamic_object_get_type ())
125 : :
126 : : typedef GObject DynamicObject;
127 : : typedef struct _DynamicObjectClass DynamicObjectClass;
128 : :
129 : : struct _DynamicObjectClass
130 : : {
131 : : GObjectClass parent_class;
132 : : guint val;
133 : : };
134 : :
135 : : static GType dynamic_object_get_type (void);
136 : 104 : G_DEFINE_DYNAMIC_TYPE(DynamicObject, dynamic_object, G_TYPE_OBJECT)
137 : :
138 : : static void
139 : 1 : dynamic_object_class_init (DynamicObjectClass *class)
140 : : {
141 : 1 : class->val = 42;
142 : 1 : g_assert (loaded == FALSE);
143 : 1 : loaded = TRUE;
144 : 1 : }
145 : :
146 : : static void
147 : 0 : dynamic_object_class_finalize (DynamicObjectClass *class)
148 : : {
149 : 0 : g_assert (loaded == TRUE);
150 : 0 : loaded = FALSE;
151 : 0 : }
152 : :
153 : : static void
154 : 0 : dynamic_object_init (DynamicObject *dynamic_object)
155 : : {
156 : 0 : }
157 : :
158 : :
159 : : static void
160 : 2 : module_register (GTypeModule *module)
161 : : {
162 : 2 : dynamic_object_register_type (module);
163 : 2 : }
164 : :
165 : : #define N_THREADS 100
166 : : #define N_REFS 10000
167 : :
168 : : static gpointer
169 : 100 : ref_unref_thread (gpointer data)
170 : : {
171 : : gint i;
172 : : /* first, synchronize with other threads,
173 : : */
174 : 100 : if (g_test_verbose())
175 : 0 : g_printerr ("WAITING!\n");
176 : 100 : g_mutex_lock (&sync_mutex);
177 : 100 : g_mutex_unlock (&sync_mutex);
178 : 100 : if (g_test_verbose ())
179 : 0 : g_printerr ("STARTING\n");
180 : :
181 : : /* ref/unref the klass 10000000 times */
182 : 1000100 : for (i = N_REFS; i; i--) {
183 : 1000000 : if (g_test_verbose ())
184 : 0 : if (i % 10)
185 : 0 : g_printerr ("%d\n", i);
186 : 1000000 : g_type_class_unref (g_type_class_ref ((GType) data));
187 : : }
188 : :
189 : 100 : if (g_test_verbose())
190 : 0 : g_printerr ("DONE !\n");
191 : :
192 : 100 : return NULL;
193 : : }
194 : :
195 : : static void
196 : 1 : test_multithreaded_dynamic_type_init (void)
197 : : {
198 : : GTypeModule *module;
199 : : DynamicObjectClass *class;
200 : : /* Create N_THREADS threads that are going to just ref/unref a class */
201 : : GThread *threads[N_THREADS];
202 : : guint i;
203 : :
204 : 1 : module = test_module_new (module_register);
205 : 1 : g_assert (module != NULL);
206 : :
207 : : /* Not loaded until we call ref for the first time */
208 : 1 : class = g_type_class_peek (DYNAMIC_OBJECT_TYPE);
209 : 1 : g_assert (class == NULL);
210 : 1 : g_assert (!loaded);
211 : :
212 : : /* pause newly created threads */
213 : 1 : g_mutex_lock (&sync_mutex);
214 : :
215 : : /* create threads */
216 : 101 : for (i = 0; i < N_THREADS; i++) {
217 : 100 : threads[i] = g_thread_new ("test", ref_unref_thread, (gpointer) DYNAMIC_OBJECT_TYPE);
218 : : }
219 : :
220 : : /* execute threads */
221 : 1 : g_mutex_unlock (&sync_mutex);
222 : :
223 : 101 : for (i = 0; i < N_THREADS; i++) {
224 : 100 : g_thread_join (threads[i]);
225 : : }
226 : 1 : }
227 : :
228 : : enum
229 : : {
230 : : PROP_0,
231 : : PROP_FOO
232 : : };
233 : :
234 : : typedef struct _DynObj DynObj;
235 : : typedef struct _DynObjClass DynObjClass;
236 : : typedef struct _DynIfaceInterface DynIfaceInterface;
237 : :
238 : : struct _DynObj
239 : : {
240 : : GObject obj;
241 : :
242 : : gint foo;
243 : : };
244 : :
245 : : struct _DynObjClass
246 : : {
247 : : GObjectClass class;
248 : : };
249 : :
250 : : struct _DynIfaceInterface
251 : : {
252 : : GTypeInterface iface;
253 : : };
254 : :
255 : : static void dyn_obj_iface_init (DynIfaceInterface *iface);
256 : :
257 : : static GType dyn_iface_get_type (void);
258 : 2 : G_DEFINE_INTERFACE (DynIface, dyn_iface, G_TYPE_OBJECT)
259 : :
260 : : static GType dyn_obj_get_type (void);
261 : 4 : G_DEFINE_DYNAMIC_TYPE_EXTENDED(DynObj, dyn_obj, G_TYPE_OBJECT, 0,
262 : : G_IMPLEMENT_INTERFACE_DYNAMIC(dyn_iface_get_type (), dyn_obj_iface_init))
263 : :
264 : :
265 : : static void
266 : 1 : dyn_iface_default_init (DynIfaceInterface *iface)
267 : : {
268 : 1 : g_object_interface_install_property (iface,
269 : : g_param_spec_int ("foo", NULL, NULL, 0, 100, 0, G_PARAM_READWRITE));
270 : 1 : }
271 : :
272 : : static void
273 : 1 : dyn_obj_iface_init (DynIfaceInterface *iface)
274 : : {
275 : 1 : }
276 : :
277 : : static void
278 : 1 : dyn_obj_init (DynObj *obj)
279 : : {
280 : 1 : obj->foo = 0;
281 : 1 : }
282 : :
283 : : static void
284 : 1 : set_prop (GObject *object,
285 : : guint prop_id,
286 : : const GValue *value,
287 : : GParamSpec *pspec)
288 : : {
289 : 1 : DynObj *obj = (DynObj *)object;
290 : :
291 : 1 : switch (prop_id)
292 : : {
293 : 1 : case PROP_FOO:
294 : 1 : obj->foo = g_value_get_int (value);
295 : 1 : break;
296 : 0 : default:
297 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
298 : 0 : break;
299 : : }
300 : 1 : }
301 : :
302 : : static void
303 : 1 : get_prop (GObject *object,
304 : : guint prop_id,
305 : : GValue *value,
306 : : GParamSpec *pspec)
307 : : {
308 : 1 : DynObj *obj = (DynObj *)object;
309 : :
310 : 1 : switch (prop_id)
311 : : {
312 : 1 : case PROP_FOO:
313 : 1 : g_value_set_int (value, obj->foo);
314 : 1 : break;
315 : 0 : default:
316 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
317 : 0 : break;
318 : : }
319 : 1 : }
320 : :
321 : : static void
322 : 1 : dyn_obj_class_init (DynObjClass *class)
323 : : {
324 : 1 : GObjectClass *object_class = G_OBJECT_CLASS (class);
325 : :
326 : 1 : object_class->set_property = set_prop;
327 : 1 : object_class->get_property = get_prop;
328 : :
329 : 1 : g_object_class_override_property (object_class, PROP_FOO, "foo");
330 : 1 : }
331 : :
332 : : static void
333 : 0 : dyn_obj_class_finalize (DynObjClass *class)
334 : : {
335 : 0 : }
336 : :
337 : : static void
338 : 2 : mod_register (GTypeModule *module)
339 : : {
340 : 2 : dyn_obj_register_type (module);
341 : 2 : }
342 : :
343 : : static void
344 : 1 : test_dynamic_interface_properties (void)
345 : : {
346 : : GTypeModule *module;
347 : : DynObj *obj;
348 : : gint val;
349 : :
350 : 1 : module = test_module_new (mod_register);
351 : 1 : g_assert (module != NULL);
352 : :
353 : 1 : obj = g_object_new (dyn_obj_get_type (), "foo", 1, NULL);
354 : 1 : g_object_get (obj, "foo", &val, NULL);
355 : 1 : g_assert_cmpint (val, ==, 1);
356 : :
357 : 1 : g_object_unref (obj);
358 : 1 : }
359 : :
360 : : int
361 : 1 : main (int argc,
362 : : char *argv[])
363 : : {
364 : 1 : g_test_init (&argc, &argv, NULL);
365 : :
366 : 1 : g_test_add_func ("/GObject/threaded-dynamic-ref-unref-init", test_multithreaded_dynamic_type_init);
367 : 1 : g_test_add_func ("/GObject/dynamic-interface-properties", test_dynamic_interface_properties);
368 : :
369 : 1 : return g_test_run();
370 : : }
|