[gtk/wip/matthiasc/focus2: 39/41] Add a focus-chain test



commit 5a182463ca45758ac8740ecad0198029f2c0597c
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Mar 4 18:08:18 2019 -0500

    Add a focus-chain test
    
    This test takes ui files and compares the focus chain
    with the expected output, as usual. ui files go in
    the testsuite/gtk/focus-chain directory, and expected
    output in the form of one widget ID per line goes
    in .txt files.

 testsuite/gtk/focus-chain/focus.test.in |   4 +
 testsuite/gtk/focus-chain/meson.build   |  34 ++++
 testsuite/gtk/focus-chain/notebook.txt  |   2 +
 testsuite/gtk/focus-chain/notebook.ui   |  37 ++++
 testsuite/gtk/focus-chain/test-focus.c  | 297 ++++++++++++++++++++++++++++++++
 testsuite/gtk/meson.build               |   2 +
 6 files changed, 376 insertions(+)
---
diff --git a/testsuite/gtk/focus-chain/focus.test.in b/testsuite/gtk/focus-chain/focus.test.in
new file mode 100644
index 0000000000..2b15a4cf0a
--- /dev/null
+++ b/testsuite/gtk/focus-chain/focus.test.in
@@ -0,0 +1,4 @@
+[Test]
+Exec=@libexecdir@/installed-tests/gtk-4.0/gtk/focus/test-focus --tap -k
+Type=session
+Output=TAP
diff --git a/testsuite/gtk/focus-chain/meson.build b/testsuite/gtk/focus-chain/meson.build
new file mode 100644
index 0000000000..4de0970d37
--- /dev/null
+++ b/testsuite/gtk/focus-chain/meson.build
@@ -0,0 +1,34 @@
+testexecdir = join_paths(installed_test_bindir, 'gtk', 'focus-chain')
+testdatadir = join_paths(installed_test_datadir, 'gtk', 'focus-chain')
+
+test_nodes = executable('test-focus', 'test-focus.c',
+                        install: get_option('install-tests'),
+                        install_dir: testexecdir,
+                        dependencies: libgtk_dep)
+test('nodes', test_nodes,
+     args: [ '--tap', '-k' ],
+     env: [ 'GIO_USE_VOLUME_MONITOR=unix',
+            'GSETTINGS_BACKEND=memory',
+            'GTK_CSD=1',
+            'G_ENABLE_DIAGNOSTIC=0',
+            'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
+            'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir())
+          ],
+     suite: 'css')
+
+test_data = [
+  'widget-factory.ui',
+  'widget-factory.txt',
+]
+
+if get_option('install-tests')
+  conf = configuration_data()
+  conf.set('libexecdir', gtk_libexecdir)
+  configure_file(input: 'focus.test.in',
+                 output: 'focus.test',
+                 configuration: conf,
+                 install_dir: testdatadir)
+
+  install_data(test_data, install_dir: testexecdir)
+
+endif
diff --git a/testsuite/gtk/focus-chain/notebook.txt b/testsuite/gtk/focus-chain/notebook.txt
new file mode 100644
index 0000000000..3fb79f17b0
--- /dev/null
+++ b/testsuite/gtk/focus-chain/notebook.txt
@@ -0,0 +1,2 @@
+notebook1
+page1
diff --git a/testsuite/gtk/focus-chain/notebook.ui b/testsuite/gtk/focus-chain/notebook.ui
new file mode 100644
index 0000000000..e18759ca42
--- /dev/null
+++ b/testsuite/gtk/focus-chain/notebook.ui
@@ -0,0 +1,37 @@
+<interface>
+  <object class="GtkWindow" id="window1">
+    <property name="type">popup</property>
+    <child>
+      <object class="GtkNotebook" id="notebook1">
+        <child>
+          <object class="GtkNotebookPage">
+            <property name="child">
+              <object class="GtkButton" id="page1">
+                <property name="label" translatable="yes">Yes</property>
+              </object>
+            </property>
+            <property name="tab">
+              <object class="GtkLabel" id="tab1">
+                <property name="label" translatable="yes">Tab 1</property>
+              </object>
+            </property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkNotebookPage">
+            <property name="child">
+              <object class="GtkButton" id="page2">
+                <property name="label" translatable="yes">No</property>
+              </object>
+            </property>
+            <property name="tab">
+              <object class="GtkLabel" id="tab2">
+                <property name="label" translatable="yes">Tab 2</property>
+              </object>
+            </property>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/testsuite/gtk/focus-chain/test-focus.c b/testsuite/gtk/focus-chain/test-focus.c
new file mode 100644
index 0000000000..468d0f4c5f
--- /dev/null
+++ b/testsuite/gtk/focus-chain/test-focus.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2019 Red Hat Inc.
+ *
+ * Author:
+ *      Matthias Clasen <mclasen redhat com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <glib/gstdio.h>
+#include <gtk/gtk.h>
+
+#ifdef G_OS_WIN32
+# include <io.h>
+#endif
+
+
+static char *
+test_get_reference_file (const char *ui_file)
+{
+  GString *file = g_string_new (NULL);
+
+  if (g_str_has_suffix (ui_file, ".ui"))
+    g_string_append_len (file, ui_file, strlen (ui_file) - 3);
+  else
+    g_string_append (file, ui_file);
+
+  g_string_append (file, ".txt");
+
+  if (!g_file_test (file->str, G_FILE_TEST_EXISTS))
+    {
+      g_string_free (file, TRUE);
+      return g_strdup (ui_file);
+    }
+
+  return g_string_free (file, FALSE);
+}
+
+static char *
+diff_with_file (const char  *file1,
+                char        *text,
+                gssize       len,
+                GError     **error)
+{
+  const char *command[] = { "diff", "-u", file1, NULL, NULL };
+  char *diff, *tmpfile;
+  int fd;
+
+  diff = NULL;
+
+  if (len < 0)
+    len = strlen (text);
+
+  /* write the text buffer to a temporary file */
+  fd = g_file_open_tmp (NULL, &tmpfile, error);
+  if (fd < 0)
+    return NULL;
+
+  if (write (fd, text, len) != (int) len)
+    {
+      close (fd);
+      g_set_error (error,
+                   G_FILE_ERROR, G_FILE_ERROR_FAILED,
+                   "Could not write data to temporary file '%s'", tmpfile);
+      goto done;
+    }
+  close (fd);
+  command[3] = tmpfile;
+
+  /* run diff command */
+  g_spawn_sync (NULL,
+                (char **) command,
+                NULL,
+                G_SPAWN_SEARCH_PATH,
+                NULL, NULL,
+                &diff,
+                NULL, NULL,
+                error);
+
+done:
+  g_unlink (tmpfile);
+  g_free (tmpfile);
+
+  return diff;
+}
+
+static char *
+generate_output (GtkWidget *window)
+{
+  GString *s = g_string_new ("");
+  GtkWidget *initial_focus;
+  GtkWidget *f;
+
+  initial_focus = gtk_root_get_focus (GTK_ROOT (window));
+  if (initial_focus == NULL)
+    {
+      g_string_append (s, "NULL\n");
+      initial_focus = gtk_widget_get_next_focus (window, GTK_DIR_TAB_FORWARD);
+    }
+
+  f = initial_focus;
+  while (f)
+    {
+      const char *name = gtk_buildable_get_name (GTK_BUILDABLE (f));
+      if (name == NULL)
+        name = G_OBJECT_TYPE_NAME (f);
+      g_string_append_printf (s, "%s\n", name); 
+      f = gtk_widget_get_next_focus (f, GTK_DIR_TAB_FORWARD);
+      if (f == initial_focus)
+        break;
+    }
+
+  if (f == NULL)
+    g_string_append (s, "NULL\n");
+
+  return g_string_free (s, FALSE);
+}
+
+static void
+load_ui_file (GFile *file, gboolean generate)
+{
+  GtkBuilder *builder;
+  GtkWidget *window;
+  char *output, *diff;
+  char *ui_file, *reference_file;
+  GError *error = NULL;
+
+  ui_file = g_file_get_path (file);
+
+  builder = gtk_builder_new_from_file (ui_file);
+  window = GTK_WIDGET (gtk_builder_get_object (builder, "window1"));
+
+  g_assert (window != NULL);
+
+  gtk_widget_show (window);
+
+  output = generate_output (window);
+
+  if (generate)
+    {
+      g_print ("%s", output);
+      goto out;
+    }
+
+  reference_file = test_get_reference_file (ui_file);
+
+  diff = diff_with_file (reference_file, output, -1, &error);
+  g_assert_no_error (error);
+
+  if (diff && diff[0])
+    {
+      g_test_message ("Resulting output doesn't match reference:\n%s", diff);
+      g_test_fail ();
+    }
+  g_free (reference_file);
+  g_free (diff);
+
+out:
+  g_free (output);
+  g_free (ui_file);
+}
+
+static void
+test_ui_file (GFile *file)
+{
+  load_ui_file (file, FALSE);
+}
+
+static void
+add_test_for_file (GFile *file)
+{
+  char *path;
+
+  path = g_file_get_path (file);
+
+  g_test_add_vtable (path,
+                     0,
+                     g_object_ref (file),
+                     NULL,
+                     (GTestFixtureFunc) test_ui_file,
+                     (GTestFixtureFunc) g_object_unref);
+
+  g_free (path);
+}
+
+static int
+compare_files (gconstpointer a, gconstpointer b)
+{
+  GFile *file1 = G_FILE (a);
+  GFile *file2 = G_FILE (b);
+  char *path1, *path2;
+  int result;
+
+  path1 = g_file_get_path (file1);
+  path2 = g_file_get_path (file2);
+
+  result = strcmp (path1, path2);
+
+  g_free (path1);
+  g_free (path2);
+
+  return result;
+}
+
+static void
+add_tests_for_files_in_directory (GFile *dir)
+{
+  GFileEnumerator *enumerator;
+  GFileInfo *info;
+  GList *files;
+  GError *error = NULL;
+
+  enumerator = g_file_enumerate_children (dir, G_FILE_ATTRIBUTE_STANDARD_NAME, 0, NULL, &error);
+  g_assert_no_error (error);
+  files = NULL;
+
+  while ((info = g_file_enumerator_next_file (enumerator, NULL, &error)))
+    {
+      const char *filename;
+
+      filename = g_file_info_get_name (info);
+
+      if (!g_str_has_suffix (filename, ".ui") ||
+          g_str_has_suffix (filename, ".txt"))
+        {
+          g_object_unref (info);
+          continue;
+        }
+
+      files = g_list_prepend (files, g_file_get_child (dir, filename));
+
+      g_object_unref (info);
+    }
+
+  g_assert_no_error (error);
+  g_object_unref (enumerator);
+
+  files = g_list_sort (files, compare_files);
+  g_list_foreach (files, (GFunc) add_test_for_file, NULL);
+  g_list_free_full (files, g_object_unref);
+}
+
+int
+main (int argc, char *argv[])
+{
+  gtk_test_init (&argc, &argv);
+
+  if (argc < 2)
+    {
+      const char *basedir;
+      GFile *dir;
+
+      basedir = g_test_get_dir (G_TEST_DIST);
+      dir = g_file_new_for_path (basedir);
+      add_tests_for_files_in_directory (dir);
+
+      g_object_unref (dir);
+    }
+  else if (strcmp (argv[1], "--generate") == 0)
+    {
+      if (argc >= 3)
+        {
+          GFile *file = g_file_new_for_commandline_arg (argv[2]);
+
+          load_ui_file (file, TRUE);
+
+          g_object_unref (file);
+        }
+    }
+  else
+    {
+      guint i;
+
+      for (i = 1; i < argc; i++)
+        {
+          GFile *file = g_file_new_for_commandline_arg (argv[i]);
+
+          add_test_for_file (file);
+
+          g_object_unref (file);
+        }
+    }
+
+  return g_test_run ();
+}
diff --git a/testsuite/gtk/meson.build b/testsuite/gtk/meson.build
index c02e4ab177..1eb5994538 100644
--- a/testsuite/gtk/meson.build
+++ b/testsuite/gtk/meson.build
@@ -1,3 +1,5 @@
+subdir('focus-chain')
+
 testexecdir = join_paths(installed_test_bindir, 'gtk')
 testdatadir = join_paths(installed_test_datadir, 'gtk')
 


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