[glade] Added Glade's first unit test (about time !)



commit f1543fca9174f965cbe19db8a0fa0e8f5f5a3ff8
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date:   Fri Apr 5 01:13:56 2013 +0900

    Added Glade's first unit test (about time !)
    
    This patch clears the way for unit testing, some environment variables
    are added to ensure unit tests run on code that is not installed but
    in tree.
    
    The added test iterates over all widgets in the catalog, uses the
    adaptor to create a GladeWidget and asserts that the GladeWidget and
    it's internal object is finalized after unreferencing the GladeWidget.

 Makefile.am                      |    2 +-
 configure.ac                     |    9 +++
 gladeui/glade-app.c              |   14 ++++-
 gladeui/glade-app.h              |    6 +-
 gladeui/glade-catalog.c          |   15 +++--
 gladeui/glade-utils.c            |    2 +-
 gladeui/glade-widget-adaptor.c   |    7 +-
 plugins/gtk+/glade-gtk-grid.c    |    5 +-
 plugins/gtk+/glade-gtk-table.c   |    4 +-
 plugins/gtk+/glade-gtk.c         |    9 ++-
 plugins/gtk+/gtk+.xml.in         |    4 +-
 plugins/gtk+/gtkunixprint.xml.in |    1 +
 tests/Makefile.am                |   30 ++++++++++
 tests/create-widgets.c           |  117 ++++++++++++++++++++++++++++++++++++++
 14 files changed, 202 insertions(+), 23 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 43de26e..f3bd3bf 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
 ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
 
-SUBDIRS = po data gladeui src plugins doc help
+SUBDIRS = po data gladeui src plugins tests doc help
 
 EXTRA_DIST = \
        autogen.sh \
diff --git a/configure.ac b/configure.ac
index 5621eec..b006306 100644
--- a/configure.ac
+++ b/configure.ac
@@ -256,6 +256,14 @@ dnl ================================================================
 AC_CHECK_FUNCS(gtk_builder_add_from_resource)
 
 
+dnl ================================================================
+dnl Testing environment
+dnl ================================================================
+GLADE_TEST_ENVIRONMENT='GLADE_TESTING=1 GLADE_PIXMAP_DIR=$(top_builddir)/data/icons 
GLADE_CATALOG_SEARCH_PATH=$(top_builddir)/plugins/gtk+ 
GLADE_MODULE_SEARCH_PATH=$(top_builddir)/plugins/gtk+/.libs'
+AC_SUBST(GLADE_TEST_ENVIRONMENT)
+
+
+
 AC_SUBST([GLADE_PREFIX])
 
 
@@ -298,6 +306,7 @@ po/Makefile.in
 doc/Makefile
 doc/version.xml
 help/Makefile
+tests/Makefile
 build/mingw-w64/glade.nsi
 ])
 
