Commit f1543fca authored by Tristan Van Berkom's avatar Tristan Van Berkom
Browse files

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.
parent fc0ea5ea
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 \
......
......@@ -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
])
......
......@@ -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);
......
......@@ -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;
......
......@@ -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)
......
......@@ -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 (),
......
......@@ -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));
}
}
}
......
......@@ -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);
}
......
......@@ -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
......
......@@ -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;
......
......@@ -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"/>
......
......@@ -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"/>
......
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)
#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 ();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment