1 | /* GLib testing framework examples and tests |
2 | * Copyright (C) 2018 Canonical Ltd |
3 | * Authors: Marco Trevisan <marco@ubuntu.com> |
4 | * |
5 | * This work is provided "as is"; redistribution and modification |
6 | * in whole or in part, in any medium, physical or electronic is |
7 | * permitted without restriction. |
8 | * |
9 | * This work 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. |
12 | * |
13 | * In no event shall the authors or contributors be liable for any |
14 | * direct, indirect, incidental, special, exemplary, or consequential |
15 | * damages (including, but not limited to, procurement of substitute |
16 | * goods or services; loss of use, data, or profits; or business |
17 | * interruption) however caused and on any theory of liability, whether |
18 | * in contract, strict liability, or tort (including negligence or |
19 | * otherwise) arising in any way out of the use of this software, even |
20 | * if advised of the possibility of such damage. |
21 | */ |
22 | |
23 | #include <glib-object.h> |
24 | #include <string.h> |
25 | |
26 | G_DECLARE_DERIVABLE_TYPE (TestAutoCleanupBase, test_base_auto_cleanup, TEST, BASE_AUTO_CLEANUP, GObject) |
27 | |
28 | struct _TestAutoCleanupBaseClass { |
29 | GObjectClass parent_class; |
30 | }; |
31 | |
32 | G_DEFINE_TYPE (TestAutoCleanupBase, test_base_auto_cleanup, G_TYPE_OBJECT) |
33 | |
34 | static void |
35 | test_base_auto_cleanup_class_init (TestAutoCleanupBaseClass *class) |
36 | { |
37 | } |
38 | |
39 | static void |
40 | test_base_auto_cleanup_init (TestAutoCleanupBase *tac) |
41 | { |
42 | } |
43 | |
44 | G_DECLARE_FINAL_TYPE (TestAutoCleanup, test_auto_cleanup, TEST, AUTO_CLEANUP, TestAutoCleanupBase) |
45 | |
46 | struct _TestAutoCleanup |
47 | { |
48 | TestAutoCleanupBase parent_instance; |
49 | }; |
50 | |
51 | G_DEFINE_TYPE (TestAutoCleanup, test_auto_cleanup, G_TYPE_OBJECT) |
52 | |
53 | static void |
54 | test_auto_cleanup_class_init (TestAutoCleanupClass *class) |
55 | { |
56 | } |
57 | |
58 | static void |
59 | test_auto_cleanup_init (TestAutoCleanup *tac) |
60 | { |
61 | } |
62 | |
63 | static TestAutoCleanup * |
64 | test_auto_cleanup_new (void) |
65 | { |
66 | return g_object_new (object_type: test_auto_cleanup_get_type (), NULL); |
67 | } |
68 | |
69 | /* Verify that an object declared with G_DECLARE_FINAL_TYPE provides by default |
70 | * autocleanup functions, defined using the ones of the base type (defined with |
71 | * G_DECLARE_DERIVABLE_TYPE) and so that it can be used with g_autoptr */ |
72 | static void |
73 | test_autoptr (void) |
74 | { |
75 | TestAutoCleanup *tac_ptr = test_auto_cleanup_new (); |
76 | g_object_add_weak_pointer (G_OBJECT (tac_ptr), weak_pointer_location: (gpointer *) &tac_ptr); |
77 | |
78 | { |
79 | g_autoptr (TestAutoCleanup) tac = tac_ptr; |
80 | g_assert_nonnull (tac); |
81 | } |
82 | #ifdef __GNUC__ |
83 | g_assert_null (tac_ptr); |
84 | #endif |
85 | } |
86 | |
87 | /* Verify that an object declared with G_DECLARE_FINAL_TYPE provides by default |
88 | * autocleanup functions, defined using the ones of the base type (defined with |
89 | * G_DECLARE_DERIVABLE_TYPE) and that stealing an autopointer works properly */ |
90 | static void |
91 | test_autoptr_steal (void) |
92 | { |
93 | g_autoptr (TestAutoCleanup) tac1 = test_auto_cleanup_new (); |
94 | TestAutoCleanup *tac_ptr = tac1; |
95 | |
96 | g_object_add_weak_pointer (G_OBJECT (tac_ptr), weak_pointer_location: (gpointer *) &tac_ptr); |
97 | |
98 | { |
99 | g_autoptr (TestAutoCleanup) tac2 = g_steal_pointer (&tac1); |
100 | g_assert_nonnull (tac_ptr); |
101 | g_assert_null (tac1); |
102 | g_assert_true (tac2 == tac_ptr); |
103 | } |
104 | #ifdef __GNUC__ |
105 | g_assert_null (tac_ptr); |
106 | #endif |
107 | } |
108 | |
109 | /* Verify that an object declared with G_DECLARE_FINAL_TYPE provides by default |
110 | * autolist cleanup functions defined using the ones of the parent type |
111 | * and so that can be used with g_autolist, and that freeing the list correctly |
112 | * unrefs the object too */ |
113 | static void |
114 | test_autolist (void) |
115 | { |
116 | TestAutoCleanup *tac1 = test_auto_cleanup_new (); |
117 | TestAutoCleanup *tac2 = test_auto_cleanup_new (); |
118 | g_autoptr (TestAutoCleanup) tac3 = test_auto_cleanup_new (); |
119 | |
120 | g_object_add_weak_pointer (G_OBJECT (tac1), weak_pointer_location: (gpointer *) &tac1); |
121 | g_object_add_weak_pointer (G_OBJECT (tac2), weak_pointer_location: (gpointer *) &tac2); |
122 | g_object_add_weak_pointer (G_OBJECT (tac3), weak_pointer_location: (gpointer *) &tac3); |
123 | |
124 | { |
125 | g_autolist (TestAutoCleanup) l = NULL; |
126 | |
127 | l = g_list_prepend (list: l, data: tac1); |
128 | l = g_list_prepend (list: l, data: tac2); |
129 | |
130 | /* Squash warnings about dead stores */ |
131 | (void) l; |
132 | } |
133 | |
134 | /* Only assert if autoptr works */ |
135 | #ifdef __GNUC__ |
136 | g_assert_null (tac1); |
137 | g_assert_null (tac2); |
138 | #endif |
139 | g_assert_nonnull (tac3); |
140 | |
141 | g_clear_object (&tac3); |
142 | g_assert_null (tac3); |
143 | } |
144 | |
145 | /* Verify that an object declared with G_DECLARE_FINAL_TYPE provides by default |
146 | * autoslist cleanup functions (defined using the ones of the base type declared |
147 | * with G_DECLARE_DERIVABLE_TYPE) and so that can be used with g_autoslist, and |
148 | * that freeing the slist correctly unrefs the object too */ |
149 | static void |
150 | test_autoslist (void) |
151 | { |
152 | TestAutoCleanup *tac1 = test_auto_cleanup_new (); |
153 | TestAutoCleanup *tac2 = test_auto_cleanup_new (); |
154 | g_autoptr (TestAutoCleanup) tac3 = test_auto_cleanup_new (); |
155 | |
156 | g_object_add_weak_pointer (G_OBJECT (tac1), weak_pointer_location: (gpointer *) &tac1); |
157 | g_object_add_weak_pointer (G_OBJECT (tac2), weak_pointer_location: (gpointer *) &tac2); |
158 | g_object_add_weak_pointer (G_OBJECT (tac3), weak_pointer_location: (gpointer *) &tac3); |
159 | |
160 | { |
161 | g_autoslist (TestAutoCleanup) l = NULL; |
162 | |
163 | l = g_slist_prepend (list: l, data: tac1); |
164 | l = g_slist_prepend (list: l, data: tac2); |
165 | } |
166 | |
167 | /* Only assert if autoptr works */ |
168 | #ifdef __GNUC__ |
169 | g_assert_null (tac1); |
170 | g_assert_null (tac2); |
171 | #endif |
172 | g_assert_nonnull (tac3); |
173 | |
174 | g_clear_object (&tac3); |
175 | g_assert_null (tac3); |
176 | } |
177 | |
178 | /* Verify that an object declared with G_DECLARE_FINAL_TYPE provides by default |
179 | * autoqueue cleanup functions (defined using the ones of the base type declared |
180 | * with G_DECLARE_DERIVABLE_TYPE) and so that can be used with g_autoqueue, and |
181 | * that freeing the queue correctly unrefs the object too */ |
182 | static void |
183 | test_autoqueue (void) |
184 | { |
185 | TestAutoCleanup *tac1 = test_auto_cleanup_new (); |
186 | TestAutoCleanup *tac2 = test_auto_cleanup_new (); |
187 | g_autoptr (TestAutoCleanup) tac3 = test_auto_cleanup_new (); |
188 | |
189 | g_object_add_weak_pointer (G_OBJECT (tac1), weak_pointer_location: (gpointer *) &tac1); |
190 | g_object_add_weak_pointer (G_OBJECT (tac2), weak_pointer_location: (gpointer *) &tac2); |
191 | g_object_add_weak_pointer (G_OBJECT (tac3), weak_pointer_location: (gpointer *) &tac3); |
192 | |
193 | { |
194 | g_autoqueue (TestAutoCleanup) q = g_queue_new (); |
195 | |
196 | g_queue_push_head (queue: q, data: tac1); |
197 | g_queue_push_tail (queue: q, data: tac2); |
198 | } |
199 | |
200 | /* Only assert if autoptr works */ |
201 | #ifdef __GNUC__ |
202 | g_assert_null (tac1); |
203 | g_assert_null (tac2); |
204 | #endif |
205 | g_assert_nonnull (tac3); |
206 | |
207 | g_clear_object (&tac3); |
208 | g_assert_null (tac3); |
209 | } |
210 | |
211 | static void |
212 | test_autoclass (void) |
213 | { |
214 | g_autoptr (TestAutoCleanupBaseClass) base_class_ptr = NULL; |
215 | g_autoptr (TestAutoCleanupClass) class_ptr = NULL; |
216 | |
217 | base_class_ptr = g_type_class_ref (type: test_base_auto_cleanup_get_type ()); |
218 | class_ptr = g_type_class_ref (type: test_auto_cleanup_get_type ()); |
219 | |
220 | g_assert_nonnull (base_class_ptr); |
221 | g_assert_nonnull (class_ptr); |
222 | } |
223 | |
224 | int |
225 | main (int argc, gchar *argv[]) |
226 | { |
227 | g_test_init (argc: &argc, argv: &argv, NULL); |
228 | |
229 | g_test_add_func (testpath: "/autoptr/autoptr" , test_func: test_autoptr); |
230 | g_test_add_func (testpath: "/autoptr/autoptr_steal" , test_func: test_autoptr_steal); |
231 | g_test_add_func (testpath: "/autoptr/autolist" , test_func: test_autolist); |
232 | g_test_add_func (testpath: "/autoptr/autoslist" , test_func: test_autoslist); |
233 | g_test_add_func (testpath: "/autoptr/autoqueue" , test_func: test_autoqueue); |
234 | g_test_add_func (testpath: "/autoptr/autoclass" , test_func: test_autoclass); |
235 | |
236 | return g_test_run (); |
237 | } |
238 | |