Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorBenjamin Berg <benjamin@sipsolutions.net>2007-05-21 18:01:49 (GMT)
committer Benjamin Berg <benjamin@sipsolutions.net>2007-05-21 18:01:49 (GMT)
commitc361b6e1866e54cba68c1aa57790dd957ad45b01 (patch)
tree402e2ca1951d556fb42c84d935e4492b9a99ad74 /test
parent9c8f5151f48ecca4c75f2be9f5722f47ec0844a5 (diff)
Forgot to commit a large part of the testing code.
Diffstat (limited to 'test')
-rw-r--r--test/Makefile.am112
-rwxr-xr-xtest/exported25
-rw-r--r--test/gtkrcs/buildin7
-rw-r--r--test/gtkrcs/sugar49
-rwxr-xr-xtest/torture61
-rw-r--r--test/torturetest.c607
-rw-r--r--test/valgrind-suppressions54
7 files changed, 915 insertions, 0 deletions
diff --git a/test/Makefile.am b/test/Makefile.am
new file mode 100644
index 0000000..4ff6627
--- /dev/null
+++ b/test/Makefile.am
@@ -0,0 +1,112 @@
+# This Makefile and everything is based on code from gtk-engines.
+
+# We just have sugar in here ...
+BUILD_ENGINES = sugar
+
+# Initilize TESTS and XFAIL_TESTS
+TESTS =
+XFAIL_TESTS =
+
+GTKRCS = \
+ gtkrcs/buildin \
+ gtkrcs/sugar
+
+EXTRA_DIST = exported torture valgrind-suppressions $(GTKRCS)
+
+
+EXTRA_PROGRAMS = torturetest
+torturetest_CFLAGS = $(GTK2_CFLAGS)
+torturetest_LDFLAGS = $(GTK2_LIBS)
+
+
+
+# Setup enviroment variables for GTK+
+# ie. add $(top_builddir)/tests to the module searchpath, so that GTK+ finds
+# the engines in tests/engines
+TESTS_ENVIRONMENT=GTK_PATH="."
+
+VALGRIND_COMMAND=valgrind --leak-resolution=high --leak-check=full --suppressions=$(srcdir)/valgrind-suppressions --num-callers=20 --log-file-exactly=valgrind-logs/THEME
+# set some flags to make glib more valgrind friendly
+VALGRIND_ENV=G_SLICE=always-malloc G_DEBUG=gc-friendly,resident-modules
+
+#################################################################
+#################################################################
+
+#############################################################
+# Exported Symbols Test - Tests all engines unconditionally
+#############################################################
+# Prefix with exported_
+EXPORTED_SYMBOLS_TESTS = $(patsubst %,exported_%,$(BUILD_ENGINES))
+
+# The whole lua crap gets exported ... so right now it has to fail
+XFAIL_TESTS += exported_lua
+
+TESTS += $(EXPORTED_SYMBOLS_TESTS)
+
+
+#############################################################
+# Torture Test
+#############################################################
+SUPPORTED_TORTURE_TEST_ENGINES = \
+ sugar
+
+# Filter engines that are not build from the set of engines
+TORTURE_TEST_ENGINES = $(filter $(SUPPORTED_TORTURE_TEST_ENGINES),$(BUILD_ENGINES))
+# Prefix with torture_
+TORTURE_TEST_TESTS = torture_buildin $(patsubst %,torture_%,$(TORTURE_TEST_ENGINES))
+
+# Add TORTURE_TEST_ENGINES to list of tests
+TESTS += $(TORTURE_TEST_TESTS)
+
+# Possible other tests:
+# - An extensive theme switch tests that loads/unloads the engine
+# multiple times. A requirement here is that multiple rc styles need
+# to be merged. (ie. the test should find the recently fixed smooth
+# memory corruption)
+# - RC style merging? Don't think there is a way to do that.
+# - Maybe a visual test that looks for visible changes? That way one can
+# check that a modification does not break anything. (eg. when doing
+# code cleanups)
+# - I would love to have some coverage statistics for the torture test
+# anyone knows how to do that?
+
+#################################################################
+#################################################################
+
+engines:
+ -rm -rf engines
+ mkdir engines
+ cd engines; \
+ ln -s ../$(top_builddir)/gtk/engine/.libs/libsugar.so libsugar.so
+
+CLEANFILES = \
+ torture_buildin-failed \
+ $(EXTRA_PROGRAMS)
+
+clean-local:
+ -$(RM) torture_*
+ -$(RM) exported_*
+ -$(RM) -r engines
+ -$(RM) -r valgrind-logs
+ -$(RM) -r symbols
+
+valgrind-logs:
+ -$(RM) -r valgrind-logs
+ mkdir valgrind-logs
+
+symbols:
+ mkdir symbols
+
+torture_%: torture torturetest engines
+ cp $(srcdir)/torture $@
+
+exported_%: exported engines symbols
+ cp $(srcdir)/exported $@
+
+check-valgrind: valgrind-logs
+ $(MAKE) $(AM_MAKEFLAGS) check TESTS_ENVIRONMENT="$(TESTS_ENVIRONMENT) $(VALGRIND_ENV) EXEC_WRAPPER=\"$(VALGRIND_COMMAND)\""
+
+test:
+ @$(MAKE) $(AM_MAKEFLAGS) check
+
+.PHONY: engines valgrind-logs
diff --git a/test/exported b/test/exported
new file mode 100755
index 0000000..324f18f
--- /dev/null
+++ b/test/exported
@@ -0,0 +1,25 @@
+#! /bin/sh
+
+ALLOWED_SYMBOLS="\(g_module_check_init\|theme_create_rc_style\|theme_exit\|theme_init\)"
+
+# exit with status 77 if nm does not exist
+which nm >/dev/null || exit 77
+
+ENGINE="`basename $0 | cut -d '_' -f 2`"
+ENGINE_FILE="engines/lib$ENGINE.so"
+
+nm -gD --defined-only $ENGINE_FILE | cut -d ' ' -f 2,3 | cut -d ' ' -f 2 | grep -v '^_' | grep -v "$ALLOWED_SYMBOLS" >symbols/$ENGINE
+
+if [ -s symbols/$ENGINE ]; then
+ exit 1;
+else
+ if [ -f symbols/$ENGINE ]; then
+ # No point in keeping an empty file around
+ rm symbols/$ENGINE
+ else
+ # Something wen't wrong, there is no file?!?
+ # This should never happen ...
+ exit 1
+ fi
+fi
+
diff --git a/test/gtkrcs/buildin b/test/gtkrcs/buildin
new file mode 100644
index 0000000..997324a
--- /dev/null
+++ b/test/gtkrcs/buildin
@@ -0,0 +1,7 @@
+
+style "default"
+{
+ engine "" {}
+}
+
+class "GtkWidget" style "default"
diff --git a/test/gtkrcs/sugar b/test/gtkrcs/sugar
new file mode 100644
index 0000000..60365d0
--- /dev/null
+++ b/test/gtkrcs/sugar
@@ -0,0 +1,49 @@
+
+style "default"
+{
+ engine "sugar" { }
+}
+
+
+style "comboboxentry"
+{
+ engine "sugar" {
+ hint = "comboboxentry"
+ }
+}
+
+style "vscale"
+{
+ engine "sugar" {
+ hint = "vscale"
+ }
+}
+
+style "hscale"
+{
+ engine "sugar" {
+ hint = "hscale"
+ }
+}
+
+style "scrollbar"
+{
+ engine "sugar" {
+ hint = "scrollbar"
+ }
+}
+
+style "spinbutton"
+{
+ engine "sugar" {
+ hint = "spinbutton"
+ }
+}
+
+
+class "GtkWidget" style "default"
+class "GtkScrollBar" style "scrollbar"
+class "GtkHScale" style "hscale"
+class "GtkVScale" style "vscale"
+class "GtkSpinButton" style "spinbutton"
+widget_class "*<GtkComboBoxEntry>*" style "comboboxentry"
diff --git a/test/torture b/test/torture
new file mode 100755
index 0000000..80be4d5
--- /dev/null
+++ b/test/torture
@@ -0,0 +1,61 @@
+#! /bin/sh
+
+ENGINE="`basename $0 | cut -d '_' -f 2`"
+
+# Do the test for every file starting with the prefix
+
+FAILED="0"
+
+for RC_FILE in $srcdir/gtkrcs/$ENGINE*; do
+ test -f $RC_FILE || continue
+ something_tested="1"
+
+ export GTK2_RC_FILES=$RC_FILE
+ RC_FILE_BASENAME="`basename $RC_FILE`"
+ MY_EXEC_WRAPPER="`echo "$EXEC_WRAPPER" | sed s/THEME/$RC_FILE_BASENAME/`"
+
+ $MY_EXEC_WRAPPER ./torturetest 2>/dev/null
+
+ if [ "$?" != "0" ]; then
+ FAILED=1;
+ fi
+done
+
+if [ "x$something_tested" = "x" ]; then
+ echo "Failed to run test for \"$ENGINE\" because no gtkrc files were found"
+ exit 77;
+fi
+
+if [ "$FAILED" != "0" ]; then
+ # This is pretty stupid, but I don't know of a better way to handle it
+ # We need to make sure that if buildin failes, all other failures don't
+ # cause an overall test failure (ie. exit 77). I know this is stupid ...
+ # Otherwise "make check" will _always_ fail with a broken GTK+.
+ if [ "$ENGINE" = "buildin" ]; then
+ echo "WARNING: The GTK+ buildin theme failed the torture test!"
+ echo "WARNING: "
+ echo "WARNING: As the other engines may fall back to the buildin theme, other tests"
+ echo "WARNING: may fail in the buildin theme that we don't control."
+ echo "WARNING: The other tests will be run, but in case of failure SKIP instead of FAIL."
+ echo "WARNING: This way 'make check' will not fail even with a broken GTK+."
+ echo "WARNING:"
+ echo "WARNING: Currently it may also mean that there is just no X server to run the test on."
+ echo
+ touch torture_buildin-failed
+ exit 77
+ else
+ # If buildin-failed, then exit with status 77
+ if [ -f torture_buildin-failed ]; then
+ exit 77
+ else
+ exit 1
+ fi
+ fi
+else
+ # Remove the torture_buildin-failed file on success
+ if [ "$ENGINE" = "buildin" ]; then
+ test -f torture_buildin-failed && rm -f torture_buildin-failed
+ fi
+
+ exit 0
+fi
diff --git a/test/torturetest.c b/test/torturetest.c
new file mode 100644
index 0000000..62b8764
--- /dev/null
+++ b/test/torturetest.c
@@ -0,0 +1,607 @@
+/* Copyright Benjamin Berg 2007
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <gtk/gtk.h>
+#include <string.h>
+#include <stdlib.h>
+
+typedef enum {
+ STYLE_NORMAL,
+ STYLE_VSCALE,
+ STYLE_HSCALE,
+ STYLE_SCROLLBAR,
+ STYLE_COMBOBOXENTRY
+} StyleType;
+#define STYLE_COUNT (STYLE_COMBOBOXENTRY+1)
+
+typedef enum {
+ WIDGET_NULL,
+ WIDGET_VSCALE,
+ WIDGET_HSCALE,
+ WIDGET_VSCROLLBAR,
+ WIDGET_TOGGLE_BUTTON
+} WidgetType;
+
+#define WIDGET_COUNT (WIDGET_TOGGLE_BUTTON+1)
+#define WIDGET_ALL (-1)
+
+
+GType
+widget_type_get_type (void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GEnumValue values[] = {
+ { WIDGET_NULL, "WIDGET_NULL", "NULL" },
+ { WIDGET_VSCALE, "WIDGET_VSCALE", "GtkVScale" },
+ { WIDGET_HSCALE, "WIDGET_HSCALE", "GtkHScale" },
+ { WIDGET_VSCROLLBAR, "WIDGET_VSCROLLBAR", "GtkVScrollBar" },
+ { WIDGET_TOGGLE_BUTTON, "WIDGET_TOGGLE_BUTTON", "GtkToggleButton" },
+ { 0, NULL, NULL }
+ };
+ type = g_enum_register_static ("WidgeType", values);
+ }
+ return type;
+}
+
+GType
+bool_get_type (void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GEnumValue values[] = {
+ { 0, "BOOL_FALSE", "False" },
+ { 1, "BOOL_TRUE", "True" },
+ { 0, NULL, NULL }
+ };
+ type = g_enum_register_static ("GtkBoolDummyType", values);
+ }
+ return type;
+}
+
+
+#define WIDGET_TYPE (widget_type_get_type ())
+#define BOOL_TYPE (bool_get_type ())
+
+
+typedef enum {
+ FUNCTION_ARROW = 1 << 0,
+ FUNCTION_BOX = 1 << 1,
+ FUNCTION_SHADOW = 1 << 2,
+ FUNCTION_BOX_GAP = 1 << 3,
+ FUNCTION_SHADOW_GAP = 1 << 4,
+ FUNCTION_CHECK = 1 << 5,
+ FUNCTION_EXPANDER = 1 << 6,
+ FUNCTION_EXTENSION = 1 << 7,
+ FUNCTION_FLAT_BOX = 1 << 8,
+ FUNCTION_FOCUS = 1 << 9,
+ FUNCTION_HANDLE = 1 << 10,
+ FUNCTION_HLINE = 1 << 11,
+ FUNCTION_VLINE = 1 << 12,
+ FUNCTION_OPTION = 1 << 13,
+ FUNCTION_RESIZE_GRIP = 1 << 14,
+ FUNCTION_SLIDER = 1 << 15,
+ FUNCTION_TAB = 1 << 16,
+
+ FUNCTION_ALL = -1
+} FunctionType;
+#define FUNCTION_LAST FUNCTION_BOX
+
+GtkWidget *window;
+GtkWidget *box;
+GtkWidget *widgets[WIDGET_COUNT];
+GtkStyle *styles[STYLE_COUNT];
+
+typedef struct {
+ FunctionType function;
+ WidgetType widget;
+ StyleType style;
+ gchar *detail;
+ GtkStateType state;
+ GtkShadowType shadow;
+ GtkArrowType arrow_type;
+ gboolean fill;
+ GtkPositionType gap_side;
+ GtkOrientation orientation;
+ GtkExpanderStyle expander_style;
+ GdkWindowEdge edge;
+} Test;
+
+#define ARROW_ALL (-1)
+#define STATE_ALL (-1)
+#define SHADOW_ALL (-1)
+#define FILL_ALL (-1)
+#define EXPANDER_ALL (-1)
+#define EDGE_ALL (-1)
+#define GAP_SIDE_ALL (-1)
+#define ORIENTATION_ALL (-1)
+
+#define CELL_DETAILS_SIDE(detail) detail ":" detail "_start" ":" detail "_middle" ":" detail "_end"
+#define CELL_DETAILS_SORTED(detail) CELL_DETAILS_SIDE(detail) ":" CELL_DETAILS_SIDE(detail "_sorted")
+#define CELL_DETAILS_RULED(detail) CELL_DETAILS_SORTED(detail) ":" CELL_DETAILS_SORTED(detail "_ruled")
+#define CELL_DETAILS CELL_DETAILS_RULED("cell_even") ":" CELL_DETAILS_RULED("cell_odd")
+#define CHECK_AND_RADIO_DETAILS "NULL:cellcheck:cellradio:check:checkbutton:radiobutton"
+#define EXPANDER_DETAILS "NULL:expander" /* also in common details list ... */
+#define ARROW_DETAILS "NULL:arrow:tab:optionmenutab"
+#define COMMON_DETAILS "NULL:arrow:bar:base:button:buttondefault:combo_entry_button:dockitem:dockitem_bin:entry:entry_bg:frame:handle:handlebox:handlebox_bin:hpaned:hruler:hscale:hscrollbar:hseparator:label:menu:menubar:menuitem:metacity:notebook:option:optionmenu:optionmenutab:paned:scrolled_window:slider:spinbutton:spinbutton_arrow:spinbutton_down:spinbutton_up:stepper:tab:text:togglebutton:togglebuttondefault:toolbar:tooltip:treeitem:treeview:trough:viewport:viewportbin:vpaned:vruler:vscale:vscrollbar:vseparator:expander"
+
+/* The following explicitly does not test EVERY combination, as that would be
+ * overkill, and would take a lot longer. */
+static Test tests[] = {
+ { /* ARROW */
+ FUNCTION_ARROW,
+ WIDGET_NULL,
+ STYLE_NORMAL,
+ ARROW_DETAILS,
+ STATE_ALL,
+ SHADOW_ALL,
+ ARROW_ALL,
+ FILL_ALL,
+ GTK_SIDE_TOP,
+ GTK_ORIENTATION_HORIZONTAL,
+ GTK_EXPANDER_EXPANDED,
+ GDK_WINDOW_EDGE_SOUTH
+ },
+ { /* things with gaps */
+ FUNCTION_BOX_GAP | FUNCTION_SHADOW_GAP | FUNCTION_EXTENSION,
+ WIDGET_NULL,
+ STYLE_NORMAL,
+ COMMON_DETAILS,
+ STATE_ALL,
+ SHADOW_ALL,
+ GTK_ARROW_UP,
+ TRUE,
+ GAP_SIDE_ALL,
+ GTK_ORIENTATION_HORIZONTAL,
+ GTK_EXPANDER_EXPANDED,
+ GDK_WINDOW_EDGE_SOUTH
+ },
+ { /* expander */
+ FUNCTION_EXPANDER,
+ WIDGET_NULL,
+ STYLE_NORMAL,
+ EXPANDER_DETAILS,
+ STATE_ALL,
+ SHADOW_ALL,
+ GTK_ARROW_UP,
+ TRUE,
+ GTK_SIDE_TOP,
+ GTK_ORIENTATION_HORIZONTAL,
+ EXPANDER_ALL,
+ GDK_WINDOW_EDGE_SOUTH
+ },
+ { /* handle, slider (+orientation wildcarded) */
+ FUNCTION_HANDLE | FUNCTION_SLIDER,
+ WIDGET_NULL,
+ STYLE_NORMAL,
+ COMMON_DETAILS,
+ STATE_ALL,
+ SHADOW_ALL,
+ GTK_ARROW_UP,
+ TRUE,
+ GTK_SIDE_TOP,
+ ORIENTATION_ALL,
+ GTK_EXPANDER_EXPANDED,
+ GDK_WINDOW_EDGE_SOUTH
+ },
+ { /* resize grip (+edge wildcarded) */
+ FUNCTION_RESIZE_GRIP,
+ WIDGET_NULL,
+ STYLE_NORMAL,
+ COMMON_DETAILS,
+ STATE_ALL,
+ SHADOW_ALL,
+ GTK_ARROW_UP,
+ TRUE,
+ GTK_SIDE_TOP,
+ GTK_ORIENTATION_HORIZONTAL,
+ GTK_EXPANDER_EXPANDED,
+ EDGE_ALL
+ },
+ { /* check and radio */
+ FUNCTION_CHECK | FUNCTION_OPTION,
+ WIDGET_NULL,
+ STYLE_NORMAL,
+ CHECK_AND_RADIO_DETAILS,
+ STATE_ALL,
+ SHADOW_ALL,
+ GTK_ARROW_UP,
+ TRUE,
+ GTK_SIDE_TOP,
+ GTK_ORIENTATION_HORIZONTAL,
+ GTK_EXPANDER_EXPANDED,
+ GDK_WINDOW_EDGE_SOUTH
+ },
+ { /* cell flat box */
+ FUNCTION_FLAT_BOX,
+ WIDGET_NULL,
+ STYLE_NORMAL,
+ CELL_DETAILS,
+ STATE_ALL,
+ SHADOW_ALL,
+ GTK_ARROW_UP,
+ TRUE,
+ GTK_SIDE_TOP,
+ GTK_ORIENTATION_HORIZONTAL,
+ GTK_EXPANDER_EXPANDED,
+ GDK_WINDOW_EDGE_SOUTH
+ },
+ { /* GENERIC STUFF (will be duplicated somewhat, but *shrug*) */
+ FUNCTION_ALL ^ (FUNCTION_ARROW | FUNCTION_BOX_GAP | FUNCTION_SHADOW_GAP | FUNCTION_EXTENSION | FUNCTION_EXPANDER | FUNCTION_HANDLE | FUNCTION_SLIDER | FUNCTION_RESIZE_GRIP | FUNCTION_CHECK | FUNCTION_OPTION),
+ WIDGET_NULL,
+ STYLE_NORMAL,
+ COMMON_DETAILS,
+ STATE_ALL,
+ SHADOW_ALL,
+ GTK_ARROW_UP,
+ TRUE,
+ GTK_SIDE_TOP,
+ GTK_ORIENTATION_HORIZONTAL,
+ GTK_EXPANDER_EXPANDED,
+ GDK_WINDOW_EDGE_SOUTH
+ },
+
+ /* The above is just copied from gtk-engines. I am too lazy right now to clean it up ... */
+
+ /* Scales */
+ {
+ FUNCTION_SLIDER | FUNCTION_BOX | FUNCTION_FOCUS | FUNCTION_ARROW,
+ WIDGET_NULL,
+ STYLE_VSCALE,
+ "NULL:trough:trough-upper:trough-lower:hscale:vscale:stepper",
+ STATE_ALL,
+ SHADOW_ALL,
+ GTK_ARROW_UP,
+ TRUE,
+ GTK_SIDE_TOP,
+ GTK_ORIENTATION_HORIZONTAL,
+ GTK_EXPANDER_EXPANDED,
+ GDK_WINDOW_EDGE_SOUTH
+ },
+ {
+ FUNCTION_SLIDER | FUNCTION_BOX | FUNCTION_FOCUS | FUNCTION_ARROW,
+ WIDGET_NULL,
+ STYLE_VSCALE,
+ "NULL:trough:trough-upper:trough-lower:hscale:vscale:stepper",
+ STATE_ALL,
+ SHADOW_ALL,
+ GTK_ARROW_UP,
+ TRUE,
+ GTK_SIDE_TOP,
+ GTK_ORIENTATION_HORIZONTAL,
+ GTK_EXPANDER_EXPANDED,
+ GDK_WINDOW_EDGE_SOUTH
+ },
+
+ /* scrollbar */
+ {
+ FUNCTION_SLIDER | FUNCTION_BOX | FUNCTION_FOCUS | FUNCTION_ARROW,
+ WIDGET_NULL,
+ STYLE_SCROLLBAR,
+ "NULL:trough:trough-upper:trough-lower:hscrollbar:vscrollbar:slider",
+ STATE_ALL,
+ SHADOW_ALL,
+ GTK_ARROW_UP,
+ TRUE,
+ GTK_SIDE_TOP,
+ GTK_ORIENTATION_HORIZONTAL,
+ GTK_EXPANDER_EXPANDED,
+ GDK_WINDOW_EDGE_SOUTH
+ },
+
+ /* comboboxentry */
+ {
+ FUNCTION_BOX | FUNCTION_FOCUS | FUNCTION_ARROW | FUNCTION_SHADOW,
+ WIDGET_NULL,
+ STYLE_SCROLLBAR,
+ "NULL:button:entry:entry_bg:arrow",
+ STATE_ALL,
+ SHADOW_ALL,
+ GTK_ARROW_UP,
+ TRUE,
+ GTK_SIDE_TOP,
+ GTK_ORIENTATION_HORIZONTAL,
+ GTK_EXPANDER_EXPANDED,
+ GDK_WINDOW_EDGE_SOUTH
+ },
+
+ /* spinbutton */
+ {
+ FUNCTION_BOX | FUNCTION_FOCUS | FUNCTION_ARROW | FUNCTION_SHADOW,
+ WIDGET_NULL,
+ STYLE_SCROLLBAR,
+ "NULL:entry:entry_bg:arrow:spinbutton:spinbutton_up:spinbutton_down",
+ STATE_ALL,
+ SHADOW_ALL,
+ GTK_ARROW_UP,
+ TRUE,
+ GTK_SIDE_TOP,
+ GTK_ORIENTATION_HORIZONTAL,
+ GTK_EXPANDER_EXPANDED,
+ GDK_WINDOW_EDGE_SOUTH
+ },
+};
+
+#define ENUM_NEXT(enum_type, ind, target) \
+ do { \
+ GEnumClass *enum_class = g_type_class_ref (enum_type); \
+ if (initial || values[ind] >= enum_class->n_values - 1) { \
+ values[ind] = 0; \
+ } else { \
+ done = FALSE; \
+ values[ind]++; \
+ } \
+ \
+ target = enum_class->values[values[ind]].value; \
+ g_type_class_unref (enum_class); \
+ if (!done && !initial) \
+ goto end; \
+ } while(0)
+
+static gboolean
+get_next_combination (Test *wildcard_test, Test *test, gboolean initial)
+{
+ gint i;
+ gchar *cur_pos, *col_pos;
+ gboolean done = !initial;
+ static gint values[10];
+
+ test->function = wildcard_test->function;
+
+ if (wildcard_test->widget == WIDGET_ALL)
+ ENUM_NEXT (WIDGET_TYPE, 0, test->widget);
+ else
+ test->widget = wildcard_test->widget;
+
+ if (wildcard_test->state == STATE_ALL)
+ ENUM_NEXT (GTK_TYPE_STATE_TYPE, 1, test->state);
+ else
+ test->state = wildcard_test->state;
+
+ if (wildcard_test->shadow == SHADOW_ALL)
+ ENUM_NEXT (GTK_TYPE_SHADOW_TYPE, 2, test->shadow);
+ else
+ test->shadow = wildcard_test->shadow;
+
+ if (wildcard_test->arrow_type == ARROW_ALL)
+ ENUM_NEXT (GTK_TYPE_ARROW_TYPE, 3, test->arrow_type);
+ else
+ test->arrow_type = wildcard_test->arrow_type;
+
+ if (wildcard_test->fill == FILL_ALL)
+ ENUM_NEXT (BOOL_TYPE, 4, test->fill);
+ else
+ test->fill = wildcard_test->fill;
+
+ if (wildcard_test->gap_side == GAP_SIDE_ALL)
+ ENUM_NEXT (GTK_TYPE_POSITION_TYPE, 5, test->gap_side);
+ else
+ test->gap_side = wildcard_test->gap_side;
+
+ if (wildcard_test->orientation == ORIENTATION_ALL)
+ ENUM_NEXT (GTK_TYPE_ORIENTATION, 6, test->orientation);
+ else
+ test->orientation = wildcard_test->orientation;
+
+ if (wildcard_test->expander_style == EXPANDER_ALL)
+ ENUM_NEXT (GTK_TYPE_EXPANDER_STYLE, 7, test->expander_style);
+ else
+ test->expander_style = wildcard_test->expander_style;
+
+ if (wildcard_test->edge == EDGE_ALL)
+ ENUM_NEXT (GDK_TYPE_WINDOW_EDGE, 8, test->edge);
+ else
+ test->edge = wildcard_test->edge;
+
+end:
+ /* the detail is a : seperated list ... */
+ if (initial) {
+ values[9] = 0;
+ } else {
+ /* increase, if nothing else got changed. */
+ if (done)
+ values[9]++;
+ }
+ i = 0;
+ cur_pos = wildcard_test->detail;
+
+ while (i < values[9] && cur_pos) {
+ cur_pos = strchr (cur_pos, ':');
+ if (cur_pos != NULL) cur_pos++;
+ i++;
+ }
+ if (cur_pos == NULL) {
+ values[9] = 0;
+ cur_pos = wildcard_test->detail;
+ if (done)
+ return TRUE;
+ } else {
+ /* not done, as we moved on */
+ done = FALSE;
+ }
+ if (cur_pos != NULL) {
+ col_pos = strchr (cur_pos, ':');
+ if (col_pos == NULL)
+ test->detail = g_strdup (cur_pos);
+ else
+ test->detail = g_strndup (cur_pos, col_pos - cur_pos);
+ } else
+ test->detail = NULL;
+
+ /* replace "NULL" with a NULL pointer */
+ if (test->detail && strcmp (test->detail, "NULL") == 0) {
+ g_free (test->detail);
+ test->detail = NULL;
+ }
+
+ return done;
+}
+
+static void
+run_functions (Test *test)
+{
+ GtkStyle *style = styles[test->style];
+
+ if (test->function & FUNCTION_ARROW)
+ gtk_paint_arrow (style, window->window, test->state, test->shadow, NULL, widgets[test->widget], test->detail, test->arrow_type, test->fill, 0, 0, 10, 10);
+
+ if (test->function & FUNCTION_BOX)
+ gtk_paint_box (style, window->window, test->state, test->shadow, NULL, widgets[test->widget], test->detail, 0, 0, 10, 10);
+
+ if (test->function & FUNCTION_SHADOW)
+ gtk_paint_shadow (style, window->window, test->state, test->shadow, NULL, widgets[test->widget], test->detail, 0, 0, 10, 10);
+
+ if (test->function & FUNCTION_BOX_GAP)
+ gtk_paint_box_gap (style, window->window, test->state, test->shadow, NULL, widgets[test->widget], test->detail, 0, 0, 10, 10, test->gap_side, 0, 100);
+
+ if (test->function & FUNCTION_SHADOW_GAP)
+ gtk_paint_shadow_gap (style, window->window, test->state, test->shadow, NULL, widgets[test->widget], test->detail, 0, 0, 10, 10, test->gap_side, 0, 100);
+
+
+ if (test->function & FUNCTION_CHECK)
+ gtk_paint_check (style, window->window, test->state, test->shadow, NULL, widgets[test->widget], test->detail, 0, 0, 10, 10);
+
+ if (test->function & FUNCTION_EXPANDER)
+ gtk_paint_expander (style, window->window, test->state, NULL, widgets[test->widget], test->detail, 10, 10, test->expander_style);
+
+ if (test->function & FUNCTION_EXTENSION)
+ gtk_paint_extension (style, window->window, test->state, test->shadow, NULL, widgets[test->widget], test->detail, 0, 0, 10, 10, test->gap_side);
+
+ if (test->function & FUNCTION_FLAT_BOX)
+ gtk_paint_flat_box (style, window->window, test->state, test->shadow, NULL, widgets[test->widget], test->detail, 0, 0, 10, 10);
+
+ if (test->function & FUNCTION_FOCUS)
+ gtk_paint_focus (style, window->window, test->state, NULL, widgets[test->widget], test->detail, 0, 0, 10, 10);
+
+ if (test->function & FUNCTION_HANDLE)
+ gtk_paint_handle (style, window->window, test->state, test->shadow, NULL, widgets[test->widget], test->detail, 0, 0, 10, 10, test->orientation);
+
+ if (test->function & FUNCTION_OPTION)
+ gtk_paint_option (style, window->window, test->state, test->shadow, NULL, widgets[test->widget], test->detail, 0, 0, 10, 10);
+
+ if (test->function & FUNCTION_RESIZE_GRIP)
+ gtk_paint_resize_grip (style, window->window, test->state, NULL, widgets[test->widget], test->detail, test->edge, 0, 0, 10, 10);
+
+ if (test->function & FUNCTION_SLIDER)
+ gtk_paint_slider (style, window->window, test->state, test->shadow, NULL, widgets[test->widget], test->detail, 0, 0, 10, 10, test->orientation);
+
+ if (test->function & FUNCTION_TAB)
+ gtk_paint_tab (style, window->window, test->state, test->shadow, NULL, widgets[test->widget], test->detail, 0, 0, 10, 10);
+
+
+ if (test->function & FUNCTION_HLINE)
+ gtk_paint_hline (style, window->window, test->state, NULL, widgets[test->widget], test->detail, 1, 10, 4);
+
+ if (test->function & FUNCTION_VLINE)
+ gtk_paint_vline (style, window->window, test->state, NULL, widgets[test->widget], test->detail, 1, 10, 4);
+}
+
+static void
+run_test (gint test)
+{
+ Test current_test = {0};
+ gint initial = TRUE;
+
+ while (!get_next_combination (&tests[test], &current_test, initial)) {
+ initial = FALSE;
+ run_functions (&current_test);
+ g_free (current_test.detail);
+ }
+}
+
+static void
+create_testwidgets ()
+{
+ widgets[WIDGET_VSCROLLBAR] = gtk_vscrollbar_new (NULL);
+ widgets[WIDGET_TOGGLE_BUTTON] = gtk_toggle_button_new_with_label ("blah");
+}
+
+static GtkStyle*
+get_attached_style (GtkStyle *fallback, GdkWindow *window, const gchar *path, GType type)
+{
+ GtkSettings *settings = gtk_settings_get_default ();
+ GtkStyle *style;
+
+ style = gtk_rc_get_style_by_paths (settings, path, path, type);
+ if (!style)
+ style = fallback;
+ else
+ g_object_ref (style);
+
+ return gtk_style_attach (style, window);
+}
+
+static void
+create_teststyles ()
+{
+ styles[STYLE_NORMAL] = get_attached_style (window->style, window->window, "GtkWindow.GtkButton", GTK_TYPE_BUTTON);
+ styles[STYLE_VSCALE] = get_attached_style (window->style, window->window, "GtkWindow.GtkVScale", GTK_TYPE_VSCALE);
+ styles[STYLE_HSCALE] = get_attached_style (window->style, window->window, "GtkWindow.GtkHScale", GTK_TYPE_HSCALE);
+ styles[STYLE_SCROLLBAR] = get_attached_style (window->style, window->window, "GtkWindow.GtkScrollbar", GTK_TYPE_SCROLLBAR);
+
+ GTK_TYPE_COMBO_BOX_ENTRY; /* Initilize the combobox entry type (not really neccessary as GTK+ will fall back to string matching) */
+ styles[STYLE_COMBOBOXENTRY] = get_attached_style (window->style, window->window, "GtkWindow.GtkComboBoxEntry.GtkButton", GTK_TYPE_BUTTON);
+}
+
+int
+main (int argc, char **argv)
+{
+ gchar *new_default_files[1] = {NULL};
+ GtkSettings *settings;
+ gint i;
+ gtk_init (&argc, &argv);
+
+ /* we get a gtkrc from GTK2_RC_FILES, remove the users theme ... */
+ settings = gtk_settings_get_default ();
+ g_object_set (settings, "gtk-theme-name", "Raleigh", NULL);
+
+ create_testwidgets ();
+
+ window = gtk_window_new (GTK_WINDOW_POPUP);
+ box = gtk_hbox_new (FALSE, 0);
+
+ gtk_container_add ((GtkContainer*)window, box);
+
+ for (i = 0; i < WIDGET_COUNT; i++) {
+ if (widgets[i])
+ gtk_box_pack_end (GTK_BOX (box), widgets[i], FALSE, FALSE, 0);
+ }
+
+ gtk_widget_show_all (window);
+
+ while (gdk_events_pending ())
+ gtk_main_iteration_do (FALSE);
+
+ create_teststyles ();
+
+ for (i = 0; i < G_N_ELEMENTS (tests); i++)
+ run_test (i);
+
+ /* remove the rc file again. This should cause an unload of the engine
+ * and destruction of all engine objects. */
+ gtk_rc_set_default_files (new_default_files);
+ gtk_rc_reparse_all_for_settings (settings, TRUE);
+
+ while (gdk_events_pending ())
+ gtk_main_iteration_do (FALSE);
+
+ /* TODO: It would be really cool to check if there is no
+ * loaded engine at this point. */
+
+ return 0;
+}
diff --git a/test/valgrind-suppressions b/test/valgrind-suppressions
new file mode 100644
index 0000000..6e3ef65
--- /dev/null
+++ b/test/valgrind-suppressions
@@ -0,0 +1,54 @@
+{
+ Some invalid access on application startup
+ Memcheck:Param
+ writev(vector[...])
+ fun:*writev
+ obj:/usr/lib/libX11.so.6.2.0
+ fun:_X11TransWritev
+ fun:_XSend
+ fun:XQueryExtension
+ fun:XInitExtension
+ fun:XFixesFindDisplay
+ fun:XFixesQueryExtension
+ fun:gdk_display_open
+}
+{
+ something else, dunno what exactly
+ Memcheck:Param
+ write(buf)
+ fun:*write*
+ fun:_X11TransWrite
+ obj:/usr/lib/libX11.so.6.2.0
+ fun:_XEventsQueued
+ fun:XPending
+ fun:_gdk_events_queue
+ fun:gdk_event_dispatch
+}
+{
+ Some home directory stuff, happens when loading the engine
+ Memcheck:Leak
+ fun:malloc
+ fun:nss_parse_service_list
+ fun:__nss_database_lookup
+ obj:*
+ obj:*
+ fun:getpwnam_r@@GLIBC_2.1.2
+ fun:g_get_any_init_do
+ fun:g_get_home_dir
+}
+{
+ pango/fc leak
+ Memcheck:Leak
+ fun:*alloc
+ fun:FcPatternObjectInsertElt
+ fun:FcPatternObjectAddWithBinding
+ fun:FcPatternObjectAdd
+ fun:FcFontRenderPrepare
+ fun:pango_fc_font_map_load_fontset
+ fun:pango_font_map_load_fontset
+ fun:itemize_state_process_run
+ fun:pango_itemize_with_base_dir
+ fun:pango_layout_check_lines
+ fun:pango_layout_get_extents_internal
+ fun:gtk_label_size_request
+}