1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 // SPDX-FileCopyrightText: 2021 Emmanuele Bassi
3
4 #include <glib-object.h>
5
6 typedef struct
7 {
8 GTypeInterface g_iface;
9 } TestInterfaceInterface;
10
11 GType test_interface_get_type (void);
12 #define TEST_TYPE_INTERFACE test_interface_get_type ()
13 G_DEFINE_INTERFACE (TestInterface, test_interface, G_TYPE_INVALID)
14
15 static void
16 test_interface_default_init (TestInterfaceInterface *iface)
17 {
18 }
19
20 static void
21 test_type_flags_interface (void)
22 {
23 g_assert_false (G_TYPE_IS_ABSTRACT (TEST_TYPE_INTERFACE));
24 g_assert_false (g_type_test_flags (TEST_TYPE_INTERFACE, G_TYPE_FLAG_ABSTRACT));
25
26 g_assert_false (G_TYPE_IS_CLASSED (TEST_TYPE_INTERFACE));
27 g_assert_false (g_type_test_flags (TEST_TYPE_INTERFACE, G_TYPE_FLAG_CLASSED));
28
29 g_assert_false (G_TYPE_IS_DEEP_DERIVABLE (TEST_TYPE_INTERFACE));
30 g_assert_false (g_type_test_flags (TEST_TYPE_INTERFACE, G_TYPE_FLAG_DEEP_DERIVABLE));
31
32 g_assert_true (G_TYPE_IS_DERIVABLE (TEST_TYPE_INTERFACE));
33 g_assert_true (g_type_test_flags (TEST_TYPE_INTERFACE, G_TYPE_FLAG_DERIVABLE));
34
35 g_assert_false (G_TYPE_IS_FINAL (TEST_TYPE_INTERFACE));
36 g_assert_false (g_type_test_flags (TEST_TYPE_INTERFACE, G_TYPE_FLAG_FINAL));
37
38 g_assert_false (G_TYPE_IS_INSTANTIATABLE (TEST_TYPE_INTERFACE));
39 g_assert_false (g_type_test_flags (TEST_TYPE_INTERFACE, G_TYPE_FLAG_INSTANTIATABLE));
40 }
41
42 #define TEST_TYPE_FINAL (test_final_get_type())
43 G_DECLARE_FINAL_TYPE (TestFinal, test_final, TEST, FINAL, GObject)
44
45 struct _TestFinal
46 {
47 GObject parent_instance;
48 };
49
50 struct _TestFinalClass
51 {
52 GObjectClass parent_class;
53 };
54
55 G_DEFINE_FINAL_TYPE (TestFinal, test_final, G_TYPE_OBJECT)
56
57 static void
58 test_final_class_init (TestFinalClass *klass)
59 {
60 }
61
62 static void
63 test_final_init (TestFinal *self)
64 {
65 }
66
67 #define TEST_TYPE_FINAL2 (test_final2_get_type())
68 G_DECLARE_FINAL_TYPE (TestFinal2, test_final2, TEST, FINAL2, TestFinal)
69
70 struct _TestFinal2
71 {
72 TestFinal parent_instance;
73 };
74
75 struct _TestFinal2Class
76 {
77 TestFinalClass parent_class;
78 };
79
80 G_DEFINE_TYPE (TestFinal2, test_final2, TEST_TYPE_FINAL)
81
82 static void
83 test_final2_class_init (TestFinal2Class *klass)
84 {
85 }
86
87 static void
88 test_final2_init (TestFinal2 *self)
89 {
90 }
91
92 /* test_type_flags_final: Check that trying to derive from a final class
93 * will result in a warning from the type system
94 */
95 static void
96 test_type_flags_final (void)
97 {
98 GType final2_type;
99
100 g_assert_true (G_TYPE_IS_FINAL (TEST_TYPE_FINAL));
101 g_assert_true (g_type_test_flags (TEST_TYPE_FINAL, G_TYPE_FLAG_FINAL));
102 g_assert_true (G_TYPE_IS_CLASSED (TEST_TYPE_FINAL));
103 g_assert_true (g_type_test_flags (TEST_TYPE_FINAL, G_TYPE_FLAG_CLASSED));
104 g_assert_true (G_TYPE_IS_INSTANTIATABLE (TEST_TYPE_FINAL));
105 g_assert_true (g_type_test_flags (TEST_TYPE_FINAL, G_TYPE_FLAG_INSTANTIATABLE));
106 g_assert_true (g_type_test_flags (TEST_TYPE_FINAL,
107 G_TYPE_FLAG_FINAL |
108 G_TYPE_FLAG_CLASSED |
109 G_TYPE_FLAG_INSTANTIATABLE));
110 g_assert_false (g_type_test_flags (TEST_TYPE_FINAL,
111 G_TYPE_FLAG_FINAL |
112 G_TYPE_FLAG_CLASSED |
113 G_TYPE_FLAG_DEPRECATED |
114 G_TYPE_FLAG_INSTANTIATABLE));
115
116 /* This is the message we print out when registering the type */
117 g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_CRITICAL,
118 "*cannot derive*");
119
120 /* This is the message when we fail to return from the GOnce init
121 * block within the test_final2_get_type() function
122 */
123 g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL,
124 "*g_once_init_leave_pointer: assertion*");
125
126 final2_type = TEST_TYPE_FINAL2;
127 g_assert_true (final2_type == G_TYPE_INVALID);
128
129 g_test_assert_expected_messages ();
130 }
131
132 #define TEST_TYPE_DEPRECATED (test_deprecated_get_type())
133 G_DECLARE_FINAL_TYPE (TestDeprecated, test_deprecated, TEST, DEPRECATED, GObject)
134
135 struct _TestDeprecated
136 {
137 GObject parent_instance;
138 };
139
140 struct _TestDeprecatedClass
141 {
142 GObjectClass parent_class;
143 };
144
145 G_DEFINE_TYPE_EXTENDED (TestDeprecated, test_deprecated, G_TYPE_OBJECT, G_TYPE_FLAG_FINAL | G_TYPE_FLAG_DEPRECATED, {})
146
147 static void
148 test_deprecated_class_init (TestDeprecatedClass *klass)
149 {
150 }
151
152 static void
153 test_deprecated_init (TestDeprecated *self)
154 {
155 }
156
157 static void
158 test_type_flags_final_instance_check (void)
159 {
160 TestFinal *final;
161
162 final = g_object_new (TEST_TYPE_FINAL, NULL);
163 g_assert_true (g_type_check_instance_is_a ((GTypeInstance *) final,
164 TEST_TYPE_FINAL));
165 g_assert_false (g_type_check_instance_is_a ((GTypeInstance *) final,
166 TEST_TYPE_DEPRECATED));
167 g_assert_true (g_type_check_instance_is_a ((GTypeInstance *) final,
168 G_TYPE_OBJECT));
169 g_assert_false (g_type_check_instance_is_a ((GTypeInstance *) final,
170 G_TYPE_INVALID));
171
172 g_clear_object (&final);
173 }
174
175 static void
176 test_type_flags_deprecated (void)
177 {
178 GType deprecated_type;
179 GObject *deprecated_object = NULL;
180
181 g_test_summary ("Test that trying to instantiate a deprecated type results in a warning.");
182
183 /* This is the message we print out when registering the type */
184 g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING,
185 "*The type TestDeprecated is deprecated and shouldn’t be used any more*");
186
187 /* The type itself should not be considered invalid. */
188 deprecated_type = TEST_TYPE_DEPRECATED;
189 g_assert_false (deprecated_type == G_TYPE_INVALID);
190 g_assert_true (G_TYPE_IS_DEPRECATED (deprecated_type));
191
192 g_assert_true (G_TYPE_IS_FINAL (deprecated_type));
193 g_assert_true (g_type_test_flags (deprecated_type, G_TYPE_FLAG_FINAL));
194
195 g_assert_true (g_type_test_flags (deprecated_type,
196 G_TYPE_FLAG_DEPRECATED |
197 G_TYPE_FLAG_CLASSED |
198 G_TYPE_FLAG_FINAL |
199 G_TYPE_FLAG_INSTANTIATABLE));
200 g_assert_false (g_type_test_flags (deprecated_type,
201 G_TYPE_FLAG_DEPRECATED |
202 G_TYPE_FLAG_CLASSED |
203 G_TYPE_FLAG_FINAL |
204 G_TYPE_FLAG_ABSTRACT |
205 G_TYPE_FLAG_INSTANTIATABLE));
206
207 /* Instantiating it should work, but emit a warning. */
208 deprecated_object = g_object_new (deprecated_type, NULL);
209 g_assert_nonnull (deprecated_object);
210
211 g_test_assert_expected_messages ();
212
213 g_object_unref (deprecated_object);
214
215 /* Instantiating it again should not emit a second warning. */
216 deprecated_object = g_object_new (deprecated_type, NULL);
217 g_assert_nonnull (deprecated_object);
218
219 g_assert_true (g_type_check_instance_is_a ((GTypeInstance *) deprecated_object,
220 TEST_TYPE_DEPRECATED));
221 g_assert_true (g_type_check_instance_is_a ((GTypeInstance *) deprecated_object,
222 G_TYPE_OBJECT));
223 g_assert_false (g_type_check_instance_is_a ((GTypeInstance *) deprecated_object,
224 TEST_TYPE_FINAL));
225 g_assert_false (g_type_check_instance_is_a ((GTypeInstance *) deprecated_object,
226 G_TYPE_INVALID));
227
228 g_test_assert_expected_messages ();
229
230 g_object_unref (deprecated_object);
231 }
232
233 int
234 main (int argc, char *argv[])
235 {
236 g_test_init (&argc, &argv, NULL);
237
238 g_setenv ("G_ENABLE_DIAGNOSTIC", "1", TRUE);
239
240 g_test_add_func ("/type/flags/interface", test_type_flags_interface);
241 g_test_add_func ("/type/flags/final", test_type_flags_final);
242 g_test_add_func ("/type/flags/final/instance-check", test_type_flags_final_instance_check);
243 g_test_add_func ("/type/flags/deprecated", test_type_flags_deprecated);
244
245 return g_test_run ();
246 }