From c361b6e1866e54cba68c1aa57790dd957ad45b01 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Mon, 21 May 2007 18:01:49 +0000 Subject: Forgot to commit a large part of the testing code. --- (limited to 'test') 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 "**" 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 +#include +#include + +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], ¤t_test, initial)) { + initial = FALSE; + run_functions (¤t_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 +} -- cgit v0.9.1