Re: GTK+ unit testing



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]