[gnome-builder/wip/gtk4-port: 1721/1774] libide/foundry: rewrite test manager to use run commands
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/gtk4-port: 1721/1774] libide/foundry: rewrite test manager to use run commands
- Date: Mon, 11 Jul 2022 22:31:55 +0000 (UTC)
commit cb516108e911fb32fc79576e8a1e0392d3b4a67a
Author: Christian Hergert <chergert redhat com>
Date: Tue Jun 28 17:23:34 2022 -0700
libide/foundry: rewrite test manager to use run commands
This does away with IdeTestProvider (still to be removed) and instead
focuses on using run commands with a filter by run command kind.
src/libide/foundry/ide-test-manager.c | 1025 ++++++++-------------------------
src/libide/foundry/ide-test-manager.h | 24 +-
src/libide/foundry/ide-test.c | 417 ++++++--------
src/libide/foundry/ide-test.h | 45 +-
4 files changed, 425 insertions(+), 1086 deletions(-)
---
diff --git a/src/libide/foundry/ide-test-manager.c b/src/libide/foundry/ide-test-manager.c
index e9d9a27b4..b34485a82 100644
--- a/src/libide/foundry/ide-test-manager.c
+++ b/src/libide/foundry/ide-test-manager.c
@@ -1,6 +1,6 @@
/* ide-test-manager.c
*
- * Copyright 2017-2019 Christian Hergert <chergert redhat com>
+ * Copyright 2017-2022 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
@@ -31,12 +31,21 @@
#include "ide-build-manager.h"
#include "ide-pipeline.h"
#include "ide-foundry-compat.h"
+#include "ide-run-command.h"
+#include "ide-run-manager.h"
#include "ide-test-manager.h"
#include "ide-test-private.h"
#include "ide-test-provider.h"
#define MAX_UNIT_TESTS 4
+typedef enum
+{
+ LIST_STATE_INITIAL,
+ LIST_STATE_WAITING_FOR_RESULTS,
+ LIST_STATE_READY,
+} ListState;
+
/**
* SECTION:ide-test-manager
* @title: IdeTestManager
@@ -52,475 +61,126 @@
struct _IdeTestManager
{
- IdeObject parent_instance;
-
- PeasExtensionSet *providers;
- GPtrArray *tests_by_provider;
- GtkTreeStore *tests_store;
- GCancellable *cancellable;
- VtePty *pty;
- gint child_pty;
- gint n_active;
+ IdeObject parent_instance;
+ GtkMapListModel *tests;
+ VtePty *pty;
+ ListState list_state;
};
typedef struct
{
- IdeTestProvider *provider;
- GPtrArray *tests;
-} TestsByProvider;
-
-typedef struct
-{
- GQueue queue;
- guint n_active;
-} RunAllTaskData;
-
-enum {
- PROP_0,
- PROP_LOADING,
- N_PROPS
-};
+ IdePipeline *pipeline;
+ GPtrArray *tests;
+ VtePty *pty;
+ guint n_active;
+} RunAll;
-static void initable_iface_init (GInitableIface *iface);
-static void ide_test_manager_actions_run_all (IdeTestManager *self,
- GVariant *param);
-static void ide_test_manager_actions_reload (IdeTestManager *self,
- GVariant *param);
-static void ide_test_manager_actions_cancel (IdeTestManager *self,
- GVariant *param);
+static void ide_test_manager_actions_test (IdeTestManager *self,
+ GVariant *param);
+static void ide_test_manager_actions_test_all (IdeTestManager *self,
+ GVariant *param);
IDE_DEFINE_ACTION_GROUP (IdeTestManager, ide_test_manager, {
- { "cancel", ide_test_manager_actions_cancel },
- { "run-all", ide_test_manager_actions_run_all },
- { "reload-tests", ide_test_manager_actions_reload },
+ { "test", ide_test_manager_actions_test, "s" },
+ { "test-all", ide_test_manager_actions_test_all },
})
G_DEFINE_FINAL_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_destroy (IdeObject *object)
-{
- IdeTestManager *self = (IdeTestManager *)object;
-
- if (self->child_pty != -1)
- {
- close (self->child_pty);
- self->child_pty = -1;
- }
-
- if (self->tests_store != NULL)
- {
- gtk_tree_store_clear (self->tests_store);
- g_clear_object (&self->tests_store);
- }
-
- g_cancellable_cancel (self->cancellable);
- g_clear_object (&self->cancellable);
-
- g_clear_object (&self->providers);
- g_clear_pointer (&self->tests_by_provider, g_ptr_array_unref);
-
- g_clear_object (&self->pty);
-
- IDE_OBJECT_CLASS (ide_test_manager_parent_class)->destroy (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_LOADING:
- g_value_set_boolean (value, ide_test_manager_get_loading (self));
- 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);
- IdeObjectClass *i_object_class = IDE_OBJECT_CLASS (klass);
-
- object_class->get_property = ide_test_manager_get_property;
-
- i_object_class->destroy = ide_test_manager_destroy;
-
- /**
- * IdeTestManager:loading:
- *
- * The "loading" property denotes if a test provider is busy loading
- * tests in the background.
- */
- properties [PROP_LOADING] =
- g_param_spec_boolean ("loading",
- "Loading",
- "If a test provider is loading tests",
- 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->child_pty = -1;
- self->cancellable = g_cancellable_new ();
- 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);
-
- ide_test_manager_set_action_enabled (self, "cancel", FALSE);
-}
-
-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,
- IDE_TEST_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,
- IDE_TEST_COLUMN_GROUP, group,
- -1);
-}
-
-static void
-ide_test_manager_test_notify_status (IdeTestManager *self,
- GParamSpec *pspec,
- IdeTest *test)
-{
- const gchar *group;
- GtkTreeIter parent;
- GtkTreeIter iter;
-
- g_assert (IDE_IS_TEST_MANAGER (self));
- g_assert (IDE_IS_TEST (test));
-
- group = ide_test_get_group (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_test = NULL;
-
- gtk_tree_model_get (GTK_TREE_MODEL (self->tests_store), &iter,
- IDE_TEST_COLUMN_TEST, &row_test,
- -1);
-
- if (row_test == test)
- {
- GtkTreePath *path;
-
- path = gtk_tree_model_get_path (GTK_TREE_MODEL (self->tests_store), &iter);
- gtk_tree_model_row_changed (GTK_TREE_MODEL (self->tests_store), path, &iter);
- gtk_tree_path_free (path);
-
- break;
- }
- }
- while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->tests_store), &iter));
- }
-}
+ G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP,
ide_test_manager_init_action_group))
static void
-ide_test_manager_add_test (IdeTestManager *self,
- const TestsByProvider *info,
- guint position,
- IdeTest *test)
+run_all_free (RunAll *state)
{
- 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);
+ g_assert (state != NULL);
+ g_assert (state->n_active == 0);
- 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,
- IDE_TEST_COLUMN_GROUP, NULL,
- IDE_TEST_COLUMN_TEST, test,
- -1);
-
- g_signal_connect_object (test,
- "notify::status",
- G_CALLBACK (ide_test_manager_test_notify_status),
- self,
- G_CONNECT_SWAPPED);
-
- IDE_EXIT;
+ g_clear_pointer (&state->tests, g_ptr_array_unref);
+ g_clear_object (&state->pipeline);
+ g_clear_object (&state->pty);
+ g_slice_free (RunAll, state);
}
static void
-ide_test_manager_remove_test (IdeTestManager *self,
- const TestsByProvider *info,
- IdeTest *test)
+ide_test_manager_actions_test (IdeTestManager *self,
+ GVariant *param)
{
- const gchar *group;
- GtkTreeIter iter;
- GtkTreeIter parent;
+ g_autoptr(GListModel) tests = NULL;
+ const char *test_id;
+ guint n_items;
IDE_ENTRY;
+ g_assert (IDE_IS_MAIN_THREAD ());
g_assert (IDE_IS_TEST_MANAGER (self));
- g_assert (info != NULL);
- g_assert (IDE_IS_TEST (test));
-
- group = ide_test_get_group (test);
+ g_assert (g_variant_is_of_type (param, G_VARIANT_TYPE_STRING));
- ide_test_manager_locate_group (self, &parent, group);
+ test_id = g_variant_get_string (param, NULL);
+ tests = ide_test_manager_list_tests (self);
+ n_items = g_list_model_get_n_items (tests);
- if (gtk_tree_model_iter_children (GTK_TREE_MODEL (self->tests_store), &iter, &parent))
+ for (guint i = 0; i < n_items; i++)
{
- do
+ g_autoptr(IdeTest) test = g_list_model_get_item (tests, i);
+
+ if (ide_str_equal0 (test_id, ide_test_get_id (test)))
{
- g_autoptr(IdeTest) row = NULL;
-
- gtk_tree_model_get (GTK_TREE_MODEL (self->tests_store), &iter,
- IDE_TEST_COLUMN_TEST, &row,
- -1);
-
- if (row == test)
- {
- g_signal_handlers_disconnect_by_func (test,
- G_CALLBACK (ide_test_manager_test_notify_status),
- self);
- gtk_tree_store_remove (self->tests_store, &iter);
- break;
- }
+ ide_test_manager_run_async (self, test, NULL, NULL, NULL);
+ IDE_EXIT;
}
- 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_test_manager_actions_test_all (IdeTestManager *self,
+ GVariant *param)
{
IDE_ENTRY;
+ g_assert (IDE_IS_MAIN_THREAD ());
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);
+ g_assert (param == NULL);
- 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);
-
- g_assert (IDE_IS_TEST (test));
- 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);
- g_assert (IDE_IS_TEST (test));
- ide_test_manager_add_test (self, info, position + j, test);
- }
- }
- }
+ ide_test_manager_run_all_async (self, NULL, NULL, NULL);
IDE_EXIT;
}
-static void
-ide_test_manager_provider_notify_loading (IdeTestManager *self,
- GParamSpec *pspec,
- IdeTestProvider *provider)
+static gpointer
+map_run_command_to_test (gpointer item,
+ gpointer user_data)
{
- g_assert (IDE_IS_TEST_MANAGER (self));
- g_assert (IDE_IS_TEST_PROVIDER (provider));
-
- g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_LOADING]);
+ return ide_test_new (IDE_RUN_COMMAND (item));
}
static void
-ide_test_manager_provider_added (PeasExtensionSet *set,
- PeasPluginInfo *plugin_info,
- PeasExtension *exten,
- gpointer user_data)
+ide_test_manager_dispose (GObject *object)
{
- 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);
- g_signal_connect_swapped (provider,
- "notify::loading",
- G_CALLBACK (ide_test_manager_provider_notify_loading),
- self);
-
- len = g_list_model_get_n_items (G_LIST_MODEL (provider));
- ide_test_manager_provider_items_changed (self, 0, 0, len, provider);
+ IdeTestManager *self = (IdeTestManager *)object;
- ide_object_append (IDE_OBJECT (self), IDE_OBJECT (provider));
+ g_clear_object (&self->pty);
+ g_clear_object (&self->tests);
- IDE_EXIT;
+ G_OBJECT_CLASS (ide_test_manager_parent_class)->dispose (object);
}
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);
- g_signal_handlers_disconnect_by_func (provider,
- G_CALLBACK (ide_test_manager_provider_notify_loading),
- self);
-
- ide_object_destroy (IDE_OBJECT (provider));
-
- IDE_EXIT;
-}
-
-static gboolean
-ide_test_manager_initiable_init (GInitable *initable,
- GCancellable *cancellable,
- GError **error)
+ide_test_manager_class_init (IdeTestManagerClass *klass)
{
- IdeTestManager *self = (IdeTestManager *)initable;
-
- IDE_ENTRY;
-
- g_assert (IDE_IS_TEST_MANAGER (self));
- g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
-
- self->providers = peas_extension_set_new (peas_engine_get_default (),
- IDE_TYPE_TEST_PROVIDER,
- 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);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
- IDE_RETURN (TRUE);
+ object_class->dispose = ide_test_manager_dispose;
}
static void
-initable_iface_init (GInitableIface *iface)
+ide_test_manager_init (IdeTestManager *self)
{
- iface->init = ide_test_manager_initiable_init;
+ self->pty = vte_pty_new_sync (VTE_PTY_DEFAULT, NULL, NULL);
+ self->tests = gtk_map_list_model_new (NULL,
+ map_run_command_to_test,
+ NULL,
+ NULL);
}
static void
@@ -528,43 +188,49 @@ ide_test_manager_run_all_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
- IdeTestManager *self = (IdeTestManager *)object;
- g_autoptr(GTask) task = user_data;
+ IdeTest *test = (IdeTest *)object;
+ g_autoptr(IdeTask) task = user_data;
g_autoptr(GError) error = NULL;
- g_autoptr(IdeTest) test = NULL;
- RunAllTaskData *task_data;
GCancellable *cancellable;
+ RunAll *state;
IDE_ENTRY;
- g_assert (IDE_IS_TEST_MANAGER (self));
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_TEST (test));
g_assert (G_IS_ASYNC_RESULT (result));
- g_assert (G_IS_TASK (task));
+ g_assert (IDE_IS_TASK (task));
- cancellable = g_task_get_cancellable (task);
- task_data = g_task_get_task_data (task);
- g_assert (task_data != NULL);
- g_assert (task_data->n_active > 0);
+ cancellable = ide_task_get_cancellable (task);
+ state = ide_task_get_task_data (task);
- if (!ide_test_manager_run_finish (self, result, &error))
- g_message ("%s", error->message);
+ g_assert (state != NULL);
+ g_assert (state->n_active > 0);
+ g_assert (!state->pty || VTE_IS_PTY (state->pty));
+ g_assert (state->tests != NULL);
- test = g_queue_pop_head (&task_data->queue);
+ if (!ide_test_run_finish (test, result, &error))
+ g_message ("%s", error->message);
- if (test != NULL)
+ if (state->tests->len > 0 &&
+ !g_cancellable_is_cancelled (cancellable))
{
- task_data->n_active++;
- ide_test_manager_run_async (self,
- test,
- cancellable,
- ide_test_manager_run_all_cb,
- g_object_ref (task));
+ g_autoptr(IdeTest) next_test = g_ptr_array_steal_index (state->tests, state->tests->len-1);
+
+ state->n_active++;
+
+ ide_test_run_async (next_test,
+ state->pipeline,
+ state->pty,
+ cancellable,
+ ide_test_manager_run_all_cb,
+ g_object_ref (task));
}
- task_data->n_active--;
+ state->n_active--;
- if (task_data->n_active == 0)
- g_task_return_boolean (task, TRUE);
+ if (state->n_active == 0)
+ ide_task_return_boolean (task, TRUE);
IDE_EXIT;
}
@@ -590,55 +256,67 @@ ide_test_manager_run_all_async (IdeTestManager *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
- g_autoptr(GTask) task = NULL;
- RunAllTaskData *task_data;
+ g_autoptr(IdeTask) task = NULL;
+ g_autoptr(GListModel) tests = NULL;
+ g_autoptr(GPtrArray) ar = NULL;
+ IdeBuildManager *build_manager;
+ IdePipeline *pipeline;
+ IdeContext *context;
+ RunAll *state;
+ guint n_items;
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);
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, ide_test_manager_run_all_async);
- task_data = g_new0 (RunAllTaskData, 1);
- g_task_set_task_data (task, task_data, g_free);
+ context = ide_object_get_context (IDE_OBJECT (self));
+ build_manager = ide_build_manager_from_context (context);
+ pipeline = ide_build_manager_get_pipeline (build_manager);
- for (guint i = 0; i < self->tests_by_provider->len; i++)
+ if (pipeline == NULL)
{
- TestsByProvider *info = g_ptr_array_index (self->tests_by_provider, i);
-
- for (guint j = 0; j < info->tests->len; j++)
- {
- IdeTest *test = g_ptr_array_index (info->tests, j);
-
- g_queue_push_tail (&task_data->queue, g_object_ref (test));
- }
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_INITIALIZED,
+ "Cannot run test until pipeline is ready");
+ IDE_EXIT;
}
- task_data->n_active = MIN (MAX_UNIT_TESTS, task_data->queue.length);
+ tests = ide_test_manager_list_tests (self);
+ n_items = g_list_model_get_n_items (tests);
- if (task_data->n_active == 0)
- {
- g_task_return_boolean (task, TRUE);
- IDE_EXIT;
- }
+ ar = g_ptr_array_new_with_free_func (g_object_unref);
+ for (guint i = n_items; i > 0; i--)
+ g_ptr_array_add (ar, g_list_model_get_item (tests, i-1));
+
+ state = g_slice_new0 (RunAll);
+ state->tests = g_ptr_array_ref (ar);
+ state->pipeline = g_object_ref (pipeline);
+ state->pty = g_object_ref (self->pty);
+ state->n_active = 0;
+ ide_task_set_task_data (task, state, run_all_free);
- for (guint i = 0; i < MAX_UNIT_TESTS; i++)
+ for (guint i = 0; i < MAX_UNIT_TESTS && ar->len > 0; i++)
{
- g_autoptr(IdeTest) test = g_queue_pop_head (&task_data->queue);
+ g_autoptr(IdeTest) test = g_ptr_array_steal_index (state->tests, ar->len-1);
- if (test == NULL)
- break;
+ state->n_active++;
- ide_test_manager_run_async (self,
- test,
- cancellable,
- ide_test_manager_run_all_cb,
- g_object_ref (task));
+ ide_test_run_async (test,
+ state->pipeline,
+ state->pty,
+ cancellable,
+ ide_test_manager_run_all_cb,
+ g_object_ref (task));
}
+ if (state->n_active == 0)
+ ide_task_return_boolean (task, TRUE);
+
IDE_EXIT;
}
@@ -666,46 +344,33 @@ ide_test_manager_run_all_finish (IdeTestManager *self,
IDE_ENTRY;
g_return_val_if_fail (IDE_IS_TEST_MANAGER (self), FALSE);
- g_return_val_if_fail (G_IS_TASK (result), FALSE);
+ g_return_val_if_fail (IDE_IS_TASK (result), FALSE);
- ret = g_task_propagate_boolean (G_TASK (result), error);
+ ret = ide_task_propagate_boolean (IDE_TASK (result), error);
IDE_RETURN (ret);
}
-static void
-run_task_completed_cb (IdeTestManager *self,
- GParamSpec *pspec,
- IdeTask *task)
-{
- g_assert (IDE_IS_TEST_MANAGER (self));
- g_assert (G_IS_TASK (task));
- g_assert (self->n_active > 0);
-
- self->n_active--;
-
- ide_test_manager_set_action_enabled (self, "cancel", self->n_active > 0);
-}
-
static void
ide_test_manager_run_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
- IdeTestProvider *provider = (IdeTestProvider *)object;
- g_autoptr(GTask) task = user_data;
+ IdeTest *test = (IdeTest *)object;
+ g_autoptr(IdeTask) task = user_data;
g_autoptr(GError) error = NULL;
IDE_ENTRY;
- g_assert (IDE_IS_TEST_PROVIDER (provider));
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_TEST (test));
g_assert (G_IS_ASYNC_RESULT (result));
- g_assert (G_IS_TASK (task));
+ g_assert (IDE_IS_TASK (task));
- if (!ide_test_provider_run_finish (provider, result, &error))
- g_task_return_error (task, g_steal_pointer (&error));
+ if (!ide_test_run_finish (test, result, &error))
+ ide_task_return_error (task, g_steal_pointer (&error));
else
- g_task_return_boolean (task, TRUE);
+ ide_task_return_boolean (task, TRUE);
IDE_EXIT;
}
@@ -730,10 +395,9 @@ ide_test_manager_run_async (IdeTestManager *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
- g_autoptr(GTask) task = NULL;
- IdePipeline *pipeline;
- IdeTestProvider *provider;
+ g_autoptr(IdeTask) task = NULL;
IdeBuildManager *build_manager;
+ IdePipeline *pipeline;
IdeContext *context;
IDE_ENTRY;
@@ -742,51 +406,25 @@ ide_test_manager_run_async (IdeTestManager *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);
-
- self->n_active++;
- g_signal_connect_object (task,
- "notify::completed",
- G_CALLBACK (run_task_completed_cb),
- self,
- G_CONNECT_SWAPPED);
- ide_test_manager_set_action_enabled (self, "cancel", TRUE);
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, ide_test_manager_run_async);
context = ide_object_get_context (IDE_OBJECT (self));
build_manager = ide_build_manager_from_context (context);
pipeline = ide_build_manager_get_pipeline (build_manager);
if (pipeline == NULL)
- {
- g_task_return_new_error (task,
+ ide_task_return_new_error (task,
G_IO_ERROR,
- G_IO_ERROR_FAILED,
+ G_IO_ERROR_NOT_INITIALIZED,
"Pipeline is not ready, cannot run test");
- IDE_EXIT;
- }
-
- provider = _ide_test_get_provider (test);
-
- if (self->pty == NULL)
- {
- g_autoptr(GError) error = NULL;
-
- if (!(self->pty = vte_pty_new_sync (VTE_PTY_DEFAULT, cancellable, &error)))
- {
- g_task_return_error (task, g_steal_pointer (&error));
- IDE_EXIT;
- }
- }
-
- ide_test_provider_run_async (provider,
- test,
- pipeline,
- self->pty,
- cancellable,
- ide_test_manager_run_cb,
- g_steal_pointer (&task));
+ else
+ ide_test_run_async (test,
+ pipeline,
+ self->pty,
+ cancellable,
+ ide_test_manager_run_cb,
+ g_steal_pointer (&task));
IDE_EXIT;
}
@@ -816,317 +454,106 @@ ide_test_manager_run_finish (IdeTestManager *self,
IDE_ENTRY;
g_return_val_if_fail (IDE_IS_TEST_MANAGER (self), FALSE);
- g_return_val_if_fail (G_IS_TASK (result), FALSE);
+ g_return_val_if_fail (IDE_IS_TASK (result), FALSE);
- ret = g_task_propagate_boolean (G_TASK (result), error);
+ ret = ide_task_propagate_boolean (IDE_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);
-}
-
-static void
-ide_test_manager_actions_reload (IdeTestManager *self,
- GVariant *param)
-{
- g_assert (IDE_IS_TEST_MANAGER (self));
-
- gtk_tree_store_clear (self->tests_store);
-
- for (guint i = 0; i < self->tests_by_provider->len; i++)
- {
- const TestsByProvider *info = g_ptr_array_index (self->tests_by_provider, i);
-
- ide_test_provider_reload (info->provider);
- }
-}
-
-GtkTreeModel *
-_ide_test_manager_get_model (IdeTestManager *self)
-{
- g_return_val_if_fail (IDE_IS_TEST_MANAGER (self), NULL);
-
- return GTK_TREE_MODEL (self->tests_store);
-}
-
-static void
-ide_test_manager_get_loading_cb (PeasExtensionSet *set,
- PeasPluginInfo *plugin_info,
- PeasExtension *exten,
- gpointer user_data)
-{
- IdeTestProvider *provider = (IdeTestProvider *)exten;
- gboolean *loading = user_data;
-
- g_assert (PEAS_IS_EXTENSION_SET (set));
- g_assert (plugin_info != NULL);
- g_assert (IDE_IS_TEST_PROVIDER (provider));
- g_assert (loading != NULL);
-
- *loading |= ide_test_provider_get_loading (provider);
-}
-
-gboolean
-ide_test_manager_get_loading (IdeTestManager *self)
-{
- gboolean loading = FALSE;
-
- g_return_val_if_fail (IDE_IS_TEST_MANAGER (self), FALSE);
-
- peas_extension_set_foreach (self->providers,
- ide_test_manager_get_loading_cb,
- &loading);
-
- return loading;
-}
-
/**
- * ide_test_manager_get_tests:
+ * ide_test_manager_get_pty:
* @self: a #IdeTestManager
- * @path: (nullable): the path to the test or %NULL for the root path
*
- * Locates and returns any #IdeTest that is found as a direct child
- * of @path.
+ * Gets the #VtePty to use for running unit tests.
*
- * Returns: (transfer full) (element-type IdeTest): an array of #IdeTest
+ * Returns: (transfer none): a #VtePty
*/
-GPtrArray *
-ide_test_manager_get_tests (IdeTestManager *self,
- const gchar *path)
+VtePty *
+ide_test_manager_get_pty (IdeTestManager *self)
{
- GPtrArray *ret;
- GtkTreeIter iter;
-
- g_return_val_if_fail (IDE_IS_MAIN_THREAD (), NULL);
g_return_val_if_fail (IDE_IS_TEST_MANAGER (self), NULL);
- ret = g_ptr_array_new ();
-
- if (path == NULL)
- {
- if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->tests_store), &iter))
- goto failure;
- }
- else
- {
- GtkTreeIter parent;
-
- ide_test_manager_locate_group (self, &parent, path);
-
- if (!gtk_tree_model_iter_children (GTK_TREE_MODEL (self->tests_store), &iter, &parent))
- goto failure;
- }
-
- do
- {
- IdeTest *test = NULL;
-
- gtk_tree_model_get (GTK_TREE_MODEL (self->tests_store), &iter,
- IDE_TEST_COLUMN_TEST, &test,
- -1);
- if (test != NULL)
- g_ptr_array_add (ret, g_steal_pointer (&test));
- }
- while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->tests_store), &iter));
-
-failure:
- return g_steal_pointer (&ret);
+ return self->pty;
}
-/**
- * ide_test_manager_get_folders:
- * @self: a #IdeTestManager
- * @path: (nullable): the path to the test or %NULL for the root path
- *
- * Gets the sub-paths of @path that are not individual tests.
- *
- * Returns: (transfer full) (array zero-terminated=1): an array of strings
- * describing available sub-paths to @path.
- */
-gchar **
-ide_test_manager_get_folders (IdeTestManager *self,
- const gchar *path)
+static gboolean
+filter_tests_func (gpointer item,
+ gpointer user_data)
{
- static const gchar *empty[] = { NULL };
- GPtrArray *ret;
- GtkTreeIter iter;
-
- g_return_val_if_fail (IDE_IS_MAIN_THREAD (), NULL);
- g_return_val_if_fail (IDE_IS_TEST_MANAGER (self), NULL);
-
- ret = g_ptr_array_new ();
-
- if (path == NULL)
- {
- if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->tests_store), &iter))
- return g_strdupv ((gchar **)empty);
- }
- else
- {
- GtkTreeIter parent;
-
- ide_test_manager_locate_group (self, &parent, path);
-
- if (!gtk_tree_model_iter_children (GTK_TREE_MODEL (self->tests_store), &iter, &parent))
- return g_strdupv ((gchar **)empty);
- }
-
- do
- {
- gchar *group = NULL;
-
- gtk_tree_model_get (GTK_TREE_MODEL (self->tests_store), &iter,
- IDE_TEST_COLUMN_GROUP, &group,
- -1);
- if (group != NULL)
- g_ptr_array_add (ret, g_steal_pointer (&group));
- }
- while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->tests_store), &iter));
-
- g_ptr_array_add (ret, NULL);
-
- return (gchar **)g_ptr_array_free (ret, FALSE);
+ return ide_run_command_get_kind (IDE_RUN_COMMAND (item)) == IDE_RUN_COMMAND_KIND_TEST;
}
static void
-ide_test_manager_ensure_loaded_cb (IdeTestManager *self,
- GParamSpec *pspec,
- IdeTask *task)
+ide_test_manager_list_commands_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
{
+ IdeRunManager *run_manager = (IdeRunManager *)object;
+ g_autoptr(IdeTestManager) self = user_data;
+ g_autoptr(GListModel) commands = NULL;
+ g_autoptr(GError) error = NULL;
+
+ IDE_ENTRY;
+
g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_RUN_MANAGER (run_manager));
+ g_assert (G_IS_ASYNC_RESULT (result));
g_assert (IDE_IS_TEST_MANAGER (self));
- g_assert (IDE_IS_TASK (task));
- if (!ide_test_manager_get_loading (self))
- {
- g_signal_handlers_disconnect_by_func (self,
- G_CALLBACK (ide_test_manager_ensure_loaded_cb),
- task);
- ide_task_return_boolean (task, TRUE);
- }
-}
-
-/**
- * ide_test_manager_ensure_loaded_async:
- * @self: a #IdeTestManager
- *
- * Calls @callback after the test manager has loaded tests.
- *
- * If the test manager has already loaded tests, then @callback will
- * be called after returning to the main loop.
- */
-void
-ide_test_manager_ensure_loaded_async (IdeTestManager *self,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- g_autoptr(IdeTask) task = NULL;
+ commands = ide_run_manager_list_commands_finish (run_manager, result, &error);
- g_return_if_fail (IDE_IS_TEST_MANAGER (self));
- g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+ if (error != NULL)
+ g_message ("Failed to list run commands: %s", error->message);
- task = ide_task_new (self, cancellable, callback, user_data);
- ide_task_set_source_tag (task, ide_test_manager_ensure_loaded_async);
+ self->list_state = commands != NULL ? LIST_STATE_READY : LIST_STATE_INITIAL;
- if (ide_test_manager_get_loading (self))
+ if (commands != NULL)
{
- g_signal_connect_data (self,
- "notify::loading",
- G_CALLBACK (ide_test_manager_ensure_loaded_cb),
- g_steal_pointer (&task),
- (GClosureNotify)g_object_unref,
- 0);
- return;
- }
+ g_autoptr(GtkFilterListModel) filtered = NULL;
+ g_autoptr(GtkCustomFilter) filter = NULL;
- ide_task_return_boolean (task, TRUE);
-}
-
-gboolean
-ide_test_manager_ensure_loaded_finish (IdeTestManager *self,
- GAsyncResult *result,
- GError **error)
-{
- g_return_val_if_fail (IDE_IS_MAIN_THREAD (), FALSE);
- g_return_val_if_fail (IDE_IS_TEST_MANAGER (self), FALSE);
- g_return_val_if_fail (IDE_IS_TASK (result), FALSE);
+ filter = gtk_custom_filter_new (filter_tests_func, NULL, NULL);
+ filtered = gtk_filter_list_model_new (g_steal_pointer (&commands),
+ GTK_FILTER (g_steal_pointer (&filter)));
+ gtk_map_list_model_set_model (self->tests, G_LIST_MODEL (filtered));
+ }
- return ide_task_propagate_boolean (IDE_TASK (result), error);
+ IDE_EXIT;
}
/**
- * ide_test_manager_get_pty:
+ * ide_test_manager_list_tests:
* @self: a #IdeTestManager
*
- * Gets the #VtePty to use for running unit tests.
+ * Gets a #GListModel of #IdeTest.
*
- * Returns: (transfer none): a #VtePty
- */
-VtePty *
-ide_test_manager_get_pty (IdeTestManager *self)
-{
- g_return_val_if_fail (IDE_IS_TEST_MANAGER (self), NULL);
-
- if (self->pty == NULL)
- self->pty = vte_pty_new_sync (VTE_PTY_DEFAULT, NULL, NULL);
-
- return self->pty;
-}
-
-/**
- * ide_test_manager_open_pty:
- * @self: a #IdeTestManager
+ * This will return a #GListModel immediately, but that list may not complete
+ * until some time in the future based on how quickly various
+ * #IdeRunCommandProvider return commands.
*
- * Gets a FD that maps to the child side of the PTY device.
- *
- * Returns: a new FD or -1 on failure
+ * Returns: (transfer none): an #GListModel of #IdeTest
*/
-gint
-ide_test_manager_open_pty (IdeTestManager *self)
+GListModel *
+ide_test_manager_list_tests (IdeTestManager *self)
{
- g_return_val_if_fail (IDE_IS_TEST_MANAGER (self), -1);
-
- if (self->child_pty == -1)
- {
- VtePty *pty = ide_test_manager_get_pty (self);
- self->child_pty = ide_pty_intercept_create_producer (vte_pty_get_fd (pty), TRUE);
- }
-
- return dup (self->child_pty);
-}
+ IDE_ENTRY;
-/**
- * ide_test_manager_get_cancellable:
- * @self: a #IdeTestManager
- *
- * Gets the cancellable for the test manager which will be cancelled
- * when the cancel action is called.
- *
- * Returns: (transfer none): a #GCancellable
- */
-GCancellable *
-ide_test_manager_get_cancellable (IdeTestManager *self)
-{
+ g_return_val_if_fail (IDE_IS_MAIN_THREAD (), NULL);
g_return_val_if_fail (IDE_IS_TEST_MANAGER (self), NULL);
- return self->cancellable;
-}
+ if (self->list_state == LIST_STATE_INITIAL)
+ {
+ IdeContext *context = ide_object_get_context (IDE_OBJECT (self));
+ IdeRunManager *run_manager = ide_run_manager_from_context (context);
-static void
-ide_test_manager_actions_cancel (IdeTestManager *self,
- GVariant *param)
-{
- g_assert (IDE_IS_TEST_MANAGER (self));
+ self->list_state = LIST_STATE_WAITING_FOR_RESULTS;
+
+ ide_run_manager_list_commands_async (run_manager,
+ NULL,
+ ide_test_manager_list_commands_cb,
+ g_object_ref (self));
+ }
- g_cancellable_cancel (self->cancellable);
- g_clear_object (&self->cancellable);
- self->cancellable = g_cancellable_new ();
+ IDE_RETURN (G_LIST_MODEL (self->tests));
}
diff --git a/src/libide/foundry/ide-test-manager.h b/src/libide/foundry/ide-test-manager.h
index b87949ac1..3e7c60e63 100644
--- a/src/libide/foundry/ide-test-manager.h
+++ b/src/libide/foundry/ide-test-manager.h
@@ -24,9 +24,10 @@
# error "Only <libide-foundry.h> can be included directly."
#endif
-#include <libide-core.h>
#include <vte/vte.h>
+#include <libide-core.h>
+
#include "ide-foundry-types.h"
G_BEGIN_DECLS
@@ -39,11 +40,9 @@ G_DECLARE_FINAL_TYPE (IdeTestManager, ide_test_manager, IDE, TEST_MANAGER, IdeOb
IDE_AVAILABLE_IN_ALL
IdeTestManager *ide_test_manager_from_context (IdeContext *context);
IDE_AVAILABLE_IN_ALL
-gboolean ide_test_manager_get_loading (IdeTestManager *self);
-IDE_AVAILABLE_IN_ALL
VtePty *ide_test_manager_get_pty (IdeTestManager *self);
IDE_AVAILABLE_IN_ALL
-gint ide_test_manager_open_pty (IdeTestManager *self);
+GListModel *ide_test_manager_list_tests (IdeTestManager *self);
IDE_AVAILABLE_IN_ALL
void ide_test_manager_run_async (IdeTestManager *self,
IdeTest *test,
@@ -63,22 +62,5 @@ IDE_AVAILABLE_IN_ALL
gboolean ide_test_manager_run_all_finish (IdeTestManager *self,
GAsyncResult *result,
GError **error);
-IDE_AVAILABLE_IN_ALL
-GPtrArray *ide_test_manager_get_tests (IdeTestManager *self,
- const gchar *path);
-IDE_AVAILABLE_IN_ALL
-gchar **ide_test_manager_get_folders (IdeTestManager *self,
- const gchar *path);
-IDE_AVAILABLE_IN_ALL
-GCancellable *ide_test_manager_get_cancellable (IdeTestManager *self);
-IDE_AVAILABLE_IN_ALL
-void ide_test_manager_ensure_loaded_async (IdeTestManager *self,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-IDE_AVAILABLE_IN_ALL
-gboolean ide_test_manager_ensure_loaded_finish (IdeTestManager *self,
- GAsyncResult *result,
- GError **error);
G_END_DECLS
diff --git a/src/libide/foundry/ide-test.c b/src/libide/foundry/ide-test.c
index f759cd015..c7d2a4943 100644
--- a/src/libide/foundry/ide-test.c
+++ b/src/libide/foundry/ide-test.c
@@ -1,6 +1,6 @@
/* ide-test.c
*
- * Copyright 2017-2019 Christian Hergert <chergert redhat com>
+ * Copyright 2017-2022 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
@@ -22,57 +22,59 @@
#include "config.h"
-#include "ide-foundry-enums.h"
+#include <libide-io.h>
+#include <libide-threading.h>
+#include "ide-run-command.h"
+#include "ide-run-context.h"
+#include "ide-foundry-enums.h"
+#include "ide-pipeline.h"
#include "ide-test.h"
-#include "ide-test-private.h"
-#include "ide-test-provider.h"
-typedef struct
+struct _IdeTest
{
- /* Unowned references */
- IdeTestProvider *provider;
-
- /* Owned references */
- gchar *display_name;
- gchar *group;
- gchar *id;
-
- IdeTestStatus status;
-} IdeTestPrivate;
-
-G_DEFINE_TYPE_WITH_PRIVATE (IdeTest, ide_test, G_TYPE_OBJECT)
+ GObject parent_instance;
+ IdeRunCommand *run_command;
+ IdeTestStatus status;
+};
enum {
PROP_0,
- PROP_DISPLAY_NAME,
- PROP_GROUP,
+ PROP_ICON_NAME,
PROP_ID,
+ PROP_RUN_COMMAND,
PROP_STATUS,
+ PROP_TITLE,
N_PROPS
};
+G_DEFINE_FINAL_TYPE (IdeTest, ide_test, G_TYPE_OBJECT)
+
static GParamSpec *properties [N_PROPS];
-IdeTest *
-ide_test_new (void)
+static void
+ide_test_set_status (IdeTest *self,
+ IdeTestStatus status)
{
- return g_object_new (IDE_TYPE_TEST, NULL);
+ g_assert (IDE_IS_TEST (self));
+
+ if (status != self->status)
+ {
+ self->status = status;
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_STATUS]);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ICON_NAME]);
+ }
}
static void
-ide_test_finalize (GObject *object)
+ide_test_dispose (GObject *object)
{
IdeTest *self = (IdeTest *)object;
- IdeTestPrivate *priv = ide_test_get_instance_private (self);
- priv->provider = NULL;
+ g_clear_object (&self->run_command);
- 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);
+ G_OBJECT_CLASS (ide_test_parent_class)->dispose (object);
}
static void
@@ -85,22 +87,26 @@ ide_test_get_property (GObject *object,
switch (prop_id)
{
- case PROP_ID:
- g_value_set_string (value, ide_test_get_id (self));
+ case PROP_ICON_NAME:
+ g_value_set_string (value, ide_test_get_icon_name (self));
break;
- case PROP_GROUP:
- g_value_set_string (value, ide_test_get_group (self));
+ case PROP_ID:
+ g_value_set_string (value, ide_test_get_id (self));
break;
- case PROP_DISPLAY_NAME:
- g_value_set_string (value, ide_test_get_display_name (self));
+ case PROP_RUN_COMMAND:
+ g_value_set_object (value, ide_test_get_run_command (self));
break;
case PROP_STATUS:
g_value_set_enum (value, ide_test_get_status (self));
break;
+ case PROP_TITLE:
+ g_value_set_string (value, ide_test_get_title (self));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -116,20 +122,8 @@ ide_test_set_property (GObject *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;
-
- case PROP_STATUS:
- ide_test_set_status (self, g_value_get_enum (value));
+ case PROP_RUN_COMMAND:
+ g_set_object (&self->run_command, g_value_get_object (value));
break;
default:
@@ -142,61 +136,32 @@ ide_test_class_init (IdeTestClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- object_class->finalize = ide_test_finalize;
+ object_class->dispose = ide_test_dispose;
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.
- */
- 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.
- */
+ properties [PROP_ICON_NAME] =
+ g_param_spec_string ("icon-name", NULL, NULL, NULL,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
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.
- */
- 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));
-
- /**
- * IdeTest::status:
- *
- * The "status" property contains the status of the test, updated by
- * providers when they have run the test.
- */
+ g_param_spec_string ("id", NULL, NULL, NULL,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_RUN_COMMAND] =
+ g_param_spec_object ("run-command", NULL, NULL,
+ IDE_TYPE_RUN_COMMAND,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
properties [PROP_STATUS] =
- g_param_spec_enum ("status",
- "Status",
- "The status of the test",
+ g_param_spec_enum ("run-command", NULL, NULL,
IDE_TYPE_TEST_STATUS,
IDE_TEST_STATUS_NONE,
- (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_TITLE] =
+ g_param_spec_string ("title", NULL, NULL, NULL,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_properties (object_class, N_PROPS, properties);
}
@@ -206,204 +171,174 @@ ide_test_init (IdeTest *self)
{
}
-IdeTestProvider *
-_ide_test_get_provider (IdeTest *self)
+IdeTest *
+ide_test_new (IdeRunCommand *run_command)
{
- IdeTestPrivate *priv = ide_test_get_instance_private (self);
-
- g_return_val_if_fail (IDE_IS_TEST (self), NULL);
+ g_return_val_if_fail (IDE_IS_RUN_COMMAND (run_command), NULL);
- return priv->provider;
+ return g_object_new (IDE_TYPE_TEST,
+ "run-command", run_command,
+ NULL);
}
-void
-_ide_test_set_provider (IdeTest *self,
- IdeTestProvider *provider)
+const char *
+ide_test_get_id (IdeTest *self)
{
- IdeTestPrivate *priv = ide_test_get_instance_private (self);
-
- g_return_if_fail (IDE_IS_TEST (self));
- g_return_if_fail (!provider || IDE_IS_TEST_PROVIDER (provider));
+ g_return_val_if_fail (IDE_IS_TEST (self), NULL);
+ g_return_val_if_fail (IDE_IS_RUN_COMMAND (self->run_command), NULL);
- priv->provider = provider;
+ return ide_run_command_get_id (self->run_command);
}
-/**
- * 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
- */
-const gchar *
-ide_test_get_display_name (IdeTest *self)
+IdeTestStatus
+ide_test_get_status (IdeTest *self)
{
- IdeTestPrivate *priv = ide_test_get_instance_private (self);
-
- g_return_val_if_fail (IDE_IS_TEST (self), NULL);
+ g_return_val_if_fail (IDE_IS_TEST (self), 0);
- return priv->display_name;
+ return self->status;
}
-/**
- * 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.
- */
-void
-ide_test_set_display_name (IdeTest *self,
- const gchar *display_name)
+const char *
+ide_test_get_title (IdeTest *self)
{
- IdeTestPrivate *priv = ide_test_get_instance_private (self);
-
- g_return_if_fail (IDE_IS_TEST (self));
+ g_return_val_if_fail (IDE_IS_TEST (self), NULL);
+ g_return_val_if_fail (IDE_IS_RUN_COMMAND (self->run_command), NULL);
- if (g_strcmp0 (display_name, priv->display_name) != 0)
- {
- g_free (priv->display_name);
- priv->display_name = g_strdup (display_name);
- g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DISPLAY_NAME]);
- }
+ return ide_run_command_get_display_name (self->run_command);
}
-/**
- * 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.
- */
-const gchar *
-ide_test_get_group (IdeTest *self)
+const char *
+ide_test_get_icon_name (IdeTest *self)
{
- IdeTestPrivate *priv = ide_test_get_instance_private (self);
-
g_return_val_if_fail (IDE_IS_TEST (self), NULL);
- return priv->group;
-}
+ switch (self->status)
+ {
+ case IDE_TEST_STATUS_NONE:
+ return "builder-unit-tests-symbolic";
-/**
- * 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.
- */
-void
-ide_test_set_group (IdeTest *self,
- const gchar *group)
-{
- IdeTestPrivate *priv = ide_test_get_instance_private (self);
+ case IDE_TEST_STATUS_RUNNING:
+ return "builder-unit-tests-running-symbolic";
- g_return_if_fail (IDE_IS_TEST (self));
+ case IDE_TEST_STATUS_FAILED:
+ return "builder-unit-tests-fail-symbolic";
- if (g_strcmp0 (group, priv->group) != 0)
- {
- g_free (priv->group);
- priv->group = g_strdup (group);
- g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_GROUP]);
+ case IDE_TEST_STATUS_SUCCESS:
+ return "builder-unit-tests-pass-symbolic";
+
+ default:
+ g_return_val_if_reached (NULL);
}
}
/**
- * ide_test_get_id:
+ * ide_test_get_run_command:
* @self: a #IdeTest
*
- * Gets the #IdeTest:id property.
+ * Gets the run command for the test.
*
- * Returns: (nullable): The id of the test, or %NULL if it has not been set.
+ * Returns: (transfer none): an #IdeTest
*/
-const gchar *
-ide_test_get_id (IdeTest *self)
+IdeRunCommand *
+ide_test_get_run_command (IdeTest *self)
{
- IdeTestPrivate *priv = ide_test_get_instance_private (self);
-
g_return_val_if_fail (IDE_IS_TEST (self), NULL);
- return priv->id;
+ return self->run_command;
}
-/**
- * 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.
- */
-void
-ide_test_set_id (IdeTest *self,
- const gchar *id)
+static void
+ide_test_wait_check_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
{
- IdeTestPrivate *priv = ide_test_get_instance_private (self);
+ IdeSubprocess *subprocess = (IdeSubprocess *)object;
+ g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+ IdeTest *self;
- g_return_if_fail (IDE_IS_TEST (self));
+ IDE_ENTRY;
- if (g_strcmp0 (id, priv->id) != 0)
- {
- g_free (priv->id);
- priv->id = g_strdup (id);
- g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ID]);
- }
-}
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_SUBPROCESS (subprocess));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_TASK (task));
-IdeTestStatus
-ide_test_get_status (IdeTest *self)
-{
- IdeTestPrivate *priv = ide_test_get_instance_private (self);
+ self = ide_task_get_source_object (task);
- g_return_val_if_fail (IDE_IS_TEST (self), 0);
+ if (!ide_subprocess_wait_check_finish (subprocess, result, &error))
+ {
+ ide_test_set_status (self, IDE_TEST_STATUS_FAILED);
+ ide_task_return_error (task, g_steal_pointer (&error));
+ }
+ else
+ {
+ ide_test_set_status (self, IDE_TEST_STATUS_SUCCESS);
+ ide_task_return_boolean (task, TRUE);
+ }
- return priv->status;
+ IDE_EXIT;
}
void
-ide_test_set_status (IdeTest *self,
- IdeTestStatus status)
+ide_test_run_async (IdeTest *self,
+ IdePipeline *pipeline,
+ VtePty *pty,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- IdeTestPrivate *priv = ide_test_get_instance_private (self);
+ g_autoptr(IdeRunContext) run_context = NULL;
+ g_autoptr(IdeSubprocess) subprocess = NULL;
+ g_autoptr(IdeTask) task = NULL;
+ g_autoptr(GError) error = NULL;
+
+ IDE_ENTRY;
g_return_if_fail (IDE_IS_TEST (self));
+ g_return_if_fail (IDE_IS_PIPELINE (pipeline));
+ g_return_if_fail (!pty || VTE_IS_PTY (pty));
+ g_return_if_fail (IDE_IS_RUN_COMMAND (self->run_command));
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, ide_test_run_async);
- if (priv->status != status)
+ if (ide_task_return_error_if_cancelled (task))
+ IDE_EXIT;
+
+ run_context = ide_pipeline_create_run_context (pipeline, self->run_command);
+
+ if (!(subprocess = ide_run_context_spawn (run_context, &error)))
{
- priv->status = status;
- g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_STATUS]);
+ ide_test_set_status (self, IDE_TEST_STATUS_FAILED);
+ ide_task_return_error (task, g_steal_pointer (&error));
+ IDE_EXIT;
+ }
+ else
+ {
+ ide_test_set_status (self, IDE_TEST_STATUS_RUNNING);
+ ide_subprocess_wait_check_async (subprocess,
+ cancellable,
+ ide_test_wait_check_cb,
+ g_steal_pointer (&task));
+ IDE_EXIT;
}
}
-const gchar *
-ide_test_get_icon_name (IdeTest *self)
+gboolean
+ide_test_run_finish (IdeTest *self,
+ GAsyncResult *result,
+ GError **error)
{
- IdeTestPrivate *priv = ide_test_get_instance_private (self);
+ gboolean ret;
- g_return_val_if_fail (IDE_IS_TEST (self), NULL);
+ IDE_ENTRY;
- switch (priv->status)
- {
- case IDE_TEST_STATUS_NONE:
- return "builder-unit-tests-symbolic";
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_TEST (self));
+ g_assert (IDE_IS_TASK (result));
- case IDE_TEST_STATUS_RUNNING:
- return "builder-unit-tests-running-symbolic";
+ ret = ide_task_propagate_boolean (IDE_TASK (result), error);
- case IDE_TEST_STATUS_FAILED:
- return "builder-unit-tests-fail-symbolic";
-
- case IDE_TEST_STATUS_SUCCESS:
- return "builder-unit-tests-pass-symbolic";
-
- default:
- g_return_val_if_reached (NULL);
- }
+ IDE_RETURN (ret);
}
diff --git a/src/libide/foundry/ide-test.h b/src/libide/foundry/ide-test.h
index 6eae9217f..de4883ce1 100644
--- a/src/libide/foundry/ide-test.h
+++ b/src/libide/foundry/ide-test.h
@@ -24,8 +24,12 @@
# error "Only <libide-foundry.h> can be included directly."
#endif
+#include <vte/vte.h>
+
#include <libide-core.h>
+#include "ide-foundry-types.h"
+
G_BEGIN_DECLS
#define IDE_TYPE_TEST (ide_test_get_type())
@@ -39,39 +43,30 @@ typedef enum
} IdeTestStatus;
IDE_AVAILABLE_IN_ALL
-G_DECLARE_DERIVABLE_TYPE (IdeTest, ide_test, IDE, TEST, GObject)
-
-struct _IdeTestClass
-{
- GObjectClass parent;
+G_DECLARE_FINAL_TYPE (IdeTest, ide_test, IDE, TEST, GObject)
- /*< private >*/
- gpointer _reserved[16];
-};
-
-IDE_AVAILABLE_IN_ALL
-IdeTest *ide_test_new (void);
-IDE_AVAILABLE_IN_ALL
-const gchar *ide_test_get_display_name (IdeTest *self);
IDE_AVAILABLE_IN_ALL
-void ide_test_set_display_name (IdeTest *self,
- const gchar *display_name);
+IdeTest *ide_test_new (IdeRunCommand *run_command);
IDE_AVAILABLE_IN_ALL
-const gchar *ide_test_get_group (IdeTest *self);
+const char *ide_test_get_id (IdeTest *self);
IDE_AVAILABLE_IN_ALL
-void ide_test_set_group (IdeTest *self,
- const gchar *group);
+IdeTestStatus ide_test_get_status (IdeTest *self);
IDE_AVAILABLE_IN_ALL
-const gchar *ide_test_get_icon_name (IdeTest *self);
+const char *ide_test_get_title (IdeTest *self);
IDE_AVAILABLE_IN_ALL
-const gchar *ide_test_get_id (IdeTest *self);
+const char *ide_test_get_icon_name (IdeTest *self);
IDE_AVAILABLE_IN_ALL
-void ide_test_set_id (IdeTest *self,
- const gchar *id);
+IdeRunCommand *ide_test_get_run_command (IdeTest *self);
IDE_AVAILABLE_IN_ALL
-IdeTestStatus ide_test_get_status (IdeTest *self);
+void ide_test_run_async (IdeTest *self,
+ IdePipeline *pipeline,
+ VtePty *pty,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
IDE_AVAILABLE_IN_ALL
-void ide_test_set_status (IdeTest *self,
- IdeTestStatus status);
+gboolean ide_test_run_finish (IdeTest *self,
+ GAsyncResult *result,
+ GError **error);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]