forked from Mirrors/wine-wine
- Change to console mode so that winetest runs under WinRash.
- Move from spawnvp() to CreateProcess(). - Force a 2-minute timeout on individual tests.oldstable
parent
8fc374d8b4
commit
90baafee4e
|
@ -3,7 +3,7 @@ TOPOBJDIR = ../..
|
||||||
SRCDIR = @srcdir@
|
SRCDIR = @srcdir@
|
||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
||||||
MODULE = winetest.exe
|
MODULE = winetest.exe
|
||||||
APPMODE = -mwindows
|
APPMODE = -mconsole
|
||||||
IMPORTS = comctl32 user32 wsock32
|
IMPORTS = comctl32 user32 wsock32
|
||||||
|
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
|
|
|
@ -45,7 +45,6 @@ struct wine_test
|
||||||
int resource;
|
int resource;
|
||||||
int subtest_count;
|
int subtest_count;
|
||||||
char **subtests;
|
char **subtests;
|
||||||
int is_elf;
|
|
||||||
char *exename;
|
char *exename;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -56,7 +55,7 @@ struct rev_info
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct wine_test *wine_tests;
|
static struct wine_test *wine_tests;
|
||||||
static struct rev_info *rev_infos;
|
static struct rev_info *rev_infos = NULL;
|
||||||
|
|
||||||
static const char *wineloader;
|
static const char *wineloader;
|
||||||
|
|
||||||
|
@ -194,7 +193,7 @@ void* extract_rcdata (int id, DWORD* size)
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fills in the name, is_elf and exename fields */
|
/* Fills in the name and exename fields */
|
||||||
void
|
void
|
||||||
extract_test (struct wine_test *test, const char *dir, int id)
|
extract_test (struct wine_test *test, const char *dir, int id)
|
||||||
{
|
{
|
||||||
|
@ -218,7 +217,6 @@ extract_test (struct wine_test *test, const char *dir, int id)
|
||||||
*exepos = 0;
|
*exepos = 0;
|
||||||
test->name = xrealloc (test->name, exepos - test->name + 1);
|
test->name = xrealloc (test->name, exepos - test->name + 1);
|
||||||
report (R_STEP, "Extracting: %s", test->name);
|
report (R_STEP, "Extracting: %s", test->name);
|
||||||
test->is_elf = !memcmp (code+1, "ELF", 3);
|
|
||||||
|
|
||||||
if (!(fout = fopen (test->exename, "wb")) ||
|
if (!(fout = fopen (test->exename, "wb")) ||
|
||||||
(fwrite (code, size, 1, fout) != 1) ||
|
(fwrite (code, size, 1, fout) != 1) ||
|
||||||
|
@ -226,54 +224,132 @@ extract_test (struct wine_test *test, const char *dir, int id)
|
||||||
test->exename);
|
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 = -1;
|
||||||
|
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
|
void
|
||||||
get_subtests (const char *tempdir, struct wine_test *test, int id)
|
get_subtests (const char *tempdir, struct wine_test *test, int id)
|
||||||
{
|
{
|
||||||
char *subname;
|
char *subname;
|
||||||
FILE *subfile;
|
FILE *subfile;
|
||||||
size_t subsize, bytes_read, total;
|
size_t total;
|
||||||
char *buffer, *index;
|
char buffer[8192], *index;
|
||||||
const char header[] = "Valid test names:", seps[] = " \r\n";
|
const char header[] = "Valid test names:", seps[] = " \r\n";
|
||||||
int oldstdout;
|
|
||||||
const char *argv[] = {"wine", NULL, NULL};
|
|
||||||
int allocated;
|
int allocated;
|
||||||
|
|
||||||
|
test->subtest_count = 0;
|
||||||
|
|
||||||
subname = tempnam (0, "sub");
|
subname = tempnam (0, "sub");
|
||||||
if (!subname) report (R_FATAL, "Can't name subtests file.");
|
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);
|
extract_test (test, tempdir, id);
|
||||||
argv[1] = test->exename;
|
run_ex (test->exename, subname, 5000);
|
||||||
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);
|
subfile = fopen (subname, "r");
|
||||||
total = 0;
|
if (!subfile) {
|
||||||
while ((bytes_read = read (1, buffer + total, subsize - total))
|
report (R_ERROR, "Can't open subtests output of %s: %d",
|
||||||
&& (signed)bytes_read != -1)
|
test->name, errno);
|
||||||
total += bytes_read;
|
goto quit;
|
||||||
if (bytes_read)
|
}
|
||||||
report (R_FATAL, "Can't get subtests of %s", test->name);
|
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;
|
buffer[total] = 0;
|
||||||
|
|
||||||
index = strstr (buffer, header);
|
index = strstr (buffer, header);
|
||||||
if (!index)
|
if (!index) {
|
||||||
report (R_FATAL, "Can't parse subtests output of %s",
|
report (R_ERROR, "Can't parse subtests output of %s",
|
||||||
test->name);
|
test->name);
|
||||||
|
goto quit;
|
||||||
|
}
|
||||||
index += sizeof header;
|
index += sizeof header;
|
||||||
|
|
||||||
allocated = 10;
|
allocated = 10;
|
||||||
test->subtests = xmalloc (allocated * sizeof(char*));
|
test->subtests = xmalloc (allocated * sizeof(char*));
|
||||||
test->subtest_count = 0;
|
|
||||||
index = strtok (index, seps);
|
index = strtok (index, seps);
|
||||||
while (index) {
|
while (index) {
|
||||||
if (test->subtest_count == allocated) {
|
if (test->subtest_count == allocated) {
|
||||||
|
@ -286,34 +362,26 @@ get_subtests (const char *tempdir, struct wine_test *test, int id)
|
||||||
}
|
}
|
||||||
test->subtests = xrealloc (test->subtests,
|
test->subtests = xrealloc (test->subtests,
|
||||||
test->subtest_count * sizeof(char*));
|
test->subtest_count * sizeof(char*));
|
||||||
free (buffer);
|
|
||||||
close (1);
|
quit:
|
||||||
if (-1 == dup2 (oldstdout, 1))
|
|
||||||
report (R_FATAL, "Can't recover old stdout.");
|
|
||||||
close (oldstdout);
|
|
||||||
if (remove (subname))
|
if (remove (subname))
|
||||||
report (R_FATAL, "Can't remove subtests file.");
|
report (R_WARNING, "Can't delete file '%s': %d",
|
||||||
|
subname, errno);
|
||||||
free (subname);
|
free (subname);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return number of failures, -1 if couldn't spawn process. */
|
void
|
||||||
int run_test (struct wine_test* test, const char* subtest)
|
run_test (struct wine_test* test, const char* subtest)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
const char* argv[] = {"wine", test->exename, subtest, NULL};
|
|
||||||
const char* file = get_test_source_file(test->name, subtest);
|
const char* file = get_test_source_file(test->name, subtest);
|
||||||
const char* rev = get_file_rev(file);
|
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);
|
xprintf ("%s:%s start %s %s\n", test->name, subtest, file, rev);
|
||||||
if (test->is_elf)
|
status = run_ex (cmd, NULL, 120000);
|
||||||
status = spawnvp (_P_WAIT, wineloader, argv);
|
free (cmd);
|
||||||
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));
|
|
||||||
xprintf ("%s:%s done (%d)\n", test->name, subtest, status);
|
xprintf ("%s:%s done (%d)\n", test->name, subtest, status);
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL CALLBACK
|
BOOL CALLBACK
|
||||||
|
|
Loading…
Reference in New Issue