2 * Wine Conformance Test EXE
4 * Copyright 2003 Jakob Eriksson (for Solid Form Sweden AB)
5 * Copyright 2003 Dimitrie O. Paun
6 * Copyright 2003 Ferenc Wagner
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
21 * This program is dedicated to Anna Lindh,
22 * Swedish Minister of Foreign Affairs.
23 * Anna was murdered September 11, 2003.
28 #include "wine/port.h"
50 static struct wine_test wine_tests
[32];
52 static const char *wineloader
;
59 ver
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEX
);
60 if (!(ext
= GetVersionEx ((OSVERSIONINFO
*) &ver
)))
62 ver
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
63 if (!GetVersionEx ((OSVERSIONINFO
*) &ver
))
64 fatal("Can't get OS version.");
67 xprintf (" dwMajorVersion=%ld\n dwMinorVersion=%ld\n"
68 " dwBuildNumber=%ld\n PlatformId=%ld\n szCSDVersion=%s\n",
69 ver
.dwMajorVersion
, ver
.dwMinorVersion
, ver
.dwBuildNumber
,
70 ver
.dwPlatformId
, ver
.szCSDVersion
);
74 xprintf (" wServicePackMajor=%d\n wServicePackMinor=%d\n"
75 " wSuiteMask=%d\n wProductType=%d\n wReserved=%d\n",
76 ver
.wServicePackMajor
, ver
.wServicePackMinor
, ver
.wSuiteMask
,
77 ver
.wProductType
, ver
.wReserved
);
80 static inline int is_dot_dir(const char* x
)
82 return ((x
[0] == '.') && ((x
[1] == 0) || ((x
[1] == '.') && (x
[2] == 0))));
85 void remove_dir (const char *dir
)
90 size_t dirlen
= strlen (dir
);
92 /* Make sure the directory exists before going further */
93 memcpy (path
, dir
, dirlen
);
94 strcpy (path
+ dirlen
++, "\\*");
95 hFind
= FindFirstFile (path
, &wfd
);
96 if (hFind
== INVALID_HANDLE_VALUE
) return;
99 char *lp
= wfd
.cFileName
;
101 if (!lp
[0]) lp
= wfd
.cAlternateFileName
; /* ? FIXME not (!lp) ? */
102 if (is_dot_dir (lp
)) continue;
103 strcpy (path
+ dirlen
, lp
);
104 if (FILE_ATTRIBUTE_DIRECTORY
& wfd
.dwFileAttributes
)
106 else if (!DeleteFile (path
))
107 warning (strmake (NULL
, "Can't delete file %s: error %d", path
, GetLastError ()));
108 } while (FindNextFile (hFind
, &wfd
));
110 if (!RemoveDirectory (dir
))
111 warning (strmake (NULL
, "Can't remove directory %s: error %d", dir
, GetLastError ()));
114 void* extract_rcdata (int id
, DWORD
* size
)
119 rsrc
= FindResource (0, (LPTSTR
)(id
+ 1), "USERDATA");
121 *size
= SizeofResource (0, rsrc
);
122 if (!*size
) return 0;
123 hdl
= LoadResource (0, rsrc
);
125 return LockResource (hdl
);
128 int extract_test (const char *dir
, int id
)
135 struct wine_test
*test
;
137 if (id
>= sizeof(wine_tests
)/sizeof(wine_tests
[0])-1) fatal("Too many tests\n");
139 code
= extract_rcdata (id
, &size
);
142 test
= &wine_tests
[id
];
143 len
= LoadStringA(0, id
+ 1, buffer
, sizeof(buffer
) );
144 test
->name
= xmalloc( len
+ 1 );
145 memcpy( test
->name
, buffer
, len
+ 1 );
146 test
->is_elf
= (code
[1] == 'E' && code
[2] == 'L' && code
[3] == 'F');
147 test
->exename
= strmake(NULL
, "%s/%s", dir
, test
->name
);
149 if (!(fout
= fopen(test
->exename
, "wb")) ||
150 (fwrite (code
, size
, 1, fout
) != 1) ||
151 fclose (fout
)) fatal (strmake (NULL
, "Failed to write file %s.", test
->name
));
155 int get_subtests (struct wine_test tests
[])
159 size_t subsize
, bytes_read
, total
;
160 char buffer
[8000], *index
;
161 const char header
[] = "Valid test names:", seps
[] = " \r\n";
163 const char *argv
[] = {"wine", NULL
, NULL
};
164 struct wine_test
* test
;
165 int allocated
, all_subtests
= 0;
167 subname
= tempnam (0, "sub");
168 if (!subname
) fatal ("Can't name subtests file.");
170 if (-1 == oldstdout
) fatal ("Can't preserve stdout.");
171 subfile
= fopen (subname
, "w+b");
172 if (!subfile
) fatal ("Can't open subtests file.");
173 if (-1 == dup2 (fileno (subfile
), 1))
174 fatal ("Can't redirect output to subtests.");
177 for (test
= tests
; test
->name
; test
++) {
178 lseek (1, 0, SEEK_SET
);
179 argv
[1] = test
->exename
;
181 spawnvp (_P_WAIT
, wineloader
, argv
);
183 spawnvp (_P_WAIT
, test
->exename
, argv
+1);
184 subsize
= lseek (1, 0, SEEK_CUR
);
185 if (subsize
>= sizeof buffer
) {
186 fprintf (stderr
, "Subtests output too big: %s.\n",
191 lseek (1, 0, SEEK_SET
);
193 while ((bytes_read
= read (1, buffer
+ total
, subsize
- total
))
194 && (signed)bytes_read
!= -1)
197 fprintf (stderr
, "Error reading %s.\n", test
->name
);
201 index
= strstr (buffer
, header
);
203 fprintf (stderr
, "Can't parse subtests output of %s.\n",
207 index
+= sizeof(header
);
209 test
->subtests
= xmalloc (allocated
* sizeof (char*));
210 test
->subtest_count
= 0;
211 index
= strtok (index
, seps
);
213 if (test
->subtest_count
== allocated
) {
215 test
->subtests
= xrealloc (test
->subtests
,
216 allocated
* sizeof (char*));
218 test
->subtests
[test
->subtest_count
++] = strdup (index
);
219 index
= strtok (NULL
, seps
);
221 test
->subtests
= xrealloc (test
->subtests
,
222 test
->subtest_count
* sizeof (char*));
223 all_subtests
+= test
->subtest_count
;
227 if (-1 == dup2 (oldstdout
, 1)) fatal ("Can't recover old stdout.");
230 if (remove (subname
)) fatal ("Can't remove subtests file.");
236 void run_test (struct wine_test
* test
, const char* subtest
)
239 const char *argv
[] = {"wine", test
->exename
, subtest
, NULL
};
241 fprintf (stderr
, "Running %s:%s\n", test
->name
, subtest
);
242 xprintf ("%s:%s start\n", test
->name
, subtest
);
244 status
= spawnvp (_P_WAIT
, wineloader
, argv
);
246 status
= spawnvp (_P_WAIT
, test
->exename
, argv
+1);
248 xprintf ("Can't run: %d, errno=%d: %s\n", status
, errno
, strerror (errno
));
249 xprintf ("%s:%s done (%x)\n", test
->name
, subtest
, status
);
252 int WINAPI
WinMain (HINSTANCE hInst
, HINSTANCE hPrevInst
, LPSTR cmdline
, int cmdshow
)
254 struct wine_test
* test
;
255 int nr_of_tests
, subtest
, i
;
256 char *tempdir
, *logname
;
260 SetErrorMode (SEM_FAILCRITICALERRORS
);
262 if (!(wineloader
= getenv("WINELOADER"))) wineloader
= "wine";
263 if (setvbuf (stdout
, NULL
, _IONBF
, 0)) fatal ("Can't unbuffer output.");
265 tempdir
= tempnam (0, "wct");
266 if (!tempdir
) fatal ("Can't name temporary dir (check TMP).");
267 fprintf (stderr
, "tempdir=%s\n", tempdir
);
268 if (!CreateDirectory (tempdir
, NULL
)) fatal (strmake (NULL
, "Could not create directory: %s", tempdir
));
270 logname
= tempnam (0, "res");
271 if (!logname
) fatal ("Can't name logfile.");
272 fprintf (stderr
, "logname=%s\n", logname
);
274 logfile
= fopen (logname
, "ab");
275 if (!logfile
) fatal ("Could not open logfile.");
276 if (-1 == dup2 (fileno (logfile
), 1)) fatal ("Can't redirect stdout.");
279 LoadStringA( 0, 0, build_tag
, sizeof(build_tag
) );
280 xprintf ("Tests from build %s\n", build_tag
);
281 xprintf ("Operating system version:\n");
283 xprintf ("Test output:\n" );
286 while (extract_test (tempdir
, i
)) i
++;
288 nr_of_tests
= get_subtests (wine_tests
);
290 for (test
= wine_tests
; test
->name
; test
++)
291 for (subtest
= 0; subtest
< test
->subtest_count
; subtest
++)
292 run_test (test
, test
->subtests
[subtest
]);
296 remove_dir (tempdir
);
298 /* FIXME: add an explanation of what is going on */
299 if (MessageBoxA( 0, "Do you want to submit the test results?", "Confirmation",
300 MB_YESNO
| MB_ICONQUESTION
) == IDYES
)
302 if (send_file (logname
))
303 fatal ("Can't submit logfile (network of file error).");
306 if (remove (logname
))
307 warning (strmake (NULL
, "Can't remove logfile: %d.", errno
));