[gnome-builder] app: add IDE_APPLICATION_MODE_TESTS



commit ab7772f8489d3f49d0a0d8c9fddbead425dff8a2
Author: Christian Hergert <chergert redhat com>
Date:   Wed Jan 13 15:43:33 2016 -0800

    app: add IDE_APPLICATION_MODE_TESTS
    
    This is a new mode for IdeApplication that allows us to add test hooks.
    This simplifies the process of running async unit tests, which need the
    application process, including plugins loaded.
    
    The benefit here, is that our tests will closely mimic how things
    run during normal use.

 libide/Makefile.am                    |    2 +
 libide/ide-application-command-line.c |   22 +++++
 libide/ide-application-private.h      |    3 +
 libide/ide-application-tests.c        |  145 +++++++++++++++++++++++++++++++++
 libide/ide-application-tests.h        |   39 +++++++++
 libide/ide-application.c              |   14 +++-
 libide/ide-application.h              |    1 +
 7 files changed, 225 insertions(+), 1 deletions(-)
---
diff --git a/libide/Makefile.am b/libide/Makefile.am
index b78ed7b..46b8867 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -277,6 +277,8 @@ libide_1_0_la_SOURCES = \
        ide-application-actions.h \
        ide-application-plugins.c \
        ide-application-private.h \
+       ide-application-tests.c \
+       ide-application-tests.h \
        ide-async-helper.c \
        ide-async-helper.h \
        ide-back-forward-list-private.h \