diff --git a/gladeui/glade-app.c b/gladeui/glade-app.c
index c9d6726..1ccf3ff 100644
--- a/gladeui/glade-app.c
+++ b/gladeui/glade-app.c
@@ -165,6 +165,12 @@ glade_app_finalize (GObject * app)
 static void
 build_package_paths (void)
 {
+  const gchar *path;
+
+  path = g_getenv (GLADE_ENV_PIXMAP_DIR);
+  if (path)
+    pixmaps_dir = g_strdup (path);
+
 #if defined (G_OS_WIN32) || (defined (MAC_INTEGRATION) && defined (MAC_BUNDLE))
   gchar *prefix;
 
@@ -176,7 +182,9 @@ build_package_paths (void)
 
 # endif
 
-  pixmaps_dir = g_build_filename (prefix, "share", PACKAGE, "pixmaps", NULL);
+  if (!pixmaps_dir)
+    pixmaps_dir = g_build_filename (prefix, "share", PACKAGE, "pixmaps", NULL);
+
   catalogs_dir = g_build_filename (prefix, "share", PACKAGE, "catalogs", NULL);
   modules_dir = g_build_filename (prefix, "lib", PACKAGE, "modules", NULL);
   locale_dir = g_build_filename (prefix, "share", "locale", NULL);
@@ -187,7 +195,9 @@ build_package_paths (void)
 #else
   catalogs_dir = g_strdup (GLADE_CATALOGSDIR);
   modules_dir = g_strdup (GLADE_MODULESDIR);
-  pixmaps_dir = g_strdup (GLADE_PIXMAPSDIR);
+
+  if (!pixmaps_dir)
+    pixmaps_dir = g_strdup (GLADE_PIXMAPSDIR);
   locale_dir = g_strdup (GLADE_LOCALEDIR);
   bin_dir = g_strdup (GLADE_BINDIR);
   lib_dir = g_strdup (GLADE_LIBDIR);
diff --git a/gladeui/glade-app.h b/gladeui/glade-app.h
index 6f10be0..29a8c57 100644
--- a/gladeui/glade-app.h
+++ b/gladeui/glade-app.h
@@ -36,8 +36,10 @@ G_BEGIN_DECLS
 #define GLADE_IS_APP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GLADE_TYPE_APP))
 #define GLADE_APP_GET_CLASS(o)    (G_TYPE_INSTANCE_GET_CLASS ((o), GLADE_APP, GladeAppClass))
 
-#define GLADE_ENV_CATALOG_PATH    "GLADE_CATALOG_SEARCH_PATH"
-#define GLADE_ENV_MODULE_PATH     "GLADE_MODULE_SEARCH_PATH"
+#define GLADE_ENV_CATALOG_PATH     "GLADE_CATALOG_SEARCH_PATH"
+#define GLADE_ENV_MODULE_PATH      "GLADE_MODULE_SEARCH_PATH"
+#define GLADE_ENV_TESTING          "GLADE_TESTING"
+#define GLADE_ENV_PIXMAP_DIR       "GLADE_PIXMAP_DIR"
 
 typedef struct _GladeApp         GladeApp;
 typedef struct _GladeAppPrivate  GladeAppPrivate;
diff --git a/gladeui/glade-catalog.c b/gladeui/glade-catalog.c
index 9596b33..0237bec 100644
--- a/gladeui/glade-catalog.c
+++ b/gladeui/glade-catalog.c
@@ -598,7 +598,8 @@ glade_catalog_load_all (void)
     }
 
   /* ... Then load catalogs from standard install directory */
-  catalogs = catalogs_from_path (catalogs, glade_app_get_catalogs_dir ());
+  if (g_getenv (GLADE_ENV_TESTING) == NULL)
+    catalogs = catalogs_from_path (catalogs, glade_app_get_catalogs_dir ());
 
   /* And then load catalogs from extra paths */
   for (l = catalog_paths; l; l = g_list_next (l))
@@ -631,20 +632,22 @@ glade_catalog_load_all (void)
     {
       GladeWidgetAdaptor *adaptor = l->data;
 
-      if (glade_widget_adaptor_get_missing_icon (adaptor))
+      /* Dont print missing icons in unit tests */
+      if (glade_widget_adaptor_get_missing_icon (adaptor) &&
+         g_getenv (GLADE_ENV_TESTING) == NULL)
         {
           if (!icon_warning)
             icon_warning = g_string_new ("Glade needs artwork; "
                                          "a default icon will be used for "
                                          "the following classes:");
 
-          g_string_append_printf (icon_warning,
-                                  "\n\t%s\tneeds an icon named '%s'",
-                                  glade_widget_adaptor_get_name (adaptor), 
+         g_string_append_printf (icon_warning,
+                                 "\n\t%s\tneeds an icon named '%s'",
+                                 glade_widget_adaptor_get_name (adaptor), 
                                  glade_widget_adaptor_get_missing_icon (adaptor));
         }
-
     }
+
   g_list_free (adaptors);
 
   if (icon_warning)
diff --git a/gladeui/glade-utils.c b/gladeui/glade-utils.c
index a9f866f..570cd7e 100644
--- a/gladeui/glade-utils.c
+++ b/gladeui/glade-utils.c
@@ -901,7 +901,7 @@ glade_util_load_library (const gchar *library_name)
         }
     }
 
