Fixed a couple of crashes.
[wine.git] / tools / testrun
blob831a82aa97208a6c4ceabe3b402e3afb5a4c7635
1 #!/usr/bin/perl
2 # Copyright 1996-1998 Marcus Meissner
3 # IPC remove code Copyright 1995 Michael Veksler
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2.1 of the License, or (at your option) any later version.
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 # NOTES:
21 # This perl script automatically test runs ALL windows .exe and .scr binaries
22 # it finds (and can access) on your computer. It creates a subdirectory called
23 # runs/ and stores the output there. It also does (unique) diffs between runs.
25 # It only reruns the test if ChangeLog or the executeable is NEWER than the
26 # run file. (If you want to rerun everything inbetween releases, touch
27 # ChangeLog.)
30 # BEGIN OF USER CONFIGURATION
32 # Path to WINE executeable. If not specified, 'wine' is searched in the path.
34 $wine = 'wine';
36 # WINE options. -managed when using a windowmanager is probably not good in
37 # automatic testruns.
39 $wineoptions='';
41 # Path to WINE ChangeLog. Used as timestamp for new releases...
43 $changelog = '/home/marcus/wine/ChangeLog';
45 # How long before automatically killing all subprocesses
46 # 30 is good for automatic testing, 300 or more for interactive testing.
48 $waittime = 50;
50 #diff command
52 $diff='diff -u';
54 # truncate at how-much-lines
56 $trunclines=200;
58 $<||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";
60 # END OF USER CONFIGURATION
63 if (! -d "runs") { die "no subdirectory runs/ found in $cwd. Please create one first!\n";}
65 # look for the exact path to wine executeable in case we need it for a
66 # replacement changelog.
67 if (! ($wine =~ /\//)) { # no path specified. Look it up.
68 @paths = split(/:/,$ENV{'PATH'});
69 foreach $path (@paths) {
70 if (-e "$path/$wine" && -x "$path/$wine") {
71 $wine = "$path/$wine";
72 last;
77 # if we don't have a changelog use the modification date of the WINE executeable
78 if (! -e $changelog) {
79 $changelog = $wine;
82 # sanity check so we just fill runs/ with errors.
83 (-x $wine) || die "no $wine executable found!\n";
84 # dito. will print usage
85 system("$wine -h >/dev/null")||die "wine call failed:$!\n";
87 print "Using $wine as WINE executeable.\n";
88 print "Using $changelog as testrun timereference.\n";
90 chomp($cwd = `pwd`);
92 # Find out all present semaphores so we don't remove them later.
93 $IPC_RMID=0;
94 $USER=$ENV{'USER'};
95 open(IPCS,"ipcs|");
96 while(<IPCS>) {
97 split;
98 # try to find out the IPC-ID, assume it is the first number.
99 foreach (@_) {
100 $_ ne int($_) && next; # not a decimal number
101 $num=$_;
102 last;
104 if (/sem/i .. /^\s*$/ ) {
105 index($_,$USER)>=0 || next;
106 $sem_used{$num}=1;
107 print "found $num\n";
110 close(IPCS);
112 sub kill_subprocesses {
113 local($killedalready,%parentof,%kids,$changed,%cmdline);
115 # FIXME: substitute ps command that shows PID,PPID and COMMAND
116 # On Linux' latest procps this is "ps aulc"
118 open(PSAUX,"ps aulc|");
119 # lookup all processes, remember their parents and cmdlines.
120 %parentof=();
121 $xline = <PSAUX>; # fmtline
122 @psformat = split(/\s\s*/,$xline);
124 psline: while (<PSAUX>) {
125 chop;
126 @psline = split(/\s\s*/);
127 $pid=0;
128 for ($i=0;$i<=$#psformat;$i++) {
129 if ($psformat[$i] =~ /COMMAND/) {
130 die unless $pid;
131 $cmdline{$pid}=$psline[$i];
132 break;
134 if ($psformat[$i] =~ /PPID/ ) {
135 $parentof{$pid} = $psline[$i];
136 next;
138 if ($psformat[$i] =~ /PID/ ) {
139 $pid = $psline[$i];
140 next;
144 close(PSAUX);
146 # find out all kids of this perlscript
147 %kids = ();
148 $kids{$$} = 1;
149 $changed = 1;
150 while ($changed) {
151 $changed = 0;
152 foreach (keys %parentof) {
153 next if ($kids{$_});
154 if ($kids{$parentof{$_}}) {
155 $changed = 1;
156 $kids{$_}=1;
160 # .. but do not consider us for killing
161 delete $kids{$$};
162 # remove all processes killed in the meantime from %killedalready.
163 foreach $pid (keys %killedalready) {
164 delete $killedalready{$pid} if (!$kids{$pid} );
166 # kill all subprocesses called 'wine'. Do not kill find, diff, sh
167 # and friends, which are also subprocesses of us.
168 foreach (keys %kids) {
169 next unless ($cmdline{$_} =~ /((.|)wine|dosmod)/);
170 # if we have already killed it using -TERM, use -KILL
171 if ($killedalready{$_}) {
172 kill(9,$_); # FIXME: use correct number?
173 } else {
174 kill(15,$_); # FIXME: use correct number?
176 $killedalready{$_}=1;
178 alarm($waittime); # wait again...
181 # borrowed from tools/ipcl. See comments there.
182 # killing wine subprocesses unluckily leaves all of their IPC stuff lying
183 # around. We have to wipe it or we run out of it.
184 sub cleanup_wine_ipc {
185 open(IPCS,"ipcs|");
186 while(<IPCS>) {
187 split;
188 # try to find out the IPC-ID, assume it is the first number.
189 foreach (@_) {
190 $_ ne int($_) && next; # not a decimal number
191 $num=$_;
192 last;
194 # was there before start of this script, skip it.
196 # FIXME: this doesn't work for programs started during the testrun.
198 if (/sem/i .. /^\s*$/ ) {
199 index($_,$USER)>=0 || next;
200 push(@sem,$num);
203 foreach (@sem) {
204 $sem_used{$_} && next;
205 semctl($_, 0, $IPC_RMID,0);
207 close(IPCS);
210 # kill all subwineprocesses for automatic runs.
211 sub alarmhandler {
212 print "timer triggered.\n";
213 &kill_subprocesses;
216 $SIG{'ALRM'} = "alarmhandler";
218 # NOTE: following find will also cross NFS mounts, so be sure to have nothing
219 # mounted that's not on campus or add relevant ! -fstype nfs or similar.
222 $startdir = '/';
224 $startdir = $ARGV[0] if ($ARGV[0] && (-d $ARGV[0]));
226 open(FIND,"find $startdir -type f \\( -name \"*.EXE\" -o -name \"*.exe\" -o -name \"*.scr\" -o -name \"*.SCR\" \\) -print|");
227 while ($exe=<FIND>) {
228 chop($exe);
230 # This could change during a testrun (by doing 'make' for instance)
231 # FIXME: doesn't handle missing libwine.so during compile...
232 (-x $wine) || die "no $wine executable found!\n";
234 # Skip all mssetup, acmsetup , installshield whatever exes.
235 # they seem to work, mostly and starting them is just annoying.
236 next if ($exe =~ /acmsetup|unwise|testexit|_msset|isun|st4u|st5u|_mstest|_isdel|ms-setup|~ms|unin/io);
238 $runfile = $exe;
239 $runfile =~ s/[\/ ]/_/g;
240 $runfile =~ s/\.exe$//g;
241 $runfile =~ s/\.scr$//ig;
242 $flag=0;
244 # Check if changelog is newer, if not, continue
246 if ( -e "runs/${runfile}.out" &&
247 (-M $changelog > -M "runs/${runfile}.out") &&
248 (-M $exe > -M "runs/${runfile}.out")
250 #print "skipping $exe, already done.\n";
251 next;
253 # now testrun...
254 print "$exe:\n";
255 $dir = $exe;
256 $dir =~ s/^(.*)\/[^\/]*$/$1/; #cut of the basename.
258 alarm($waittime);
260 chdir($dir)||die "$dir:$!";
261 if ($exe =~ /\.scr/i) {
262 system("echo quit|$wine $wineoptions \"$exe /s\" >$cwd/${runfile}.out 2>&1");
263 } else {
264 system("echo quit|$wine $wineoptions \"$exe\" >$cwd/${runfile}.out 2>&1");
266 alarm(1000);# so it doesn't trigger in the diff, kill or find.
268 system("touch $cwd/runs/${runfile}.out");
269 system("$diff $cwd/runs/${runfile}.out $cwd/${runfile}.out|head -n $trunclines");
270 system("head -n $trunclines $cwd/${runfile}.out >$cwd/runs/${runfile}.out");
271 unlink("$cwd/${runfile}.out");
272 &kill_subprocesses;
273 &cleanup_wine_ipc;
274 chdir($cwd);
276 close(FIND);