[gnome-builder/wip/chergert/unittests] testing: start on unit testing
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/chergert/unittests] testing: start on unit testing
- Date: Thu, 19 Oct 2017 02:30:42 +0000 (UTC)
commit 229bf9e169b8efd4af412294f4289c441415d215
Author: Christian Hergert <chergert redhat com>
Date: Fri Oct 13 17:40:19 2017 -0700
testing: start on unit testing
src/libide/ide-context.c | 50 +++-
src/libide/ide-context.h | 1 +
src/libide/ide-types.h | 4 +
src/libide/ide.h | 2 +
src/libide/meson.build | 1 +
src/libide/testing/ide-test-manager.c | 565 ++++++++++++++++++++++++++++++++
src/libide/testing/ide-test-manager.h | 45 +++
src/libide/testing/ide-test-provider.c | 147 +++++++++
src/libide/testing/ide-test-provider.h | 51 +++
src/libide/testing/ide-test.c | 313 ++++++++++++++++++
src/libide/testing/ide-test.h | 55 +++
src/libide/testing/meson.build | 16 +
12 files changed, 1249 insertions(+), 1 deletions(-)
---
diff --git a/src/libide/ide-context.c b/src/libide/ide-context.c
index 9e5a826..6ad0ced 100644
--- a/src/libide/ide-context.c
+++ b/src/libide/ide-context.c
@@ -39,6 +39,7 @@
#include "debugger/ide-debug-manager.h"
#include "devices/ide-device-manager.h"
#include "doap/ide-doap.h"
+#include "documentation/ide-documentation.h"
#include "plugins/ide-extension-util.h"
#include "projects/ide-project-files.h"
#include "projects/ide-project-item.h"
@@ -49,7 +50,7 @@
#include "search/ide-search-engine.h"
#include "search/ide-search-provider.h"
#include "snippets/ide-source-snippets-manager.h"
-#include "documentation/ide-documentation.h"
+#include "testing/ide-test-manager.h"
#include "transfers/ide-transfer-manager.h"
#include "util/ide-async-helper.h"
#include "util/ide-settings.h"
@@ -78,6 +79,7 @@ struct _IdeContext
IdeRuntimeManager *runtime_manager;
IdeSearchEngine *search_engine;
IdeSourceSnippetsManager *snippets_manager;
+ IdeTestManager *test_manager;
IdeProject *project;
GFile *project_file;
gchar *root_build_dir;
@@ -534,6 +536,7 @@ ide_context_finalize (GObject *object)
g_clear_object (&self->project_file);
g_clear_object (&self->recent_manager);
g_clear_object (&self->runtime_manager);
+ g_clear_object (&self->test_manager);
g_clear_object (&self->unsaved_files);
g_clear_object (&self->vcs);
@@ -817,6 +820,10 @@ ide_context_init (IdeContext *self)
"context", self,
NULL);
+ self->test_manager = g_object_new (IDE_TYPE_TEST_MANAGER,
+ "context", self,
+ NULL);
+
self->unsaved_files = g_object_new (IDE_TYPE_UNSAVED_FILES,
"context", self,
NULL);
@@ -1118,6 +1125,28 @@ ide_context_init_snippets (gpointer source_object,
}
static void
+ide_context_init_tests (gpointer source_object,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ IdeContext *self = source_object;
+ g_autoptr(GTask) task = NULL;
+ g_autoptr(GError) error = NULL;
+
+ g_return_if_fail (IDE_IS_CONTEXT (self));
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_priority (task, G_PRIORITY_LOW);
+ g_task_set_source_tag (task, ide_context_init_tests);
+
+ if (!g_initable_init (G_INITABLE (self->test_manager), cancellable, &error))
+ g_task_return_error (task, g_steal_pointer (&error));
+ else
+ g_task_return_boolean (task, TRUE);
+}
+
+static void
ide_context_service_added (PeasExtensionSet *set,
PeasPluginInfo *info,
PeasExtension *exten,
@@ -1648,6 +1677,7 @@ ide_context_init_async (GAsyncInitable *initable,
ide_context_init_build_manager,
ide_context_init_run_manager,
ide_context_init_diagnostics_manager,
+ ide_context_init_tests,
ide_context_init_loaded,
NULL);
}
@@ -2320,6 +2350,24 @@ ide_context_get_debug_manager (IdeContext *self)
}
/**
+ * ide_context_get_test_manager:
+ * @self: An #IdeTestManager
+ *
+ * Gets the test manager for the #IdeContext.
+ *
+ * Returns: (transfer none): An #IdeTestManager
+ *
+ * Since: 3.28
+ */
+IdeTestManager *
+ide_context_get_test_manager (IdeContext *self)
+{
+ g_return_val_if_fail (IDE_IS_CONTEXT (self), NULL);
+
+ return self->test_manager;
+}
+
+/**
* ide_context_add_pausable:
* @self: an #IdeContext
* @pausable: an #IdePausable
diff --git a/src/libide/ide-context.h b/src/libide/ide-context.h
index e2a3351..5b5161e 100644
--- a/src/libide/ide-context.h
+++ b/src/libide/ide-context.h
@@ -47,6 +47,7 @@ IdeSettings *ide_context_get_settings (IdeContext
const gchar *schema_id,
const gchar *relative_path);
IdeSourceSnippetsManager *ide_context_get_snippets_manager (IdeContext *self);
+IdeTestManager *ide_context_get_test_manager (IdeContext *self);
IdeUnsavedFiles *ide_context_get_unsaved_files (IdeContext *self);
IdeVcs *ide_context_get_vcs (IdeContext *self);
const gchar *ide_context_get_root_build_dir (IdeContext *self);
diff --git a/src/libide/ide-types.h b/src/libide/ide-types.h
index 49a43de..72a05b6 100644
--- a/src/libide/ide-types.h
+++ b/src/libide/ide-types.h
@@ -129,6 +129,10 @@ typedef struct _IdeSubprocessLauncher IdeSubprocessLauncher;
typedef struct _IdeSymbol IdeSymbol;
typedef struct _IdeSymbolResolver IdeSymbolResolver;
+typedef struct _IdeTest IdeTest;
+typedef struct _IdeTestManager IdeTestManager;
+typedef struct _IdeTestProvider IdeTestProvider;
+
typedef struct _IdeTransferManager IdeTransferManager;
typedef struct _IdeTransfer IdeTransfer;
diff --git a/src/libide/ide.h b/src/libide/ide.h
index a12d853..61e2023 100644
--- a/src/libide/ide.h
+++ b/src/libide/ide.h
@@ -165,6 +165,8 @@ G_BEGIN_DECLS
#include "symbols/ide-tags-builder.h"
#include "template/ide-project-template.h"
#include "template/ide-template-provider.h"
+#include "testing/ide-test.h"
+#include "testing/ide-test-provider.h"
#include "threading/ide-thread-pool.h"
#include "transfers/ide-pkcon-transfer.h"
#include "transfers/ide-transfer.h"
diff --git a/src/libide/meson.build b/src/libide/meson.build
index 5e1473f..67fc7af 100644
--- a/src/libide/meson.build
+++ b/src/libide/meson.build
@@ -87,6 +87,7 @@ subdir('sourceview')
subdir('subprocess')
subdir('symbols')
subdir('template')
+subdir('testing')
subdir('threading')
subdir('transfers')
subdir('util')
diff --git a/src/libide/testing/ide-test-manager.c b/src/libide/testing/ide-test-manager.c
new file mode 100644
index 0000000..8c0ec09
--- /dev/null
+++ b/src/libide/testing/ide-test-manager.c
@@ -0,0 +1,565 @@
+/* ide-test-manager.c
+ *
+ * Copyright © 2017 Christian Hergert <chergert redhat com>
+ *
+ * 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-test-manager"
+
+#include <dazzle.h>
+#include <libpeas/peas.h>
+
+#include "ide-debug.h"
+
+#include "testing/ide-test-manager.h"
+#include "testing/ide-test-provider.h"
+
+/**
+ * SECTION:ide-test-manager
+ * @title: IdeTestManager
+ * @short_description: Unit test discover and execution manager
+ *
+ * The #IdeTestManager is responsible for loading unit test provider
+ * plugins (via the #IdeTestProvider interface) and running those unit
+ * tests on behalf of the user.
+ *
+ * You can access the test manager using ide_context_get_text_manager()
+ * using the #IdeContext for the loaded project.
+ *
+ * Since: 3.28
+ */
+
+struct _IdeTestManager
+{
+ IdeObject parent_instance;
+ PeasExtensionSet *providers;
+ GPtrArray *tests_by_provider;
+ GtkTreeStore *tests_store;
+ guint busy : 1;
+};
+
+typedef struct
+{
+ IdeTestProvider *provider;
+ GPtrArray *tests;
+} TestsByProvider;
+
+enum {
+ PROP_0,
+ PROP_BUSY,
+ N_PROPS
+};
+
+enum {
+ COLUMN_GROUP,
+ COLUMN_TEST,
+};
+
+static void initable_iface_init (GInitableIface *iface);
+static void ide_test_manager_actions_run_all (IdeTestManager *self,
+ GVariant *param);
+
+DZL_DEFINE_ACTION_GROUP (IdeTestManager, ide_test_manager, {
+ { "run-all", ide_test_manager_actions_run_all },
+})
+
+G_DEFINE_TYPE_WITH_CODE (IdeTestManager, ide_test_manager, IDE_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
+ G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP,
+ ide_test_manager_init_action_group))
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+tests_by_provider_free (gpointer data)
+{
+ TestsByProvider *info = data;
+
+ g_clear_pointer (&info->tests, g_ptr_array_unref);
+ g_clear_object (&info->provider);
+ g_slice_free (TestsByProvider, info);
+}
+
+static void
+ide_test_manager_dispose (GObject *object)
+{
+ IdeTestManager *self = (IdeTestManager *)object;
+
+ g_clear_object (&self->providers);
+ g_clear_object (&self->tests_store);
+ g_clear_pointer (&self->tests_by_provider, g_ptr_array_unref);
+
+ G_OBJECT_CLASS (ide_test_manager_parent_class)->dispose (object);
+}
+
+static void
+ide_test_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ IdeTestManager *self = IDE_TEST_MANAGER (object);
+
+ switch (prop_id)
+ {
+ case PROP_BUSY:
+ g_value_set_boolean (value, self->busy);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_test_manager_class_init (IdeTestManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = ide_test_manager_dispose;
+ object_class->get_property = ide_test_manager_get_property;
+
+ /**
+ * IdeTestManager:busy:
+ *
+ * The "busy" property indicates if the #IdeTestManager is currently
+ * processing various background unit tests.
+ *
+ * Since: 3.28
+ */
+ properties [PROP_BUSY] =
+ g_param_spec_boolean ("busy",
+ "Busy",
+ "If the test manager is busy processing",
+ FALSE,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+ide_test_manager_init (IdeTestManager *self)
+{
+ self->tests_by_provider = g_ptr_array_new_with_free_func (tests_by_provider_free);
+ self->tests_store = gtk_tree_store_new (2, G_TYPE_STRING, IDE_TYPE_TEST);
+}
+
+static void
+ide_test_manager_locate_group (IdeTestManager *self,
+ GtkTreeIter *iter,
+ const gchar *group)
+{
+ g_assert (IDE_IS_TEST_MANAGER (self));
+ g_assert (iter != NULL);
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->tests_store), iter))
+ {
+ do
+ {
+ g_autofree gchar *row_group = NULL;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (self->tests_store), iter,
+ COLUMN_GROUP, &row_group,
+ -1);
+
+ if (ide_str_equal0 (row_group, group))
+ return;
+ }
+ while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->tests_store), iter));
+ }
+
+ /* TODO: Sort groups by name? */
+
+ gtk_tree_store_append (self->tests_store, iter, NULL);
+ gtk_tree_store_set (self->tests_store, iter,
+ COLUMN_GROUP, group,
+ -1);
+}
+
+static void
+ide_test_manager_add_test (IdeTestManager *self,
+ const TestsByProvider *info,
+ guint position,
+ IdeTest *test)
+{
+ const gchar *group;
+ GtkTreeIter iter;
+ GtkTreeIter parent;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_TEST_MANAGER (self));
+ g_assert (info != NULL);
+ g_assert (IDE_IS_TEST (test));
+
+ g_ptr_array_insert (info->tests, position, g_object_ref (test));
+
+ group = ide_test_get_group (test);
+
+ ide_test_manager_locate_group (self, &parent, group);
+ gtk_tree_store_append (self->tests_store, &iter, &parent);
+ gtk_tree_store_set (self->tests_store, &iter,
+ COLUMN_GROUP, NULL,
+ COLUMN_TEST, test,
+ -1);
+
+ IDE_EXIT;
+}
+
+static void
+ide_test_manager_remove_test (IdeTestManager *self,
+ const TestsByProvider *info,
+ IdeTest *test)
+{
+ const gchar *group;
+ GtkTreeIter iter;
+ GtkTreeIter parent;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_TEST_MANAGER (self));
+ g_assert (info != NULL);
+ g_assert (IDE_IS_TEST (test));
+
+ ide_test_manager_locate_group (self, &parent, group);
+
+ if (gtk_tree_model_iter_children (GTK_TREE_MODEL (self->tests_store), &iter, &parent))
+ {
+ do
+ {
+ g_autoptr(IdeTest) row = NULL;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (self->tests_store), &iter,
+ COLUMN_TEST, &row,
+ -1);
+
+ if (row == test)
+ {
+ gtk_tree_store_remove (self->tests_store, &iter);
+ break;
+ }
+ }
+ while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->tests_store), &iter));
+ }
+
+ g_ptr_array_remove (info->tests, test);
+
+ IDE_EXIT;
+}
+
+static void
+ide_test_manager_provider_items_changed (IdeTestManager *self,
+ guint position,
+ guint removed,
+ guint added,
+ IdeTestProvider *provider)
+{
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_TEST_MANAGER (self));
+ g_assert (IDE_IS_TEST_PROVIDER (provider));
+
+ for (guint i = 0; i < self->tests_by_provider->len; i++)
+ {
+ const TestsByProvider *info = g_ptr_array_index (self->tests_by_provider, i);
+
+ if (info->provider == provider)
+ {
+ /* Remove tests from cache that were deleted */
+ for (guint j = 0; j < removed; j++)
+ {
+ IdeTest *test = g_ptr_array_index (info->tests, position);
+ ide_test_manager_remove_test (self, info, test);
+ }
+
+ /* Add tests to cache that were added */
+ for (guint j = 0; j < added; j++)
+ {
+ g_autoptr(IdeTest) test = NULL;
+
+ test = g_list_model_get_item (G_LIST_MODEL (provider), position + j);
+ ide_test_manager_add_test (self, info, position + j, test);
+ }
+ }
+ }
+
+ IDE_EXIT;
+}
+
+static void
+ide_test_manager_provider_added (PeasExtensionSet *set,
+ PeasPluginInfo *plugin_info,
+ PeasExtension *exten,
+ gpointer user_data)
+{
+ IdeTestManager *self = user_data;
+ IdeTestProvider *provider = (IdeTestProvider *)exten;
+ TestsByProvider *tests;
+ guint len;
+
+ IDE_ENTRY;
+
+ g_assert (PEAS_IS_EXTENSION_SET (set));
+ g_assert (plugin_info != NULL);
+ g_assert (IDE_IS_TEST_PROVIDER (provider));
+ g_assert (G_IS_LIST_MODEL (provider));
+ g_assert (IDE_IS_TEST_MANAGER (self));
+
+ tests = g_slice_new0 (TestsByProvider);
+ tests->provider = g_object_ref (provider);
+ tests->tests = g_ptr_array_new_with_free_func (g_object_unref);
+ g_ptr_array_add (self->tests_by_provider, tests);
+
+ g_signal_connect_swapped (provider,
+ "items-changed",
+ G_CALLBACK (ide_test_manager_provider_items_changed),
+ self);
+
+ len = g_list_model_get_n_items (G_LIST_MODEL (provider));
+ ide_test_manager_provider_items_changed (self, 0, 0, len, provider);
+
+ IDE_EXIT;
+}
+
+static void
+ide_test_manager_provider_removed (PeasExtensionSet *set,
+ PeasPluginInfo *plugin_info,
+ PeasExtension *exten,
+ gpointer user_data)
+{
+ IdeTestManager *self = user_data;
+ IdeTestProvider *provider = (IdeTestProvider *)exten;
+
+ IDE_ENTRY;
+
+ g_assert (PEAS_IS_EXTENSION_SET (set));
+ g_assert (plugin_info != NULL);
+ g_assert (IDE_IS_TEST_PROVIDER (provider));
+ g_assert (IDE_IS_TEST_MANAGER (self));
+
+ for (guint i = 0; i < self->tests_by_provider->len; i++)
+ {
+ const TestsByProvider *info = g_ptr_array_index (self->tests_by_provider, i);
+
+ if (info->provider == provider)
+ {
+ g_ptr_array_remove_index (self->tests_by_provider, i);
+ break;
+ }
+ }
+
+ g_signal_handlers_disconnect_by_func (provider,
+ G_CALLBACK (ide_test_manager_provider_items_changed),
+ self);
+
+ IDE_EXIT;
+}
+
+static gboolean
+ide_test_manager_initiable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ IdeTestManager *self = (IdeTestManager *)initable;
+ IdeContext *context;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_TEST_MANAGER (self));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+
+ self->providers = peas_extension_set_new (peas_engine_get_default (),
+ IDE_TYPE_TEST_PROVIDER,
+ "context", context,
+ NULL);
+
+ g_signal_connect (self->providers,
+ "extension-added",
+ G_CALLBACK (ide_test_manager_provider_added),
+ self);
+
+ g_signal_connect (self->providers,
+ "extension-removed",
+ G_CALLBACK (ide_test_manager_provider_removed),
+ self);
+
+ peas_extension_set_foreach (self->providers,
+ ide_test_manager_provider_added,
+ self);
+
+ IDE_RETURN (TRUE);
+}
+
+static void
+initable_iface_init (GInitableIface *iface)
+{
+ iface->init = ide_test_manager_initiable_init;
+}
+
+/**
+ * ide_test_manager_run_all_async:
+ * @self: An #IdeTestManager
+ * @cancellable: (nullable): A #GCancellable or %NULL
+ * @callback: a callback to execute upon completion
+ * @user_data: user data for @callback
+ *
+ * Executes all tests in an undefined order.
+ *
+ * Upon completion, @callback will be executed which must call
+ * ide_test_manager_run_all_finish() to get the result.
+ *
+ * Note that the individual test result information will be attached
+ * to the specific #IdeTest instances.
+ *
+ * Since: 3.28
+ */
+void
+ide_test_manager_run_all_async (IdeTestManager *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ IDE_ENTRY;
+
+ g_return_if_fail (IDE_IS_TEST_MANAGER (self));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_priority (task, G_PRIORITY_LOW);
+ g_task_set_source_tag (task, ide_test_manager_run_all_async);
+
+ g_task_return_boolean (task, TRUE);
+
+ IDE_EXIT;
+}
+
+/**
+ * ide_test_manager_run_all_finish:
+ * @self: An #IdeTestManager
+ * @result: A #GAsyncResult
+ * @error: a location for a #GError, or %NULL
+ *
+ * Completes an asynchronous request to execute all unit tests.
+ *
+ * A return value of %TRUE does not indicate that all tests succeeded,
+ * only that all tests were executed. Individual test failures will be
+ * attached to the #IdeTest instances.
+ *
+ * Returns: %TRUE if successful; otherwise %FALSE and @error is set.
+ *
+ * Since: 3.28
+ */
+gboolean
+ide_test_manager_run_all_finish (IdeTestManager *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ gboolean ret;
+
+ IDE_ENTRY;
+
+ g_return_val_if_fail (IDE_IS_TEST_MANAGER (self), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+
+ ret = g_task_propagate_boolean (G_TASK (result), error);
+
+ IDE_RETURN (ret);
+}
+
+/**
+ * ide_test_manager_run_async:
+ * @self: An #IdeTestManager
+ * @test: An #IdeTest
+ * @cancellable: (nullable): A #GCancellable, or %NULL
+ * @callback: a callback to execute upon completion
+ * @user_data: user data for @callback
+ *
+ * Executes a single unit test, asynchronously.
+ *
+ * The caller can access the result of the operation from @callback
+ * by calling ide_test_manager_run_finish() with the provided result.
+ *
+ * Since: 3.28
+ */
+void
+ide_test_manager_run_async (IdeTestManager *self,
+ IdeTest *test,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ IDE_ENTRY;
+
+ g_return_if_fail (IDE_IS_TEST_MANAGER (self));
+ g_return_if_fail (IDE_IS_TEST (test));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_priority (task, G_PRIORITY_LOW);
+ g_task_set_source_tag (task, ide_test_manager_run_async);
+
+ g_task_return_boolean (task, TRUE);
+
+ IDE_EXIT;
+}
+
+/**
+ * ide_test_manager_run_finish:
+ * @self: An #IdeTestManager
+ * @result: The #GAsyncResult provided to callback
+ * @error: A location for a #GError, or %NULL
+ *
+ * Completes a request to ide_test_manager_run_finish().
+ *
+ * When this function returns %TRUE, it does not indicate that the test
+ * succeeded; only that the test was executed. Thest #IdeTest instance
+ * itself will contain information about the success of the test.
+ *
+ * Returns: %TRUE if the test was executed; otherwise %FALSE
+ * and @error is set.
+ *
+ * Since: 3.28
+ */
+gboolean
+ide_test_manager_run_finish (IdeTestManager *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ gboolean ret;
+
+ IDE_ENTRY;
+
+ g_return_val_if_fail (IDE_IS_TEST_MANAGER (self), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+
+ ret = g_task_propagate_boolean (G_TASK (result), error);
+
+ IDE_RETURN (ret);
+}
+
+static void
+ide_test_manager_actions_run_all (IdeTestManager *self,
+ GVariant *param)
+{
+ g_assert (IDE_IS_TEST_MANAGER (self));
+
+ ide_test_manager_run_all_async (self, NULL, NULL, NULL);
+}
diff --git a/src/libide/testing/ide-test-manager.h b/src/libide/testing/ide-test-manager.h
new file mode 100644
index 0000000..18f6ccd
--- /dev/null
+++ b/src/libide/testing/ide-test-manager.h
@@ -0,0 +1,45 @@
+/* ide-test-manager.h
+ *
+ * Copyright © 2017 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include "ide-object.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_TEST_MANAGER (ide_test_manager_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeTestManager, ide_test_manager, IDE, TEST_MANAGER, IdeObject)
+
+void ide_test_manager_run_async (IdeTestManager *self,
+ IdeTest *test,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean ide_test_manager_run_finish (IdeTestManager *self,
+ GAsyncResult *result,
+ GError **error);
+void ide_test_manager_run_all_async (IdeTestManager *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean ide_test_manager_run_all_finish (IdeTestManager *self,
+ GAsyncResult *result,
+ GError **error);
+
+G_END_DECLS
diff --git a/src/libide/testing/ide-test-provider.c b/src/libide/testing/ide-test-provider.c
new file mode 100644
index 0000000..b77bb09
--- /dev/null
+++ b/src/libide/testing/ide-test-provider.c
@@ -0,0 +1,147 @@
+/* ide-test-provider.c
+ *
+ * Copyright © 2017 Christian Hergert <chergert redhat com>
+ *
+ * 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-test-provider"
+
+#include "testing/ide-test-provider.h"
+
+typedef struct
+{
+ GPtrArray *items;
+} IdeTestProviderPrivate;
+
+static void list_model_iface_init (GListModelInterface *iface);
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (IdeTestProvider, ide_test_provider, IDE_TYPE_OBJECT,
+ G_ADD_PRIVATE (IdeTestProvider)
+ G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init))
+
+static void
+ide_test_provider_dispose (GObject *object)
+{
+ IdeTestProvider *self = (IdeTestProvider *)object;
+ IdeTestProviderPrivate *priv = ide_test_provider_get_instance_private (self);
+
+ if (priv->items != NULL && priv->items->len > 0)
+ {
+ guint len = priv->items->len;
+
+ g_ptr_array_remove_range (priv->items, 0, len);
+ g_list_model_items_changed (G_LIST_MODEL (self), 0, len, 0);
+ g_clear_pointer (&priv->items, g_ptr_array_unref);
+ }
+
+ G_OBJECT_CLASS (ide_test_provider_parent_class)->finalize (object);
+}
+
+static void
+ide_test_provider_class_init (IdeTestProviderClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = ide_test_provider_dispose;
+}
+
+static void
+ide_test_provider_init (IdeTestProvider *self)
+{
+}
+
+static GType
+ide_test_provider_get_item_type (GListModel *model)
+{
+ return IDE_TYPE_TEST;
+}
+
+static guint
+ide_test_provider_get_n_items (GListModel *model)
+{
+ IdeTestProvider *self = (IdeTestProvider *)model;
+ IdeTestProviderPrivate *priv = ide_test_provider_get_instance_private (self);
+
+ g_assert (IDE_IS_TEST_PROVIDER (self));
+
+ return priv->items ? priv->items->len : 0;
+}
+
+static gpointer
+ide_test_provider_get_item (GListModel *model,
+ guint position)
+{
+ IdeTestProvider *self = (IdeTestProvider *)model;
+ IdeTestProviderPrivate *priv = ide_test_provider_get_instance_private (self);
+
+ g_assert (IDE_IS_TEST_PROVIDER (self));
+
+ if (priv->items != NULL)
+ {
+ if (position < priv->items->len)
+ return g_object_ref (g_ptr_array_index (priv->items, position));
+ }
+
+ return NULL;
+}
+
+static void
+list_model_iface_init (GListModelInterface *iface)
+{
+ iface->get_item = ide_test_provider_get_item;
+ iface->get_n_items = ide_test_provider_get_n_items;
+ iface->get_item_type = ide_test_provider_get_item_type;
+}
+
+void
+ide_test_provider_add (IdeTestProvider *self,
+ IdeTest *test)
+{
+ IdeTestProviderPrivate *priv = ide_test_provider_get_instance_private (self);
+
+ g_return_if_fail (IDE_IS_TEST_PROVIDER (self));
+ g_return_if_fail (IDE_IS_TEST (test));
+
+ if (priv->items != NULL)
+ {
+ g_ptr_array_add (priv->items, g_object_ref (test));
+ g_list_model_items_changed (G_LIST_MODEL (self), priv->items->len - 1, 0, 1);
+ }
+}
+
+void
+ide_test_provider_remove (IdeTestProvider *self,
+ IdeTest *test)
+{
+ IdeTestProviderPrivate *priv = ide_test_provider_get_instance_private (self);
+
+ g_return_if_fail (IDE_IS_TEST_PROVIDER (self));
+ g_return_if_fail (IDE_IS_TEST (test));
+
+ if (priv->items != NULL)
+ {
+ for (guint i = 0; i < priv->items->len; i++)
+ {
+ IdeTest *element = g_ptr_array_index (priv->items, i);
+
+ if (element == test)
+ {
+ g_ptr_array_remove_index (priv->items, i);
+ g_list_model_items_changed (G_LIST_MODEL (self), i, 1, 0);
+ break;
+ }
+ }
+ }
+}
diff --git a/src/libide/testing/ide-test-provider.h b/src/libide/testing/ide-test-provider.h
new file mode 100644
index 0000000..cc3e5fd
--- /dev/null
+++ b/src/libide/testing/ide-test-provider.h
@@ -0,0 +1,51 @@
+/* ide-test-provider.h
+ *
+ * Copyright (C) 2017 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include "ide-object.h"
+
+#include "testing/ide-test.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_TEST_PROVIDER (ide_test_provider_get_type ())
+
+G_DECLARE_DERIVABLE_TYPE (IdeTestProvider, ide_test_provider, IDE, TEST_PROVIDER, IdeObject)
+
+struct _IdeTestProviderClass
+{
+ IdeObjectClass parent_class;
+
+ /*< private >*/
+ gpointer _reserved1;
+ gpointer _reserved2;
+ gpointer _reserved3;
+ gpointer _reserved4;
+ gpointer _reserved5;
+ gpointer _reserved6;
+ gpointer _reserved7;
+ gpointer _reserved8;
+};
+
+void ide_test_provider_add (IdeTestProvider *self,
+ IdeTest *test);
+void ide_test_provider_remove (IdeTestProvider *self,
+ IdeTest *test);
+
+G_END_DECLS
diff --git a/src/libide/testing/ide-test.c b/src/libide/testing/ide-test.c
new file mode 100644
index 0000000..2ac6e70
--- /dev/null
+++ b/src/libide/testing/ide-test.c
@@ -0,0 +1,313 @@
+/* ide-test.c
+ *
+ * Copyright © 2017 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include "ide-test.h"
+
+typedef struct
+{
+ gchar *display_name;
+ gchar *group;
+ gchar *id;
+} IdeTestPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (IdeTest, ide_test, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_DISPLAY_NAME,
+ PROP_GROUP,
+ PROP_ID,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+IdeTest *
+ide_test_new (void)
+{
+ return g_object_new (IDE_TYPE_TEST, NULL);
+}
+
+static void
+ide_test_finalize (GObject *object)
+{
+ IdeTest *self = (IdeTest *)object;
+ IdeTestPrivate *priv = ide_test_get_instance_private (self);
+
+ g_clear_pointer (&priv->group, g_free);
+ g_clear_pointer (&priv->id, g_free);
+ g_clear_pointer (&priv->display_name, g_free);
+
+ G_OBJECT_CLASS (ide_test_parent_class)->finalize (object);
+}
+
+static void
+ide_test_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ IdeTest *self = IDE_TEST (object);
+
+ switch (prop_id)
+ {
+ case PROP_ID:
+ g_value_set_string (value, ide_test_get_id (self));
+ break;
+
+ case PROP_GROUP:
+ g_value_set_string (value, ide_test_get_group (self));
+ break;
+
+ case PROP_DISPLAY_NAME:
+ g_value_set_string (value, ide_test_get_display_name (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_test_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ IdeTest *self = IDE_TEST (object);
+
+ switch (prop_id)
+ {
+ case PROP_GROUP:
+ ide_test_set_group (self, g_value_get_string (value));
+ break;
+
+ case PROP_ID:
+ ide_test_set_id (self, g_value_get_string (value));
+ break;
+
+ case PROP_DISPLAY_NAME:
+ ide_test_set_display_name (self, g_value_get_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_test_class_init (IdeTestClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = ide_test_finalize;
+ object_class->get_property = ide_test_get_property;
+ object_class->set_property = ide_test_set_property;
+
+ /**
+ * IdeTest:display_name:
+ *
+ * The "display-name" property contains the display name of the test as
+ * the user is expected to read in UI elements.
+ *
+ * Since: 3.28
+ */
+ properties [PROP_DISPLAY_NAME] =
+ g_param_spec_string ("display-name",
+ "Name",
+ "The display_name of the unit test",
+ NULL,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * IdeTest:id:
+ *
+ * The "id" property contains the unique identifier of the test.
+ *
+ * Since: 3.28
+ */
+ properties [PROP_ID] =
+ g_param_spec_string ("id",
+ "Id",
+ "The unique identifier of the test",
+ NULL,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * IdeTest:group:
+ *
+ * The "group" property contains the name of the gruop the test belongs
+ * to, if any.
+ *
+ * Since: 3.28
+ */
+ properties [PROP_GROUP] =
+ g_param_spec_string ("group",
+ "Group",
+ "The name of the group the test belongs to, if any",
+ NULL,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+ide_test_init (IdeTest *self)
+{
+}
+
+/**
+ * ide_test_get_display_name:
+ * @self: An #IdeTest
+ *
+ * Gets the "display-name" property of the test.
+ *
+ * Returns: (nullable): The display_name of the test or %NULL
+ *
+ * Since: 3.28
+ */
+const gchar *
+ide_test_get_display_name (IdeTest *self)
+{
+ IdeTestPrivate *priv = ide_test_get_instance_private (self);
+
+ g_return_val_if_fail (IDE_IS_TEST (self), NULL);
+
+ return priv->display_name;
+}
+
+/**
+ * ide_test_set_display_name:
+ * @self: An #IdeTest
+ * @display_name: (nullable): The display_name of the test, or %NULL to unset
+ *
+ * Sets the "display-name" property of the unit test.
+ *
+ * Since: 3.28
+ */
+void
+ide_test_set_display_name (IdeTest *self,
+ const gchar *display_name)
+{
+ IdeTestPrivate *priv = ide_test_get_instance_private (self);
+
+ g_return_if_fail (IDE_IS_TEST (self));
+
+ if (g_strcmp0 (display_name, priv->display_name) != 0)
+ {
+ g_free (priv->display_name);
+ priv->display_name = g_strdup (priv->display_name);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DISPLAY_NAME]);
+ }
+}
+
+/**
+ * ide_test_get_group:
+ * @self: a #IdeTest
+ *
+ * Gets the "group" property.
+ *
+ * The group name is used to group tests together.
+ *
+ * Returns: (nullable): The group name or %NULL.
+ *
+ * Since: 3.28
+ */
+const gchar *
+ide_test_get_group (IdeTest *self)
+{
+ IdeTestPrivate *priv = ide_test_get_instance_private (self);
+
+ g_return_val_if_fail (IDE_IS_TEST (self), NULL);
+
+ return priv->group;
+}
+
+/**
+ * ide_test_set_group:
+ * @self: a #IdeTest
+ * @group: (nullable): the name of the group or %NULL
+ *
+ * Sets the #IdeTest:group property.
+ *
+ * The group property is used to group related tests together.
+ *
+ * Since: 3.28
+ */
+void
+ide_test_set_group (IdeTest *self,
+ const gchar *group)
+{
+ IdeTestPrivate *priv = ide_test_get_instance_private (self);
+
+ g_return_if_fail (IDE_IS_TEST (self));
+
+ if (g_strcmp0 (group, priv->group) != 0)
+ {
+ g_free (priv->group);
+ priv->group = g_strdup (priv->group);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_GROUP]);
+ }
+}
+
+/**
+ * ide_test_get_id:
+ * @self: a #IdeTest
+ *
+ * Gets the #IdeTest:id property.
+ *
+ * Returns: (nullable): The id of the test, or %NULL if it has not been set.
+ *
+ * Since: 3.28
+ */
+const gchar *
+ide_test_get_id (IdeTest *self)
+{
+ IdeTestPrivate *priv = ide_test_get_instance_private (self);
+
+ g_return_val_if_fail (IDE_IS_TEST (self), NULL);
+
+ return priv->id;
+}
+
+/**
+ * ide_test_set_id:
+ * @self: a #IdeTest
+ * @id: (nullable): the id of the test or %NULL
+ *
+ * Sets the #IdeTest:id property.
+ *
+ * The id property is used to uniquely identify the test.
+ *
+ * Since: 3.28
+ */
+void
+ide_test_set_id (IdeTest *self,
+ const gchar *id)
+{
+ IdeTestPrivate *priv = ide_test_get_instance_private (self);
+
+ g_return_if_fail (IDE_IS_TEST (self));
+
+ if (g_strcmp0 (id, priv->id) != 0)
+ {
+ g_free (priv->id);
+ priv->id = g_strdup (priv->id);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ID]);
+ }
+}
diff --git a/src/libide/testing/ide-test.h b/src/libide/testing/ide-test.h
new file mode 100644
index 0000000..6e1702b
--- /dev/null
+++ b/src/libide/testing/ide-test.h
@@ -0,0 +1,55 @@
+/* ide-test.h
+ *
+ * Copyright © 2017 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_TEST (ide_test_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (IdeTest, ide_test, IDE, TEST, GObject)
+
+struct _IdeTestClass
+{
+ GObjectClass parent;
+
+ /*< private >*/
+ gpointer _reserved1;
+ gpointer _reserved2;
+ gpointer _reserved3;
+ gpointer _reserved4;
+ gpointer _reserved5;
+ gpointer _reserved6;
+ gpointer _reserved7;
+ gpointer _reserved8;
+};
+
+IdeTest *ide_test_new (void);
+const gchar *ide_test_get_display_name (IdeTest *self);
+void ide_test_set_display_name (IdeTest *self,
+ const gchar *display_name);
+const gchar *ide_test_get_group (IdeTest *self);
+void ide_test_set_group (IdeTest *self,
+ const gchar *group);
+const gchar *ide_test_get_id (IdeTest *self);
+void ide_test_set_id (IdeTest *self,
+ const gchar *id);
+
+G_END_DECLS
diff --git a/src/libide/testing/meson.build b/src/libide/testing/meson.build
new file mode 100644
index 0000000..02fa382
--- /dev/null
+++ b/src/libide/testing/meson.build
@@ -0,0 +1,16 @@
+testing_headers = [
+ 'ide-test.h',
+ 'ide-test-manager.h',
+ 'ide-test-provider.h',
+]
+
+testing_sources = [
+ 'ide-test.c',
+ 'ide-test-manager.c',
+ 'ide-test-provider.c',
+]
+
+libide_public_headers += files(testing_headers)
+libide_public_sources += files(testing_sources)
+
+install_headers(testing_headers, subdir: join_paths(libide_header_subdir, 'testing'))
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]