diff --git a/libide/ide-application-command-line.c b/libide/ide-application-command-line.c
index 1da38d6..e5442cf 100644
--- a/libide/ide-application-command-line.c
+++ b/libide/ide-application-command-line.c
@@ -143,6 +143,7 @@ ide_application_local_command_line (GApplication   *application,
                                     gint           *exit_status)
 {
   IdeApplication *self = (IdeApplication *)application;
+  g_autofree gchar *path_copy = NULL;
   GOptionContext *context = NULL;
   GOptionGroup *group;
   const gchar *shortdesc = NULL;
@@ -206,6 +207,17 @@ ide_application_local_command_line (GApplication   *application,
   *exit_status = EXIT_SUCCESS;
 
   prgname = g_get_prgname ();
+
+  /*
+   * Sometimes we can get a path like "/foo/bar/lt-test-foo"
+   * and this let's us strip it to lt-test-foo.
+   */
+  if (g_path_is_absolute (prgname))
+    {
+      path_copy = g_path_get_basename (prgname);
+      prgname = path_copy;
+    }
+
   if (prgname && g_str_has_prefix (prgname, "lt-"))
     prgname += strlen ("lt-");
 
@@ -248,6 +260,16 @@ ide_application_local_command_line (GApplication   *application,
     {
       self->mode = IDE_APPLICATION_MODE_WORKER;
     }
+  else if (g_str_has_prefix (prgname, "test-"))
+    {
+      self->mode = IDE_APPLICATION_MODE_TESTS;
+
+      if (!g_test_initialized ())
+        {
+          g_error ("Attempt to start IdeApplication in test mode, "
+                   "but g_test_init() has not been called.");
+        }
+    }
 
   if (!g_option_context_parse_strv (context, arguments, &error))
     {
diff --git a/libide/ide-application-private.h b/libide/ide-application-private.h
index 52ad8bd..0d6003a 100644
--- a/libide/ide-application-private.h
+++ b/libide/ide-application-private.h
@@ -57,6 +57,8 @@ struct _IdeApplication
 
   EggMenuManager      *menu_manager;
   GHashTable          *merge_ids;
+
+  GList               *test_funcs;
 };
 
 void     ide_application_discover_plugins   (IdeApplication   *self) G_GNUC_INTERNAL;
@@ -66,6 +68,7 @@ void     ide_application_init_plugin_menus  (IdeApplication   *self) G_GNUC_INTE
 gboolean ide_application_local_command_line (GApplication     *application,
                                              gchar          ***arguments,
                                              gint             *exit_status) G_GNUC_INTERNAL;
+void     ide_application_run_tests          (IdeApplication   *self);
 
 G_END_DECLS
 
diff --git a/libide/ide-application-tests.c b/libide/ide-application-tests.c
new file mode 100644
index 0000000..f4d9452
--- /dev/null
+++ b/libide/ide-application-tests.c
@@ -0,0 +1,145 @@
+/* ide-application-tests.c
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define G_LOG_DOMAIN "ide-application-tests"
+
+#include <stdlib.h>
+
+#include "ide-application-private.h"
+#include "ide-application-tests.h"
+#include "ide-debug.h"
+
+typedef struct
+{
+  IdeApplication               *self;
+  gchar                        *name;
+  IdeApplicationTest            test_func;
+  IdeApplicationTestCompletion  test_completion;
+} AsyncTest;
+
+static void ide_application_run_next_test (IdeApplication *self);
+
+gboolean
+fatal_log_handler (const gchar    *log_domain,
+                   GLogLevelFlags  log_level,
+                   const gchar    *message,
+                   gpointer        user_data)
+{
+  if ((g_strcmp0 (log_domain, "Devhelp") == 0) ||
+      (g_strcmp0 (log_domain, "Gtk") == 0))
+    return FALSE;
+
+  return TRUE;
+}
+
+static void
+ide_application_run_tests_cb (GObject      *object,
+                              GAsyncResult *result,
+                              gpointer      user_data)
+{
+  AsyncTest *test = user_data;
+  GError *error = NULL;
+  gboolean ret;
+
+  ret = test->test_completion (result, &error);
+  g_assert_no_error (error);
+  g_assert (ret == TRUE);
+
+  if (test->self->test_funcs)
+    ide_application_run_next_test (test->self);
+  else
+    g_application_release (G_APPLICATION (test->self));
+
+  g_clear_pointer (&test->name, g_free);
+  g_clear_object (&test->self);
+  g_slice_free (AsyncTest, test);
+}
+
+static void
+ide_application_run_next_test (IdeApplication *self)
+{
+  g_autoptr(GCancellable) cancellable = NULL;
+  AsyncTest *test;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_APPLICATION (self));
+
+  cancellable = g_cancellable_new ();
+
+  test = self->test_funcs->data;
+  test->self = g_object_ref (self);
+  test->test_func (cancellable, ide_application_run_tests_cb, test);
+
+  self->test_funcs = g_list_delete_link (self->test_funcs, self->test_funcs);
+
+  IDE_EXIT;
+}
+
+void
+ide_application_run_tests (IdeApplication *self)
+{
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_APPLICATION (self));
+
+  if (self->test_funcs != NULL)
+    {
+      g_test_log_set_fatal_handler (fatal_log_handler, NULL);
+      g_application_hold (G_APPLICATION (self));
+      ide_application_run_next_test (self);
+    }
+
+  IDE_EXIT;
+}
+
+static gboolean
+ide_application_task_completion (GAsyncResult  *result,
+                                 GError       **error)
+{
+  g_assert (G_IS_TASK (result));
+
+  return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+void
+ide_application_add_test (IdeApplication               *self,
+                          const gchar                  *test_name,
+                          IdeApplicationTest            test_func,
+                          IdeApplicationTestCompletion  test_completion)
+{
+  AsyncTest *test;
+
+  IDE_ENTRY;
+
+  g_return_if_fail (IDE_IS_APPLICATION (self));
+  g_return_if_fail (test_name != NULL);
+  g_return_if_fail (test_func != NULL);
+
+  if (test_completion == NULL)
+    test_completion = ide_application_task_completion;
+
+  test = g_slice_new0 (AsyncTest);
+  test->name = g_strdup (test_name);
+  test->test_func = test_func;
+  test->test_completion = test_completion;
+
+  self->test_funcs = g_list_append (self->test_funcs, test);
+
+  IDE_EXIT;
+}
diff --git a/libide/ide-application-tests.h b/libide/ide-application-tests.h
new file mode 100644
index 0000000..b1f7f3a
--- /dev/null
+++ b/libide/ide-application-tests.h
@@ -0,0 +1,39 @@
+/* ide-application-tests.h
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef IDE_APPLICATION_TESTS_H
+#define IDE_APPLICATION_TESTS_H
+
+#include "ide-application.h"
+
+G_BEGIN_DECLS
+
+typedef void     (*IdeApplicationTest)           (GCancellable         *cancellable,
+                                                  GAsyncReadyCallback   callback,
+                                                  gpointer              user_data);
+typedef gboolean (*IdeApplicationTestCompletion) (GAsyncResult         *result,
+                                                  GError              **error);
+
+void ide_application_add_test (IdeApplication               *self,
+                               const gchar                  *test_name,
+                               IdeApplicationTest            test_func,
+                               IdeApplicationTestCompletion  test_completion);
+
+G_END_DECLS
+
+#endif /* IDE_APPLICATION_TESTS_H */
diff --git a/libide/ide-application.c b/libide/ide-application.c
index 51d4f18..3cd2f84 100644
--- a/libide/ide-application.c
+++ b/libide/ide-application.c
@@ -35,6 +35,7 @@
 #include "ide-application.h"
 #include "ide-application-actions.h"
 #include "ide-application-private.h"
+#include "ide-application-tests.h"
 #include "ide-application-tool.h"
 #include "ide-css-provider.h"
 #include "ide-debug.h"
@@ -278,6 +279,14 @@ ide_application_activate_tool (IdeApplication *self)
 }
 
 static void
+ide_application_activate_tests (IdeApplication *self)
+{
+  g_assert (IDE_IS_APPLICATION (self));
+
+  ide_application_run_tests (self);
+}
+
+static void
 ide_application_activate (GApplication *application)
 {
   IdeApplication *self = (IdeApplication *)application;
@@ -290,6 +299,8 @@ ide_application_activate (GApplication *application)
     ide_application_activate_worker (self);
   else if (self->mode == IDE_APPLICATION_MODE_TOOL)
     ide_application_activate_tool (self);
+  else if (self->mode == IDE_APPLICATION_MODE_TESTS)
+    ide_application_activate_tests (self);
 }
 
 static void
@@ -309,7 +320,7 @@ ide_application_startup (GApplication *application)
   small_thread_pool = (self->mode != IDE_APPLICATION_MODE_PRIMARY);
   _ide_thread_pool_init (small_thread_pool);
 
-  if (self->mode == IDE_APPLICATION_MODE_PRIMARY)
+  if ((self->mode == IDE_APPLICATION_MODE_PRIMARY) || (self->mode == IDE_APPLICATION_MODE_TESTS))
     {
       ide_application_make_skeleton_dirs (self);
       ide_application_register_theme_overrides (self);
@@ -344,6 +355,7 @@ ide_application_finalize (GObject *object)
 {
   IdeApplication *self = (IdeApplication *)object;
 
+  g_clear_pointer (&self->test_funcs, g_list_free);
   g_clear_pointer (&self->dbus_address, g_free);
   g_clear_pointer (&self->tool_arguments, g_strfreev);
   g_clear_pointer (&self->started_at, g_date_time_unref);
diff --git a/libide/ide-application.h b/libide/ide-application.h
index ebc1247..747ad8b 100644
--- a/libide/ide-application.h
+++ b/libide/ide-application.h
@@ -35,6 +35,7 @@ typedef enum
   IDE_APPLICATION_MODE_PRIMARY,
   IDE_APPLICATION_MODE_WORKER,
   IDE_APPLICATION_MODE_TOOL,
+  IDE_APPLICATION_MODE_TESTS,
 } IdeApplicationMode;
 
 IdeApplicationMode  ide_application_get_mode             (IdeApplication       *self);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]