-  if (!module)
+  if (g_getenv (GLADE_ENV_TESTING) == NULL && !module)
     {
       const gchar *paths[] = { glade_app_get_modules_dir (),
                                glade_app_get_lib_dir (),
diff --git a/gladeui/glade-widget-adaptor.c b/gladeui/glade-widget-adaptor.c
index 38f8ee8..1d7d172 100644
--- a/gladeui/glade-widget-adaptor.c
+++ b/gladeui/glade-widget-adaptor.c
@@ -2478,9 +2478,10 @@ gwa_displayable_values_check (GladeWidgetAdaptor *adaptor, gboolean packing)
           pspec->value_type != GLADE_TYPE_STOCK_IMAGE)
         {
           /* We do not need displayable values if the property is not visible */
-          g_message ("No displayable values for %sproperty %s::%s",
-                     (packing) ? "child " : "", adaptor->priv->name, 
-                    glade_property_class_id (klass));
+         if (g_getenv (GLADE_ENV_TESTING) == NULL)
+           g_message ("No displayable values for %sproperty %s::%s",
+                      (packing) ? "child " : "", adaptor->priv->name, 
+                      glade_property_class_id (klass));
         }
     }
 }
diff --git a/plugins/gtk+/glade-gtk-grid.c b/plugins/gtk+/glade-gtk-grid.c
index d5a5900..3204d39 100644
--- a/plugins/gtk+/glade-gtk-grid.c
+++ b/plugins/gtk+/glade-gtk-grid.c
@@ -103,7 +103,7 @@ glade_gtk_grid_refresh_placeholders (GtkGrid *grid,
   project = glade_widget_get_project (widget);
 
   /* Wait for project to finish loading */
-  if (glade_project_is_loading (project) && !load_finished)
+  if ((project && glade_project_is_loading (project)) && !load_finished)
     return;
 
   glade_widget_property_get (widget, "n-columns", &n_columns);
@@ -127,7 +127,8 @@ glade_gtk_grid_refresh_placeholders (GtkGrid *grid,
       if (glade_gtk_grid_has_child (grid, children, i, j) == FALSE)
         gtk_grid_attach (grid, glade_placeholder_new (), i, j, 1, 1);
 
-  gtk_container_check_resize (container);
+  if (gtk_widget_get_realized (GTK_WIDGET (grid)))
+    gtk_container_check_resize (container);
   g_list_free (children);
 }
 
diff --git a/plugins/gtk+/glade-gtk-table.c b/plugins/gtk+/glade-gtk-table.c
index 169bddf..69838da 100644
--- a/plugins/gtk+/glade-gtk-table.c
+++ b/plugins/gtk+/glade-gtk-table.c
@@ -175,7 +175,9 @@ glade_gtk_table_refresh_placeholders (GtkTable * table)
     }
   g_free(child_map);
   g_free(placeholder_map);
-  gtk_container_check_resize (GTK_CONTAINER (table));
+
+  if (gtk_widget_get_realized (GTK_WIDGET (table)))
+    gtk_container_check_resize (GTK_CONTAINER (table));
 }
 
 static void
diff --git a/plugins/gtk+/glade-gtk.c b/plugins/gtk+/glade-gtk.c
index 28e0a62..988c46f 100644
--- a/plugins/gtk+/glade-gtk.c
+++ b/plugins/gtk+/glade-gtk.c
@@ -7441,9 +7441,10 @@ glade_gtk_assistant_post_create (GladeWidgetAdaptor * adaptor,
       glade_widget_property_set (parent, "n-pages", 3);
     }
 
-  g_signal_connect (project, "selection-changed",
-                    G_CALLBACK (on_assistant_project_selection_changed),
-                    parent);
+  if (project)
+    g_signal_connect (project, "selection-changed",
+                     G_CALLBACK (on_assistant_project_selection_changed),
+                     parent);
 }
 
 void
@@ -8270,7 +8271,7 @@ glade_gtk_cell_renderer_sync_attributes (GObject * object)
 
   GtkCellLayout *layout;
   GtkCellRenderer *cell;
