1 /* GObject - GLib Type, Object, Parameter and Signal Library
2 * Copyright (C) 2001, 2003 Red Hat, Inc.
4 * SPDX-License-Identifier: LGPL-2.1-or-later
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.
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.
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/>.
20 #include <glib-object.h>
22 #include "marshalers.h"
23 #include "testcommon.h"
25 /* What this test tests is the behavior of signal accumulators
26 * Two accumulators are tested:
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.
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;
40 GObject parent_instance;
42 struct _TestObjectClass
44 GObjectClass parent_class;
46 gchar* (*test_signal1) (TestObject *tobject,
48 gboolean (*test_signal2) (TestObject *tobject,
50 GVariant* (*test_signal3) (TestObject *tobject,
54 static GType test_object_get_type (void);
57 test_signal1_accumulator (GSignalInvocationHint *ihint,
59 const GValue *handler_return,
62 const gchar *accu_string = g_value_get_string (return_accu);
63 const gchar *new_string = g_value_get_string (handler_return);
67 result_string = g_strconcat (accu_string, new_string, NULL);
69 result_string = g_strdup (new_string);
73 g_value_take_string (return_accu, result_string);
79 test_object_signal1_callback_before (TestObject *tobject,
83 return g_strdup ("<before>");
87 test_object_real_signal1 (TestObject *tobject,
90 return g_strdup ("<default>");
94 test_object_signal1_callback_after (TestObject *tobject,
98 return g_strdup ("<after>");
102 test_object_signal2_callback_before (TestObject *tobject,
108 case 2: return FALSE;
109 case 3: return FALSE;
110 case 4: return FALSE;
113 g_assert_not_reached ();
118 test_object_real_signal2 (TestObject *tobject,
123 case 1: g_assert_not_reached (); return FALSE;
125 case 3: return FALSE;
126 case 4: return FALSE;
129 g_assert_not_reached ();
134 test_object_signal2_callback_after (TestObject *tobject,
139 case 1: g_assert_not_reached (); return FALSE;
140 case 2: g_assert_not_reached (); return FALSE;
142 case 4: return FALSE;
145 g_assert_not_reached ();
150 test_signal3_accumulator (GSignalInvocationHint *ihint,
152 const GValue *handler_return,
157 variant = g_value_get_variant (handler_return);
158 g_assert_false (g_variant_is_floating (variant));
160 g_value_set_variant (return_accu, variant);
162 return variant == NULL;
165 /* To be notified when the variant is finalised, we construct
166 * it from data with a custom GDestroyNotify.
176 free_data (VariantData *data)
178 *(data->weak_ptr) = TRUE;
180 g_slice_free (VariantData, data);
184 test_object_real_signal3 (TestObject *tobject,
190 variant = g_variant_ref_sink (g_variant_new_uint32 (42));
191 data = g_slice_new (VariantData);
192 data->weak_ptr = weak_ptr;
193 data->n = g_variant_get_size (variant);
194 data->mem = g_malloc (data->n);
195 g_variant_store (variant, data->mem);
196 g_variant_unref (variant);
198 variant = g_variant_new_from_data (G_VARIANT_TYPE ("u"),
202 (GDestroyNotify) free_data,
204 return g_variant_ref_sink (variant);
208 test_object_class_init (TestObjectClass *class)
210 class->test_signal1 = test_object_real_signal1;
211 class->test_signal2 = test_object_real_signal2;
212 class->test_signal3 = test_object_real_signal3;
214 g_signal_new ("test-signal1",
215 G_OBJECT_CLASS_TYPE (class),
217 G_STRUCT_OFFSET (TestObjectClass, test_signal1),
218 test_signal1_accumulator, NULL,
220 G_TYPE_STRING, 1, G_TYPE_INT);
221 g_signal_new ("test-signal2",
222 G_OBJECT_CLASS_TYPE (class),
224 G_STRUCT_OFFSET (TestObjectClass, test_signal2),
225 g_signal_accumulator_true_handled, NULL,
227 G_TYPE_BOOLEAN, 1, G_TYPE_INT);
228 g_signal_new ("test-signal3",
229 G_OBJECT_CLASS_TYPE (class),
231 G_STRUCT_OFFSET (TestObjectClass, test_signal3),
232 test_signal3_accumulator, NULL,
233 test_VARIANT__POINTER,
234 G_TYPE_VARIANT, 1, G_TYPE_POINTER);
237 static DEFINE_TYPE(TestObject, test_object,
238 test_object_class_init, NULL, NULL,
242 test_accumulator (void)
245 gchar *string_result;
246 gboolean bool_result;
247 gboolean variant_finalised;
248 GVariant *variant_result;
250 object = g_object_new (TEST_TYPE_OBJECT, NULL);
252 g_signal_connect (object, "test-signal1",
253 G_CALLBACK (test_object_signal1_callback_before), NULL);
254 g_signal_connect_after (object, "test-signal1",
255 G_CALLBACK (test_object_signal1_callback_after), NULL);
257 g_signal_emit_by_name (object, "test-signal1", 0, &string_result);
258 g_assert_cmpstr (string_result, ==, "<before><default><after>");
259 g_free (string_result);
261 g_signal_connect (object, "test-signal2",
262 G_CALLBACK (test_object_signal2_callback_before), NULL);
263 g_signal_connect_after (object, "test-signal2",
264 G_CALLBACK (test_object_signal2_callback_after), NULL);
267 g_signal_emit_by_name (object, "test-signal2", 1, &bool_result);
268 g_assert_true (bool_result);
270 g_signal_emit_by_name (object, "test-signal2", 2, &bool_result);
271 g_assert_true (bool_result);
273 g_signal_emit_by_name (object, "test-signal2", 3, &bool_result);
274 g_assert_true (bool_result);
276 g_signal_emit_by_name (object, "test-signal2", 4, &bool_result);
277 g_assert_false (bool_result);
279 variant_finalised = FALSE;
280 variant_result = NULL;
281 g_signal_emit_by_name (object, "test-signal3", &variant_finalised, &variant_result);
282 g_assert_nonnull (variant_result);
283 g_assert_false (g_variant_is_floating (variant_result));
285 /* Test that variant_result had refcount 1 */
286 g_assert_false (variant_finalised);
287 g_variant_unref (variant_result);
288 g_assert_true (variant_finalised);
290 g_object_unref (object);
297 g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
298 G_LOG_LEVEL_WARNING |
299 G_LOG_LEVEL_CRITICAL);
301 g_test_init (&argc, &argv, NULL);
303 g_test_add_func ("/gobject/accumulator", test_accumulator);
305 return g_test_run ();