[glib/wip/gapplication] Add some tests for GApplication
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/wip/gapplication] Add some tests for GApplication
- Date: Fri, 21 May 2010 04:05:17 +0000 (UTC)
commit 2a04dfee3c17d6154a7d6aec74e8305270ca6cc0
Author: Matthias Clasen <mclasen redhat com>
Date: Thu May 20 22:58:34 2010 -0400
Add some tests for GApplication
Test various aspects of GApplication behaviour with actual
DBus calls.
gio/tests/Makefile.am | 8 +
gio/tests/testapp.c | 61 +++++++
gio/tests/testapps.c | 453 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 522 insertions(+), 0 deletions(-)
---
diff --git a/gio/tests/Makefile.am b/gio/tests/Makefile.am
index 0b1da7b..02fafc5 100644
--- a/gio/tests/Makefile.am
+++ b/gio/tests/Makefile.am
@@ -51,6 +51,7 @@ TEST_PROGS += \
gdbus-peer \
gdbus-exit-on-close \
application \
+ testapps \
$(NULL)
SAMPLE_PROGS = \
@@ -69,6 +70,7 @@ SAMPLE_PROGS = \
gdbus-example-subtree \
gdbus-example-peer \
gdbus-example-proxy-subclass \
+ testapp \
$(NULL)
@@ -247,6 +249,12 @@ gdbus_example_export_LDADD = $(progs_ldadd)
application_SOURCES = application.c
application_LDADD = $(progs_ldadd)
+testapp_SOURCES = testapp.c
+testapp_LDADD = $(progs_ldadd)
+
+testapps_SOURCES = testapps.c
+testapps_LDADD = $(progs_ldadd)
+
EXTRA_DIST += \
socket-common.c \
org.gtk.test.gschema \
diff --git a/gio/tests/testapp.c b/gio/tests/testapp.c
new file mode 100644
index 0000000..67927a0
--- /dev/null
+++ b/gio/tests/testapp.c
@@ -0,0 +1,61 @@
+#include <stdlib.h>
+#include <gio.h>
+#include <gstdio.h>
+#include <string.h>
+
+static void
+on_app_action (GApplication *application,
+ const gchar *action_name,
+ guint action_timestamp)
+{
+ if (strcmp (action_name, "action1") == 0)
+ exit (1);
+}
+
+static gboolean
+invoke_action1 (gpointer data)
+{
+ GApplication *app = data;
+
+ g_application_invoke_action (app, "action1", 0);
+
+ return FALSE;
+}
+
+int
+main (int argc, char *argv[])
+{
+ GApplication *app;
+ GMainLoop *loop;
+
+ if (argc > 1 && strcmp (argv[1], "--non-unique") == 0)
+ {
+ g_type_init ();
+
+ app = g_object_new (G_TYPE_APPLICATION,
+ "appid", "org.gtk.test.app",
+ "default-quit", FALSE,
+ NULL);
+ }
+ else
+ {
+ app = g_application_new ("org.gtk.test.app");
+ }
+
+ if (g_application_is_remote (app))
+ {
+ g_timeout_add (1000, invoke_action1, app);
+ loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (loop);
+ }
+ else
+ {
+ g_application_add_action (app, "action1", "Action1");
+ g_application_add_action (app, "action2", "Action2");
+ g_signal_connect (app, "action",
+ G_CALLBACK (on_app_action), NULL);
+ g_application_run (app);
+ }
+
+ return 0;
+}
diff --git a/gio/tests/testapps.c b/gio/tests/testapps.c
new file mode 100644
index 0000000..a31b4f9
--- /dev/null
+++ b/gio/tests/testapps.c
@@ -0,0 +1,453 @@
+#include <gio/gio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+static gint appeared;
+static gint disappeared;
+static gboolean died;
+static gboolean timed_out;
+GPid pid;
+
+static void
+name_appeared (GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ gpointer user_data)
+{
+ GMainLoop *loop = user_data;
+
+ appeared++;
+
+ if (loop)
+ g_main_loop_quit (loop);
+}
+
+static void
+name_disappeared (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ GMainLoop *loop = user_data;
+
+ disappeared++;
+
+ if (loop)
+ g_main_loop_quit (loop);
+}
+
+static gboolean
+start_application (gpointer data)
+{
+ gchar *argv[] = { "./testapp", NULL };
+
+ g_assert (g_spawn_async (NULL, argv, NULL, 0, NULL, NULL, &pid, NULL));
+
+ return FALSE;
+}
+
+static gboolean
+run_application_sync (gpointer data)
+{
+ GMainLoop *loop = data;
+
+ g_assert (g_spawn_command_line_sync ("./testapp", NULL, NULL, NULL, NULL));
+
+ if (loop)
+ g_main_loop_quit (loop);
+
+ return FALSE;
+}
+
+static gboolean
+timeout (gpointer data)
+{
+ GMainLoop *loop = data;
+
+ timed_out = TRUE;
+
+ g_main_loop_quit (loop);
+
+ return TRUE;
+}
+
+/* This test starts an application, checks that its name appears
+ * on the bus, then starts it again and checks that the second
+ * instance exits right away.
+ */
+static void
+test_unique (void)
+{
+ GMainLoop *loop;
+ gint watch;
+ guint id1, id2, id3;
+
+ appeared = 0;
+ timed_out = FALSE;
+
+ loop = g_main_loop_new (NULL, FALSE);
+ id1 = g_timeout_add (5000, timeout, loop);
+
+ watch = g_bus_watch_name (G_BUS_TYPE_SESSION,
+ "org.gtk.test.app",
+ 0,
+ name_appeared,
+ NULL,
+ loop,
+ NULL);
+
+ id2 = g_timeout_add (0, start_application, loop);
+
+ g_main_loop_run (loop);
+
+ g_assert_cmpint (appeared, ==, 1);
+
+ id3 = g_timeout_add (0, run_application_sync, loop);
+
+ g_main_loop_run (loop);
+
+ g_assert_cmpint (appeared, ==, 1);
+ g_assert_cmpint (timed_out, ==, FALSE);
+
+ g_bus_unwatch_name (watch);
+
+ kill (pid, SIGTERM);
+
+ g_main_loop_unref (loop);
+ g_source_remove (id1);
+ g_source_remove (id2);
+ g_source_remove (id3);
+}
+
+static gboolean
+quit_app (gpointer data)
+{
+ GDBusConnection *connection;
+ GVariant *res;
+
+ connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+ res = g_dbus_connection_call_sync (connection,
+ "org.gtk.test.app",
+ "/org/freedesktop/Application",
+ "org.freedesktop.Application",
+ "Quit",
+ g_variant_new ("(u)", 0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL);
+ if (res)
+ g_variant_unref (res);
+ g_object_unref (connection);
+
+ return FALSE;
+}
+
+static void
+child_is_dead (GPid pid,
+ gint status,
+ gpointer data)
+{
+ GMainLoop *loop = data;
+
+ died++;
+
+ g_assert (WIFEXITED (status) && WEXITSTATUS(status) == 0);
+
+ if (loop)
+ g_main_loop_quit (loop);
+}
+
+/* This test start an application, checks that its name appears on
+ * the bus, then calls Quit, and verifies that the name disappears
+ * and the application exits.
+ */
+static void
+test_quit (void)
+{
+ GMainLoop *loop;
+ gint watch;
+ guint id1, id2, id3;
+ gchar *argv[] = { "./testapp", NULL };
+
+ appeared = 0;
+ disappeared = 0;
+ died = FALSE;
+ timed_out = FALSE;
+
+ loop = g_main_loop_new (NULL, FALSE);
+ watch = g_bus_watch_name (G_BUS_TYPE_SESSION,
+ "org.gtk.test.app",
+ 0,
+ name_appeared,
+ name_disappeared,
+ NULL,
+ NULL);
+
+ g_assert (g_spawn_async (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, NULL));
+
+ id1 = g_child_watch_add (pid, child_is_dead, loop);
+
+ id2 = g_timeout_add (500, quit_app, NULL);
+
+ id3 = g_timeout_add (5000, timeout, loop);
+
+ g_main_loop_run (loop);
+ g_assert_cmpint (timed_out, ==, FALSE);
+ g_assert_cmpint (appeared, ==, 1);
+ g_assert_cmpint (disappeared, >=, 1);
+ g_assert_cmpint (died, ==, TRUE);
+
+ g_bus_unwatch_name (watch);
+
+ g_main_loop_unref (loop);
+ g_source_remove (id1);
+ g_source_remove (id2);
+ g_source_remove (id3);
+}
+
+static gboolean
+_g_strv_has_string (const gchar* const * haystack,
+ const gchar *needle)
+{
+ guint n;
+
+ for (n = 0; haystack != NULL && haystack[n] != NULL; n++)
+ {
+ if (g_strcmp0 (haystack[n], needle) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gchar **
+list_actions (void)
+{
+ GDBusConnection *connection;
+ GVariant *res;
+ gchar **strv;
+ gchar *str;
+ GVariantIter *iter;
+ gint i;
+
+ connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+ res = g_dbus_connection_call_sync (connection,
+ "org.gtk.test.app",
+ "/org/freedesktop/Application",
+ "org.freedesktop.Application",
+ "ListActions",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL);
+
+ strv = g_new0 (gchar *, 32);
+ g_variant_get (res, "(as)", &iter);
+ i = 0;
+ while (g_variant_iter_loop (iter, "s", &str))
+ {
+ strv[i] = g_strdup (str);
+ i++;
+ g_assert (i < 32);
+ }
+ g_variant_iter_free (iter);
+
+ strv[i] = NULL;
+
+ g_variant_unref (res);
+ g_object_unref (connection);
+
+ return strv;
+}
+
+/* This test start an application, waits for its name to appear on
+ * the bus, then calls ListActions, and verifies that it gets the expected
+ * actions back.
+ */
+static void
+test_list_actions (void)
+{
+ GMainLoop *loop;
+ gchar *argv[] = { "./testapp", NULL };
+ gchar **actions;
+ gint watch;
+
+ appeared = 0;
+
+ loop = g_main_loop_new (NULL, FALSE);
+ watch = g_bus_watch_name (G_BUS_TYPE_SESSION,
+ "org.gtk.test.app",
+ 0,
+ name_appeared,
+ NULL,
+ loop,
+ NULL);
+
+ g_assert (g_spawn_async (NULL, argv, NULL, 0, NULL, NULL, &pid, NULL));
+ if (!appeared)
+ g_main_loop_run (loop);
+ g_main_loop_unref (loop);
+
+ actions = list_actions ();
+
+ g_assert (g_strv_length (actions) == 2);
+ g_assert (_g_strv_has_string (actions, "action1"));
+ g_assert (_g_strv_has_string (actions, "action2"));
+
+ g_strfreev (actions);
+
+ kill (pid, SIGTERM);
+
+ g_bus_unwatch_name (watch);
+}
+
+static gboolean
+invoke_action1 (gpointer data)
+{
+ GDBusConnection *connection;
+ GVariant *res;
+
+ connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+ res = g_dbus_connection_call_sync (connection,
+ "org.gtk.test.app",
+ "/org/freedesktop/Application",
+ "org.freedesktop.Application",
+ "InvokeAction",
+ g_variant_new ("(su)",
+ "action1",
+ 0),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL);
+ if (res)
+ g_variant_unref (res);
+ g_object_unref (connection);
+
+ return FALSE;
+}
+
+static void
+exit_with_code_1 (GPid pid,
+ gint status,
+ gpointer data)
+{
+ GMainLoop *loop = data;
+
+ died++;
+
+ g_assert (WIFEXITED (status) && WEXITSTATUS(status) == 1);
+
+ if (loop)
+ g_main_loop_quit (loop);
+}
+
+/* This test starts an application, waits for it to appear,
+ * then invokes 'action1' and checks that it causes the application
+ * to exit with an exit code of 1.
+ */
+static void
+test_invoke (void)
+{
+ GMainLoop *loop;
+ gint watch;
+ gchar *argv[] = { "./testapp", NULL };
+ guint id1, id2, id3;
+
+ appeared = 0;
+ disappeared = 0;
+ died = FALSE;
+ timed_out = FALSE;
+
+ loop = g_main_loop_new (NULL, FALSE);
+ watch = g_bus_watch_name (G_BUS_TYPE_SESSION,
+ "org.gtk.test.app",
+ 0,
+ name_appeared,
+ name_disappeared,
+ NULL,
+ NULL);
+
+ g_assert (g_spawn_async (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, NULL));
+
+ id1 = g_child_watch_add (pid, exit_with_code_1, loop);
+
+ id2 = g_timeout_add (500, invoke_action1, NULL);
+
+ id3 = g_timeout_add (5000, timeout, loop);
+
+ g_main_loop_run (loop);
+ g_assert_cmpint (timed_out, ==, FALSE);
+ g_assert_cmpint (appeared, >=, 1);
+ g_assert_cmpint (disappeared, >=, 1);
+ g_assert_cmpint (died, ==, TRUE);
+
+ g_bus_unwatch_name (watch);
+ g_main_loop_unref (loop);
+ g_source_remove (id1);
+ g_source_remove (id2);
+ g_source_remove (id3);
+
+ kill (pid, SIGTERM);
+}
+
+static void
+test_remote (void)
+{
+ GMainLoop *loop;
+ gint watch;
+ GPid pid1, pid2;
+ gchar *argv[] = { "./testapp", NULL, NULL };
+
+ appeared = 0;
+ timed_out = FALSE;
+
+ loop = g_main_loop_new (NULL, FALSE);
+ g_timeout_add (5000, timeout, loop);
+
+ watch = g_bus_watch_name (G_BUS_TYPE_SESSION,
+ "org.gtk.test.app",
+ 0,
+ name_appeared,
+ NULL,
+ loop,
+ NULL);
+
+ g_assert (g_spawn_async (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid1, NULL));
+ g_child_watch_add (pid1, exit_with_code_1, loop);
+
+ g_main_loop_run (loop);
+
+ g_assert_cmpint (appeared, ==, 1);
+
+ argv[1] = "--non-unique";
+ g_assert (g_spawn_async (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid2, NULL));
+
+ g_main_loop_run (loop);
+
+ g_assert_cmpint (appeared, ==, 1);
+ g_assert_cmpint (timed_out, ==, FALSE);
+
+ g_main_loop_unref (loop);
+ g_bus_unwatch_name (watch);
+
+ kill (pid1, SIGTERM);
+ kill (pid2, SIGTERM);
+}
+
+int
+main (int argc, char *argv[])
+{
+ g_type_init ();
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/application/unique", test_unique);
+ g_test_add_func ("/application/quit", test_quit);
+ g_test_add_func ("/application/list-actions", test_list_actions);
+ g_test_add_func ("/application/invoke", test_invoke);
+ g_test_add_func ("/application/remote", test_remote);
+
+ return g_test_run ();
+}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]