Release 981025.
[wine/gsoc-2012-control.git] / tools / testrun
blob665cbe2e7f77317765fabbd3a667720dad254203
1 #!/usr/bin/perl
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
11 # ChangeLog.)
14 # BEGIN OF USER CONFIGURATION
16 # Path to WINE executeable. If not specified, 'wine' is searched in the path.
18 $wine = 'wine';
20 # WINE options. -managed when using a windowmanager is probably not good in
21 # automatic testruns.
23 $wineoptions='';
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.
32 $waittime = 50;
34 #diff command
36 $diff='diff -u';
38 # truncate at how-much-lines
40 $trunclines=200;
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";
56 last;
61 # if we don't have a changelog use the modification date of the WINE executeable
62 if (! -e $changelog) {
63 $changelog = $wine;
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";
74 chomp($cwd = `pwd`);
76 # Find out all present semaphores so we don't remove them later.
77 $IPC_RMID=0;
78 $USER=$ENV{'USER'};
79 open(IPCS,"ipcs|");
80 while(<IPCS>) {
81 split;
82 # try to find out the IPC-ID, assume it is the first number.
83 foreach (@_) {
84 $_ ne int($_) && next; # not a decimal number
85 $num=$_;
86 last;
88 if (/sem/i .. /^\s*$/ ) {
89 index($_,$USER)>=0 || next;
90 $sem_used{$num}=1;
91 print "found $num\n";
94 close(IPCS);
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.
104 %parentof=();
105 $xline = <PSAUX>; # fmtline
106 @psformat = split(/\s\s*/,$xline);
108 psline: while (<PSAUX>) {
109 chop;
110 @psline = split(/\s\s*/);
111 $pid=0;
112 for ($i=0;$i<=$#psformat;$i++) {
113 if ($psformat[$i] =~ /COMMAND/) {
114 die unless $pid;
115 $cmdline{$pid}=$psline[$i];
116 break;
118 if ($psformat[$i] =~ /PPID/ ) {
119 $parentof{$pid} = $psline[$i];
120 next;
122 if ($psformat[$i] =~ /PID/ ) {
123 $pid = $psline[$i];
124 next;
128 close(PSAUX);
130 # find out all kids of this perlscript
131 %kids = ();
132 $kids{$$} = 1;
133 $changed = 1;
134 while ($changed) {
135 $changed = 0;
136 foreach (keys %parentof) {
137 next if ($kids{$_});
138 if ($kids{$parentof{$_}}) {
139 $changed = 1;
140 $kids{$_}=1;
144 # .. but do not consider us for killing
145 delete $kids{$$};
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?
157 } else {
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 {
169 open(IPCS,"ipcs|");
170 while(<IPCS>) {
171 split;
172 # try to find out the IPC-ID, assume it is the first number.
173 foreach (@_) {
174 $_ ne int($_) && next; # not a decimal number
175 $num=$_;
176 last;
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;
184 push(@sem,$num);
187 foreach (@sem) {
188 $sem_used{$_} && next;
189 semctl($_, 0, $IPC_RMID,0);
191 close(IPCS);
194 # kill all subwineprocesses for automatic runs.
195 sub alarmhandler {
196 print "timer triggered.\n";
197 &kill_subprocesses;
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.
206 open(FIND,"find / -type f \\( -name \"*.EXE\" -o -name \"*.exe\" -o -name \"*.scr\" -o -name \"*.SCR\" \\) -print|");
207 while ($exe=<FIND>) {
208 chop($exe);
210 # This could change during a testrun (by doing 'make' for instance)
211 # FIXME: doesn't handle missing libwine.so during compile...
212 (-x $wine) || die "no $wine executable found!\n";
214 # Skip all mssetup, acmsetup , installshield whatever exes.
215 # they seem to work, mostly and starting them is just annoying.
216 next if ($exe =~ /acmsetup|unwise|testexit|_msset|isun|st4u|st5u|_mstest|_isdel|ms-setup|~ms|unin/io);
218 $runfile = $exe;
219 $runfile =~ s/[\/ ]/_/g;
220 $runfile =~ s/\.exe$//g;
221 $runfile =~ s/\.scr$//ig;
222 $flag=0;
224 # Check if changelog is newer, if not, continue
226 if ( -e "runs/${runfile}.out" &&
227 (-M $changelog > -M "runs/${runfile}.out") &&
228 (-M $exe > -M "runs/${runfile}.out")
230 #print "skipping $exe, already done.\n";
231 next;
233 # now testrun...
234 print "$exe:\n";
235 $dir = $exe;
236 $dir =~ s/^(.*)\/[^\/]*$/$1/; #cut of the basename.
238 alarm($waittime);
240 chdir($dir)||die "$dir:$!";
241 if ($exe =~ /\.scr/i) {
242 system("echo quit|$wine $wineoptions \"$exe /s\" >$cwd/${runfile}.out 2>&1");
243 } else {
244 system("echo quit|$wine $wineoptions \"$exe\" >$cwd/${runfile}.out 2>&1");
246 alarm(1000);# so it doesn't trigger in the diff, kill or find.
248 system("touch $cwd/runs/${runfile}.out");
249 system("$diff $cwd/runs/${runfile}.out $cwd/${runfile}.out");
250 system("head -$trunclines $cwd/${runfile}.out >$cwd/runs/${runfile}.out");
251 unlink("$cwd/${runfile}.out");
252 &kill_subprocesses;
253 &cleanup_wine_ipc;
254 chdir($cwd);
256 close(FIND);