Branch data Line data Source code
1 : : /* GObject - GLib Type, Object, Parameter and Signal Library
2 : : *
3 : : * Copyright (C) 2015-2022 Christian Hergert <christian@hergert.me>
4 : : * Copyright (C) 2015 Garrett Regier <garrettregier@gmail.com>
5 : : *
6 : : * SPDX-License-Identifier: LGPL-2.1-or-later
7 : : *
8 : : * This library is free software; you can redistribute it and/or
9 : : * modify it under the terms of the GNU Lesser General Public
10 : : * License as published by the Free Software Foundation; either
11 : : * version 2.1 of the License, or (at your option) any later version.
12 : : *
13 : : * This library is distributed in the hope that it will be useful,
14 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : : * Lesser General Public License for more details.
17 : : *
18 : : * You should have received a copy of the GNU Lesser General
19 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 : : *
21 : : * SPDX-License-Identifier: LGPL-2.1-or-later
22 : : */
23 : :
24 : : #include <glib-object.h>
25 : :
26 : 118 : G_DECLARE_FINAL_TYPE (SignalTarget, signal_target, TEST, SIGNAL_TARGET, GObject)
27 : :
28 : : struct _SignalTarget
29 : : {
30 : : GObject parent_instance;
31 : : };
32 : :
33 : 146 : G_DEFINE_TYPE (SignalTarget, signal_target, G_TYPE_OBJECT)
34 : :
35 : 52 : static G_DEFINE_QUARK (detail, signal_detail);
36 : :
37 : : enum {
38 : : THE_SIGNAL,
39 : : NEVER_EMITTED,
40 : : LAST_SIGNAL
41 : : };
42 : :
43 : : static guint signals[LAST_SIGNAL];
44 : :
45 : : static void
46 : 2 : signal_target_class_init (SignalTargetClass *klass)
47 : : {
48 : 2 : signals[THE_SIGNAL] =
49 : 2 : g_signal_new ("the-signal",
50 : : G_TYPE_FROM_CLASS (klass),
51 : : G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
52 : : 0,
53 : : NULL, NULL, NULL,
54 : : G_TYPE_NONE,
55 : : 1,
56 : : G_TYPE_OBJECT);
57 : :
58 : 2 : signals[NEVER_EMITTED] =
59 : 2 : g_signal_new ("never-emitted",
60 : : G_TYPE_FROM_CLASS (klass),
61 : : G_SIGNAL_RUN_LAST,
62 : : 0,
63 : : NULL, NULL, NULL,
64 : : G_TYPE_NONE,
65 : : 1,
66 : : G_TYPE_OBJECT);
67 : 2 : }
68 : :
69 : : static void
70 : 10 : signal_target_init (SignalTarget *self)
71 : : {
72 : 10 : }
73 : :
74 : : static gint global_signal_calls;
75 : : static gint global_weak_notify_called;
76 : :
77 : : static void
78 : 33 : connect_before_cb (SignalTarget *target,
79 : : GSignalGroup *group,
80 : : gint *signal_calls)
81 : : {
82 : : SignalTarget *readback;
83 : :
84 : 33 : g_assert_true (TEST_IS_SIGNAL_TARGET (target));
85 : 33 : g_assert_true (G_IS_SIGNAL_GROUP (group));
86 : 33 : g_assert_nonnull (signal_calls);
87 : 33 : g_assert_true (signal_calls == &global_signal_calls);
88 : :
89 : 33 : readback = g_signal_group_dup_target (group);
90 : 33 : g_assert_true (readback == target);
91 : 33 : g_object_unref (readback);
92 : :
93 : 33 : *signal_calls += 1;
94 : 33 : }
95 : :
96 : : static void
97 : 11 : connect_after_cb (SignalTarget *target,
98 : : GSignalGroup *group,
99 : : gint *signal_calls)
100 : : {
101 : : SignalTarget *readback;
102 : :
103 : 11 : g_assert_true (TEST_IS_SIGNAL_TARGET (target));
104 : 11 : g_assert_true (G_IS_SIGNAL_GROUP (group));
105 : 11 : g_assert_nonnull (signal_calls);
106 : 11 : g_assert_true (signal_calls == &global_signal_calls);
107 : :
108 : 11 : readback = g_signal_group_dup_target (group);
109 : 11 : g_assert_true (readback == target);
110 : 11 : g_object_unref (readback);
111 : :
112 : 11 : g_assert_cmpint (*signal_calls, ==, 5);
113 : 11 : *signal_calls += 1;
114 : 11 : }
115 : :
116 : : static void
117 : 11 : connect_swapped_cb (gint *signal_calls,
118 : : GSignalGroup *group,
119 : : SignalTarget *target)
120 : : {
121 : : SignalTarget *readback;
122 : :
123 : 11 : g_assert_true (signal_calls != NULL);
124 : 11 : g_assert_true (signal_calls == &global_signal_calls);
125 : 11 : g_assert_true (G_IS_SIGNAL_GROUP (group));
126 : 11 : g_assert_true (TEST_IS_SIGNAL_TARGET (target));
127 : :
128 : 11 : readback = g_signal_group_dup_target (group);
129 : 11 : g_assert_true (readback == target);
130 : 11 : g_object_unref (readback);
131 : :
132 : 11 : *signal_calls += 1;
133 : 11 : }
134 : :
135 : : static void
136 : 11 : connect_object_cb (SignalTarget *target,
137 : : GSignalGroup *group,
138 : : GObject *object)
139 : : {
140 : : SignalTarget *readback;
141 : : gint *signal_calls;
142 : :
143 : 11 : g_assert_true (TEST_IS_SIGNAL_TARGET (target));
144 : 11 : g_assert_true (G_IS_SIGNAL_GROUP (group));
145 : 11 : g_assert_true (G_IS_OBJECT (object));
146 : :
147 : 11 : readback = g_signal_group_dup_target (group);
148 : 11 : g_assert_true (readback == target);
149 : 11 : g_object_unref (readback);
150 : :
151 : 11 : signal_calls = g_object_get_data (object, "signal-calls");
152 : 11 : g_assert_nonnull (signal_calls);
153 : 11 : g_assert_true (signal_calls == &global_signal_calls);
154 : :
155 : 11 : *signal_calls += 1;
156 : 11 : }
157 : :
158 : : static void
159 : 0 : connect_bad_detail_cb (SignalTarget *target,
160 : : GSignalGroup *group,
161 : : GObject *object)
162 : : {
163 : 0 : g_error ("This detailed signal is never emitted!");
164 : : }
165 : :
166 : : static void
167 : 0 : connect_never_emitted_cb (SignalTarget *target,
168 : : gboolean *weak_notify_called)
169 : : {
170 : 0 : g_error ("This signal is never emitted!");
171 : : }
172 : :
173 : : static void
174 : 3 : connect_data_notify_cb (gboolean *weak_notify_called,
175 : : GClosure *closure)
176 : : {
177 : 3 : g_assert_nonnull (weak_notify_called);
178 : 3 : g_assert_true (weak_notify_called == &global_weak_notify_called);
179 : 3 : g_assert_nonnull (closure);
180 : :
181 : 3 : g_assert_false (*weak_notify_called);
182 : 3 : *weak_notify_called = TRUE;
183 : 3 : }
184 : :
185 : : static void
186 : 3 : connect_data_weak_notify_cb (gboolean *weak_notify_called,
187 : : GSignalGroup *group)
188 : : {
189 : 3 : g_assert_nonnull (weak_notify_called);
190 : 3 : g_assert_true (weak_notify_called == &global_weak_notify_called);
191 : 3 : g_assert_true (G_IS_SIGNAL_GROUP (group));
192 : :
193 : 3 : g_assert_true (*weak_notify_called);
194 : 3 : }
195 : :
196 : : static void
197 : 3 : connect_all_signals (GSignalGroup *group)
198 : : {
199 : : GObject *object;
200 : : GClosure *closure;
201 : :
202 : : /* Check that these are called in the right order */
203 : 3 : g_signal_group_connect (group,
204 : : "the-signal",
205 : : G_CALLBACK (connect_before_cb),
206 : : &global_signal_calls);
207 : 3 : g_signal_group_connect_after (group,
208 : : "the-signal",
209 : : G_CALLBACK (connect_after_cb),
210 : : &global_signal_calls);
211 : :
212 : : /* Check that this is called with the arguments swapped */
213 : 3 : g_signal_group_connect_swapped (group,
214 : : "the-signal",
215 : : G_CALLBACK (connect_swapped_cb),
216 : : &global_signal_calls);
217 : :
218 : : /* Check that this is called with the arguments swapped */
219 : 3 : object = g_object_new (G_TYPE_OBJECT, NULL);
220 : 3 : g_object_set_data (object, "signal-calls", &global_signal_calls);
221 : 3 : g_signal_group_connect_object (group,
222 : : "the-signal",
223 : : G_CALLBACK (connect_object_cb),
224 : : object,
225 : : 0);
226 : 3 : g_object_weak_ref (G_OBJECT (group),
227 : : (GWeakNotify)g_object_unref,
228 : : object);
229 : :
230 : : /* Check that a detailed signal is handled correctly */
231 : 3 : g_signal_group_connect (group,
232 : : "the-signal::detail",
233 : : G_CALLBACK (connect_before_cb),
234 : : &global_signal_calls);
235 : 3 : g_signal_group_connect (group,
236 : : "the-signal::bad-detail",
237 : : G_CALLBACK (connect_bad_detail_cb),
238 : : NULL);
239 : :
240 : : /* Check that the notify is called correctly */
241 : 3 : global_weak_notify_called = FALSE;
242 : 3 : g_signal_group_connect_data (group,
243 : : "never-emitted",
244 : : G_CALLBACK (connect_never_emitted_cb),
245 : : &global_weak_notify_called,
246 : : (GClosureNotify)connect_data_notify_cb,
247 : : 0);
248 : 3 : g_object_weak_ref (G_OBJECT (group),
249 : : (GWeakNotify)connect_data_weak_notify_cb,
250 : : &global_weak_notify_called);
251 : :
252 : :
253 : : /* Check that this can be called as a GClosure */
254 : 3 : closure = g_cclosure_new (G_CALLBACK (connect_before_cb),
255 : : &global_signal_calls,
256 : : NULL);
257 : 3 : g_signal_group_connect_closure (group, "the-signal", closure, FALSE);
258 : :
259 : : /* Check that invalidated GClosures don't get called */
260 : 3 : closure = g_cclosure_new (G_CALLBACK (connect_before_cb),
261 : : &global_signal_calls,
262 : : NULL);
263 : 3 : g_closure_invalidate (closure);
264 : 3 : g_signal_group_connect_closure (group, "the-signal", closure, FALSE);
265 : 3 : }
266 : :
267 : : static void
268 : 52 : assert_signals (SignalTarget *target,
269 : : GSignalGroup *group,
270 : : gboolean success)
271 : : {
272 : 52 : g_assert (TEST_IS_SIGNAL_TARGET (target));
273 : 52 : g_assert (group == NULL || G_IS_SIGNAL_GROUP (group));
274 : :
275 : 52 : global_signal_calls = 0;
276 : 52 : g_signal_emit (target, signals[THE_SIGNAL],
277 : : signal_detail_quark (), group);
278 : 52 : g_assert_cmpint (global_signal_calls, ==, success ? 6 : 0);
279 : 52 : }
280 : :
281 : : static void
282 : 0 : dummy_handler (void)
283 : : {
284 : 0 : }
285 : :
286 : : static void
287 : 1 : test_signal_group_invalid (void)
288 : : {
289 : 1 : GObject *invalid_target = g_object_new (G_TYPE_OBJECT, NULL);
290 : 1 : SignalTarget *target = g_object_new (signal_target_get_type (), NULL);
291 : 1 : GSignalGroup *group = g_signal_group_new (signal_target_get_type ());
292 : :
293 : : /* Invalid Target Type */
294 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
295 : : "*g_type_is_a*G_TYPE_OBJECT*");
296 : 1 : g_signal_group_new (G_TYPE_DATE_TIME);
297 : 1 : g_test_assert_expected_messages ();
298 : :
299 : : /* Invalid Target */
300 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
301 : : "*Failed to set GSignalGroup of target type SignalTarget using target * of type GObject*");
302 : 1 : g_signal_group_set_target (group, invalid_target);
303 : 1 : g_assert_finalize_object (group);
304 : 1 : g_test_assert_expected_messages ();
305 : :
306 : : /* Invalid Signal Name */
307 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
308 : : "*Invalid signal name “does-not-exist”*");
309 : 1 : group = g_signal_group_new (signal_target_get_type ());
310 : 1 : g_signal_group_connect (group,
311 : : "does-not-exist",
312 : : G_CALLBACK (connect_before_cb),
313 : : NULL);
314 : 1 : g_test_assert_expected_messages ();
315 : 1 : g_assert_finalize_object (group);
316 : :
317 : : /* Invalid Callback */
318 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
319 : : "*c_handler != NULL*");
320 : 1 : group = g_signal_group_new (signal_target_get_type ());
321 : 1 : g_signal_group_connect (group,
322 : : "the-signal",
323 : : G_CALLBACK (NULL),
324 : : NULL);
325 : 1 : g_test_assert_expected_messages ();
326 : 1 : g_assert_finalize_object (group);
327 : :
328 : : /* Connecting after setting target */
329 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
330 : : "*Cannot add signals after setting target*");
331 : 1 : group = g_signal_group_new (signal_target_get_type ());
332 : 1 : g_signal_group_set_target (group, target);
333 : 1 : g_signal_group_connect (group,
334 : : "the-signal",
335 : : G_CALLBACK (dummy_handler),
336 : : NULL);
337 : 1 : g_test_assert_expected_messages ();
338 : 1 : g_assert_finalize_object (group);
339 : :
340 : 1 : g_assert_finalize_object (target);
341 : 1 : g_assert_finalize_object (invalid_target);
342 : 1 : }
343 : :
344 : : static void
345 : 1 : test_signal_group_simple (void)
346 : : {
347 : : SignalTarget *target;
348 : : GSignalGroup *group;
349 : : SignalTarget *readback;
350 : :
351 : : /* Set the target before connecting the signals */
352 : 1 : group = g_signal_group_new (signal_target_get_type ());
353 : 1 : target = g_object_new (signal_target_get_type (), NULL);
354 : 1 : g_assert_null (g_signal_group_dup_target (group));
355 : 1 : g_signal_group_set_target (group, target);
356 : 1 : readback = g_signal_group_dup_target (group);
357 : 1 : g_assert_true (readback == target);
358 : 1 : g_object_unref (readback);
359 : 1 : g_assert_finalize_object (group);
360 : 1 : assert_signals (target, NULL, FALSE);
361 : 1 : g_assert_finalize_object (target);
362 : :
363 : 1 : group = g_signal_group_new (signal_target_get_type ());
364 : 1 : target = g_object_new (signal_target_get_type (), NULL);
365 : 1 : connect_all_signals (group);
366 : 1 : g_signal_group_set_target (group, target);
367 : 1 : assert_signals (target, group, TRUE);
368 : 1 : g_assert_finalize_object (target);
369 : 1 : g_assert_finalize_object (group);
370 : 1 : }
371 : :
372 : : static void
373 : 1 : test_signal_group_changing_target (void)
374 : : {
375 : : SignalTarget *target1, *target2;
376 : 1 : GSignalGroup *group = g_signal_group_new (signal_target_get_type ());
377 : : SignalTarget *readback;
378 : :
379 : 1 : connect_all_signals (group);
380 : 1 : g_assert_null (g_signal_group_dup_target (group));
381 : :
382 : : /* Set the target after connecting the signals */
383 : 1 : target1 = g_object_new (signal_target_get_type (), NULL);
384 : 1 : g_signal_group_set_target (group, target1);
385 : 1 : readback = g_signal_group_dup_target (group);
386 : 1 : g_assert_true (readback == target1);
387 : 1 : g_object_unref (readback);
388 : :
389 : 1 : assert_signals (target1, group, TRUE);
390 : :
391 : : /* Set the same target */
392 : 1 : readback = g_signal_group_dup_target (group);
393 : 1 : g_assert_true (readback == target1);
394 : 1 : g_object_unref (readback);
395 : 1 : g_signal_group_set_target (group, target1);
396 : :
397 : 1 : readback = g_signal_group_dup_target (group);
398 : 1 : g_assert_true (readback == target1);
399 : 1 : g_object_unref (readback);
400 : :
401 : 1 : assert_signals (target1, group, TRUE);
402 : :
403 : : /* Set a new target when the current target is non-NULL */
404 : 1 : target2 = g_object_new (signal_target_get_type (), NULL);
405 : 1 : readback = g_signal_group_dup_target (group);
406 : 1 : g_assert_true (readback == target1);
407 : 1 : g_object_unref (readback);
408 : :
409 : 1 : g_signal_group_set_target (group, target2);
410 : 1 : readback = g_signal_group_dup_target (group);
411 : 1 : g_assert_true (readback == target2);
412 : 1 : g_object_unref (readback);
413 : :
414 : 1 : assert_signals (target2, group, TRUE);
415 : :
416 : 1 : g_assert_finalize_object (target2);
417 : 1 : g_assert_finalize_object (target1);
418 : 1 : g_assert_finalize_object (group);
419 : 1 : }
420 : :
421 : : static void
422 : 3 : assert_blocking (SignalTarget *target,
423 : : GSignalGroup *group,
424 : : gint count)
425 : : {
426 : : gint i;
427 : :
428 : 3 : assert_signals (target, group, TRUE);
429 : :
430 : : /* Assert that multiple blocks are effective */
431 : 22 : for (i = 0; i < count; ++i)
432 : : {
433 : 19 : g_signal_group_block (group);
434 : 19 : assert_signals (target, group, FALSE);
435 : : }
436 : :
437 : : /* Assert that the signal is not emitted after the first unblock */
438 : 22 : for (i = 0; i < count; ++i)
439 : : {
440 : 19 : assert_signals (target, group, FALSE);
441 : 19 : g_signal_group_unblock (group);
442 : : }
443 : :
444 : 3 : assert_signals (target, group, TRUE);
445 : 3 : }
446 : :
447 : : static void
448 : 1 : test_signal_group_blocking (void)
449 : : {
450 : : SignalTarget *target1, *target2, *readback;
451 : 1 : GSignalGroup *group = g_signal_group_new (signal_target_get_type ());
452 : :
453 : : /* Test blocking and unblocking null target */
454 : 1 : g_signal_group_block (group);
455 : 1 : g_signal_group_unblock (group);
456 : :
457 : 1 : connect_all_signals (group);
458 : 1 : g_assert_null (g_signal_group_dup_target (group));
459 : :
460 : 1 : target1 = g_object_new (signal_target_get_type (), NULL);
461 : 1 : g_signal_group_set_target (group, target1);
462 : 1 : readback = g_signal_group_dup_target (group);
463 : 1 : g_assert_true (readback == target1);
464 : 1 : g_object_unref (readback);
465 : :
466 : 1 : assert_blocking (target1, group, 1);
467 : 1 : assert_blocking (target1, group, 3);
468 : 1 : assert_blocking (target1, group, 15);
469 : :
470 : : /* Assert that blocking transfers across changing the target */
471 : 1 : g_signal_group_block (group);
472 : 1 : g_signal_group_block (group);
473 : :
474 : : /* Set a new target when the current target is non-NULL */
475 : 1 : target2 = g_object_new (signal_target_get_type (), NULL);
476 : 1 : readback = g_signal_group_dup_target (group);
477 : 1 : g_assert_true (readback == target1);
478 : 1 : g_object_unref (readback);
479 : 1 : g_signal_group_set_target (group, target2);
480 : 1 : readback = g_signal_group_dup_target (group);
481 : 1 : g_assert_true (readback == target2);
482 : 1 : g_object_unref (readback);
483 : :
484 : 1 : assert_signals (target2, group, FALSE);
485 : 1 : g_signal_group_unblock (group);
486 : 1 : assert_signals (target2, group, FALSE);
487 : 1 : g_signal_group_unblock (group);
488 : 1 : assert_signals (target2, group, TRUE);
489 : :
490 : 1 : g_assert_finalize_object (target2);
491 : 1 : g_assert_finalize_object (target1);
492 : 1 : g_assert_finalize_object (group);
493 : 1 : }
494 : :
495 : : static void
496 : 1 : test_signal_group_weak_ref_target (void)
497 : : {
498 : 1 : SignalTarget *target = g_object_new (signal_target_get_type (), NULL);
499 : 1 : GSignalGroup *group = g_signal_group_new (signal_target_get_type ());
500 : : SignalTarget *readback;
501 : :
502 : 1 : g_assert_null (g_signal_group_dup_target (group));
503 : 1 : g_signal_group_set_target (group, target);
504 : 1 : readback = g_signal_group_dup_target (group);
505 : 1 : g_assert_true (readback == target);
506 : 1 : g_object_unref (readback);
507 : :
508 : 1 : g_assert_finalize_object (target);
509 : 1 : g_assert_null (g_signal_group_dup_target (group));
510 : 1 : g_assert_finalize_object (group);
511 : 1 : }
512 : :
513 : : static void
514 : 1 : test_signal_group_connect_object (void)
515 : : {
516 : 1 : GObject *object = g_object_new (G_TYPE_OBJECT, NULL);
517 : 1 : SignalTarget *target = g_object_new (signal_target_get_type (), NULL);
518 : 1 : GSignalGroup *group = g_signal_group_new (signal_target_get_type ());
519 : : SignalTarget *readback;
520 : :
521 : : /* We already do basic connect_object() tests in connect_signals(),
522 : : * this is only needed to test the specifics of connect_object()
523 : : */
524 : 1 : g_signal_group_connect_object (group,
525 : : "the-signal",
526 : : G_CALLBACK (connect_object_cb),
527 : : object,
528 : : 0);
529 : :
530 : 1 : g_assert_null (g_signal_group_dup_target (group));
531 : 1 : g_signal_group_set_target (group, target);
532 : 1 : readback = g_signal_group_dup_target (group);
533 : 1 : g_assert_true (readback == target);
534 : 1 : g_object_unref (readback);
535 : :
536 : 1 : g_assert_finalize_object (object);
537 : :
538 : : /* This would cause a warning if the SignalGroup did not
539 : : * have a weakref on the object as it would try to connect again
540 : : */
541 : 1 : g_signal_group_set_target (group, NULL);
542 : 1 : g_assert_null (g_signal_group_dup_target (group));
543 : 1 : g_signal_group_set_target (group, target);
544 : 1 : readback = g_signal_group_dup_target (group);
545 : 1 : g_assert_true (readback == target);
546 : 1 : g_object_unref (readback);
547 : :
548 : 1 : g_assert_finalize_object (group);
549 : 1 : g_assert_finalize_object (target);
550 : 1 : }
551 : :
552 : : static void
553 : 1 : test_signal_group_signal_parsing (void)
554 : : {
555 : 1 : g_test_trap_subprocess ("/GObject/SignalGroup/signal-parsing/subprocess", 0,
556 : : G_TEST_SUBPROCESS_INHERIT_STDERR);
557 : 1 : g_test_trap_assert_passed ();
558 : 1 : g_test_trap_assert_stderr ("");
559 : 1 : }
560 : :
561 : : static void
562 : 1 : test_signal_group_signal_parsing_subprocess (void)
563 : : {
564 : : GSignalGroup *group;
565 : :
566 : : /* Check that the class has not been created and with it the
567 : : * signals registered. This will cause g_signal_parse_name()
568 : : * to fail unless GSignalGroup calls g_type_class_ref().
569 : : */
570 : 1 : g_assert_null (g_type_class_peek (signal_target_get_type ()));
571 : :
572 : 1 : group = g_signal_group_new (signal_target_get_type ());
573 : 1 : g_signal_group_connect (group,
574 : : "the-signal",
575 : : G_CALLBACK (connect_before_cb),
576 : : NULL);
577 : :
578 : 1 : g_assert_finalize_object (group);
579 : 1 : }
580 : :
581 : : static void
582 : 1 : test_signal_group_properties (void)
583 : : {
584 : : GSignalGroup *group;
585 : : SignalTarget *target, *other;
586 : : GType gtype;
587 : :
588 : 1 : group = g_signal_group_new (signal_target_get_type ());
589 : 1 : g_object_get (group,
590 : : "target", &target,
591 : : "target-type", >ype,
592 : : NULL);
593 : 1 : g_assert_cmpint (gtype, ==, signal_target_get_type ());
594 : 1 : g_assert_null (target);
595 : :
596 : 1 : target = g_object_new (signal_target_get_type (), NULL);
597 : 1 : g_object_set (group, "target", target, NULL);
598 : 1 : g_object_get (group, "target", &other, NULL);
599 : 1 : g_assert_true (target == other);
600 : 1 : g_object_unref (other);
601 : :
602 : 1 : g_assert_finalize_object (target);
603 : 1 : g_assert_null (g_signal_group_dup_target (group));
604 : 1 : g_assert_finalize_object (group);
605 : 1 : }
606 : :
607 : : G_DECLARE_INTERFACE (SignalThing, signal_thing, SIGNAL, THING, GObject)
608 : :
609 : : struct _SignalThingInterface
610 : : {
611 : : GTypeInterface iface;
612 : : void (*changed) (SignalThing *thing);
613 : : };
614 : :
615 : 1 : G_DEFINE_INTERFACE (SignalThing, signal_thing, G_TYPE_OBJECT)
616 : :
617 : : static guint signal_thing_changed;
618 : :
619 : : static void
620 : 1 : signal_thing_default_init (SignalThingInterface *iface)
621 : : {
622 : 1 : signal_thing_changed =
623 : 1 : g_signal_new ("changed",
624 : : G_TYPE_FROM_INTERFACE (iface),
625 : : G_SIGNAL_RUN_LAST,
626 : : G_STRUCT_OFFSET (SignalThingInterface, changed),
627 : : NULL, NULL, NULL,
628 : : G_TYPE_NONE, 0);
629 : 1 : }
630 : :
631 : : G_GNUC_NORETURN static void
632 : 0 : thing_changed_cb (SignalThing *thing,
633 : : gpointer user_data G_GNUC_UNUSED)
634 : : {
635 : : g_assert_not_reached ();
636 : : }
637 : :
638 : : static void
639 : 1 : test_signal_group_interface (void)
640 : : {
641 : : GSignalGroup *group;
642 : :
643 : 1 : group = g_signal_group_new (signal_thing_get_type ());
644 : 1 : g_signal_group_connect (group,
645 : : "changed",
646 : : G_CALLBACK (thing_changed_cb),
647 : : NULL);
648 : 1 : g_assert_finalize_object (group);
649 : 1 : }
650 : :
651 : : gint
652 : 2 : main (gint argc,
653 : : gchar *argv[])
654 : : {
655 : 2 : g_test_init (&argc, &argv, NULL);
656 : 2 : g_test_add_func ("/GObject/SignalGroup/invalid", test_signal_group_invalid);
657 : 2 : g_test_add_func ("/GObject/SignalGroup/simple", test_signal_group_simple);
658 : 2 : g_test_add_func ("/GObject/SignalGroup/changing-target", test_signal_group_changing_target);
659 : 2 : g_test_add_func ("/GObject/SignalGroup/blocking", test_signal_group_blocking);
660 : 2 : g_test_add_func ("/GObject/SignalGroup/weak-ref-target", test_signal_group_weak_ref_target);
661 : 2 : g_test_add_func ("/GObject/SignalGroup/connect-object", test_signal_group_connect_object);
662 : 2 : g_test_add_func ("/GObject/SignalGroup/signal-parsing", test_signal_group_signal_parsing);
663 : 2 : g_test_add_func ("/GObject/SignalGroup/signal-parsing/subprocess", test_signal_group_signal_parsing_subprocess);
664 : 2 : g_test_add_func ("/GObject/SignalGroup/properties", test_signal_group_properties);
665 : 2 : g_test_add_func ("/GObject/SignalGroup/interface", test_signal_group_interface);
666 : 2 : return g_test_run ();
667 : : }
|