Branch data Line data Source code
1 : : /* GObject - GLib Type, Object, Parameter and Signal Library
2 : : * Copyright (C) 2001, 2003 Red Hat, Inc.
3 : : *
4 : : * SPDX-License-Identifier: LGPL-2.1-or-later
5 : : *
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.
10 : : *
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.
15 : : *
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/>.
18 : : */
19 : :
20 : : #include <glib-object.h>
21 : :
22 : : #include "testcommon.h"
23 : : #include "testmodule.h"
24 : :
25 : : /* This test tests the macros for defining dynamic types */
26 : :
27 : : static gboolean loaded = FALSE;
28 : :
29 : : struct _TestIfaceClass
30 : : {
31 : : GTypeInterface base_iface;
32 : : guint val;
33 : : };
34 : :
35 : : static GType test_iface_get_type (void);
36 : :
37 : : #define TEST_TYPE_IFACE (test_iface_get_type ())
38 : : #define TEST_IFACE_GET_CLASS(obj) \
39 : : (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TEST_TYPE_IFACE, TestIfaceClass))
40 : :
41 : : typedef struct _TestIface TestIface;
42 : : typedef struct _TestIfaceClass TestIfaceClass;
43 : :
44 : : static void test_iface_base_init (TestIfaceClass *iface);
45 : : static void test_iface_default_init (TestIfaceClass *iface, gpointer class_data);
46 : :
47 : 6 : static DEFINE_IFACE(TestIface, test_iface, test_iface_base_init, test_iface_default_init)
48 : :
49 : : static void
50 : 1 : test_iface_default_init (TestIfaceClass *iface,
51 : : gpointer class_data)
52 : : {
53 : 1 : }
54 : :
55 : : static void
56 : 2 : test_iface_base_init (TestIfaceClass *iface)
57 : : {
58 : 2 : }
59 : :
60 : : GType dynamic_object_get_type (void);
61 : : #define DYNAMIC_OBJECT_TYPE (dynamic_object_get_type ())
62 : :
63 : : typedef GObject DynamicObject;
64 : : typedef struct _DynamicObjectClass DynamicObjectClass;
65 : :
66 : : struct _DynamicObjectClass
67 : : {
68 : : GObjectClass parent_class;
69 : : guint val;
70 : : };
71 : :
72 : : static void dynamic_object_iface_init (TestIface *iface);
73 : :
74 : 15 : G_DEFINE_DYNAMIC_TYPE_EXTENDED(DynamicObject, dynamic_object, G_TYPE_OBJECT, 0,
75 : : G_IMPLEMENT_INTERFACE_DYNAMIC (TEST_TYPE_IFACE,
76 : : dynamic_object_iface_init));
77 : :
78 : : static void
79 : 1 : dynamic_object_class_init (DynamicObjectClass *class)
80 : : {
81 : 1 : class->val = 42;
82 : 1 : loaded = TRUE;
83 : 1 : }
84 : :
85 : : static void
86 : 0 : dynamic_object_class_finalize (DynamicObjectClass *class)
87 : : {
88 : 0 : loaded = FALSE;
89 : 0 : }
90 : :
91 : : static void
92 : 1 : dynamic_object_iface_init (TestIface *iface)
93 : : {
94 : 1 : }
95 : :
96 : : static void
97 : 0 : dynamic_object_init (DynamicObject *dynamic_object)
98 : : {
99 : 0 : }
100 : :
101 : : static void
102 : 2 : module_register (GTypeModule *module)
103 : : {
104 : 2 : dynamic_object_register_type (module);
105 : 2 : }
106 : :
107 : : static void
108 : 1 : test_dynamic_type (void)
109 : : {
110 : : DynamicObjectClass *class;
111 : :
112 : : /* Not loaded until we call ref for the first time */
113 : 1 : class = g_type_class_peek (DYNAMIC_OBJECT_TYPE);
114 : 1 : g_assert_null (class);
115 : 1 : g_assert_false (loaded);
116 : :
117 : : /* Make sure interfaces work */
118 : 1 : g_assert_true (g_type_is_a (DYNAMIC_OBJECT_TYPE,
119 : : TEST_TYPE_IFACE));
120 : :
121 : : /* Ref loads */
122 : 1 : class = g_type_class_ref (DYNAMIC_OBJECT_TYPE);
123 : 1 : g_assert_nonnull (class);
124 : 1 : g_assert_cmpint (class->val, ==, 42);
125 : 1 : g_assert_true (loaded);
126 : :
127 : : /* Peek then works */
128 : 1 : class = g_type_class_peek (DYNAMIC_OBJECT_TYPE);
129 : 1 : g_assert_nonnull (class);
130 : 1 : g_assert_cmpint (class->val, ==, 42);
131 : 1 : g_assert_true (loaded);
132 : :
133 : : /* Make sure interfaces still work */
134 : 1 : g_assert_true (g_type_is_a (DYNAMIC_OBJECT_TYPE,
135 : : TEST_TYPE_IFACE));
136 : :
137 : : /* Unref causes finalize */
138 : 1 : g_type_class_unref (class);
139 : :
140 : : /* Peek returns NULL */
141 : 1 : class = g_type_class_peek (DYNAMIC_OBJECT_TYPE);
142 : : #if 0
143 : : /* Disabled as unloading dynamic types is disabled.
144 : : * See https://gitlab.gnome.org/GNOME/glib/-/issues/667 */
145 : : g_assert_false (class);
146 : : g_assert_false (loaded);
147 : : #endif
148 : :
149 : : /* Ref reloads */
150 : 1 : class = g_type_class_ref (DYNAMIC_OBJECT_TYPE);
151 : 1 : g_assert_nonnull (class);
152 : 1 : g_assert_cmpint (class->val, ==, 42);
153 : 1 : g_assert_true (loaded);
154 : :
155 : : /* And Unref causes finalize once more*/
156 : 1 : g_type_class_unref (class);
157 : 1 : class = g_type_class_peek (DYNAMIC_OBJECT_TYPE);
158 : : #if 0
159 : : /* Disabled as unloading dynamic types is disabled.
160 : : * See https://gitlab.gnome.org/GNOME/glib/-/issues/667 */
161 : : g_assert_null (class);
162 : : g_assert_false (loaded);
163 : : #endif
164 : 1 : }
165 : :
166 : : static void
167 : 1 : test_dynamic_type_query (void)
168 : : {
169 : : DynamicObjectClass *class;
170 : : GTypeQuery query_result;
171 : :
172 : 1 : g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/623");
173 : :
174 : 1 : class = g_type_class_ref (DYNAMIC_OBJECT_TYPE);
175 : 1 : g_assert_nonnull (class);
176 : :
177 : 1 : g_type_query (DYNAMIC_OBJECT_TYPE, &query_result);
178 : :
179 : 1 : g_assert_cmpuint (query_result.type, !=, 0);
180 : 1 : g_assert_cmpstr (query_result.type_name, ==, "DynamicObject");
181 : 1 : g_assert_cmpuint (query_result.class_size, >=, sizeof (DynamicObjectClass));
182 : 1 : g_assert_cmpuint (query_result.instance_size, >=, sizeof (DynamicObject));
183 : :
184 : 1 : g_type_class_unref (class);
185 : 1 : }
186 : :
187 : : int
188 : 1 : main (int argc,
189 : : char *argv[])
190 : : {
191 : 1 : g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
192 : 1 : G_LOG_LEVEL_WARNING |
193 : : G_LOG_LEVEL_CRITICAL);
194 : :
195 : 1 : g_test_init (&argc, &argv, NULL);
196 : :
197 : 1 : test_module_new (module_register);
198 : :
199 : 1 : g_test_add_func ("/gobject/dynamic-type", test_dynamic_type);
200 : 1 : g_test_add_func ("/gobject/dynamic-type/query", test_dynamic_type_query);
201 : :
202 : 1 : return g_test_run ();
203 : : }
|