Preliminary version of the C unit tests run-time environment.

Added make rules for building and running C unit tests.
This commit is contained in:
Alexandre Julliard 2002-02-20 19:03:59 +00:00
parent 5d5f36f7ce
commit caa03388bc
6 changed files with 238 additions and 25 deletions

View File

@ -59,10 +59,6 @@ LINT = @LINT@
LINTFLAGS = @LINTFLAGS@
ALLLINTFLAGS = $(LINTFLAGS) $(DEFS) $(OPTIONS) $(DIVINCL)
WINAPI_CHECK = $(TOPSRCDIR)/tools/winapi_check/winapi_check
WINETEST = $(TOPOBJDIR)/programs/winetest/winetest
RUNTEST = $(TOPSRCDIR)/programs/winetest/runtest
RUNTESTFLAGS = -q -P wine -M $(MODULE) -T $(TOPOBJDIR)
TESTRESULTS = $(PLTESTS:.pl=.ok) $(CTESTS:.c=.ok)
WINEBUILD = $(TOPOBJDIR)/tools/winebuild/winebuild
MAKEDEP = $(TOPOBJDIR)/tools/makedep
WRC = $(TOPOBJDIR)/tools/wrc/wrc
@ -74,6 +70,15 @@ LIBTSX11 = -L$(TOPOBJDIR)/tsx11 -lwine_tsx11
LIBUNICODE= -L$(TOPOBJDIR)/unicode -lwine_unicode
LIBUUID = -L$(TOPOBJDIR)/ole -lwine_uuid
WINETEST = $(TOPOBJDIR)/programs/winetest/winetest
RUNTEST = $(TOPSRCDIR)/programs/winetest/runtest
RUNTESTFLAGS = -q -P wine -M $(MODULE) -T $(TOPOBJDIR)
TESTRESULTS = $(PLTESTS:.pl=.ok) $(CTESTS:.c=.ok)
TESTPROGRAM = tests/$(MODULE)_test
TESTLIST = tests/testlist.c
TESTOBJS = $(TESTMAIN) $(TESTLIST:.c=.o) $(CTESTS:.c=.o)
TESTMAIN = $(TOPOBJDIR)/programs/winetest/wtmain.o
@SET_MAKE@
# Installation infos
@ -130,6 +135,9 @@ LINTS = $(C_SRCS:.c=.ln)
.c.ln:
$(LINT) -c $(ALLLINTFLAGS) $< || ( $(RM) $@ && exit 1 )
.c.ok:
$(RUNTEST) $(RUNTESTFLAGS) -p $(TESTPROGRAM) $< && touch $@
.pl.ok:
$(RUNTEST) $(RUNTESTFLAGS) $< && touch $@
@ -217,7 +225,7 @@ $(SUBDIRS:%=%/__depend__): $(MAKEDEP) dummy
cd `dirname $@` && $(MAKE) depend
depend: $(MAKEDEP) $(GEN_C_SRCS) $(SUBDIRS:%=%/__depend__)
$(MAKEDEP) $(DIVINCL) -C$(SRCDIR) $(C_SRCS) $(RC_SRCS) $(RC_SRCS16) $(MC_SRCS) $(EXTRA_SRCS) -C. $(GEN_C_SRCS)
$(MAKEDEP) $(DIVINCL) -C$(SRCDIR) $(C_SRCS) $(RC_SRCS) $(RC_SRCS16) $(MC_SRCS) $(EXTRA_SRCS) $(CTESTS) -C. $(GEN_C_SRCS)
# Rules for cleaning
@ -248,11 +256,28 @@ $(SUBDIRS:%=%/__uninstall__): dummy
test:: $(TESTRESULTS)
$(TESTRESULTS): $(WINETEST)
$(PLTESTS:.c=.ok): $(WINETEST)
$(CTESTS:.c=.ok): $(TESTPROGRAM).so
$(WINETEST):
cd $(TOPOBJDIR)/programs/winetest && $(MAKE) winetest
$(TESTMAIN):
cd $(TOPOBJDIR)/programs/winetest && $(MAKE) wtmain.o
$(TESTLIST): Makefile.in
$(TOPSRCDIR)/programs/winetest/make_ctests $(CTESTS) >$(TESTLIST) || $(RM) $(TESTLIST)
$(TESTPROGRAM).so: $(TESTPROGRAM).spec.o $(TESTOBJS)
$(LDSHARED) $(LDDLLFLAGS) $(TESTPROGRAM).spec.o $(TESTOBJS) -o $@ $(LIBWINE) $(LIBS)
$(TESTPROGRAM).tmp.o: $(TESTOBJS)
$(LDCOMBINE) $(TESTOBJS) -o $@
-strip --strip-unneeded $@
$(TESTPROGRAM).spec.c: $(TESTPROGRAM).spec $(TESTPROGRAM).tmp.o $(WINEBUILD)
$(LDPATH) $(WINEBUILD) @DLLFLAGS@ -L$(DLLDIR) -sym $(TESTPROGRAM).tmp.o -o $@ -spec $(SRCDIR)/$(TESTPROGRAM).spec
# Misc. rules
$(SPEC_SRCS:.spec=.spec.c): $(WINEBUILD)

