+static void
+test_wakeup(void)
+{
+ GMainContext *ctx;
+ int i;
+
+ ctx = g_main_context_new ();
+
+ /* run a random large enough number of times because
+ * main contexts tend to wake up a few times after creation.
+ */
+ for (i = 0; i < 100; i++)
+ {
+ /* This is the invariant we care about:
+ * g_main_context_wakeup(ctx,) ensures that the next call to
+ * g_main_context_iteration (ctx, TRUE) returns and doesn't
+ * block.
+ * This is important in threaded apps where we might not know
+ * if the thread calls g_main_context_wakeup() before or after
+ * we enter g_main_context_iteration().
+ */
+ g_main_context_wakeup (ctx);
+ g_main_context_iteration (ctx, TRUE);
+ }
+
+ g_main_context_unref (ctx);
+}
+
+static void
+test_remove_invalid (void)
+{
+ g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "Source ID 3000000000 was not found*");
+ g_source_remove (3000000000u);
+ g_test_assert_expected_messages ();
+}
+
+static gboolean
+trivial_prepare (GSource *source,
+ gint *timeout)
+{
+ *timeout = 0;
+ return TRUE;
+}
+
+static gint n_finalized;
+
+static void
+trivial_finalize (GSource *source)
+{
+ n_finalized++;
+}
+
+static void
+test_unref_while_pending (void)
+{
+ static GSourceFuncs funcs = { trivial_prepare, NULL, NULL, trivial_finalize };
+ GMainContext *context;
+ GSource *source;
+
+ context = g_main_context_new ();
+
+ source = g_source_new (&funcs, sizeof (GSource));
+ g_source_attach (source, context);
+ g_source_unref (source);
+
+ /* Do incomplete main iteration -- get a pending source but don't dispatch it. */
+ g_main_context_prepare (context, NULL);
+ g_main_context_query (context, 0, NULL, NULL, 0);
+ g_main_context_check (context, 1000, NULL, 0);
+
+ /* Destroy the context */
+ g_main_context_unref (context);
+
+ /* Make sure we didn't leak the source */
+ g_assert_cmpint (n_finalized, ==, 1);
+}
+