tests: add signal disconnection test

This commit adds a test to ensure that during a signal emission, if
a signal handler gets disconnected, it won't be run, even if it would
have run before the disconnection.
This commit is contained in:
Ray Strode 2013-09-20 15:20:39 -04:00
parent cb7059e17f
commit 29ef821766
2 changed files with 137 additions and 0 deletions

View File

@ -19,6 +19,7 @@ installed_test_programs = \
defaultiface \
dynamictype \
override \
signals \
singleton \
references \
$(NULL)
@ -39,6 +40,7 @@ TESTS_ENVIRONMENT = \
MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256))
accumulator_SOURCES = accumulator.c testmarshal.c testmarshal.h
signals_SOURCES = signals.c
defaultiface_SOURCES = defaultiface.c testmodule.c testmodule.h
dynamictype_SOURCES = dynamictype.c testmodule.c testmodule.h

135
tests/gobject/signals.c Normal file
View File

@ -0,0 +1,135 @@
/* GObject - GLib Type, Object, Parameter and Signal Library
* Copyright (C) 2013 Red Hat, Inc.
* Copy and pasted from accumulator.c and modified.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "TestSignals"
#undef G_DISABLE_ASSERT
#undef G_DISABLE_CHECKS
#undef G_DISABLE_CAST_CHECKS
#include <glib-object.h>
#include "testcommon.h"
/* What this test tests is the behavior of signal disconnection
* from within a signal handler for the signal being disconnected.
*
* The test demonstrates that signal handlers disconnected from a signal
* from an earlier handler in the same emission will not be run.
*
* It also demonstrates that signal handlers connected from a signal
* from an earlier handler in the same emission will not be run.
*/
/*
* TestObject, a parent class for TestObject
*/
#define TEST_TYPE_OBJECT (test_object_get_type ())
typedef struct _TestObject TestObject;
typedef struct _TestObjectClass TestObjectClass;
static gboolean callback1_ran = FALSE, callback2_ran = FALSE, callback3_ran = FALSE, default_handler_ran = FALSE;
struct _TestObject
{
GObject parent_instance;
};
struct _TestObjectClass
{
GObjectClass parent_class;
void (*test_signal) (TestObject *object);
};
static GType test_object_get_type (void);
static void
test_object_real_signal (TestObject *object)
{
default_handler_ran = TRUE;
}
static void
test_object_signal_callback3 (TestObject *object,
gpointer data)
{
callback3_ran = TRUE;
}
static void
test_object_signal_callback2 (TestObject *object,
gpointer data)
{
callback2_ran = TRUE;
}
static void
test_object_signal_callback1 (TestObject *object,
gpointer data)
{
callback1_ran = TRUE;
g_signal_handlers_disconnect_by_func (G_OBJECT (object),
test_object_signal_callback2,
data);
g_signal_connect (object, "test-signal",
G_CALLBACK (test_object_signal_callback3), NULL);
}
static void
test_object_class_init (TestObjectClass *class)
{
class->test_signal = test_object_real_signal;
g_signal_new ("test-signal",
G_OBJECT_CLASS_TYPE (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (TestObjectClass, test_signal),
NULL, NULL, NULL, G_TYPE_NONE, 0);
}
static DEFINE_TYPE(TestObject, test_object,
test_object_class_init, NULL, NULL,
G_TYPE_OBJECT)
int
main (int argc,
char *argv[])
{
TestObject *object;
g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
G_LOG_LEVEL_WARNING |
G_LOG_LEVEL_CRITICAL);
object = g_object_new (TEST_TYPE_OBJECT, NULL);
g_signal_connect (object, "test-signal",
G_CALLBACK (test_object_signal_callback1), NULL);
g_signal_connect (object, "test-signal",
G_CALLBACK (test_object_signal_callback2), NULL);
g_signal_emit_by_name (object, "test-signal");
g_assert (callback1_ran);
g_assert (!callback2_ran);
g_assert (!callback3_ran);
g_assert (default_handler_ran);
return 0;
}