diff options
Diffstat (limited to 'gio/tests')
-rw-r--r-- | gio/tests/Makefile.am | 20 | ||||
-rw-r--r-- | gio/tests/appinfo-test.c | 20 | ||||
-rw-r--r-- | gio/tests/appinfo-test.desktop | 4 | ||||
-rw-r--r-- | gio/tests/appinfo.c | 25 | ||||
-rw-r--r-- | gio/tests/application.c | 134 | ||||
-rw-r--r-- | gio/tests/testapp.c | 79 | ||||
-rw-r--r-- | gio/tests/testapps.c | 533 |
7 files changed, 815 insertions, 0 deletions
diff --git a/gio/tests/Makefile.am b/gio/tests/Makefile.am index caab30912..8fcdd9cb7 100644 --- a/gio/tests/Makefile.am +++ b/gio/tests/Makefile.am @@ -54,6 +54,9 @@ TEST_PROGS += \ gdbus-error \ gdbus-peer \ gdbus-exit-on-close \ + application \ + testapps \ + appinfo \ $(NULL) endif @@ -73,6 +76,8 @@ SAMPLE_PROGS = \ gdbus-example-subtree \ gdbus-example-peer \ gdbus-example-proxy-subclass \ + testapp \ + appinfo-test \ $(NULL) @@ -248,6 +253,21 @@ gdbus_example_proxy_subclass_LDADD = $(progs_ldadd) gdbus_example_export_SOURCES = gdbus-example-export.c gdbus_example_export_LDADD = $(progs_ldadd) +application_SOURCES = application.c +application_LDADD = $(progs_ldadd) + +appinfo_SOURCES = appinfo.c +appinfo_LDADD = $(progs_ldadd) + +appinfo_test_SOURCES = appinfo-test.c +appinfo_test_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/appinfo-test.c b/gio/tests/appinfo-test.c new file mode 100644 index 000000000..9d6a5ff3c --- /dev/null +++ b/gio/tests/appinfo-test.c @@ -0,0 +1,20 @@ +#include <stdlib.h> +#include <gio/gio.h> + +int +main (int argc, char *argv[]) +{ + const gchar *envvar; + gint pid_from_env; + + envvar = g_getenv ("GIO_LAUNCHED_DESKTOP_FILE_PID"); + g_assert (envvar != NULL); + pid_from_env = atoi (envvar); + g_assert_cmpint (pid_from_env, ==, getpid ()); + + envvar = g_getenv ("GIO_LAUNCHED_DESKTOP_FILE"); + g_assert_cmpstr (envvar, ==, SRCDIR "/appinfo-test.desktop"); + + return 0; +} + diff --git a/gio/tests/appinfo-test.desktop b/gio/tests/appinfo-test.desktop new file mode 100644 index 000000000..becc1c4a6 --- /dev/null +++ b/gio/tests/appinfo-test.desktop @@ -0,0 +1,4 @@ +[Desktop Entry] +Type=Application +Name=appinfo-test +Exec=./appinfo-test diff --git a/gio/tests/appinfo.c b/gio/tests/appinfo.c new file mode 100644 index 000000000..099068a1b --- /dev/null +++ b/gio/tests/appinfo.c @@ -0,0 +1,25 @@ +#include <gio/gio.h> +#include <gio/gdesktopappinfo.h> + +static void +test_launch (void) +{ + GAppInfo *appinfo; + + appinfo = (GAppInfo*)g_desktop_app_info_new_from_filename (SRCDIR "/appinfo-test.desktop"); + g_assert (appinfo != NULL); + + g_assert (g_app_info_launch (appinfo, NULL, NULL, NULL)); +} + +int +main (int argc, char *argv[]) +{ + g_type_init (); + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/appinfo/launch", test_launch); + + return g_test_run (); +} + diff --git a/gio/tests/application.c b/gio/tests/application.c new file mode 100644 index 000000000..5dba027d7 --- /dev/null +++ b/gio/tests/application.c @@ -0,0 +1,134 @@ +#include <stdlib.h> +#include <gio.h> +#include <gstdio.h> + +enum +{ + INVOKE_ACTION, + CHECK_ACTION, + DISABLE_ACTION, + INVOKE_DISABLED_ACTION, + CHECK_DISABLED_ACTION, + END +}; + +static guint timestamp = 0; +static gint state = -1; +static gboolean action_invoked = FALSE; + +static void +on_app_action (GApplication *application, + const gchar *action_name, + guint action_timestamp) +{ + if (g_test_verbose ()) + g_print ("Action '%s' invoked (timestamp: %u, expected: %u)\n", + action_name, + action_timestamp, + timestamp); + + g_assert_cmpstr (action_name, ==, "About"); + g_assert_cmpint (action_timestamp, ==, timestamp); + + action_invoked = TRUE; +} + +static gboolean +check_invoke_action (gpointer data) +{ + GApplication *application = data; + + if (state == INVOKE_ACTION) + { + timestamp = (guint) time (NULL); + + if (g_test_verbose ()) + g_print ("Invoking About...\n"); + + g_application_invoke_action (application, "About", timestamp); + state = CHECK_ACTION; + return TRUE; + } + + if (state == CHECK_ACTION) + { + if (g_test_verbose ()) + g_print ("Verifying About invocation...\n"); + + g_assert (action_invoked); + state = DISABLE_ACTION; + return TRUE; + } + + if (state == DISABLE_ACTION) + { + if (g_test_verbose ()) + g_print ("Disabling About...\n"); + + g_application_set_action_enabled (application, "About", FALSE); + action_invoked = FALSE; + state = INVOKE_DISABLED_ACTION; + return TRUE; + } + + if (state == INVOKE_DISABLED_ACTION) + { + if (g_test_verbose ()) + g_print ("Invoking disabled About action...\n"); + + g_application_invoke_action (application, "About", (guint) time (NULL)); + state = CHECK_DISABLED_ACTION; + return TRUE; + } + + if (state == CHECK_DISABLED_ACTION) + { + if (g_test_verbose ()) + g_print ("Verifying lack of About invocation...\n"); + + g_assert (!action_invoked); + state = END; + return TRUE; + } + + if (state == END) + { + if (g_test_verbose ()) + g_print ("Test complete\n"); + + g_application_quit (application, (guint) time (NULL)); + return FALSE; + } + + g_assert_not_reached (); +} + +static void +test_basic (void) +{ + GApplication *app; + + app = g_application_new_and_register ("org.gtk.TestApplication", 0, NULL); + g_application_add_action (app, "About", "Print an about message"); + + g_signal_connect (app, "action::About", G_CALLBACK (on_app_action), NULL); + + state = INVOKE_ACTION; + g_timeout_add (100, check_invoke_action, app); + + g_application_run (app); + + g_assert (state == END); + g_object_unref (app); +} + +int +main (int argc, char *argv[]) +{ + g_type_init (); + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/application/basic", test_basic); + + return g_test_run (); +} diff --git a/gio/tests/testapp.c b/gio/tests/testapp.c new file mode 100644 index 000000000..8ed309185 --- /dev/null +++ b/gio/tests/testapp.c @@ -0,0 +1,79 @@ +#include <stdlib.h> +#include <gio.h> +#include <gstdio.h> +#include <string.h> + +static gboolean action3_added = FALSE; + +static void +on_app_action (GApplication *application, + const gchar *action_name, + guint action_timestamp) +{ + if (strcmp (action_name, "action1") == 0) + exit (1); + else if (strcmp (action_name, "action2") == 0) + { + if (action3_added) + g_application_remove_action (application, "action3"); + else + g_application_add_action (application, "action3", "An extra action"); + action3_added = !action3_added; + } +} + +static gboolean +invoke_action1 (gpointer data) +{ + GApplication *app = data; + + g_application_invoke_action (app, "action1", 0); + + return FALSE; +} + +static void +on_app_activated (GApplication *application, + GVariant *args, + GVariant *platform_data) +{ + char *str; + + g_print ("got args: "); + str = g_variant_print (args, TRUE); + g_print ("%s ", str); + g_free (str); + str = g_variant_print (platform_data, TRUE); + g_print ("%s\n", str); + g_free (str); +} + +int +main (int argc, char *argv[]) +{ + GApplication *app; + GMainLoop *loop; + + app = g_application_new ("org.gtk.test.app"); + if (!(argc > 1 && strcmp (argv[1], "--non-unique") == 0)) + g_application_register_with_data (app, argc, argv, NULL); + + 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_signal_connect (app, "prepare-activation", + G_CALLBACK (on_app_activated), NULL); + g_application_run (app); + } + + return 0; +} diff --git a/gio/tests/testapps.c b/gio/tests/testapps.c new file mode 100644 index 000000000..51db0b879 --- /dev/null +++ b/gio/tests/testapps.c @@ -0,0 +1,533 @@ +#include <gio/gio.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> + +static gint appeared; +static gint disappeared; +static gint changed; +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/gtk/test/app", + "org.gtk.Application", + "Quit", + g_variant_new ("(u)", 0), + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + NULL); + if (res) + g_variant_unref (res); + + 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/gtk/test/app", + "org.gtk.Application", + "ListActions", + NULL, + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + NULL); + + strv = g_new0 (gchar *, 32); + g_variant_get (res, "(a{s(sb)})", &iter); + i = 0; + while (g_variant_iter_loop (iter, "{s(sb)}", &str, NULL, NULL)) + { + 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 ((const char *const *)actions, "action1")); + g_assert (_g_strv_has_string ((const char *const *)actions, "action2")); + + g_strfreev (actions); + + kill (pid, SIGTERM); + + g_bus_unwatch_name (watch); +} + +static gboolean +invoke_action (gpointer data) +{ + const gchar *action = 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/gtk/test/app", + "org.gtk.Application", + "InvokeAction", + g_variant_new ("(su)", + action, + 0), + NULL, + 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_action, "action1"); + + 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); +} + +static void +actions_changed (GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + GMainLoop *loop = user_data; + + g_assert_cmpstr (interface_name, ==, "org.gtk.Application"); + g_assert_cmpstr (signal_name, ==, "ActionsChanged"); + + changed++; + + g_main_loop_quit (loop); +} + +static void +test_change_action (void) +{ + GMainLoop *loop; + gint watch; + guint id; + GPid pid1; + gchar *argv[] = { "./testapp", NULL, NULL }; + GDBusConnection *connection; + + appeared = 0; + changed = 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_main_loop_run (loop); + + g_assert_cmpint (appeared, ==, 1); + + connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); + id = g_dbus_connection_signal_subscribe (connection, + NULL, + "org.gtk.Application", + "ActionsChanged", + "/org/gtk/test/app", + NULL, + actions_changed, + loop, + NULL); + + g_timeout_add (1000, invoke_action, "action2"); + + g_main_loop_run (loop); + + g_assert_cmpint (changed, >, 0); + g_assert_cmpint (timed_out, ==, FALSE); + + g_dbus_connection_signal_unsubscribe (connection, id); + g_object_unref (connection); + g_main_loop_unref (loop); + g_bus_unwatch_name (watch); + + kill (pid1, 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); + g_test_add_func ("/application/change-action", test_change_action); + + return g_test_run (); +} + |