View File

@ -11,7 +11,6 @@
DEFS = @DLLFLAGS@ -D__WINE__ $(EXTRADEFS)
LIBEXT = @LIBEXT@
SONAME = lib$(MODULE).so
IMPORTLIBS = $(IMPORTS:%=$(DLLDIR)/lib%.$(LIBEXT))
SPEC_SRCS = $(ALTNAMES:%=%.spec)
ALL_OBJS = $(MODULE).spec.o $(OBJS)

22
include/wine/test.h Normal file
View File

@ -0,0 +1,22 @@
/*
* Definitions for Wine C unit tests.
*
* Copyright (C) 2002 Alexandre Julliard
*/
#ifndef __WINE_TEST_H
#define __WINE_TEST_H
/* debug level */
extern int winetest_debug;
/* current platform */
extern const char *winetest_platform;
extern void winetest_ok( int condition, const char *msg, const char *file, int line );
#define START_TEST(name) void func_##name(void)
#define ok(test,msg) winetest_ok( (test), (msg), __FILE__, __LINE__ )
#endif /* __WINE_TEST_H */

28
programs/winetest/make_ctests Executable file
View File

@ -0,0 +1,28 @@
#!/usr/bin/perl
use strict;
print "/* Automatically generated file; DO NOT EDIT!! */\n\n";
my @testlist = @ARGV;
foreach (@testlist)
{
s!.*/([^/]+)\.c$!$1!;
printf "extern void func_%s(void);\n", $_;
}
print <<EOF;
const struct
{
const char *name;
void (*func)(void);
} winetest_testlist[] =
{
EOF
foreach (@testlist)
{
printf " { \"%s\", func_%s },\n", $_, $_;
}
print " { 0, 0 }\n};\n";

View File

@ -16,6 +16,7 @@ Usage: $0 [options] input_file [perl_args...]
Options:
-q quiet mode
-v verbose mode (can be specified multiple times)
-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
-M names set the module names to be tested
@ -31,6 +32,7 @@ $ENV{WINETEST_DEBUG} ||= 1;
my $topobjdir;
my $infile;
my $program;
my @include_dirs;
my @modules;
@ -39,6 +41,7 @@ while ($#ARGV >= 0)
{
my $arg = shift @ARGV;
if ($arg eq "-h") { usage; }
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 "-P") { $platform = shift @ARGV; next; }
@ -57,6 +60,12 @@ while ($#ARGV >= 0)
# we must have found an input file
usage unless defined($infile);
if ($infile =~ /\.c$/ && !defined($program))
{
# set program to the .c file base name if not specified otherwise
($program = $infile) =~ s/\.c$//;
}
# check/detect topobjdir
if (defined($topobjdir))
{
@ -74,20 +83,6 @@ else # try to detect it automatically
elsif (-f "../../../server/wineserver") { $topobjdir = "../../.."; }
}
# set environment variables needed for Wine
if (defined($topobjdir))
{
chop($topobjdir = `cd $topobjdir && pwd`);
$ENV{LD_LIBRARY_PATH} = $topobjdir . "/dlls:" . $topobjdir . ":" . $ENV{LD_LIBRARY_PATH};
$ENV{WINESERVER} ||= $topobjdir . "/server/wineserver";
$ENV{WINELOADER} ||= $topobjdir . "/wine";
$ENV{WINETEST_PLATFORM} = $platform || "wine";
}
else
{
$ENV{WINETEST_PLATFORM} = $platform || "windows";
}
# check for include/ dir in script source directory and append it to search path
my $basedir = $0;
if ($basedir =~ /\//) { $basedir =~ s!/[^/]+$!!; }
@ -101,10 +96,25 @@ if (@modules)
$ENV{WINEOPTIONS} .= "--dll " . join(',',@modules) . "=b";
}
# and now exec winetest
# set environment variables needed for Wine
if (defined($topobjdir))
{
exec $topobjdir . "/programs/winetest/winetest", $infile, @ARGV;
chop($topobjdir = `cd $topobjdir && pwd`);
$ENV{LD_LIBRARY_PATH} = $topobjdir . "/dlls:" . $topobjdir . ":" . $ENV{LD_LIBRARY_PATH};
$ENV{WINESERVER} ||= $topobjdir . "/server/wineserver";
$ENV{WINELOADER} ||= $topobjdir . "/wine";
$ENV{WINETEST_PLATFORM} = $platform || "wine";
$ENV{WINEPRELOAD}=($program || ($topobjdir . "/programs/winetest/winetest")) . ".so";
# try to exec the wine loader directly; if it fails continue on to normal exec
exec $ENV{WINELOADER}, $infile, @ARGV;
}
exec "winetest", $infile, @ARGV;
print STDERR "Could not exec winetest\n";
else
{
$ENV{WINETEST_PLATFORM} = $platform || "windows";
}
# and now exec the program
$program ||= "winetest";
exec $program, $infile, @ARGV;
print STDERR "Could not exec $program\n";
exit 1;

129
programs/winetest/wtmain.c Normal file
View File

@ -0,0 +1,129 @@
/*
* Main routine for Wine C unit tests.
*
* Copyright 2002 Alexandre Julliard
* Copyright 2002 Andriy Palamarchuk
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* debug level */
int winetest_debug = 1;
/* current platform */
const char *winetest_platform = "windows";
struct test
{
const char *name;
void (*func)(void);
};
extern const struct test winetest_testlist[];
static const struct test *current_test; /* test currently being run */
static int successes; /* number of successful tests */
static int failures; /* number of failures */
static int todo_successes; /* number of successful tests inside todo block */
static int todo_failures; /* number of failures inside todo block */
static int todo_level; /* current todo nesting level */
/*
* 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
*/
void winetest_ok( int condition, const char *msg, const char *file, int line )
{
if (todo_level)
{
if (condition)
{
fprintf( stderr, "%s:%d: Test succeeded inside todo block", file, line );
if (msg && msg[0]) fprintf( stderr, ": %s", msg );
fputc( '\n', stderr );
todo_failures++;
}
else todo_successes++;
}
else
{
if (!condition)
{
fprintf( stderr, "%s:%d: Test failed", file, line );
if (msg && msg[0]) fprintf( stderr, ": %s", msg );
fputc( '\n', stderr );
failures++;
}
else successes++;
}
}
/* Find a test by name */
static const struct test *find_test( const char *name )
{
const struct test *test;
const char *p;
int len;
if ((p = strrchr( name, '/' ))) name = p + 1;
if ((p = strrchr( name, '\\' ))) name = p + 1;
len = strlen(name);
if (len > 2 && !strcmp( name + len - 2, ".c" )) len -= 2;
for (test = winetest_testlist; test->name; test++)
{
if (!strncmp( test->name, name, len ) && !test->name[len]) break;
}
return test->name ? test : NULL;
}
/* Run a named test, and return exit status */
static int run_test( const char *name )
{
const struct test *test;
int status;
if (!(test = find_test( name )))
{
fprintf( stderr, "Fatal: test '%s' does not exist.\n", name );
exit(1);
}
successes = failures = todo_successes = todo_failures = 0;
todo_level = 0;
current_test = test;
test->func();
if (winetest_debug)
{
fprintf( stderr, "%s: %d tests executed, %d marked as todo, %d %s.\n",
name, successes + failures + todo_successes + todo_failures,
todo_successes, failures + todo_failures,
(failures + todo_failures != 1) ? "failures" : "failure" );
}
status = (failures + todo_failures < 255) ? failures + todo_failures : 255;
return status;
}
/* main function */
int main( int argc, char **argv )
{
char *p;
if ((p = getenv( "WINETEST_PLATFORM" ))) winetest_platform = p;
if ((p = getenv( "WINETEST_DEBUG" ))) winetest_debug = atoi(p);
if (!argv[1])
{
fprintf( stderr, "Usage: %s test_name\n", argv[0] );
exit(1);
}
exit( run_test(argv[1]) );
}