update to regression testing framework

Paul Millar paulm at astro.gla.ac.uk
Wed Apr 10 11:37:15 CDT 2002


Hi,

The attached patch changes the way the regression testing works slightly.
The default behaviour should be the same, but there's some optional
"enhancements":

 o  If you set WINETEST_REPORT_SUCCESS environment variable to 1, 
    successful tests are reported as well as unsuccessful ones.

 o  If you set WINETEST_CONTINUE_ON_FAIL environment variable to 1, "make
    test" will run all tests from all modules, rather than failing on the
    first failing module.

 o  The commands "named_ok", "set_name" and "unset_name" now exist (in C 
    and Perl). You can use these to specify a name for tests either 
    individually (via named_ok) or for a region (via set_name and 
    unset_name)

The patch changes both the C and Perl frameworks. I'm pretty sure the Perl
is right but someone who actually knows Perl ought to check it :)

The second patch illustrates these by changing dlls/kernel/tests/atom.pl 
and dlls/kernel/tests/directory.c (apologies to Alexandre & Dmitry if I 
got the test semantics wrong).

HTH

----
Paul Millar

ChangeLog:
  Adding test names and some optional behaviour.
-------------- next part --------------
? dlls/kernel/tests/new
Index: include/wine/test.h
===================================================================
RCS file: /home/wine/wine/include/wine/test.h,v
retrieving revision 1.3
diff -u -r1.3 test.h
--- include/wine/test.h	22 Mar 2002 00:58:00 -0000	1.3
+++ include/wine/test.h	10 Apr 2002 16:03:43 -0000
@@ -35,6 +35,9 @@
 
 extern winetest_ok_funcptr winetest_set_ok_location( const char* file, int line );
 extern winetest_trace_funcptr winetest_set_trace_location( const char* file, int line );
+extern int winetest_named_ok( const char* name, int condition, const char* msg, ...);
+extern void winetest_set_name( const char* name);
+extern void winetest_unset_name( void);
 extern void winetest_start_todo( const char* platform );
 extern int winetest_loop_todo(void);
 extern void winetest_end_todo( const char* platform );
@@ -43,6 +46,9 @@
 
 #define ok             (*winetest_set_ok_location(__FILE__, __LINE__))
 #define trace          (*winetest_set_trace_location(__FILE__, __LINE__))
+#define named_ok       winetest_named_ok
+#define set_name       winetest_set_name
+#define unset_name     winetest_unset_name
 
 #define todo(platform) for (winetest_start_todo(platform); \
                             winetest_loop_todo(); \
Index: programs/winetest/runtest
===================================================================
RCS file: /home/wine/wine/programs/winetest/runtest,v
retrieving revision 1.7
diff -u -r1.7 runtest
--- programs/winetest/runtest	28 Mar 2002 18:21:06 -0000	1.7
+++ programs/winetest/runtest	10 Apr 2002 16:03:43 -0000
@@ -32,6 +32,8 @@
 Options:
     -q       quiet mode
     -v       verbose mode (can be specified multiple times)
+    -s       announce successful tests
+    -c       always return 0 even if tests fail
     -p prog  name of the program to run for C tests
     -I dir   prepend dir to Perl include path
     -P name  set the current platform name
@@ -45,6 +47,8 @@
 # default values
 my $platform = $ENV{WINETEST_PLATFORM};
 $ENV{WINETEST_DEBUG} ||= 1;
+$ENV{WINETEST_CONTINUE_ON_FAIL} ||=0;
+$ENV{WINETEST_REPORT_SUCCESS} ||=0;
 
 my $topobjdir;
 my $infile;
@@ -60,6 +64,8 @@
     if ($arg eq "-p") { $program = shift @ARGV; next; }
     if ($arg eq "-q") { $ENV{WINETEST_DEBUG} = 0; next; }
     if ($arg eq "-v") { $ENV{WINETEST_DEBUG}++; next; }