-  GladeWidget *widget = glade_widget_get_from_gobject (object);
+  GladeWidget *widget;
   GladeWidget *parent;
   GladeWidget *gmodel;
   GladeProperty *property;
diff --git a/plugins/gtk+/gtk+.xml.in b/plugins/gtk+/gtk+.xml.in
index 789f913..4282b98 100644
--- a/plugins/gtk+/gtk+.xml.in
+++ b/plugins/gtk+/gtk+.xml.in
@@ -19,6 +19,7 @@
       <write-widget-function>glade_gtk_widget_write_widget</write-widget-function>
       <create-editor-property-function>glade_gtk_widget_create_eprop</create-editor-property-function>
       <string-from-value-function>glade_gtk_widget_string_from_value</string-from-value-function>
+      <destroy-object-function>glade_gtk_widget_destroy_widget</destroy-object-function>
 
       <signals>
        <signal id="drag-failed" since="2.12"/>
@@ -3768,9 +3769,10 @@ embedded in another object</_tooltip>
       </properties>
     </glade-widget-class>
 
-
     <glade-widget-class name="GtkStatusIcon" generic-name="statusicon" _title="Status Icon" toplevel="True">
       <properties>
+       <property id="visible" default="False"/>
+       <property id="screen" disabled="True"/>
        <property id="gicon" disabled="True" since="2.14"/>
        <property id="title" since="2.18" translatable="True"/>
        <property id="tooltip-text" since="2.16" translatable="True"/>
diff --git a/plugins/gtk+/gtkunixprint.xml.in b/plugins/gtk+/gtkunixprint.xml.in
index 63006a1..a029cff 100644
--- a/plugins/gtk+/gtkunixprint.xml.in
+++ b/plugins/gtk+/gtkunixprint.xml.in
@@ -9,6 +9,7 @@
     <glade-widget-class name="GtkPageSetupUnixDialog" generic-name="pagesetupdialog" _title="Page Setup 
Dialog"/>
     <glade-widget-class name="GtkPrintUnixDialog" generic-name="printdialog" _title="Print Dialog">
       <properties>
