winetest: timeout & no consoles
Ferenc Wagner
wferi at afavant.elte.hu
Mon Apr 19 17:27:23 CDT 2004
ChangeLog:
- change to console mode so that winetest runs under WinRash.
- move from spawnvp() to CreateProcess().
- force a 2-minute timeout on individual tests.
Feri.
Index: Makefile.in
===================================================================
RCS file: /home/wine/wine/programs/winetest/Makefile.in,v
retrieving revision 1.24
diff -u -r1.24 Makefile.in
--- Makefile.in 24 Mar 2004 23:40:06 -0000 1.24
+++ Makefile.in 19 Apr 2004 22:21:30 -0000
@@ -3,7 +3,7 @@
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = winetest.exe
-APPMODE = -mwindows
+APPMODE = -mconsole
IMPORTS = comctl32 user32 wsock32
C_SRCS = \
Index: main.c
===================================================================
RCS file: /home/wine/wine/programs/winetest/main.c,v
retrieving revision 1.10
diff -u -r1.10 main.c
--- main.c 31 Mar 2004 00:55:41 -0000 1.10
+++ main.c 19 Apr 2004 22:21:30 -0000
@@ -45,7 +45,6 @@
int resource;
int subtest_count;
char **subtests;
- int is_elf;
char *exename;
};
@@ -56,7 +55,7 @@
};
static struct wine_test *wine_tests;
-static struct rev_info *rev_infos;
+static struct rev_info *rev_infos = NULL;
static const char *wineloader;
@@ -194,7 +193,7 @@
return addr;
}
-/* Fills in the name, is_elf and exename fields */
+/* Fills in the name and exename fields */
void
extract_test (struct wine_test *test, const char *dir, int id)
{
@@ -218,7 +217,6 @@
*exepos = 0;
test->name = xrealloc (test->name, exepos - test->name + 1);
report (R_STEP, "Extracting: %s", test->name);
- test->is_elf = !memcmp (code+1, "ELF", 3);
if (!(fout = fopen (test->exename, "wb")) ||
(fwrite (code, size, 1, fout) != 1) ||
@@ -226,54 +224,132 @@
test->exename);
}
+/* Run a command for MS milliseconds. If OUT != NULL, also redirect
+ stdout to there.
+
+ Return the exit status, -2 if can't create process or the return
+ value of WaitForSingleObject.
+ */
+int
+run_ex (char *cmd, const char *out, DWORD ms)
+{
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ int fd, oldstdout;
+ DWORD wait, status;
+
+ GetStartupInfo (&si);
+ si.wShowWindow = SW_HIDE;
+ si.dwFlags = STARTF_USESHOWWINDOW;
+
+ if (out) {
+ fd = open (out, O_WRONLY | O_CREAT, 0666);
+ if (-1 == fd)
+ report (R_FATAL, "Can't open '%s': %d", out, errno);
+ oldstdout = dup (1);
+ if (-1 == oldstdout)
+ report (R_FATAL, "Can't save stdout: %d", errno);
+ if (-1 == dup2 (fd, 1))
+ report (R_FATAL, "Can't redirect stdout: %d", errno);
+ close (fd);
+ }
+
+ if (!CreateProcessA (NULL, cmd, NULL, NULL, TRUE, 0,
+ NULL, NULL, &si, &pi)) {
+ status = -2;
+ } else {
+ CloseHandle (pi.hThread);
+ wait = WaitForSingleObject (pi.hProcess, ms);
+ if (wait == WAIT_OBJECT_0) {
+ GetExitCodeProcess (pi.hProcess, &status);
+ } else {
+ switch (wait) {
+ case WAIT_FAILED:
+ report (R_ERROR, "Wait for '%s' failed: %d", cmd,
+ GetLastError ());
+ break;
+ case WAIT_TIMEOUT:
+ report (R_ERROR, "Process '%s' timed out.", cmd);
+ break;
+ default:
+ report (R_ERROR, "Wait returned %d", wait);
+ }
+ status = wait;
+ if (!TerminateProcess (pi.hProcess, 257))
+ report (R_ERROR, "TerminateProcess failed: %d",
+ GetLastError ());
+ wait = WaitForSingleObject (pi.hProcess, 5000);
+ switch (wait) {
+ case WAIT_FAILED:
+ report (R_ERROR,
+ "Wait for termination of '%s' failed: %d",
+ cmd, GetLastError ());
+ break;
+ case WAIT_OBJECT_0:
+ break;
+ case WAIT_TIMEOUT:
+ report (R_ERROR, "Can't kill process '%s'", cmd);
+ break;
+ default:
+ report (R_ERROR, "Waiting for termination: %d",
+ wait);
+ }
+ }
+ CloseHandle (pi.hProcess);
+ }
+
+ if (out) {
+ close (1);
+ if (-1 == dup2 (oldstdout, 1))
+ report (R_FATAL, "Can't recover stdout: %d", errno);
+ close (oldstdout);
+ }
+ return status;
+}
+
void
get_subtests (const char *tempdir, struct wine_test *test, int id)
{
char *subname;
FILE *subfile;
- size_t subsize, bytes_read, total;
- char *buffer, *index;
+ size_t total;
+ char buffer[8192], *index;
const char header[] = "Valid test names:", seps[] = " \r\n";
- int oldstdout;
- const char *argv[] = {"wine", NULL, NULL};
int allocated;
+ test->subtest_count = 0;
+
subname = tempnam (0, "sub");
if (!subname) report (R_FATAL, "Can't name subtests file.");
- oldstdout = dup (1);
- if (-1 == oldstdout) report (R_FATAL, "Can't preserve stdout.");
- subfile = fopen (subname, "w+b");
- if (!subfile) report (R_FATAL, "Can't open subtests file.");
- if (-1 == dup2 (fileno (subfile), 1))
- report (R_FATAL, "Can't redirect output to subtests.");
- fclose (subfile);
extract_test (test, tempdir, id);
- argv[1] = test->exename;
- if (test->is_elf)
- spawnvp (_P_WAIT, wineloader, argv);
- else
- spawnvp (_P_WAIT, test->exename, argv+1);
- subsize = lseek (1, 0, SEEK_CUR);
- buffer = xmalloc (subsize+1);
-
- lseek (1, 0, SEEK_SET);
- total = 0;
- while ((bytes_read = read (1, buffer + total, subsize - total))
- && (signed)bytes_read != -1)
- total += bytes_read;
- if (bytes_read)
- report (R_FATAL, "Can't get subtests of %s", test->name);
+ run_ex (test->exename, subname, 5000);
+
+ subfile = fopen (subname, "r");
+ if (!subfile) {
+ report (R_ERROR, "Can't open subtests output of %s: %d",
+ test->name, errno);
+ goto quit;
+ }
+ total = fread (buffer, 1, sizeof buffer, subfile);
+ fclose (subfile);
+ if (sizeof buffer == total) {
+ report (R_ERROR, "Subtest list of %s too big.",
+ test->name, sizeof buffer);
+ goto quit;
+ }
buffer[total] = 0;
+
index = strstr (buffer, header);
- if (!index)
- report (R_FATAL, "Can't parse subtests output of %s",
+ if (!index) {
+ report (R_ERROR, "Can't parse subtests output of %s",
test->name);
+ goto quit;
+ }
index += sizeof header;
allocated = 10;
test->subtests = xmalloc (allocated * sizeof(char*));
- test->subtest_count = 0;
index = strtok (index, seps);
while (index) {
if (test->subtest_count == allocated) {
@@ -286,34 +362,26 @@
}
test->subtests = xrealloc (test->subtests,
test->subtest_count * sizeof(char*));
- free (buffer);
- close (1);
- if (-1 == dup2 (oldstdout, 1))
- report (R_FATAL, "Can't recover old stdout.");
- close (oldstdout);
+
+ quit:
if (remove (subname))
- report (R_FATAL, "Can't remove subtests file.");
+ report (R_WARNING, "Can't delete file '%s': %d",
+ subname, errno);
free (subname);
}
-/* Return number of failures, -1 if couldn't spawn process. */
-int run_test (struct wine_test* test, const char* subtest)
+void
+run_test (struct wine_test* test, const char* subtest)
{
int status;
- const char* argv[] = {"wine", test->exename, subtest, NULL};
const char* file = get_test_source_file(test->name, subtest);
const char* rev = get_file_rev(file);
+ char *cmd = strmake (NULL, "%s %s", test->exename, subtest);
xprintf ("%s:%s start %s %s\n", test->name, subtest, file, rev);
- if (test->is_elf)
- status = spawnvp (_P_WAIT, wineloader, argv);
- else
- status = spawnvp (_P_WAIT, test->exename, argv+1);
- if (status == -1)
- xprintf ("Can't run: %d, errno=%d: %s\n",
- status, errno, strerror (errno));
+ status = run_ex (cmd, NULL, 120000);
+ free (cmd);
xprintf ("%s:%s done (%d)\n", test->name, subtest, status);
- return status;
}
BOOL CALLBACK
More information about the wine-patches
mailing list