[gnome-builder/wip/gtk4-port: 1435/1774] plugins/gradle: add test provider for gradle




commit 74b976aa0d0f17f945fdc1ecb37b6c90851d0565
Author: Christian Hergert <chergert redhat com>
Date:   Wed Jun 8 21:42:54 2022 -0700

    plugins/gradle: add test provider for gradle

 src/plugins/gradle/gbp-gradle-test-provider.c | 291 ++++++++++++++++++++++++++
 src/plugins/gradle/gbp-gradle-test-provider.h |  31 +++
 src/plugins/gradle/gbp-gradle-test.c          |  72 +++++++
 src/plugins/gradle/gbp-gradle-test.h          |  34 +++
 src/plugins/gradle/gradle-plugin.c            |   4 +
 src/plugins/gradle/meson.build                |   2 +
 6 files changed, 434 insertions(+)
---
diff --git a/src/plugins/gradle/gbp-gradle-test-provider.c b/src/plugins/gradle/gbp-gradle-test-provider.c
new file mode 100644
index 000000000..dbfb07a40
--- /dev/null
+++ b/src/plugins/gradle/gbp-gradle-test-provider.c
@@ -0,0 +1,291 @@
+/* gbp-gradle-test-provider.c
+ *
+ * Copyright 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
+ * 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-gradle-test-provider"
+
+#include "config.h"
+
+#include <libide-foundry.h>
+#include <libide-io.h>
+#include <libide-threading.h>
+
+#include "gbp-gradle-build-system.h"
+#include "gbp-gradle-test.h"
+#include "gbp-gradle-test-provider.h"
+
+struct _GbpGradleTestProvider
+{
+  IdeTestProvider parent_instance;
+};
+
+G_DEFINE_FINAL_TYPE (GbpGradleTestProvider, gbp_gradle_test_provider, IDE_TYPE_TEST_PROVIDER)
+
+static void
+gbp_gradle_test_provider_add (GbpGradleTestProvider *self,
+                              GFile                 *file,
+                              const char            *test_name)
+{
+  g_autoptr(GbpGradleTest) test = NULL;
+  g_autofree char *class_name = NULL;
+  g_autofree char *full_name = NULL;
+  g_autofree char *id = NULL;
+  char *dot;
+
+  g_assert (GBP_IS_GRADLE_TEST_PROVIDER (self));
+  g_assert (G_IS_FILE (file));
+  g_assert (test_name != NULL);
+
+  class_name = g_file_get_basename (file);
+  if ((dot = strrchr (class_name, '.')))
+    *dot = 0;
+
+  full_name = g_strconcat (class_name, ".", "test_name", NULL);
+  id = g_strconcat ("gradle:%s", full_name, NULL);
+  test = gbp_gradle_test_new (full_name);
+
+  ide_test_set_id (IDE_TEST (test), id);
+  ide_test_set_group (IDE_TEST (test), class_name);
+  ide_test_set_display_name (IDE_TEST (test), test_name);
+
+  ide_test_provider_add (IDE_TEST_PROVIDER (self), IDE_TEST (test));
+}
+
+static void
+find_test_files_cb (GObject      *object,
+                    GAsyncResult *result,
+                    gpointer      user_data)
+{
+  GFile *basedir = (GFile *)object;
+  g_autoptr(GbpGradleTestProvider) self = user_data;
+  g_autoptr(GPtrArray) files = NULL;
+  g_autoptr(GError) error = NULL;
+
+  IDE_ENTRY;
+
+  g_assert (G_IS_FILE (basedir));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (GBP_IS_GRADLE_TEST_PROVIDER (self));
+
+  if (!(files = ide_g_file_find_finish (basedir, result, &error)))
+    {
+      g_debug ("Failed to find test files: %s", error->message);
+      IDE_GOTO (failure);
+    }
+
+  ide_test_provider_clear (IDE_TEST_PROVIDER (self));
+
+  for (guint i = 0; i < files->len; i++)
+    {
+      GFile *file = g_ptr_array_index (files, i);
+      g_autofree char *contents = NULL;
+      IdeLineReader reader;
+      char *line;
+      gsize line_len;
+      gsize len;
+
+      if (!g_file_load_contents (file, NULL, &contents, &len, NULL, NULL))
+        continue;
+
+      /* Obviously this isn't a great way to find tests, but it
+       * does allow for skipping any sort of introspection. Mostly
+       * just copying what the python plugin did.
+       */
+      ide_line_reader_init (&reader, contents, len);
+      while ((line = ide_line_reader_next (&reader, &line_len)))
+        {
+          char *name;
+          char *paren;
+
+          line[line_len] = 0;
+
+          if (!(name = strstr (line, "public void")))
+            continue;
+
+          if (!(paren = strchr (name, '(')))
+            continue;
+
+          *paren = 0;
+          name += strlen ("public void");
+          g_strstrip (name);
+
+          gbp_gradle_test_provider_add (self, file, name);
+        }
+    }
+
+failure:
+  ide_test_provider_set_loading (IDE_TEST_PROVIDER (self), FALSE);
+
+  IDE_EXIT;
+}
+
+static void
+gbp_gradle_test_provider_reload (IdeTestProvider *provider)
+{
+  g_autofree char *project_dir = NULL;
+  g_autoptr(GFile) testdir = NULL;
+  IdeBuildSystem *build_system;
+  IdeContext *context;
+
+  IDE_ENTRY;
+
+  g_assert (GBP_IS_GRADLE_TEST_PROVIDER (provider));
+
+  context = ide_object_get_context (IDE_OBJECT (provider));
+  build_system = ide_build_system_from_context (context);
+
+  if (!GBP_IS_GRADLE_BUILD_SYSTEM (build_system))
+    IDE_EXIT;
+
+  if (ide_test_provider_get_loading (provider))
+    IDE_EXIT;
+
+  ide_test_provider_set_loading (provider, TRUE);
+
+  project_dir = gbp_gradle_build_system_get_project_dir (GBP_GRADLE_BUILD_SYSTEM (build_system));
+  testdir = g_file_new_build_filename (project_dir, "src", "test", "java", NULL);
+
+  ide_g_file_find_with_depth_async (testdir, "*.java", 5,
+                                    NULL,
+                                    find_test_files_cb,
+                                    g_object_ref (provider));
+
+  IDE_EXIT;
+}
+
+static void
+gbp_gradle_test_provider_run_cb (GObject      *object,
+                                 GAsyncResult *result,
+                                 gpointer      user_data)
+{
+  IdeRunner *runner = (IdeRunner *)object;
+  g_autoptr(IdeTask) task = user_data;
+  g_autoptr(GError) error = NULL;
+  IdeTest *test;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_RUNNER (runner));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (IDE_IS_TASK (task));
+
+  test = ide_task_get_task_data (task);
+
+  if (!ide_runner_run_finish (runner, result, &error))
+    {
+      ide_test_set_status (test, IDE_TEST_STATUS_FAILED);
+      ide_task_return_error (task, g_steal_pointer (&error));
+    }
+  else
+    {
+      ide_test_set_status (test, IDE_TEST_STATUS_SUCCESS);
+      ide_task_return_boolean (task, TRUE);
+    }
+
+  IDE_EXIT;
+}
+
+static void
+gbp_gradle_test_provider_run_async (IdeTestProvider     *provider,
+                                    IdeTest             *test,
+                                    IdePipeline         *pipeline,
+                                    VtePty              *pty,
+                                    GCancellable        *cancellable,
+                                    GAsyncReadyCallback  callback,
+                                    gpointer             user_data)
+{
+  g_autoptr(IdeRunner) runner = NULL;
+  g_autoptr(IdeTask) task = NULL;
+  const char *suite_name;
+  IdeRuntime *runtime;
+
+  IDE_ENTRY;
+
+  g_assert (GBP_IS_GRADLE_TEST_PROVIDER (provider));
+  g_assert (GBP_IS_GRADLE_TEST (test));
+  g_assert (IDE_IS_PIPELINE (pipeline));
+  g_assert (!pty || VTE_IS_PTY (pty));
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = ide_task_new (provider, cancellable, callback, user_data);
+  ide_task_set_source_tag (task, gbp_gradle_test_provider_run_async);
+  ide_task_set_task_data (task, g_object_ref (test), g_object_unref);
+
+  suite_name = gbp_gradle_test_get_suite_name (GBP_GRADLE_TEST (test));
+
+  if (!(runtime = ide_pipeline_get_runtime (pipeline)) ||
+      !(runner = ide_runtime_create_runner (runtime, NULL)))
+    IDE_GOTO (failure);
+
+  if (pty != NULL)
+    ide_runner_set_pty (runner, pty);
+
+  ide_runner_set_cwd (runner, ide_pipeline_get_srcdir (pipeline));
+  ide_runner_push_args (runner, IDE_STRV_INIT ("./gradlew", "test", "--tests", suite_name));
+
+  ide_test_set_status (test, IDE_TEST_STATUS_RUNNING);
+
+  ide_runner_run_async (runner,
+                        cancellable,
+                        gbp_gradle_test_provider_run_cb,
+                        g_steal_pointer (&task));
+
+  IDE_EXIT;
+
+failure:
+  ide_task_return_new_error (task,
+                             G_IO_ERROR,
+                             G_IO_ERROR_FAILED,
+                             "Failed to run test: %s",
+                             gbp_gradle_test_get_suite_name (GBP_GRADLE_TEST (test)));
+
+  IDE_EXIT;
+}
+
+static gboolean
+gbp_gradle_test_provider_run_finish (IdeTestProvider  *provider,
+                                     GAsyncResult     *result,
+                                     GError          **error)
+{
+  gboolean ret;
+
+  IDE_ENTRY;
+
+  g_assert (GBP_IS_GRADLE_TEST_PROVIDER (provider));
+  g_assert (G_IS_ASYNC_RESULT (result));
+
+  ret = ide_task_propagate_boolean (IDE_TASK (result), error);
+
+  IDE_RETURN (ret);
+}
+
+static void
+gbp_gradle_test_provider_class_init (GbpGradleTestProviderClass *klass)
+{
+  IdeTestProviderClass *test_provider_class = IDE_TEST_PROVIDER_CLASS (klass);
+
+  test_provider_class->reload = gbp_gradle_test_provider_reload;
+  test_provider_class->run_async = gbp_gradle_test_provider_run_async;
+  test_provider_class->run_finish = gbp_gradle_test_provider_run_finish;
+}
+
+static void
+gbp_gradle_test_provider_init (GbpGradleTestProvider *self)
+{
+}
diff --git a/src/plugins/gradle/gbp-gradle-test-provider.h b/src/plugins/gradle/gbp-gradle-test-provider.h
new file mode 100644
index 000000000..10666192d
--- /dev/null
+++ b/src/plugins/gradle/gbp-gradle-test-provider.h
@@ -0,0 +1,31 @@
+/* gbp-gradle-test-provider.h
+ *
+ * Copyright 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
+ * 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libide-core.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_GRADLE_TEST_PROVIDER (gbp_gradle_test_provider_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpGradleTestProvider, gbp_gradle_test_provider, GBP, GRADLE_TEST_PROVIDER, IdeObject)
+
+G_END_DECLS
diff --git a/src/plugins/gradle/gbp-gradle-test.c b/src/plugins/gradle/gbp-gradle-test.c
new file mode 100644
index 000000000..9dd56f3a2
--- /dev/null
+++ b/src/plugins/gradle/gbp-gradle-test.c
@@ -0,0 +1,72 @@
+/* gbp-gradle-test.c
+ *
+ * Copyright 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
+ * 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-gradle-test"
+
+#include "config.h"
+
+#include "gbp-gradle-test.h"
+
+struct _GbpGradleTest
+{
+  IdeTest parent_instance;
+  char *suite_name;
+};
+
+G_DEFINE_FINAL_TYPE (GbpGradleTest, gbp_gradle_test, IDE_TYPE_TEST)
+
+static void
+gbp_gradle_test_finalize (GObject *object)
+{
+  GbpGradleTest *self = (GbpGradleTest *)object;
+
+  g_clear_pointer (&self->suite_name, g_free);
+
+  G_OBJECT_CLASS (gbp_gradle_test_parent_class)->finalize (object);
+}
+
+static void
+gbp_gradle_test_class_init (GbpGradleTestClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gbp_gradle_test_finalize;
+}
+
+static void
+gbp_gradle_test_init (GbpGradleTest *self)
+{
+}
+
+GbpGradleTest *
+gbp_gradle_test_new (const char *suite_name)
+{
+  GbpGradleTest *self = g_object_new (GBP_TYPE_GRADLE_TEST, NULL);
+  self->suite_name = g_strdup (suite_name);
+  return self;
+}
+
+const char *
+gbp_gradle_test_get_suite_name (GbpGradleTest *self)
+{
+  g_return_val_if_fail (GBP_IS_GRADLE_TEST (self), NULL);
+
+  return self->suite_name;
+}
diff --git a/src/plugins/gradle/gbp-gradle-test.h b/src/plugins/gradle/gbp-gradle-test.h
new file mode 100644
index 000000000..6f1c26419
--- /dev/null
+++ b/src/plugins/gradle/gbp-gradle-test.h
@@ -0,0 +1,34 @@
+/* gbp-gradle-test.h
+ *
+ * Copyright 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
+ * 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libide-foundry.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_GRADLE_TEST (gbp_gradle_test_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpGradleTest, gbp_gradle_test, GBP, GRADLE_TEST, IdeTest)
+
+GbpGradleTest *gbp_gradle_test_new            (const char    *suite_name);
+const char    *gbp_gradle_test_get_suite_name (GbpGradleTest *self);
+
+G_END_DECLS
diff --git a/src/plugins/gradle/gradle-plugin.c b/src/plugins/gradle/gradle-plugin.c
index a2b54497e..f4cc251ce 100644
--- a/src/plugins/gradle/gradle-plugin.c
+++ b/src/plugins/gradle/gradle-plugin.c
@@ -30,6 +30,7 @@
 #include "gbp-gradle-build-system-discovery.h"
 #include "gbp-gradle-pipeline-addin.h"
 #include "gbp-gradle-run-command-provider.h"
+#include "gbp-gradle-test-provider.h"
 
 _IDE_EXTERN void
 _gbp_gradle_register_types (PeasObjectModule *module)
@@ -46,4 +47,7 @@ _gbp_gradle_register_types (PeasObjectModule *module)
   peas_object_module_register_extension_type (module,
                                               IDE_TYPE_RUN_COMMAND_PROVIDER,
                                               GBP_TYPE_GRADLE_RUN_COMMAND_PROVIDER);
+  peas_object_module_register_extension_type (module,
+                                              IDE_TYPE_TEST_PROVIDER,
+                                              GBP_TYPE_GRADLE_TEST_PROVIDER);
 }
diff --git a/src/plugins/gradle/meson.build b/src/plugins/gradle/meson.build
index 5001ebddd..57a4b3300 100644
--- a/src/plugins/gradle/meson.build
+++ b/src/plugins/gradle/meson.build
@@ -6,6 +6,8 @@ plugins_sources += files([
   'gbp-gradle-build-system.c',
   'gbp-gradle-pipeline-addin.c',
   'gbp-gradle-run-command-provider.c',
+  'gbp-gradle-test.c',
+  'gbp-gradle-test-provider.c',
 ])
 
 plugin_gradle_resources = gnome.compile_resources(


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