Re: GTK+ unit testing
- From: Fernando Herrera <fernando herrera-de-las-heras nokia com>
- To: ext Iago Toral Quiroga <itoral igalia com>
- Cc: build-brigade-list gnome org
- Subject: Re: GTK+ unit testing
- Date: Thu, 03 Aug 2006 15:27:41 +0300
On Thu, 2006-08-03 at 11:05 +0200, ext Iago Toral Quiroga wrote:
> -These tests take a *lot lot lot* of execution time -> this might be a
> problem. Maybe we should consider filtering some of them, or something
> to make them a bit less painful. I'll post something about this later
> on.
>
> - Some tests seem to hang (I needed to send a Crtl+C to stop them
> manually) -> this *is* a problem, at least using TET (Check provides
> timeout support).
>
> - You need an X server up and running (GTK+ requisiton).
>
> - If we want to use Check as testing framework instead of TET (as Fer
> suggests) it will take some more time. I know Fer has already done some
> work on this but I do not know exactly its current state. Anyway, I'll
> send what should be done to achive this in a later post.
Yeah, execution time with tet framework currently is taking lot of time,
mostly because of the gtk template code to run mainloop.
In the "check hack" I did it quite faster. Also I guess that we would
like to be able to run only certains tests, for example:
- Developer Bob fixes some GtkButton bug
- Bob runs: "make test GtkButton" and the system only runs the GtkButton
test.
Attached is the patch I hacked some days ago for having these gtkvts
tests under "check" framework. IIRC correctly it does the test code
generation correctly and Makefiles, however I created by hand the
check_utils.o code.
I'll try do clean it up to get all the thing compiling out-of-the-box,
however here is it in the more "hackish" way :)
Salu2
? COPYING
? INSTALL
? Makefile
? Makefile.in
? aclocal.m4
? autom4te.cache
? config.guess
? config.h
? config.h.in
? config.log
? config.status
? config.sub
? configure
? install-sh
? missing
? mkinstalldirs
? results
? stamp-h
? stamp-h.in
? tet_scen
? tet_tmp_dir
? bin/bugs_statistics
? bin/doc_parser
? bin/func_tests_gen
? bin/hdr_tests_addit_files_gen
? bin/hdr_tests_generator
? bin/s_doc_parser
? bin/test_cov
? bin/x_doc_parser
? coverage/asr_list.txt
? scenarios/func_scen
? scenarios/headers_scen
? src/Makefile
? src/Makefile.in
? src/libs/.deps
? src/libs/Makefile
? src/libs/Makefile.in
? src/tests/check_utils.c
? src/tests/check_utils.h
? src/tests/functions/Widgets/.tmp.swp
? src/tests/headers/hdr_list.txt
? src/tools/Makefile
? src/tools/Makefile.in
? src/tools/stat/.deps
? src/tools/stat/Makefile
? src/tools/stat/Makefile.in
? src/tools/testcov/.deps
? src/tools/testcov/Makefile
? src/tools/testcov/Makefile.in
? src/tools/testgen/.deps
? src/tools/testgen/Makefile
? src/tools/testgen/Makefile.in
? src/tools/testgen/check_func_tests_gen.c
? src/tools/testgen/check_utils.c
? src/tools/testgen/check_utils.h
? src/tools/testgen/test_suites.h
? tests/functions
? tests/headers
? tests/runtests.log
Index: src/tests/functions/GdkPixbuf/tmpfile/file_cur_new.ico
===================================================================
RCS file: /cvsroot/lsb/tests/lsb-desktop-test/lsb-gtkvts/src/tests/functions/GdkPixbuf/tmpfile/file_cur_new.ico,v
retrieving revision 1.1
diff -u -r1.1 file_cur_new.ico
Binary files /tmp/cvsYQcHxO and file_cur_new.ico differ
Index: src/tests/functions/_Templates/_purpose.tpl
===================================================================
RCS file: /cvsroot/lsb/tests/lsb-desktop-test/lsb-gtkvts/src/tests/functions/_Templates/_purpose.tpl,v
retrieving revision 1.1
diff -u -r1.1 _purpose.tpl
--- src/tests/functions/_Templates/_purpose.tpl 9 Sep 2005 09:24:16 -0000 1.1
+++ src/tests/functions/_Templates/_purpose.tpl 25 Jul 2006 11:34:59 -0000
@@ -1,17 +1,10 @@
<%comment%>
-static void test_purpose_<%purpose_number%>()
+START_TEST(test_purpose_<%purpose_number%>)
{
<%define%>
- bug_inf = NULL;
- test_passed_flag = 1;
- all_test_purp_num++;
- fprintf (stderr, mark_symbol (all_test_purp_num));
- tet_printf("test case: %s, TP number: %d ", tet_pname, tet_thistest);
-
<%code%>
- test_passed ();
-
- double_bug = 0;
}
+END_TEST
+
Index: src/tests/functions/_Templates/_test.tpl
===================================================================
RCS file: /cvsroot/lsb/tests/lsb-desktop-test/lsb-gtkvts/src/tests/functions/_Templates/_test.tpl,v
retrieving revision 1.7
diff -u -r1.7 _test.tpl
--- src/tests/functions/_Templates/_test.tpl 14 Mar 2006 00:23:33 -0000 1.7
+++ src/tests/functions/_Templates/_test.tpl 25 Jul 2006 11:34:59 -0000
@@ -4,41 +4,18 @@
*
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <tet_api.h>
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include <fontconfig/fontconfig.h>
-#define _XFT_NO_COMPAT
-#define _XFTCOMPAT_H_
-#include <X11/Xlib.h>
-#include <X11/Xft/Xft.h>
-#include <pango/pangoft2.h>
-#include <gtk/gtk.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gmodule.h>
-#include <gdk/gdkkeysyms.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include "libtestgen.h"
-#include "libstr.h"
-#include "libfile.h"
-#include "libthr.h"
+#define TEST_VISUALIZE(widget) {test_visualize(widget, NULL);}
+#define TEST_VISUALIZE_AND_DO(widget,func) {test_visualize(widget, func);}
+#define TEST_VISUALIZE_TOPLEVEL(widget) {test_visualize(widget, NULL);}
-#define TEST_FAIL(str, ...) {test_failed ();tet_printf("%s, line %d: ", __FILE__, __LINE__);tet_printf (str, __VA_ARGS__);}
-/*
- * global variables
- */
+#include <stdlib.h>
+#include <check.h>
+#include <check_utils.h>
+
+#include <gtk/gtk.h>
-int test_purp_passed_num = 0;
-int all_test_purp_num = 0;
-int double_bug = 0;
-unsigned test_passed_flag = 1;
+#define TEST_FAIL(str, ...) fail(str)
/*
* function prototypes
@@ -72,16 +49,6 @@
static void
test_passed (void)
{
- if (bug_inf && !double_bug)
- {
- double_bug = 1;
- }
-
- if (test_passed_flag)
- {
- test_purp_passed_num++;
- }
- tet_result (TET_PASS);
}
/*
@@ -90,13 +57,6 @@
static void
test_failed (void)
{
- if (bug_inf && !double_bug)
- {
- double_bug = 1;
- }
-
- test_passed_flag = 0;
- tet_result (TET_FAIL);
}
/*
@@ -106,41 +66,59 @@
static void
startup_func()
{
- int argc = 1;
- char** argv = NULL;
-
- argv = calloc(argc, sizeof(char*));
- argv[0] = (char*)strdup("");
- gtk_init(&argc, &argv);
- fprintf (stderr, "Function tests for <%object_name%> ");
+ int argc = 0;
+ gtk_init(&argc, NULL);
+ fprintf (stderr, "Function tests for <%object_name%>\n");
}
-
-/*
- * cleanup_func
- */
-static void
-cleanup_func()
+
+/* ---------- Suite creation ---------- */
+Suite *create_<%object_name%>_suite ()
{
- fprintf (stderr, " %d passed", test_purp_passed_num);
- if (all_test_purp_num != test_purp_passed_num)
- {
- fprintf (stderr, " %d FAILED", all_test_purp_num - test_purp_passed_num);
- }
- fprintf (stderr, "\n");
+
+ int i;
+
+ /* Create the suite */
+ Suite *s = suite_create ("<%object_name%>");
+
+ /* Create test cases */
+ TCase *tc1 = tcase_create ("<%object_name%>");
+ tcase_add_checked_fixture (tc1, startup_func, NULL);
+ <%tet_hooks%>
+ suite_add_tcase (s, tc1);
+
+
+ /* Return created suite */
+ return s;
}
+static SRunner *
+configure_tests()
+{
+ SRunner *sr;
+ sr = srunner_create (create_<%object_name%>_suite());
+ return sr;
+}
-/*
- *Program hooks into the tet harness
- */
-void (*tet_startup)() = startup_func;
-void (*tet_cleanup)() = cleanup_func;
+int
+main(void)
+{
+ gint nf = 0;
+ gint environment = 0;
+
+ /* Configure test suites to be executed */
+ SRunner *sr = configure_tests();
+
+ /* Run tests */
+ srunner_run_all(sr, CK_VERBOSE);
+
+ /* Retrieve number of failed tests */
+ nf = srunner_ntests_failed(sr);
+
+ /* Free resouces */
+ srunner_free(sr);
+
+ /* Return global success or failure */
+ return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
-/*
- * TET Tests included in this file.
- */
-struct tet_testlist tet_testlist[] = {
- <%tet_hooks%>
- {NULL,0}
-};
Index: src/tools/testgen/func_tests_gen.c
===================================================================
RCS file: /cvsroot/lsb/tests/lsb-desktop-test/lsb-gtkvts/src/tools/testgen/func_tests_gen.c,v
retrieving revision 1.3
diff -u -r1.3 func_tests_gen.c
--- src/tools/testgen/func_tests_gen.c 9 Jun 2006 03:48:36 -0000 1.3
+++ src/tools/testgen/func_tests_gen.c 25 Jul 2006 11:34:59 -0000
@@ -1053,7 +1053,7 @@
{
int i;
char iStr[8];
- char* tet_hook_tpl = "{test_purpose_<%purpose_number%>, 1},\n";
+ char* tet_hook_tpl = "tcase_add_test (tc1, test_purpose_<%purpose_number%>);\n";
char* cur_tet_hook = NULL;
char* all_tet_hooks = NULL;
char* pSave = NULL;
@@ -1094,19 +1094,7 @@
makefile_path = str_sum(dir_path, "/makefile");
mf = open_file (makefile_path, "w+", NULL);
- fprintf (mf, "TET_INC_DIR = $(TET_PATH)/inc/tet3\n");
- fprintf (mf, "TET_LIB_DIR = $(TET_PATH)/lib/tet3\n");
- fprintf (mf, "GTKVTS_ROOT = %s\n", gtkvts_root);
- fprintf (mf, "GTKVTS_LIB_DIR = $(GTKVTS_ROOT)/lib\n");
- fprintf (mf, "\n");
- fprintf (mf, "OS = $(shell uname -s)\n");
- fprintf (mf, "LIBS_SunOS = -lX11\n");
- fprintf (mf, "LIBS_Linux = \n");
- fprintf (mf, "ADD_LIBS = $(LIBS_$(OS))\n");
- fprintf (mf, "\n");
- fprintf (mf, "LIBS = $(TET_LIB_DIR)/tcm.o $(TET_LIB_DIR)/libapi.a $(GTKVTS_LIB_DIR)/libthr.a $(GTKVTS_LIB_DIR)/librobot.a $(GTKVTS_LIB_DIR)/libtestgen.a $(GTKVTS_LIB_DIR)/libfile.a $(GTKVTS_LIB_DIR)/libstr.a $(GTKVTS_LIB_DIR)/libmem.a $(ADD_LIBS)\n");
- fprintf (mf, "\n");
- fprintf (mf, "%s: %s.c $(TET_INC_DIR)/tet_api.h\n",
+ fprintf (mf, "%s: %s.c \n",
ftest_nme, ftest_nme);
fprintf (mf, "\t$(CC) ");
{
@@ -1116,7 +1104,7 @@
fprintf (mf, "%s", cflags);
}
}
- fprintf (mf, " `pkg-config --cflags gtk+-2.0` -I$(GTKVTS_ROOT)/src/tools/testgen -I$(GTKVTS_ROOT)/src/libs -I$(TET_INC_DIR) -o $@ $< `pkg-config --libs gtk+-2.0` $(LIBS)\n");
+ fprintf (mf, " -I/opt/gnome216/include/gtk-2.0/gtk/ `pkg-config --cflags gtk+-2.0 freetype2` -I$(GTKVTS_ROOT)/src/tools/testgen -I$(GTKVTS_ROOT)/src/libs -o $@ $< `pkg-config --libs gtk+-2.0` $(LIBS) /usr/lib/libcheck.a $(GTKVTS_ROOT)/src/tests/check_utils.o\n");
fprintf (mf, "\tchmod a+x %s\n", ftest_nme);
fprintf (mf, "\n");
fprintf (mf, "clean:\n");
#include "gtkmain.h"
#include "check_utils.h"
#include <gtk/gtk.h>
/**
* Creates a window of a fixed, well known size
*/
GtkWidget *
create_test_window ()
{
GtkWidget *window = NULL;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_resize (GTK_WINDOW (window), TEST_WINDOW_WIDTH, TEST_WINDOW_HEIGHT);
return window;
}
/**
* Wrapper to gtk_widget_show, that call to gtk_events_pending serving events.
*/
void show_test_window(GtkWidget * window)
{
gtk_widget_show (window);
while (gtk_events_pending ())
{
gtk_main_iteration ();
}
}
/**
* Wrapper to gtk_widget_show_all, that call to gtk_events_pending serving events.
*/
void show_all_test_window(GtkWidget * window)
{
gtk_widget_show_all (window);
while (gtk_events_pending ())
{
gtk_main_iteration ();
}
}
/**
* Wrapper to gtk_hide_show, that call to gtk_events_pending serving events.
*/
void hide_test_window(GtkWidget * window)
{
gtk_widget_hide (window);
while (gtk_events_pending ())
{
gtk_main_iteration ();
}
}
/**
* Wrapper to gtk_widget_hide_all, that call to gtk_events_pending serving events.
*/
void hide_all_test_window(GtkWidget * window)
{
gtk_widget_hide_all (window);
while (gtk_events_pending ())
{
gtk_main_iteration ();
}
}
/*
* Global variables
*/
static gint test_synchronize_events_count = 0;
static GtkCallback test_func = NULL;
const static gint sleep_delay = 200000;
/*
* Send "synchronize" event (GDK_KEY_PRESS, keyval = 0)
*/
static void
test_send_synchronize_event (GtkWidget* widget)
{
const guint keyval = 0;
GdkEventKey e;
e.type = GDK_KEY_PRESS;
e.string = gdk_keyval_name (keyval);
e.length = 1;
e.state = 0;
e.group = 0;
e.hardware_keycode = 0;
e.keyval = keyval;
e.window = widget->window;
e.send_event = TRUE;
e.time = GDK_CURRENT_TIME;
g_object_ref (G_OBJECT (widget->window));
gtk_main_do_event ((GdkEvent*)&e);
g_object_unref (G_OBJECT (widget->window));
}
/*
* Handles GDK_EXPOSE, GDK_MAP and "synchronize" events.
*
* When GDK_EXPOSE and GDK_MAP events received (i.e. window shown),
* send "synchronize" events.
* If there no events between two "synchronize" events,
* the main events queue is empty and quit main loop.
*/
static gboolean
test_catch_synchronize_event (GtkWidget *widget, GdkEvent *event, gpointer data)
{
if (!GTK_WIDGET_REALIZED (widget)) return FALSE;
if (event->type == GDK_EXPOSE)
{
test_send_synchronize_event (widget);
test_synchronize_events_count = 0;
return FALSE;
}
if (event->type == GDK_MAP)
{
GdkRectangle rect;
GtkWidget* top = gtk_widget_get_toplevel (widget);
gdk_window_get_frame_extents (top->window, &rect);
gdk_window_invalidate_rect (top->window, &rect, TRUE);
gdk_window_process_all_updates ();
return FALSE;
}
if ((event->type == GDK_KEY_PRESS) &&
(((GdkEventKey*)event)->state == 0) &&
(((GdkEventKey*)event)->keyval == 0))
{
test_synchronize_events_count++;
if (test_synchronize_events_count < 2)
{
gdk_window_process_all_updates ();
test_send_synchronize_event (widget);
return TRUE;
} else {
if (test_func)
{
(*test_func) (widget, NULL);
test_func = NULL;
test_send_synchronize_event (widget);
test_synchronize_events_count = 0;
return FALSE;
}
test_synchronize_events_count = 0;
if (gtk_main_level () > 0)
gtk_main_quit ();
}
} else {
test_synchronize_events_count = 0;
}
return FALSE;
}
/*
* Includes widget in toplevel container, show and enter main loop
*/
void
test_visualize (GtkWidget* widget, GtkCallback func)
{
GtkWidget* window = widget;
if (!widget) return;
if ((!GTK_WIDGET_TOPLEVEL (widget) && !GTK_IS_MENU_SHELL (widget)) || (GTK_IS_MENU_BAR (widget)))
{
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
if (!window) return;
g_object_ref (G_OBJECT (widget));
gtk_container_add (GTK_CONTAINER (window),
gtk_widget_get_toplevel (widget));
gtk_window_set_position (GTK_WINDOW (window),
GTK_WIN_POS_CENTER_ALWAYS);
gtk_container_set_border_width (GTK_CONTAINER (window), 20);
}
test_func = func;
g_signal_connect (G_OBJECT (window), "event", GTK_SIGNAL_FUNC (test_catch_synchronize_event), NULL);
gtk_widget_show_all (window);
gtk_main ();
g_usleep (sleep_delay);
}
#ifndef _CHECK_UTILS_H_
#define _CHECK_UTILS_H_
#include "gtkwidget.h"
#define TEST_WINDOW_WIDTH 100
#define TEST_WINDOW_HEIGHT 100
GtkWidget *create_test_window (void);
void show_test_window(GtkWidget * window);
void show_all_test_window(GtkWidget * window);
void hide_test_window(GtkWidget * window);
void hide_all_test_window(GtkWidget * window);
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]