+    if ($arg eq "-s") { $ENV{WINETEST_REPORT_SUCCESS} = 1; next;}
+    if ($arg eq "-c") { $ENV{WINETEST_CONTINUE_ON_FAIL} = 1; next;}
     if ($arg eq "-P") { $platform = shift @ARGV; next; }
     if ($arg eq "-M") { push @modules, split /,/, shift @ARGV; next; }
     if ($arg eq "-I") { push @include_dirs, shift @ARGV; next; }
Index: programs/winetest/wtmain.c
===================================================================
RCS file: /home/wine/wine/programs/winetest/wtmain.c,v
retrieving revision 1.5
diff -u -r1.5 wtmain.c
--- programs/winetest/wtmain.c	2 Apr 2002 00:44:17 -0000	1.5
+++ programs/winetest/wtmain.c	10 Apr 2002 16:03:43 -0000
@@ -26,12 +26,33 @@
 #include "wine/test.h"
 #include "winbase.h"
 
+#define WINETEST_OUTPUT_LINE( DATA, STRING) \
+    {if( name || data->current_name) \
+        fprintf( stderr, "%s:%s: ", data->current_file, \
+                 name ? name : data->current_name); \
+    else \
+        fprintf( stderr, "%s:%d: ", data->current_file, data->current_line); \
+    fprintf( stderr, "%s", STRING);}
+
+#define WINETEST_OUTPUT_TRACE( DATA, STRING) \
+    {if( data->current_name) \
+        fprintf( stderr, "%s ", data->current_name); \
+    else \
+        fprintf( stderr, "%s:%d: ", data->current_file, data->current_line); \
+    fprintf( stderr, "%s", STRING);}
+
 /* debug level */
 int winetest_debug = 1;
 
 /* current platform */
 const char *winetest_platform = "windows";
 
