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 getting the default vtable for an interface
26 * and the initialization and finalization of such default
27 * interfaces.
28 *
29 * We test this both for static and for dynamic interfaces.
30 */
31
32 /**********************************************************************
33 * Static interface tests
34 **********************************************************************/
35
36 typedef struct _TestStaticIfaceClass TestStaticIfaceClass;
37
38 struct _TestStaticIfaceClass
39 {
40 GTypeInterface base_iface;
41 guint val;
42 };
43
44 GType test_static_iface_get_type (void);
45 #define TEST_TYPE_STATIC_IFACE (test_static_iface_get_type ())
46
47 static void
48 test_static_iface_default_init (TestStaticIfaceClass *iface)
49 {
50 iface->val = 42;
51 }
52
53 DEFINE_IFACE (TestStaticIface, test_static_iface,
54 NULL, test_static_iface_default_init)
55
56 static void
57 test_static_iface (void)
58 {
59 TestStaticIfaceClass *static_iface;
60
61 /* Not loaded until we call ref for the first time */
62 static_iface = g_type_default_interface_peek (TEST_TYPE_STATIC_IFACE);
63 g_assert_null (static_iface);
64
65 /* Ref loads */
66 static_iface = g_type_default_interface_ref (TEST_TYPE_STATIC_IFACE);
67 g_assert_nonnull (static_iface);
68 g_assert_cmpint (static_iface->val, ==, 42);
69
70 /* Peek then works */
71 static_iface = g_type_default_interface_peek (TEST_TYPE_STATIC_IFACE);
72 g_assert_nonnull (static_iface);
73 g_assert_cmpint (static_iface->val, ==, 42);
74
75 /* Unref does nothing */
76 g_type_default_interface_unref (static_iface);
77
78 /* And peek still works */
79 static_iface = g_type_default_interface_peek (TEST_TYPE_STATIC_IFACE);
80 g_assert_nonnull (static_iface);
81 g_assert_cmpint (static_iface->val, ==, 42);
82 }
83
84 /**********************************************************************
85 * Dynamic interface tests
86 **********************************************************************/
87
88 typedef struct _TestDynamicIfaceClass TestDynamicIfaceClass;
89
90 struct _TestDynamicIfaceClass
91 {
92 GTypeInterface base_iface;
93 guint val;
94 };
95
96 static GType test_dynamic_iface_type;
97 static gboolean dynamic_iface_init = FALSE;
98
99 #define TEST_TYPE_DYNAMIC_IFACE (test_dynamic_iface_type)
100
101 static void
102 test_dynamic_iface_default_init (TestStaticIfaceClass *iface)
103 {
104 dynamic_iface_init = TRUE;
105 iface->val = 42;
106 }
107
108 static void
109 test_dynamic_iface_default_finalize (TestStaticIfaceClass *iface)
110 {
111 dynamic_iface_init = FALSE;
112 }
113
114 static void
115 test_dynamic_iface_register (GTypeModule *module)
116 {
117 const GTypeInfo iface_info =
118 {
119 sizeof (TestDynamicIfaceClass),
120 (GBaseInitFunc) NULL,
121 (GBaseFinalizeFunc) NULL,
122 (GClassInitFunc) test_dynamic_iface_default_init,
123 (GClassFinalizeFunc) test_dynamic_iface_default_finalize,
124 NULL,
125 0,
126 0,
127 NULL,
128 NULL
129 };
130
131 test_dynamic_iface_type =
132 g_type_module_register_type (module, G_TYPE_INTERFACE,
133 "TestDynamicIface", &iface_info, 0);
134 }
135
136 static void
137 module_register (GTypeModule *module)
138 {
139 test_dynamic_iface_register (module);
140 }
141
142 static void
143 test_dynamic_iface (void)
144 {
145 TestDynamicIfaceClass *dynamic_iface;
146
147 test_module_new (module_register);
148
149 /* Not loaded until we call ref for the first time */
150 dynamic_iface = g_type_default_interface_peek (TEST_TYPE_DYNAMIC_IFACE);
151 g_assert_null (dynamic_iface);
152
153 /* Ref loads */
154 dynamic_iface = g_type_default_interface_ref (TEST_TYPE_DYNAMIC_IFACE);
155 g_assert_true (dynamic_iface_init);
156 g_assert_nonnull (dynamic_iface);
157 g_assert_cmpint (dynamic_iface->val, ==, 42);
158
159 /* Peek then works */
160 dynamic_iface = g_type_default_interface_peek (TEST_TYPE_DYNAMIC_IFACE);
161 g_assert_nonnull (dynamic_iface);
162 g_assert_cmpint (dynamic_iface->val, ==, 42);
163
164 /* Unref causes finalize */
165 g_type_default_interface_unref (dynamic_iface);
166 #if 0
167 /* Disabled as unloading dynamic types is disabled.
168 * See https://gitlab.gnome.org/GNOME/glib/-/issues/667 */
169 g_assert_false (dynamic_iface_init);
170 #endif
171
172 /* Peek returns NULL */
173 dynamic_iface = g_type_default_interface_peek (TEST_TYPE_DYNAMIC_IFACE);
174 #if 0
175 /* Disabled as unloading dynamic types is disabled.
176 * See https://gitlab.gnome.org/GNOME/glib/-/issues/667 */
177 g_assert_null (dynamic_iface);
178 #endif
179
180 /* Ref reloads */
181 dynamic_iface = g_type_default_interface_ref (TEST_TYPE_DYNAMIC_IFACE);
182 g_assert_true (dynamic_iface_init);
183 g_assert_nonnull (dynamic_iface);
184 g_assert_cmpint (dynamic_iface->val, ==, 42);
185
186 /* And Unref causes finalize once more*/
187 g_type_default_interface_unref (dynamic_iface);
188 #if 0
189 /* Disabled as unloading dynamic types is disabled.
190 * See https://gitlab.gnome.org/GNOME/glib/-/issues/667 */
191 g_assert_false (dynamic_iface_init);
192 #endif
193 }
194
195 int
196 main (int argc,
197 char *argv[])
198 {
199 g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
200 G_LOG_LEVEL_WARNING |
201 G_LOG_LEVEL_CRITICAL);
202
203 g_test_init (&argc, &argv, NULL);
204
205 g_test_add_func ("/gobject/static-iface", test_static_iface);
206 g_test_add_func ("/gobject/dynamic-iface", test_dynamic_iface);
207
208 return g_test_run ();
209 }