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 "marshalers.h"
23 : : #include "testcommon.h"
24 : :
25 : : /* What this test tests is the behavior of signal accumulators
26 : : * Two accumulators are tested:
27 : : *
28 : : * 1: A custom accumulator that appends the returned strings
29 : : * 2: The standard g_signal_accumulator_true_handled that stops
30 : : * emission on TRUE returns.
31 : : */
32 : :
33 : : /* TestObject, a parent class for TestObject */
34 : : #define TEST_TYPE_OBJECT (test_object_get_type ())
35 : : typedef struct _TestObject TestObject;
36 : : typedef struct _TestObjectClass TestObjectClass;
37 : :
38 : : struct _TestObject
39 : : {
40 : : GObject parent_instance;
41 : : };
42 : : struct _TestObjectClass
43 : : {
44 : : GObjectClass parent_class;
45 : :
46 : : gchar* (*test_signal1) (TestObject *tobject,
47 : : gint param);
48 : : gboolean (*test_signal2) (TestObject *tobject,
49 : : gint param);
50 : : GVariant* (*test_signal3) (TestObject *tobject,
51 : : gboolean *weak_ptr);
52 : : };
53 : :
54 : : static GType test_object_get_type (void);
55 : :
56 : : static gboolean
57 : 3 : test_signal1_accumulator (GSignalInvocationHint *ihint,
58 : : GValue *return_accu,
59 : : const GValue *handler_return,
60 : : gpointer data)
61 : : {
62 : 3 : const gchar *accu_string = g_value_get_string (return_accu);
63 : 3 : const gchar *new_string = g_value_get_string (handler_return);
64 : : gchar *result_string;
65 : :
66 : 3 : if (accu_string)
67 : 2 : result_string = g_strconcat (accu_string, new_string, NULL);
68 : 1 : else if (new_string)
69 : 1 : result_string = g_strdup (new_string);
70 : : else
71 : 0 : result_string = NULL;
72 : :
73 : 3 : g_value_take_string (return_accu, result_string);
74 : :
75 : 3 : return TRUE;
76 : : }
77 : :
78 : : static gchar *
79 : 1 : test_object_signal1_callback_before (TestObject *tobject,
80 : : gint param,
81 : : gpointer data)
82 : : {
83 : 1 : return g_strdup ("<before>");
84 : : }
85 : :
86 : : static gchar *
87 : 1 : test_object_real_signal1 (TestObject *tobject,
88 : : gint param)
89 : : {
90 : 1 : return g_strdup ("<default>");
91 : : }
92 : :
93 : : static gchar *
94 : 1 : test_object_signal1_callback_after (TestObject *tobject,
95 : : gint param,
96 : : gpointer data)
97 : : {
98 : 1 : return g_strdup ("<after>");
99 : : }
100 : :
101 : : static gboolean
102 : 4 : test_object_signal2_callback_before (TestObject *tobject,
103 : : gint param)
104 : : {
105 : 4 : switch (param)
106 : : {
107 : 1 : case 1: return TRUE;
108 : 1 : case 2: return FALSE;
109 : 1 : case 3: return FALSE;
110 : 1 : case 4: return FALSE;
111 : : }
112 : :
113 : : g_assert_not_reached ();
114 : : return FALSE;
115 : : }
116 : :
117 : : static gboolean
118 : 3 : test_object_real_signal2 (TestObject *tobject,
119 : : gint param)
120 : : {
121 : 3 : switch (param)
122 : : {
123 : : case 1: g_assert_not_reached (); return FALSE;
124 : 1 : case 2: return TRUE;
125 : 1 : case 3: return FALSE;
126 : 1 : case 4: return FALSE;
127 : : }
128 : :
129 : : g_assert_not_reached ();
130 : : return FALSE;
131 : : }
132 : :
133 : : static gboolean
134 : 2 : test_object_signal2_callback_after (TestObject *tobject,
135 : : gint param)
136 : : {
137 : 2 : switch (param)
138 : : {
139 : : case 1: g_assert_not_reached (); return FALSE;
140 : : case 2: g_assert_not_reached (); return FALSE;
141 : 1 : case 3: return TRUE;
142 : 1 : case 4: return FALSE;
143 : : }
144 : :
145 : : g_assert_not_reached ();
146 : : return FALSE;
147 : : }
148 : :
149 : : static gboolean
150 : 1 : test_signal3_accumulator (GSignalInvocationHint *ihint,
151 : : GValue *return_accu,
152 : : const GValue *handler_return,
153 : : gpointer data)
154 : : {
155 : : GVariant *variant;
156 : :
157 : 1 : variant = g_value_get_variant (handler_return);
158 : 1 : g_assert_false (g_variant_is_floating (variant));
159 : :
160 : 1 : g_value_set_variant (return_accu, variant);
161 : :
162 : 1 : return variant == NULL;
163 : : }
164 : :
165 : : /* To be notified when the variant is finalised, we construct
166 : : * it from data with a custom GDestroyNotify.
167 : : */
168 : :
169 : : typedef struct {
170 : : char *mem;
171 : : gsize n;
172 : : gboolean *weak_ptr;
173 : : } VariantData;
174 : :
175 : : static void
176 : 1 : free_data (VariantData *data)
177 : : {
178 : 1 : *(data->weak_ptr) = TRUE;
179 : 1 : g_free (data->mem);
180 : 1 : g_slice_free (VariantData, data);
181 : 1 : }
182 : :
183 : : static GVariant *
184 : 1 : test_object_real_signal3 (TestObject *tobject,
185 : : gboolean *weak_ptr)
186 : : {
187 : : GVariant *variant;
188 : : VariantData *data;
189 : :
190 : 1 : variant = g_variant_ref_sink (g_variant_new_uint32 (42));
191 : 1 : data = g_slice_new (VariantData);
192 : 1 : data->weak_ptr = weak_ptr;
193 : 1 : data->n = g_variant_get_size (variant);
194 : 1 : data->mem = g_malloc (data->n);
195 : 1 : g_variant_store (variant, data->mem);
196 : 1 : g_variant_unref (variant);
197 : :
198 : 1 : variant = g_variant_new_from_data (G_VARIANT_TYPE ("u"),
199 : 1 : data->mem,
200 : : data->n,
201 : : TRUE,
202 : : (GDestroyNotify) free_data,
203 : : data);
204 : 1 : return g_variant_ref_sink (variant);
205 : : }
206 : :
207 : : static void
208 : 1 : test_object_class_init (TestObjectClass *class)
209 : : {
210 : 1 : class->test_signal1 = test_object_real_signal1;
211 : 1 : class->test_signal2 = test_object_real_signal2;
212 : 1 : class->test_signal3 = test_object_real_signal3;
213 : :
214 : 1 : g_signal_new ("test-signal1",
215 : : G_OBJECT_CLASS_TYPE (class),
216 : : G_SIGNAL_RUN_LAST,
217 : : G_STRUCT_OFFSET (TestObjectClass, test_signal1),
218 : : test_signal1_accumulator, NULL,
219 : : test_STRING__INT,
220 : : G_TYPE_STRING, 1, G_TYPE_INT);
221 : 1 : g_signal_new ("test-signal2",
222 : : G_OBJECT_CLASS_TYPE (class),
223 : : G_SIGNAL_RUN_LAST,
224 : : G_STRUCT_OFFSET (TestObjectClass, test_signal2),
225 : : g_signal_accumulator_true_handled, NULL,
226 : : test_BOOLEAN__INT,
227 : : G_TYPE_BOOLEAN, 1, G_TYPE_INT);
228 : 1 : g_signal_new ("test-signal3",
229 : : G_OBJECT_CLASS_TYPE (class),
230 : : G_SIGNAL_RUN_LAST,
231 : : G_STRUCT_OFFSET (TestObjectClass, test_signal3),
232 : : test_signal3_accumulator, NULL,
233 : : test_VARIANT__POINTER,
234 : : G_TYPE_VARIANT, 1, G_TYPE_POINTER);
235 : 1 : }
236 : :
237 : 1 : static DEFINE_TYPE(TestObject, test_object,
238 : : test_object_class_init, NULL, NULL,
239 : : G_TYPE_OBJECT);
240 : :
241 : : static void
242 : 1 : test_accumulator (void)
243 : : {
244 : : TestObject *object;
245 : : gchar *string_result;
246 : : gboolean bool_result;
247 : : gboolean variant_finalised;
248 : : GVariant *variant_result;
249 : :
250 : 1 : object = g_object_new (TEST_TYPE_OBJECT, NULL);
251 : :
252 : 1 : g_signal_connect (object, "test-signal1",
253 : : G_CALLBACK (test_object_signal1_callback_before), NULL);
254 : 1 : g_signal_connect_after (object, "test-signal1",
255 : : G_CALLBACK (test_object_signal1_callback_after), NULL);
256 : :
257 : 1 : g_signal_emit_by_name (object, "test-signal1", 0, &string_result);
258 : 1 : g_assert_cmpstr (string_result, ==, "<before><default><after>");
259 : 1 : g_free (string_result);
260 : :
261 : 1 : g_signal_connect (object, "test-signal2",
262 : : G_CALLBACK (test_object_signal2_callback_before), NULL);
263 : 1 : g_signal_connect_after (object, "test-signal2",
264 : : G_CALLBACK (test_object_signal2_callback_after), NULL);
265 : :
266 : 1 : bool_result = FALSE;
267 : 1 : g_signal_emit_by_name (object, "test-signal2", 1, &bool_result);
268 : 1 : g_assert_true (bool_result);
269 : 1 : bool_result = FALSE;
270 : 1 : g_signal_emit_by_name (object, "test-signal2", 2, &bool_result);
271 : 1 : g_assert_true (bool_result);
272 : 1 : bool_result = FALSE;
273 : 1 : g_signal_emit_by_name (object, "test-signal2", 3, &bool_result);
274 : 1 : g_assert_true (bool_result);
275 : 1 : bool_result = TRUE;
276 : 1 : g_signal_emit_by_name (object, "test-signal2", 4, &bool_result);
277 : 1 : g_assert_false (bool_result);
278 : :
279 : 1 : variant_finalised = FALSE;
280 : 1 : variant_result = NULL;
281 : 1 : g_signal_emit_by_name (object, "test-signal3", &variant_finalised, &variant_result);
282 : 1 : g_assert_nonnull (variant_result);
283 : 1 : g_assert_false (g_variant_is_floating (variant_result));
284 : :
285 : : /* Test that variant_result had refcount 1 */
286 : 1 : g_assert_false (variant_finalised);
287 : 1 : g_variant_unref (variant_result);
288 : 1 : g_assert_true (variant_finalised);
289 : :
290 : 1 : g_object_unref (object);
291 : 1 : }
292 : :
293 : : int
294 : 1 : main (int argc,
295 : : char *argv[])
296 : : {
297 : 1 : g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
298 : 1 : G_LOG_LEVEL_WARNING |
299 : : G_LOG_LEVEL_CRITICAL);
300 : :
301 : 1 : g_test_init (&argc, &argv, NULL);
302 : :
303 : 1 : g_test_add_func ("/gobject/accumulator", test_accumulator);
304 : :
305 : 1 : return g_test_run ();
306 : : }
|