+/* continue after an unsuccessful test (BOOL) */
+int winetest_continue_on_fail = 0;
+
+/* report successful tests (BOOL) */
+int winetest_report_success = 0;
+
 struct test
 {
     const char  *name;
@@ -51,11 +72,16 @@
 {
     const char* current_file;        /* file of current check */
     int current_line;                /* line of current check */
+    const char* current_name;        /* name of current check (or NULL) */
     int todo_level;                  /* current todo nesting level */
     int todo_do_loop;
 } tls_data;
 static DWORD tls_index;
 
+/* Private prototype: backend for winetest_ok() and winetest_named_ok() */
+int winetest_generic_ok( const char *, int, const char *, va_list *);
+
+
 static tls_data* get_tls_data(void)
 {
     tls_data* data;
@@ -72,33 +98,53 @@
     return data;
 }
 
+
 /*
  * Checks condition.
  * Parameters:
  *   - condition - condition to check;
  *   - msg test description;
- *   - file - test application source code file name of the check
- *   - line - test application source code file line number of the check
  * Return:
  *   0 if condition does not have the expected value, 1 otherwise
  */
 int winetest_ok( int condition, const char *msg, ... )
 {
+    int status;
     va_list valist;
+
+    va_start( valist, msg);
+    status = winetest_generic_ok( NULL, condition, msg, &valist);
+    va_end( valist);
+
+    return status;
+}
+
+int winetest_named_ok( const char *name, int condition, const char *msg, ... )
+{
+    int status;
+    va_list valist;
+
+    va_start( valist, msg);
+    status = winetest_generic_ok( name, condition, msg, &valist);
+    va_end( valist);
+
+    return status;
+}
+
+int winetest_generic_ok( const char *name, int condition, const char *msg, va_list *valist )
+{
     tls_data* data=get_tls_data();
 
     if (data->todo_level)
     {
         if (condition)
         {
-            fprintf( stderr, "%s:%d: Test succeeded inside todo block",
-                     data->current_file, data->current_line );
+            WINETEST_OUTPUT_LINE( data, "Test succeeded inside todo block")
+
             if (msg && msg[0])
             {
-                va_start(valist, msg);
                 fprintf(stderr,": ");
-                vfprintf(stderr, msg, valist);
-                va_end(valist);
+                vfprintf(stderr, msg, *valist);
             }
             fputc( '\n', stderr );
             InterlockedIncrement(&todo_failures);
@@ -110,20 +156,22 @@
     {
         if (!condition)
         {
-            fprintf( stderr, "%s:%d: Test failed",
-                     data->current_file, data->current_line );
+            WINETEST_OUTPUT_LINE( data, "Test failed")
             if (msg && msg[0])
             {
-                va_start(valist, msg);
                 fprintf( stderr,": ");
-                vfprintf(stderr, msg, valist);
-                va_end(valist);
+                vfprintf(stderr, msg, *valist);
             }
             fputc( '\n', stderr );
             InterlockedIncrement(&failures);
             return 0;
         }
-        else InterlockedIncrement(&successes);
+        else
+        {
+            if( winetest_report_success)
+                WINETEST_OUTPUT_LINE( data, "Test succeeded\n")
+            InterlockedIncrement(&successes);
+        }
     }
     return 1;
 }
@@ -136,6 +184,19 @@
     return &winetest_ok;
 }
 
+extern void winetest_set_name( const char* name)
+{
+    tls_data* data=get_tls_data();
+    data->current_name=name;
+}
+
+extern void winetest_unset_name( void)
+{
+    tls_data* data=get_tls_data();
+    data->current_name=NULL;
+}
+
+
 void winetest_trace( const char *msg, ... )
 {
     va_list valist;
@@ -143,7 +204,7 @@
 
     if (winetest_debug > 0)
     {
-        fprintf( stderr, "%s:%d:", data->current_file, data->current_line );
+        WINETEST_OUTPUT_TRACE( data, "")
         va_start(valist, msg);
         vfprintf(stderr, msg, valist);
         va_end(valist);
@@ -227,7 +288,7 @@
                  (failures + todo_failures != 1) ? "failures" : "failure" );
     }
     status = (failures + todo_failures < 255) ? failures + todo_failures : 255;
-    return status;
+    return winetest_continue_on_fail ? 0 : status;
 }
 
 
@@ -238,6 +299,10 @@
 
     if ((p = getenv( "WINETEST_PLATFORM" ))) winetest_platform = p;
     if ((p = getenv( "WINETEST_DEBUG" ))) winetest_debug = atoi(p);
+    if ((p = getenv( "WINETEST_CONTINUE_ON_FAIL"))) winetest_continue_on_fail=\
+		atoi(p);
+    if ((p = getenv( "WINETEST_REPORT_SUCCESS"))) winetest_report_success = \
+                atoi(p);
     if (!argv[1])
     {
         fprintf( stderr, "Usage: %s test_name\n", argv[0] );
Index: programs/winetest/include/wine.pm
===================================================================
RCS file: /home/wine/wine/programs/winetest/include/wine.pm,v
retrieving revision 1.4
diff -u -r1.4 wine.pm
--- programs/winetest/include/wine.pm	10 Mar 2002 00:21:20 -0000	1.4
+++ programs/winetest/include/wine.pm	10 Apr 2002 16:03:43 -0000
@@ -26,6 +26,8 @@
 use strict;
 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD $todo_level
             $successes $failures $todo_successes $todo_failures
+            $winetest_continue_on_fail $winetest_report_success
+            $name
             %return_types %prototypes %loaded_modules);
 
 require Exporter;
@@ -41,9 +43,12 @@
              assert
              hd
              ok
+             named_ok
              todo
              todo_wine
              trace
+             set_name
+             unset_name
              wc
              wclen
             );
@@ -63,6 +68,9 @@
 $todo_successes = 0;
 $todo_failures = 0;
 %loaded_modules = ();
+$name = "";
+$winetest_report_success = defined($ENV{WINETEST_REPORT_SUCCESS}) ? $ENV{WINETEST_REPORT_SUCCESS} : 0;
+$winetest_continue_on_fail = defined($ENV{WINETEST_CONTINUE_ON_FAIL}) ? $ENV{WINETEST_CONTINUE_ON_FAIL} : 0;
 
 # --------------------------------------------------------------
 # | Return-type constants                                      |
