mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-26 15:36:14 +01:00
GMainContext - Add tests for !1353 and related situations
This commit is contained in:
parent
730a75fc8e
commit
aaa7640f7c
@ -1832,14 +1832,188 @@ test_maincontext_source_finalization (void)
|
||||
g_assert_true (source_finalize_called);
|
||||
}
|
||||
|
||||
/* GSource implementation which optionally keeps a strong reference to another
|
||||
* GSource until finalization, when it destroys and unrefs the other source.
|
||||
*/
|
||||
typedef struct {
|
||||
GSource source;
|
||||
|
||||
GSource *other_source;
|
||||
} SourceWithSource;
|
||||
|
||||
static void
|
||||
finalize_source_with_source (GSource *source)
|
||||
{
|
||||
SourceWithSource *s = (SourceWithSource *) source;
|
||||
|
||||
if (s->other_source)
|
||||
{
|
||||
g_source_destroy (s->other_source);
|
||||
g_source_unref (s->other_source);
|
||||
s->other_source = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static GSourceFuncs source_with_source_funcs = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
finalize_source_with_source
|
||||
};
|
||||
|
||||
static void
|
||||
test_maincontext_source_finalization_from_source (gconstpointer user_data)
|
||||
{
|
||||
GMainContext *c = g_main_context_new ();
|
||||
GSource *s1, *s2;
|
||||
|
||||
g_test_summary ("Tests if freeing a GSource as part of another GSource "
|
||||
"during main context destruction works.");
|
||||
g_test_bug ("https://gitlab.gnome.org/GNOME/glib/merge_requests/1353");
|
||||
|
||||
s1 = g_source_new (&source_with_source_funcs, sizeof (SourceWithSource));
|
||||
s2 = g_source_new (&source_with_source_funcs, sizeof (SourceWithSource));
|
||||
((SourceWithSource *)s1)->other_source = g_source_ref (s2);
|
||||
|
||||
/* Attach sources in a different order so they end up being destroyed
|
||||
* in a different order by the main context */
|
||||
if (GPOINTER_TO_INT (user_data) < 5)
|
||||
{
|
||||
g_source_attach (s1, c);
|
||||
g_source_attach (s2, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_source_attach (s2, c);
|
||||
g_source_attach (s1, c);
|
||||
}
|
||||
|
||||
/* Test a few different permutations here */
|
||||
if (GPOINTER_TO_INT (user_data) % 5 == 0)
|
||||
{
|
||||
/* Get rid of our references so that destroying the context
|
||||
* will unref them immediately */
|
||||
g_source_unref (s1);
|
||||
g_source_unref (s2);
|
||||
g_main_context_unref (c);
|
||||
}
|
||||
else if (GPOINTER_TO_INT (user_data) % 5 == 1)
|
||||
{
|
||||
/* Destroy and free the sources before the context */
|
||||
g_source_destroy (s1);
|
||||
g_source_unref (s1);
|
||||
g_source_destroy (s2);
|
||||
g_source_unref (s2);
|
||||
g_main_context_unref (c);
|
||||
}
|
||||
else if (GPOINTER_TO_INT (user_data) % 5 == 2)
|
||||
{
|
||||
/* Destroy and free the sources before the context */
|
||||
g_source_destroy (s2);
|
||||
g_source_unref (s2);
|
||||
g_source_destroy (s1);
|
||||
g_source_unref (s1);
|
||||
g_main_context_unref (c);
|
||||
}
|
||||
else if (GPOINTER_TO_INT (user_data) % 5 == 3)
|
||||
{
|
||||
/* Destroy and free the context before the sources */
|
||||
g_main_context_unref (c);
|
||||
g_source_unref (s2);
|
||||
g_source_unref (s1);
|
||||
}
|
||||
else if (GPOINTER_TO_INT (user_data) % 5 == 4)
|
||||
{
|
||||
/* Destroy and free the context before the sources */
|
||||
g_main_context_unref (c);
|
||||
g_source_unref (s1);
|
||||
g_source_unref (s2);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
dispatch_source_with_source (GSource *source, GSourceFunc callback, gpointer user_data)
|
||||
{
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static GSourceFuncs source_with_source_funcs_dispatch = {
|
||||
NULL,
|
||||
NULL,
|
||||
dispatch_source_with_source,
|
||||
finalize_source_with_source
|
||||
};
|
||||
|
||||
static void
|
||||
test_maincontext_source_finalization_from_dispatch (gconstpointer user_data)
|
||||
{
|
||||
GMainContext *c = g_main_context_new ();
|
||||
GSource *s1, *s2;
|
||||
|
||||
g_test_summary ("Tests if freeing a GSource as part of another GSource "
|
||||
"during main context iteration works.");
|
||||
|
||||
s1 = g_source_new (&source_with_source_funcs_dispatch, sizeof (SourceWithSource));
|
||||
s2 = g_source_new (&source_with_source_funcs_dispatch, sizeof (SourceWithSource));
|
||||
((SourceWithSource *)s1)->other_source = g_source_ref (s2);
|
||||
|
||||
g_source_attach (s1, c);
|
||||
g_source_attach (s2, c);
|
||||
|
||||
if (GPOINTER_TO_INT (user_data) == 0)
|
||||
{
|
||||
/* This finalizes s1 as part of the iteration, which then destroys and
|
||||
* frees s2 too */
|
||||
g_source_set_ready_time (s1, 0);
|
||||
}
|
||||
else if (GPOINTER_TO_INT (user_data) == 1)
|
||||
{
|
||||
/* This destroys s2 as part of the iteration but does not free it as
|
||||
* it's still referenced by s1 */
|
||||
g_source_set_ready_time (s2, 0);
|
||||
}
|
||||
else if (GPOINTER_TO_INT (user_data) == 2)
|
||||
{
|
||||
/* This destroys both s1 and s2 as part of the iteration */
|
||||
g_source_set_ready_time (s1, 0);
|
||||
g_source_set_ready_time (s2, 0);
|
||||
}
|
||||
|
||||
/* Get rid of our references so only the main context has one now */
|
||||
g_source_unref (s1);
|
||||
g_source_unref (s2);
|
||||
|
||||
/* Iterate as long as there are sources to dispatch */
|
||||
while (g_main_context_iteration (c, FALSE))
|
||||
{
|
||||
/* Do nothing here */
|
||||
}
|
||||
|
||||
g_main_context_unref (c);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
gint i;
|
||||
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
g_test_bug_base ("http://bugzilla.gnome.org/");
|
||||
|
||||
g_test_add_func ("/maincontext/basic", test_maincontext_basic);
|
||||
g_test_add_func ("/maincontext/source_finalization", test_maincontext_source_finalization);
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
gchar *name = g_strdup_printf ("/maincontext/source_finalization_from_source/%d", i);
|
||||
g_test_add_data_func (name, GINT_TO_POINTER (i), test_maincontext_source_finalization_from_source);
|
||||
g_free (name);
|
||||
}
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
gchar *name = g_strdup_printf ("/maincontext/source_finalization_from_dispatch/%d", i);
|
||||
g_test_add_data_func (name, GINT_TO_POINTER (i), test_maincontext_source_finalization_from_dispatch);
|
||||
g_free (name);
|
||||
}
|
||||
g_test_add_func ("/mainloop/basic", test_mainloop_basic);
|
||||
g_test_add_func ("/mainloop/timeouts", test_timeouts);
|
||||
g_test_add_func ("/mainloop/priorities", test_priorities);
|
||||
|
Loading…
Reference in New Issue
Block a user