Authors: Jakob Eriksson <jakov@vmlinux.org>, Dimitrie O. Paun <dpaun@rogers.com>, Ferenc Wagner <wferi@afavant.elte.hu>
New Wine test shell utility.
This commit is contained in:
parent
42fc4bec2d
commit
9f71bd9824
|
@ -1657,6 +1657,7 @@ programs/winefile/Makefile
|
|||
programs/winemenubuilder/Makefile
|
||||
programs/winemine/Makefile
|
||||
programs/winepath/Makefile
|
||||
programs/winetest/Makefile
|
||||
programs/winevdm/Makefile
|
||||
programs/winhelp/Makefile
|
||||
programs/winver/Makefile
|
||||
|
|
|
@ -29,6 +29,7 @@ SUBDIRS = \
|
|||
winemenubuilder \
|
||||
winemine \
|
||||
winepath \
|
||||
winetest \
|
||||
winevdm \
|
||||
winhelp \
|
||||
winver
|
||||
|
@ -56,6 +57,7 @@ INSTALLSUBDIRS = \
|
|||
winemenubuilder \
|
||||
winemine \
|
||||
winepath \
|
||||
winetest \
|
||||
winevdm \
|
||||
winhelp \
|
||||
winver
|
||||
|
@ -104,6 +106,7 @@ SYMLINKS = \
|
|||
winemenubuilder.exe \
|
||||
winemine.exe \
|
||||
winepath.exe \
|
||||
winetest.exe \
|
||||
winevdm.exe \
|
||||
winhelp.exe \
|
||||
winver.exe
|
||||
|
@ -226,6 +229,9 @@ winemine.exe$(DLLEXT): winemine/winemine.exe$(DLLEXT)
|
|||
winepath.exe$(DLLEXT): winepath/winepath.exe$(DLLEXT)
|
||||
$(RM) $@ && $(LN_S) winepath/winepath.exe$(DLLEXT) $@
|
||||
|
||||
winetest.exe$(DLLEXT): winetest/winetest.exe$(DLLEXT)
|
||||
$(RM) $@ && $(LN_S) winetest/winetest.exe$(DLLEXT) $@
|
||||
|
||||
winevdm.exe$(DLLEXT): winevdm/winevdm.exe$(DLLEXT)
|
||||
$(RM) $@ && $(LN_S) winevdm/winevdm.exe$(DLLEXT) $@
|
||||
|
||||
|
@ -260,6 +266,7 @@ winefile/winefile.exe$(DLLEXT): winefile
|
|||
winemenubuilder/winemenubuilder.exe$(DLLEXT): winemenubuilder
|
||||
winemine/winemine.exe$(DLLEXT): winemine
|
||||
winepath/winepath.exe$(DLLEXT): winepath
|
||||
winetest/winetest.exe$(DLLEXT): winetest
|
||||
winevdm/winevdm.exe$(DLLEXT): winevdm
|
||||
winhelp/winhelp.exe$(DLLEXT): winhelp
|
||||
winver/winver.exe$(DLLEXT): winver
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
Makefile
|
||||
winetest.exe.dbg.c
|
||||
winetest.exe.spec.c
|
||||
winetest.rc
|
||||
winetest.res
|
|
@ -0,0 +1,88 @@
|
|||
TOPSRCDIR = @top_srcdir@
|
||||
TOPOBJDIR = ../..
|
||||
SRCDIR = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
MODULE = winetest.exe
|
||||
APPMODE = gui
|
||||
IMPORTS = user32 wsock32
|
||||
|
||||
C_SRCS = \
|
||||
main.c \
|
||||
send.c \
|
||||
util.c
|
||||
|
||||
RC_SRCS = winetest.rc
|
||||
|
||||
TESTS = \
|
||||
advapi32 \
|
||||
comctl32 \
|
||||
gdi32 \
|
||||
kernel32 \
|
||||
msvcrt \
|
||||
netapi32 \
|
||||
ntdll \
|
||||
oleaut32 \
|
||||
rpcrt4 \
|
||||
shell32 \
|
||||
shlwapi \
|
||||
urlmon \
|
||||
user32 \
|
||||
wininet \
|
||||
winmm \
|
||||
winspool.drv \
|
||||
ws2_32
|
||||
|
||||
@MAKE_PROG_RULES@
|
||||
|
||||
# Special rules
|
||||
|
||||
TESTBINS = $(TESTS:%=%_test.exe$(DLLEXT))
|
||||
|
||||
winetest.rc: maketest Makefile.in
|
||||
$(SRCDIR)/maketest $(TESTBINS) > $@ || ( $(RM) $@ && exit 1 )
|
||||
|
||||
winetest.res: $(TESTBINS)
|
||||
|
||||
clean::
|
||||
$(RM) winetest.rc $(TESTBINS)
|
||||
|
||||
depend: winetest.rc
|
||||
|
||||
# rules for stripping the test executables
|
||||
|
||||
advapi32_test.exe$(DLLEXT): $(DLLDIR)/advapi32/tests/advapi32_test.exe$(DLLEXT)
|
||||
cp $(DLLDIR)/advapi32/tests/advapi32_test.exe$(DLLEXT) $@ && $(STRIP) -s $@
|
||||
comctl32_test.exe$(DLLEXT): $(DLLDIR)/comctl32/tests/comctl32_test.exe$(DLLEXT)
|
||||
cp $(DLLDIR)/comctl32/tests/comctl32_test.exe$(DLLEXT) $@ && $(STRIP) -s $@
|
||||
gdi32_test.exe$(DLLEXT): $(DLLDIR)/gdi/tests/gdi32_test.exe$(DLLEXT)
|
||||
cp $(DLLDIR)/gdi/tests/gdi32_test.exe$(DLLEXT) $@ && $(STRIP) -s $@
|
||||
kernel32_test.exe$(DLLEXT): $(DLLDIR)/kernel/tests/kernel32_test.exe$(DLLEXT)
|
||||
cp $(DLLDIR)/kernel/tests/kernel32_test.exe$(DLLEXT) $@ && $(STRIP) -s $@
|
||||
msvcrt_test.exe$(DLLEXT): $(DLLDIR)/msvcrt/tests/msvcrt_test.exe$(DLLEXT)
|
||||
cp $(DLLDIR)/msvcrt/tests/msvcrt_test.exe$(DLLEXT) $@ && $(STRIP) -s $@
|
||||
netapi32_test.exe$(DLLEXT): $(DLLDIR)/netapi32/tests/netapi32_test.exe$(DLLEXT)
|
||||
cp $(DLLDIR)/netapi32/tests/netapi32_test.exe$(DLLEXT) $@ && $(STRIP) -s $@
|
||||
ntdll_test.exe$(DLLEXT): $(DLLDIR)/ntdll/tests/ntdll_test.exe$(DLLEXT)
|
||||
cp $(DLLDIR)/ntdll/tests/ntdll_test.exe$(DLLEXT) $@ && $(STRIP) -s $@
|
||||
oleaut32_test.exe$(DLLEXT): $(DLLDIR)/oleaut32/tests/oleaut32_test.exe$(DLLEXT)
|
||||
cp $(DLLDIR)/oleaut32/tests/oleaut32_test.exe$(DLLEXT) $@ && $(STRIP) -s $@
|
||||
rpcrt4_test.exe$(DLLEXT): $(DLLDIR)/rpcrt4/tests/rpcrt4_test.exe$(DLLEXT)
|
||||
cp $(DLLDIR)/rpcrt4/tests/rpcrt4_test.exe$(DLLEXT) $@ && $(STRIP) -s $@
|
||||
shell32_test.exe$(DLLEXT): $(DLLDIR)/shell32/tests/shell32_test.exe$(DLLEXT)
|
||||
cp $(DLLDIR)/shell32/tests/shell32_test.exe$(DLLEXT) $@ && $(STRIP) -s $@
|
||||
shlwapi_test.exe$(DLLEXT): $(DLLDIR)/shlwapi/tests/shlwapi_test.exe$(DLLEXT)
|
||||
cp $(DLLDIR)/shlwapi/tests/shlwapi_test.exe$(DLLEXT) $@ && $(STRIP) -s $@
|
||||
urlmon_test.exe$(DLLEXT): $(DLLDIR)/urlmon/tests/urlmon_test.exe$(DLLEXT)
|
||||
cp $(DLLDIR)/urlmon/tests/urlmon_test.exe$(DLLEXT) $@ && $(STRIP) -s $@
|
||||
user32_test.exe$(DLLEXT): $(DLLDIR)/user/tests/user32_test.exe$(DLLEXT)
|
||||
cp $(DLLDIR)/user/tests/user32_test.exe$(DLLEXT) $@ && $(STRIP) -s $@
|
||||
wininet_test.exe$(DLLEXT): $(DLLDIR)/wininet/tests/wininet_test.exe$(DLLEXT)
|
||||
cp $(DLLDIR)/wininet/tests/wininet_test.exe$(DLLEXT) $@ && $(STRIP) -s $@
|
||||
winmm_test.exe$(DLLEXT): $(DLLDIR)/winmm/tests/winmm_test.exe$(DLLEXT)
|
||||
cp $(DLLDIR)/winmm/tests/winmm_test.exe$(DLLEXT) $@ && $(STRIP) -s $@
|
||||
winspool.drv_test.exe$(DLLEXT): $(DLLDIR)/winspool/tests/winspool.drv_test.exe$(DLLEXT)
|
||||
cp $(DLLDIR)/winspool/tests/winspool.drv_test.exe$(DLLEXT) $@ && $(STRIP) -s $@
|
||||
ws2_32_test.exe$(DLLEXT): $(DLLDIR)/winsock/tests/ws2_32_test.exe$(DLLEXT)
|
||||
cp $(DLLDIR)/winsock/tests/ws2_32_test.exe$(DLLEXT) $@ && $(STRIP) -s $@
|
||||
|
||||
### Dependencies:
|
|
@ -0,0 +1,310 @@
|
|||
/*
|
||||
* Wine Conformance Test EXE
|
||||
*
|
||||
* Copyright 2003 Jakob Eriksson (for Solid Form Sweden AB)
|
||||
* Copyright 2003 Dimitrie O. Paun
|
||||
* Copyright 2003 Ferenc Wagner
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
*
|
||||
* This program is dedicated to Anna Lindh,
|
||||
* Swedish Minister of Foreign Affairs.
|
||||
* Anna was murdered September 11, 2003.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
#include "winetest.h"
|
||||
|
||||
struct wine_test
|
||||
{
|
||||
char *name;
|
||||
int resource;
|
||||
int subtest_count;
|
||||
char **subtests;
|
||||
int is_elf;
|
||||
char *exename;
|
||||
};
|
||||
|
||||
static struct wine_test wine_tests[32];
|
||||
|
||||
static const char *wineloader;
|
||||
|
||||
void print_version ()
|
||||
{
|
||||
OSVERSIONINFOEX ver;
|
||||
BOOL ext;
|
||||
|
||||
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||
if (!(ext = GetVersionEx ((OSVERSIONINFO *) &ver)))
|
||||
{
|
||||
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
if (!GetVersionEx ((OSVERSIONINFO *) &ver))
|
||||
fatal("Can't get OS version.");
|
||||
}
|
||||
|
||||
xprintf (" dwMajorVersion=%ld\n dwMinorVersion=%ld\n"
|
||||
" dwBuildNumber=%ld\n PlatformId=%ld\n szCSDVersion=%s\n",
|
||||
ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber,
|
||||
ver.dwPlatformId, ver.szCSDVersion);
|
||||
|
||||
if (!ext) return;
|
||||
|
||||
xprintf (" wServicePackMajor=%d\n wServicePackMinor=%d\n"
|
||||
" wSuiteMask=%d\n wProductType=%d\n wReserved=%d\n",
|
||||
ver.wServicePackMajor, ver.wServicePackMinor, ver.wSuiteMask,
|
||||
ver.wProductType, ver.wReserved);
|
||||
}
|
||||
|
||||
static inline int is_dot_dir(const char* x)
|
||||
{
|
||||
return ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))));
|
||||
}
|
||||
|
||||
void remove_dir (const char *dir)
|
||||
{
|
||||
HANDLE hFind;
|
||||
WIN32_FIND_DATA wfd;
|
||||
char path[MAX_PATH];
|
||||
size_t dirlen = strlen (dir);
|
||||
|
||||
/* Make sure the directory exists before going further */
|
||||
memcpy (path, dir, dirlen);
|
||||
strcpy (path + dirlen++, "\\*");
|
||||
hFind = FindFirstFile (path, &wfd);
|
||||
if (hFind == INVALID_HANDLE_VALUE) return;
|
||||
|
||||
do {
|
||||
char *lp = wfd.cFileName;
|
||||
|
||||
if (!lp[0]) lp = wfd.cAlternateFileName; /* ? FIXME not (!lp) ? */
|
||||
if (is_dot_dir (lp)) continue;
|
||||
strcpy (path + dirlen, lp);
|
||||
if (FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes)
|
||||
remove_dir(path);
|
||||
else if (!DeleteFile (path))
|
||||
warning (strmake (NULL, "Can't delete file %s: error %d", path, GetLastError ()));
|
||||
} while (FindNextFile (hFind, &wfd));
|
||||
FindClose (hFind);
|
||||
if (!RemoveDirectory (dir))
|
||||
warning (strmake (NULL, "Can't remove directory %s: error %d", dir, GetLastError ()));
|
||||
}
|
||||
|
||||
void* extract_rcdata (int id, DWORD* size)
|
||||
{
|
||||
HRSRC rsrc;
|
||||
HGLOBAL hdl;
|
||||
|
||||
rsrc = FindResource (0, (LPTSTR)(id + 1), "USERDATA");
|
||||
if (!rsrc) return 0;
|
||||
*size = SizeofResource (0, rsrc);
|
||||
if (!*size) return 0;
|
||||
hdl = LoadResource (0, rsrc);
|
||||
if (!hdl) return 0;
|
||||
return LockResource (hdl);
|
||||
}
|
||||
|
||||
int extract_test (const char *dir, int id)
|
||||
{
|
||||
BYTE* code;
|
||||
DWORD size;
|
||||
FILE* fout;
|
||||
char buffer[128];
|
||||
int len;
|
||||
struct wine_test *test;
|
||||
|
||||
if (id >= sizeof(wine_tests)/sizeof(wine_tests[0])-1) fatal("Too many tests\n");
|
||||
|
||||
code = extract_rcdata (id, &size);
|
||||
if (!code) return 0;
|
||||
|
||||
test = &wine_tests[id];
|
||||
len = LoadStringA(0, id + 1, buffer, sizeof(buffer) );
|
||||
test->name = xmalloc( len + 1 );
|
||||
memcpy( test->name, buffer, len + 1 );
|
||||
test->is_elf = (code[1] == 'E' && code[2] == 'L' && code[3] == 'F');
|
||||
test->exename = strmake(NULL, "%s/%s", dir, test->name);
|
||||
|
||||
if (!(fout = fopen(test->exename, "wb")) ||
|
||||
(fwrite (code, size, 1, fout) != 1) ||
|
||||
fclose (fout)) fatal (strmake (NULL, "Failed to write file %s.", test->name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int get_subtests (struct wine_test tests[])
|
||||
{
|
||||
char *subname;
|
||||
FILE *subfile;
|
||||
size_t subsize, bytes_read, total;
|
||||
char buffer[8000], *index;
|
||||
const char header[] = "Valid test names:", seps[] = " \r\n";
|
||||
int oldstdout;
|
||||
const char *argv[] = {"wine", NULL, NULL};
|
||||
struct wine_test* test;
|
||||
int allocated, all_subtests = 0;
|
||||
|
||||
subname = tempnam (0, "sub");
|
||||
if (!subname) fatal ("Can't name subtests file.");
|
||||
oldstdout = dup (1);
|
||||
if (-1 == oldstdout) fatal ("Can't preserve stdout.");
|
||||
subfile = fopen (subname, "w+b");
|
||||
if (!subfile) fatal ("Can't open subtests file.");
|
||||
if (-1 == dup2 (fileno (subfile), 1))
|
||||
fatal ("Can't redirect output to subtests.");
|
||||
fclose (subfile);
|
||||
|
||||
for (test = tests; test->name; test++) {
|
||||
lseek (1, 0, SEEK_SET);
|
||||
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);
|
||||
if (subsize >= sizeof buffer) {
|
||||
fprintf (stderr, "Subtests output too big: %s.\n",
|
||||
test->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
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) {
|
||||
fprintf (stderr, "Error reading %s.\n", test->name);
|
||||
continue;
|
||||
}
|
||||
buffer[total] = 0;
|
||||
index = strstr (buffer, header);
|
||||
if (!index) {
|
||||
fprintf (stderr, "Can't parse subtests output of %s.\n",
|
||||
test->name);
|
||||
continue;
|
||||
}
|
||||
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) {
|
||||
allocated *= 2;
|
||||
test->subtests = xrealloc (test->subtests,
|
||||
allocated * sizeof (char*));
|
||||
}
|
||||
test->subtests[test->subtest_count++] = strdup (index);
|
||||
index = strtok (NULL, seps);
|
||||
}
|
||||
test->subtests = xrealloc (test->subtests,
|
||||
test->subtest_count * sizeof (char*));
|
||||
all_subtests += test->subtest_count;
|
||||
}
|
||||
close (1);
|
||||
|
||||
if (-1 == dup2 (oldstdout, 1)) fatal ("Can't recover old stdout.");
|
||||
close (oldstdout);
|
||||
|
||||
if (remove (subname)) fatal ("Can't remove subtests file.");
|
||||
free (subname);
|
||||
|
||||
return all_subtests;
|
||||
}
|
||||
|
||||
void run_test (struct wine_test* test, const char* subtest)
|
||||
{
|
||||
int status;
|
||||
const char *argv[] = {"wine", test->exename, subtest, NULL};
|
||||
|
||||
fprintf (stderr, "Running %s:%s\n", test->name, subtest);
|
||||
xprintf ("%s:%s start\n", test->name, subtest);
|
||||
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));
|
||||
xprintf ("%s:%s done (%x)\n", test->name, subtest, status);
|
||||
}
|
||||
|
||||
int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdline, int cmdshow)
|
||||
{
|
||||
struct wine_test* test;
|
||||
int nr_of_tests, subtest, i;
|
||||
char *tempdir, *logname;
|
||||
FILE *logfile;
|
||||
char build_tag[128];
|
||||
|
||||
SetErrorMode (SEM_FAILCRITICALERRORS);
|
||||
|
||||
if (!(wineloader = getenv("WINELOADER"))) wineloader = "wine";
|
||||
if (setvbuf (stdout, NULL, _IONBF, 0)) fatal ("Can't unbuffer output.");
|
||||
|
||||
tempdir = tempnam (0, "wct");
|
||||
if (!tempdir) fatal ("Can't name temporary dir (check TMP).");
|
||||
fprintf (stderr, "tempdir=%s\n", tempdir);
|
||||
if (!CreateDirectory (tempdir, NULL)) fatal (strmake (NULL, "Could not create directory: %s", tempdir));
|
||||
|
||||
logname = tempnam (0, "res");
|
||||
if (!logname) fatal ("Can't name logfile.");
|
||||
fprintf (stderr, "logname=%s\n", logname);
|
||||
|
||||
logfile = fopen (logname, "ab");
|
||||
if (!logfile) fatal ("Could not open logfile.");
|
||||
if (-1 == dup2 (fileno (logfile), 1)) fatal ("Can't redirect stdout.");
|
||||
fclose (logfile);
|
||||
|
||||
LoadStringA( 0, 0, build_tag, sizeof(build_tag) );
|
||||
xprintf ("Tests from build %s\n", build_tag);
|
||||
xprintf ("Operating system version:\n");
|
||||
print_version ();
|
||||
xprintf ("Test output:\n" );
|
||||
|
||||
i = 0;
|
||||
while (extract_test (tempdir, i)) i++;
|
||||
|
||||
nr_of_tests = get_subtests (wine_tests);
|
||||
|
||||
for (test = wine_tests; test->name; test++)
|
||||
for (subtest = 0; subtest < test->subtest_count; subtest++)
|
||||
run_test (test, test->subtests[subtest]);
|
||||
|
||||
close (1);
|
||||
|
||||
remove_dir (tempdir);
|
||||
|
||||
/* FIXME: add an explanation of what is going on */
|
||||
if (MessageBoxA( 0, "Do you want to submit the test results?", "Confirmation",
|
||||
MB_YESNO | MB_ICONQUESTION ) == IDYES)
|
||||
{
|
||||
if (send_file (logname))
|
||||
fatal ("Can't submit logfile (network of file error).");
|
||||
}
|
||||
|
||||
if (remove (logname))
|
||||
warning (strmake (NULL, "Can't remove logfile: %d.", errno));
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [ -z "$WINE_BUILD" ]; then
|
||||
WINE_BUILD="`date`"
|
||||
echo "warning: using automatically generated BUILD tag: $WINE_BUILD" 1>&2
|
||||
fi
|
||||
|
||||
echo "/* Automatically generated -- do not edit! */"
|
||||
echo "STRINGTABLE {"
|
||||
echo "0 \"$WINE_BUILD\""
|
||||
|
||||
i=0
|
||||
for test
|
||||
do
|
||||
i=$(($i+1))
|
||||
echo "$i \"$test\""
|
||||
done
|
||||
echo "}"
|
||||
|
||||
i=0
|
||||
for test
|
||||
do
|
||||
i=$(($i+1))
|
||||
echo "$i USERDATA \"$test\""
|
||||
done
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* HTTP handling functions.
|
||||
*
|
||||
* Copyright 2003 Ferenc Wagner
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
*
|
||||
*/
|
||||
#include <winsock.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "winetest.h"
|
||||
|
||||
SOCKET
|
||||
open_http (const char *ipnum)
|
||||
{
|
||||
WSADATA wsad;
|
||||
struct sockaddr_in sa;
|
||||
SOCKET s;
|
||||
|
||||
if (WSAStartup (MAKEWORD (2,2), &wsad)) return INVALID_SOCKET;
|
||||
|
||||
s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (s != INVALID_SOCKET) {
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons (80);
|
||||
sa.sin_addr.s_addr = inet_addr (ipnum);
|
||||
if (!connect (s, (struct sockaddr*)&sa,
|
||||
sizeof (struct sockaddr_in)))
|
||||
return s;
|
||||
}
|
||||
WSACleanup ();
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
int
|
||||
close_http (SOCKET s)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = closesocket (s);
|
||||
return (WSACleanup () || ret);
|
||||
}
|
||||
|
||||
int
|
||||
send_buf (SOCKET s, const char *buf, size_t length)
|
||||
{
|
||||
int sent;
|
||||
|
||||
while (length > 0) {
|
||||
sent = send (s, buf, length, 0);
|
||||
if (sent == SOCKET_ERROR) return 1;
|
||||
buf += sent;
|
||||
length -= sent;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
send_str (SOCKET s, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *p;
|
||||
int ret;
|
||||
size_t len;
|
||||
|
||||
va_start (ap, fmt);
|
||||
p = vstrmake (&len, fmt, ap);
|
||||
va_end (ap);
|
||||
if (!p) return 1;
|
||||
ret = send_buf (s, p, len);
|
||||
free (p);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
send_file (const char *name)
|
||||
{
|
||||
SOCKET s;
|
||||
FILE *f;
|
||||
unsigned char buffer[8192];
|
||||
size_t bytes_read, total, filesize;
|
||||
char *str;
|
||||
int ret;
|
||||
|
||||
/* RFC 2068 */
|
||||
#define SEP "-"
|
||||
const char head[] = "POST /~wferi/cgi-bin/winetests.cgi HTTP/1.0\r\n"
|
||||
"Host: afavant\r\n"
|
||||
"User-Agent: Winetests Shell\r\n"
|
||||
"Content-Type: multipart/form-data; boundary=" SEP "\r\n"
|
||||
"Content-Length: %u\r\n\r\n";
|
||||
const char body1[] = "--" SEP "\r\n"
|
||||
"Content-Disposition: form-data; name=reportfile; filename=\"%s\"\r\n"
|
||||
"Content-Type: application/octet-stream\r\n\r\n";
|
||||
const char body2[] = "\r\n--" SEP "\r\n"
|
||||
"Content-Dispoition: form-data; name=submit\r\n\r\n"
|
||||
"Upload File\r\n"
|
||||
"--" SEP "--\r\n";
|
||||
|
||||
s = open_http ("157.181.170.47");
|
||||
if (s == INVALID_SOCKET) {
|
||||
fprintf (stderr, "Can't open connection: %x.\n",
|
||||
WSAGetLastError ());
|
||||
return 1;
|
||||
}
|
||||
|
||||
f = fopen (name, "rb");
|
||||
if (!f) goto abort1;
|
||||
fseek (f, 0, SEEK_END);
|
||||
filesize = ftell (f);
|
||||
if (filesize > 1024*1024) goto abort2;
|
||||
fseek (f, 0, SEEK_SET);
|
||||
|
||||
str = strmake (&total, body1, name);
|
||||
ret = send_str (s, head, filesize + total + sizeof body2 - 1) ||
|
||||
send_buf (s, str, total);
|
||||
free (str);
|
||||
if (ret) {
|
||||
fprintf (stderr, "Can't send header.\n");
|
||||
goto abort2;
|
||||
}
|
||||
|
||||
while ((bytes_read = fread (buffer, 1, sizeof buffer, f)))
|
||||
if (send_buf (s, buffer, bytes_read)) {
|
||||
fprintf (stderr, "Can't send body.\n");
|
||||
goto abort2;
|
||||
}
|
||||
fclose (f);
|
||||
|
||||
if (send_buf (s, body2, sizeof body2 - 1)) {
|
||||
fprintf (stderr, "Can't send trailer.\n");
|
||||
goto abort2;
|
||||
}
|
||||
|
||||
total = 0;
|
||||
while ((bytes_read = recv (s, buffer + total,
|
||||
sizeof buffer - total, 0))) {
|
||||
if ((signed)bytes_read == SOCKET_ERROR) {
|
||||
fprintf (stderr, "Error receiving response: %d.\n",
|
||||
WSAGetLastError ());
|
||||
goto abort1;
|
||||
}
|
||||
total += bytes_read;
|
||||
if (total == sizeof buffer) {
|
||||
fprintf (stderr, "Buffer overflow.\n");
|
||||
goto abort1;
|
||||
}
|
||||
}
|
||||
if (close_http (s)) {
|
||||
fprintf (stderr, "Error closing connection.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
str = strmake (&bytes_read, "Received %s (%d bytes).\n",
|
||||
name, filesize);
|
||||
ret = memcmp (str, buffer + total - bytes_read, bytes_read);
|
||||
free (str);
|
||||
return ret!=0;
|
||||
|
||||
abort2:
|
||||
fclose (f);
|
||||
abort1:
|
||||
close_http (s);
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Utility functions.
|
||||
*
|
||||
* Copyright 2003 Dimitrie O. Paun
|
||||
* Copyright 2003 Ferenc Wagner
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
*
|
||||
*/
|
||||
#include <windows.h>
|
||||
|
||||
#include "winetest.h"
|
||||
|
||||
void fatal (const char* msg)
|
||||
{
|
||||
MessageBox (NULL, msg, "Fatal Error", MB_ICONERROR | MB_OK);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void warning (const char* msg)
|
||||
{
|
||||
MessageBox (NULL, msg, "Warning", MB_ICONWARNING | MB_OK);
|
||||
}
|
||||
|
||||
void *xmalloc (size_t len)
|
||||
{
|
||||
void *p = malloc (len);
|
||||
|
||||
if (!p) fatal ("Out of memory.");
|
||||
return p;
|
||||
}
|
||||
|
||||
void *xrealloc (void *op, size_t len)
|
||||
{
|
||||
void *p = realloc (op, len);
|
||||
|
||||
if (!p) fatal ("Out of memory.");
|
||||
return p;
|
||||
}
|
||||
|
||||
void xprintf (const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, fmt);
|
||||
if (vprintf (fmt, ap) < 0) fatal ("Can't write logs.");
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
char *vstrmake (size_t *lenp, const char *fmt, va_list ap)
|
||||
{
|
||||
size_t size = 1000;
|
||||
char *p, *q;
|
||||
int n;
|
||||
|
||||
p = malloc (size);
|
||||
if (!p) return NULL;
|
||||
while (1) {
|
||||
n = vsnprintf (p, size, fmt, ap);
|
||||
if (n < 0) size *= 2; /* Windows */
|
||||
else if ((unsigned)n >= size) size = n+1; /* glibc */
|
||||
else break;
|
||||
q = realloc (p, size);
|
||||
if (!q) {
|
||||
free (p);
|
||||
return NULL;
|
||||
}
|
||||
p = q;
|
||||
}
|
||||
if (lenp) *lenp = n;
|
||||
return p;
|
||||
}
|
||||
|
||||
char *strmake (size_t *lenp, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *p;
|
||||
|
||||
va_start (ap, fmt);
|
||||
p = vstrmake (lenp, fmt, ap);
|
||||
if (!p) fatal ("Out of memory.");
|
||||
va_end (ap);
|
||||
return p;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* winetest definitions
|
||||
*
|
||||
* Copyright 2003 Dimitrie O. Paun
|
||||
* Copyright 2003 Ferenc Wagner
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __WINETESTS_H
|
||||
#define __WINETESTS_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
void fatal (const char* msg);
|
||||
void warning (const char* msg);
|
||||
void *xmalloc (size_t len);
|
||||
void *xrealloc (void *op, size_t len);
|
||||
void xprintf (const char *fmt, ...);
|
||||
char *vstrmake (size_t *lenp, const char *fmt, va_list ap);
|
||||
char *strmake (size_t *lenp, const char *fmt, ...);
|
||||
|
||||
int send_file (const char *name);
|
||||
|
||||
#endif /* __WINETESTS_H */
|
Loading…
Reference in New Issue