@@ -448,28 +456,123 @@
     my $assertion = shift;
     my $description = shift;
     my ($filename, $line) = (caller (0))[1,2];
+    generic_ok( $name, $assertion, $description, $filename, $line);
+}
+
+# ----------------------------------------------------------------------
+# Subroutine:  named_ok
+#
+# Purpose:     Print a specific label with warning if something fails
+#
+# Usage:       named_ok NAME CONDITION [DESCRIPTION]
+#
+# Returns:     (none)
+# ----------------------------------------------------------------------
+sub named_ok($;$;$)
+{
+    my $name = shift;
+    my $assertion = shift;
+    my $description = shift;
+    my ($filename, $line) = (caller (0))[1,2];
+    generic_ok( $name, $assertion, $description, $filename, $line);
+}
+
+# ----------------------------------------------------------------------
+# Subroutine:  winetest_output_line
+#
+# Purpose:     Print a generic formatted line to STDERR
+#
+# Usage:       winetest_output_line filename line_number message [name
+#                   [description] ]
+#
+# Returns:     (none)
+# ----------------------------------------------------------------------
+sub winetest_output_line($;$;$;$;$)
+{
+  my $filename = shift;
+  my $line = shift;
+  my $msg = shift;
+  my $name = shift;
+  my $description = shift;
+
+      
+  $line=$name if ($name ne "");
+
+  print STDERR ("$filename:$line: $msg" .
+                ($description ? ": $description" : "") . "\n");
+}
+
+# ----------------------------------------------------------------------
+# Subroutine:  generic_ok
+#
+# Purpose:     Test an assertion and display appropriate message
+#
+# Usage:       generic_ok test_name assertion description filename line_no
+#
+# Returns:     (none)
+# ----------------------------------------------------------------------
+sub generic_ok($;$;$;$;$)
+{
+    my $name = shift;
+    my $assertion = shift;
+    my $description = shift;
+    my $filename = shift;
+    my $line = shift;
+ 
     if ($todo_level)
     {
         if ($assertion)
         {
-            print STDERR ("$filename:$line: Test succeeded inside todo block" .
-                          ($description ? ": $description" : "") . "\n");
+            winetest_output_line( $filename, $line, "Test succeeded inside todo block", $name, $description);
             $todo_failures++;
         }
-        else { $todo_successes++; }
+        else
+        {
+            $todo_successes++;
+        }
     }
     else
     {
         if (!$assertion)
         {
-            print STDERR ("$filename:$line: Test failed" .
-                          ($description ? ": $description" : "") . "\n");
+            winetest_output_line( $filename, $line, "Test failed", $name, $description);
             $failures++;
         }
-        else { $successes++; }
+        else { 
+            winetest_output_line( $filename, $line, "Test succeeded", $name, $description) if ($winetest_report_success);
+            $successes++;
+        }
     }
 }
 
+# ----------------------------------------------------------------------
+# Subroutine:  set_name
+#
+# Purpose:     Specify the name for next series of tests
+#
+# Usage:       set_name NAME
+#
+# Returns:     (none)
+# ----------------------------------------------------------------------
+sub set_name($)
+{
+    $name = shift;
+}
+
+# ----------------------------------------------------------------------
+# Subroutine:  unset_name
+#
+# Purpose:     Return to default naming scheme
+#
+# Usage:       unset_name
+#
+# Returns:     (none)
+# ----------------------------------------------------------------------
+sub unset_name()
+{
+    $name = "";
+}
+
 
 # ----------------------------------------------------------------------
 # Subroutine:  assert
@@ -562,6 +665,7 @@
                        ($failures + $todo_failures != 1) ? "failures" : "failure" );
     }
     $? = ($failures + $todo_failures < 255) ? $failures + $todo_failures : 255;
+    $? = 0 if ($winetest_continue_on_fail);
 }
 
 