+        <property id="page-setup" disabled="True"/>
         <property id="manual-capabilities">
          <displayable-values>
            <value id="GTK_PRINT_CAPABILITY_PAGE_SET" _name="Page Set"/>
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 0000000..e8b026d
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1,30 @@
+include $(top_srcdir)/glade-rules.mk
+
+noinst_PROGRAMS = $(TEST_PROGS)
+
+progs_cppflags = \
+       $(common_defines)   \
+       -I$(top_srcdir)     \
+       -I$(top_builddir)   \
+       $(GTK_CFLAGS)       \
+       $(GTK_MAC_BUNDLE_FLAG) \
+       $(GTK_MAC_CFLAGS)  \
+       $(WARN_CFLAGS)      \
+       $(AM_CPPFLAGS)
+
+progs_cflags = \
+       $(AM_CFLAGS)
+
+progs_libs  = $(GTK_LIBS) $(GTK_MAC_LIBS)
+progs_ldadd = $(top_builddir)/gladeui/libgladeui-2.la
+
+# Namespace expected names and naming exclusivity tests
+TEST_PROGS              = create-widgets
+create_widgets_CPPFLAGS = $(progs_cppflags)
+create_widgets_CFLAGS   = $(progs_cflags)
+create_widgets_LDFLAGS  = $(progs_libs)
+create_widgets_LDADD    = $(progs_ldadd)
+create_widgets_SOURCES  = create-widgets.c
+
+TESTS = $(TEST_PROGS)
+TESTS_ENVIRONMENT=$(GLADE_TEST_ENVIRONMENT)
diff --git a/tests/create-widgets.c b/tests/create-widgets.c
new file mode 100644
index 0000000..97e5e1a
--- /dev/null
+++ b/tests/create-widgets.c
@@ -0,0 +1,117 @@
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gladeui/glade-app.h>
+
+/* Avoid warnings from GVFS-RemoteVolumeMonitor */
+static gboolean
+ignore_gvfs_warning (const gchar *log_domain,
+                    GLogLevelFlags log_level,
+                    const gchar *message,
+                    gpointer user_data)
+{
+  if (g_strcmp0 (log_domain, "GVFS-RemoteVolumeMonitor") == 0)
+    return FALSE;
+
+  return TRUE;
+}
+
+static gboolean
+main_loop_quit_cb (gpointer data)
+{
+  gtk_main_quit ();
+
+  return FALSE;
+}
+
+static void
+check_finalized (gpointer data,
+                GObject *where_the_object_was)
+{
+  gboolean *did_finalize = (gboolean *)data;
+
+  *did_finalize = TRUE;
+}
+
+static void
+test_create_widget (gconstpointer data)
+{
+  GladeWidgetAdaptor *adaptor = (GladeWidgetAdaptor *)data;
+  GladeWidget        *widget;
+  GObject            *object;
+  gboolean            widget_finalized = FALSE;
+  gboolean            object_finalized = FALSE;
+
+  g_test_log_set_fatal_handler (ignore_gvfs_warning, NULL);
+
+
+  widget = glade_widget_adaptor_create_widget (adaptor, FALSE, NULL);
+  g_assert (GLADE_IS_WIDGET (widget));
+
+  object = glade_widget_get_object (widget);
+  g_assert (G_IS_OBJECT (object));
+
+  g_object_weak_ref (G_OBJECT (widget),  check_finalized, &widget_finalized);
+  g_object_weak_ref (G_OBJECT (object),  check_finalized, &object_finalized);
+
+  /* filechoosers hold a reference until an async operation is complete */
+  if (GTK_IS_FILE_CHOOSER (object))
+    {
+      g_timeout_add (500, main_loop_quit_cb, NULL);
+      gtk_main();
+    }
+  /* Our plugin code adds an idle when cell renderers are created */
+  else if (GTK_IS_CELL_RENDERER (object))
+    {
+      g_timeout_add (50, main_loop_quit_cb, NULL);
+      gtk_main();
+    }
+
+  /* Get rid of the GladeWidget and assert that it finalizes along 
+   * with it's internal object
+   */
+  g_object_unref (widget);
+
+  g_assert (widget_finalized);
+  g_assert (object_finalized);
+}
+
+int
+main (int   argc,
+      char *argv[])
+{
+  GList *adaptors, *l;
+
+  gtk_test_init (&argc, &argv, NULL);
+
+  glade_init ();
+  glade_app_get ();
+
+  adaptors = glade_widget_adaptor_list_adaptors ();
+
+  for (l = adaptors; l; l = l->next)
+    {
+      GladeWidgetAdaptor *adaptor = l->data;
+      GType               adaptor_type;
+
+      adaptor_type = glade_widget_adaptor_get_object_type (adaptor);
+
+      if (G_TYPE_IS_INSTANTIATABLE (adaptor_type) && !G_TYPE_IS_ABSTRACT (adaptor_type) &&
+         /* FIXME: Status Icon crashes at dispose time unrealizing it's GtkTrayIcon without a window */
+         adaptor_type != GTK_TYPE_STATUS_ICON &&
+         /* FIXME: Icon factory adds itself to the default but never removes itself */
+         adaptor_type != GTK_TYPE_ICON_FACTORY &&
+         /* FIXME: Combo box types dont finalize properly for some reason */
+         !g_type_is_a (adaptor_type, GTK_TYPE_COMBO_BOX) &&
+         /* FIXME: App choosers leak some async operations after finalization, causing subsequent tests to 
fail */
+         !g_type_is_a (adaptor_type, GTK_TYPE_APP_CHOOSER))
+       {
+         gchar *test_path = g_strdup_printf ("/CreateWidget/%s", glade_widget_adaptor_get_name (adaptor));
+
+         g_test_add_data_func (test_path, adaptor, test_create_widget);
+       }
+    }
+  g_list_free (adaptors);
+
+  return g_test_run ();
+}


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