2 # Copyright 1996-1998 Marcus Meissner
3 # IPC remove code Copyright 1995 Michael Veksler
5 # This perl script automatically test runs ALL windows .exe and .scr binaries
6 # it finds (and can access) on your computer. It creates a subdirectory called
7 # runs/ and stores the output there. It also does (unique) diffs between runs.
9 # It only reruns the test if ChangeLog or the executeable is NEWER than the
10 # run file. (If you want to rerun everything inbetween releases, touch
14 # BEGIN OF USER CONFIGURATION
16 # Path to WINE executeable. If not specified, 'wine' is searched in the path.
20 # WINE options. -managed when using a windowmanager is probably not good in
25 # Path to WINE ChangeLog. Used as timestamp for new releases...
27 $changelog = '/home/marcus/wine/ChangeLog';
29 # How long before automatically killing all subprocesses
30 # 30 is good for automatic testing, 300 or more for interactive testing.
38 # truncate at how-much-lines
42 $<||die "Running this script under UID 0 is a great security risk (and risk for existing windows installations on mounted DOS/W95 partitions). If you really want to, comment out this line.\n";
44 # END OF USER CONFIGURATION
47 if (! -d
"runs") { die "no subdirectory runs/ found in $cwd. Please create one first!\n";}
49 # look for the exact path to wine executeable in case we need it for a
50 # replacement changelog.
51 if (! ($wine =~ /\//)) { # no path specified. Look it up.
52 @paths = split(/:/,$ENV{'PATH'});
53 foreach $path (@paths) {
54 if (-e
"$path/$wine" && -x
"$path/$wine") {
55 $wine = "$path/$wine";
61 # if we don't have a changelog use the modification date of the WINE executeable
62 if (! -e
$changelog) {
66 # sanity check so we just fill runs/ with errors.
67 (-x
$wine) || die "no $wine executable found!\n";
68 # dito. will print usage
69 system("$wine -h >/dev/null")||die "wine call failed:$!\n";
71 print "Using $wine as WINE executeable.\n";
72 print "Using $changelog as testrun timereference.\n";
76 # Find out all present semaphores so we don't remove them later.
82 # try to find out the IPC-ID, assume it is the first number.
84 $_ ne int($_) && next; # not a decimal number
88 if (/sem/i .. /^\s*$/ ) {
89 index($_,$USER)>=0 || next;
96 sub kill_subprocesses
{
97 local($killedalready,%parentof,%kids,$changed,%cmdline);
99 # FIXME: substitute ps command that shows PID,PPID and COMMAND
100 # On Linux' latest procps this is "ps aulc"
102 open(PSAUX
,"ps aulc|");
103 # lookup all processes, remember their parents and cmdlines.
105 $xline = <PSAUX
>; # fmtline
106 @psformat = split(/\s\s*/,$xline);
108 psline
: while (<PSAUX
>) {
110 @psline = split(/\s\s*/);
112 for ($i=0;$i<=$#psformat;$i++) {
113 if ($psformat[$i] =~ /COMMAND/) {
115 $cmdline{$pid}=$psline[$i];
118 if ($psformat[$i] =~ /PPID/ ) {
119 $parentof{$pid} = $psline[$i];
122 if ($psformat[$i] =~ /PID/ ) {
130 # find out all kids of this perlscript
136 foreach (keys %parentof) {
138 if ($kids{$parentof{$_}}) {
144 # .. but do not consider us for killing
146 # remove all processes killed in the meantime from %killedalready.
147 foreach $pid (keys %killedalready) {
148 delete $killedalready{$pid} if (!$kids{$pid} );
150 # kill all subprocesses called 'wine'. Do not kill find, diff, sh
151 # and friends, which are also subprocesses of us.
152 foreach (keys %kids) {
153 next unless ($cmdline{$_} =~ /((.|)wine|dosmod)/);
154 # if we have already killed it using -TERM, use -KILL
155 if ($killedalready{$_}) {
156 kill(9,$_); # FIXME: use correct number?
158 kill(15,$_); # FIXME: use correct number?
160 $killedalready{$_}=1;
162 alarm($waittime); # wait again...
165 # borrowed from tools/ipcl. See comments there.
166 # killing wine subprocesses unluckily leaves all of their IPC stuff lying
167 # around. We have to wipe it or we run out of it.
168 sub cleanup_wine_ipc
{
172 # try to find out the IPC-ID, assume it is the first number.
174 $_ ne int($_) && next; # not a decimal number
178 # was there before start of this script, skip it.
180 # FIXME: this doesn't work for programs started during the testrun.
182 if (/sem/i .. /^\s*$/ ) {
183 index($_,$USER)>=0 || next;
188 $sem_used{$_} && next;
189 semctl($_, 0, $IPC_RMID,0);
194 # kill all subwineprocesses for automatic runs.
196 print "timer triggered.\n";
200 $SIG{'ALRM'} = "alarmhandler";
202 # NOTE: following find will also cross NFS mounts, so be sure to have nothing
203 # mounted that's not on campus or add relevant ! -fstype nfs or similar.
208 $startdir = $ARGV[0] if ($ARGV[0] && (-d
$ARGV[0]));
210 open(FIND
,"find $startdir -type f \\( -name \"*.EXE\" -o -name \"*.exe\" -o -name \"*.scr\" -o -name \"*.SCR\" \\) -print|");
211 while ($exe=<FIND
>) {
214 # This could change during a testrun (by doing 'make' for instance)
215 # FIXME: doesn't handle missing libwine.so during compile...
216 (-x
$wine) || die "no $wine executable found!\n";
218 # Skip all mssetup, acmsetup , installshield whatever exes.
219 # they seem to work, mostly and starting them is just annoying.
220 next if ($exe =~ /acmsetup|unwise|testexit|_msset|isun|st4u|st5u|_mstest|_isdel|ms-setup|~ms|unin/io);
223 $runfile =~ s/[\/ ]/_
/g
;
224 $runfile =~ s/\.exe$//g;
225 $runfile =~ s/\.scr$//ig;
228 # Check if changelog is newer, if not, continue
230 if ( -e
"runs/${runfile}.out" &&
231 (-M
$changelog > -M
"runs/${runfile}.out") &&
232 (-M
$exe > -M
"runs/${runfile}.out")
234 #print "skipping $exe, already done.\n";
240 $dir =~ s/^(.*)\/[^\/]*$/$1/; #cut of the basename.
244 chdir($dir)||die "$dir:$!";
245 if ($exe =~ /\.scr/i) {
246 system("echo quit|$wine $wineoptions \"$exe /s\" >$cwd/${runfile}.out 2>&1");
248 system("echo quit|$wine $wineoptions \"$exe\" >$cwd/${runfile}.out 2>&1");
250 alarm(1000);# so it doesn't trigger in the diff, kill or find.
252 system("touch $cwd/runs/${runfile}.out");
253 system("$diff $cwd/runs/${runfile}.out $cwd/${runfile}.out|head -$trunclines");
254 system("head -$trunclines $cwd/${runfile}.out >$cwd/runs/${runfile}.out");
255 unlink("$cwd/${runfile}.out");