-------------- next part --------------
Index: dlls/kernel/tests/atom.pl
===================================================================
RCS file: /home/wine/wine/dlls/kernel/tests/atom.pl,v
retrieving revision 1.3
diff -u -r1.3 atom.pl
--- dlls/kernel/tests/atom.pl	1 Apr 2002 21:00:42 -0000	1.3
+++ dlls/kernel/tests/atom.pl	10 Apr 2002 16:22:40 -0000
@@ -29,12 +29,12 @@
 
 # Add an atom
 my $atom = GlobalAddAtomA( $name );
-ok( ($atom >= 0xc000) && ($atom <= 0xffff) && !defined($wine::err) );
+named_ok( "Adding atom \"$name\" via GlobalAddAtomA()", ($atom >= 0xc000) && ($atom <= 0xffff) && !defined($wine::err) );
 
 # Verify that it can be found (or not) appropriately
-ok( GlobalFindAtomA($name) == $atom );
+named_ok( "Testing added atom \"".$name."\"", GlobalFindAtomA($name) == $atom );
 ok( GlobalFindAtomA(uc $name) == $atom );
-ok( !GlobalFindAtomA( "_" . $name ) );
+named_ok( "Checking can't find atom \"_$name\"", !GlobalFindAtomA( "_" . $name ) );
 
 # Add the same atom, specifying string as unicode; should
 # find the first one, not add a new one
@@ -68,16 +68,19 @@
 ok( !GlobalAddAtomW(0xffff) && ($wine::err == ERROR_INVALID_PARAMETER) );
 
 # test some in between
+set_name( "Checking GlobalAddAtom[AW](i) i < 0xbffff");
 for ($i = 0x0001; ($i <= 0xbfff); $i += 27)
 {
     ok( GlobalAddAtomA($i) && !defined($wine::err) );
     ok( GlobalAddAtomW($i) && !defined($wine::err) );
 }
+set_name( "Checking GlobalAddAtom[AW](i) 0xc000 < i < 0xfffff");
 for ($i = 0xc000; ($i <= 0xffff); $i += 29)
 {
     ok( !GlobalAddAtomA($i) && ($wine::err == ERROR_INVALID_PARAMETER) );
     ok( !GlobalAddAtomW($i) && ($wine::err == ERROR_INVALID_PARAMETER) );
 }
+unset_name();
 
 
 ################################################################
Index: dlls/kernel/tests/directory.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/tests/directory.c,v
retrieving revision 1.2
diff -u -r1.2 directory.c
--- dlls/kernel/tests/directory.c	1 Apr 2002 21:00:26 -0000	1.2
+++ dlls/kernel/tests/directory.c	10 Apr 2002 16:22:40 -0000
@@ -32,8 +32,10 @@
 
     lstrcpyA(buf, "foo");
     len_with_null = GetWindowsDirectoryA(buf, 1);
-    ok(lstrcmpA(buf, "foo") == 0, "should not touch the buffer");
-    ok(len_with_null <= MAX_PATH, "should fit into MAX_PATH");
+    named_ok("Testing GetWindowsDirectoryA() doesn't touch buffer",
+       lstrcmpA(buf, "foo") == 0, "should not touch the buffer");
+    named_ok("Testing GetWindowsDirectoryA() returns <= MAX_PATH",
+       len_with_null <= MAX_PATH, "should fit into MAX_PATH");
 
     lstrcpyA(buf, "foo");
     len = GetWindowsDirectoryA(buf, len_with_null - 1);
@@ -41,10 +43,12 @@
     ok(len == len_with_null, "should return length with terminating 0");
 
     lstrcpyA(buf, "foo");
+    set_name( "Testing GetWindowsDirectoryA");
     len = GetWindowsDirectoryA(buf, len_with_null);
     ok(lstrcmpA(buf, "foo") != 0, "should touch the buffer");
     ok(len == lstrlenA(buf), "returned length should be equal to the length of string");
     ok(len == (len_with_null - 1), "should return length without terminating 0");
+    unset_name();
 }
 
 static void test_GetWindowsDirectoryW(void)


More information about the wine-devel mailing list