1*9512fe85Sahl#!/usr/perl5/bin/perl
2*9512fe85Sahl#
3*9512fe85Sahl# CDDL HEADER START
4*9512fe85Sahl#
5*9512fe85Sahl# The contents of this file are subject to the terms of the
6*9512fe85Sahl# Common Development and Distribution License (the "License").
7*9512fe85Sahl# You may not use this file except in compliance with the License.
8*9512fe85Sahl#
9*9512fe85Sahl# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*9512fe85Sahl# or http://www.opensolaris.org/os/licensing.
11*9512fe85Sahl# See the License for the specific language governing permissions
12*9512fe85Sahl# and limitations under the License.
13*9512fe85Sahl#
14*9512fe85Sahl# When distributing Covered Code, include this CDDL HEADER in each
15*9512fe85Sahl# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*9512fe85Sahl# If applicable, add the following below this CDDL HEADER, with the
17*9512fe85Sahl# fields enclosed by brackets "[]" replaced with your own identifying
18*9512fe85Sahl# information: Portions Copyright [yyyy] [name of copyright owner]
19*9512fe85Sahl#
20*9512fe85Sahl# CDDL HEADER END
21*9512fe85Sahl#
22*9512fe85Sahl
23*9512fe85Sahl#
24*9512fe85Sahl# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
25*9512fe85Sahl# Use is subject to license terms.
26*9512fe85Sahl#
27*9512fe85Sahl#ident	"%Z%%M%	%I%	%E% SMI"
28*9512fe85Sahl
29*9512fe85Sahlrequire 5.6.1;
30*9512fe85Sahl
31*9512fe85Sahluse File::Find;
32*9512fe85Sahluse File::Basename;
33*9512fe85Sahluse Getopt::Std;
34*9512fe85Sahluse Cwd;
35*9512fe85Sahl
36*9512fe85Sahl$PNAME = $0;
37*9512fe85Sahl$PNAME =~ s:.*/::;
38*9512fe85Sahl$USAGE = "Usage: $PNAME [-abghlqsu] [-d dir] [-i isa] "
39*9512fe85Sahl    . "[-x opt[=arg]] [file | dir ...]\n";
40*9512fe85Sahl($MACH = `uname -p`) =~ s/\W*\n//;
41*9512fe85Sahl
42*9512fe85Sahl$dtrace_path = '/usr/sbin/dtrace';
43*9512fe85Sahl@dtrace_argv = ();
44*9512fe85Sahl
45*9512fe85Sahl$ksh_path = '/usr/bin/ksh';
46*9512fe85Sahl
47*9512fe85Sahl@files = ();
48*9512fe85Sahl$errs = 0;
49*9512fe85Sahl$bypassed = 0;
50*9512fe85Sahl
51*9512fe85Sahl#
52*9512fe85Sahl# If no test files are specified on the command-line, execute a find on "."
53*9512fe85Sahl# and append any tst.*.d, tst.*.ksh, err.*.d or drp.*.d files found within
54*9512fe85Sahl# the directory tree.
55*9512fe85Sahl#
56*9512fe85Sahlsub wanted
57*9512fe85Sahl{
58*9512fe85Sahl	push(@files, $File::Find::name)
59*9512fe85Sahl	    if ($_ =~ /^(tst|err|drp)\..+\.(d|ksh)$/ && -f "$_");
60*9512fe85Sahl}
61*9512fe85Sahl
62*9512fe85Sahlsub dirname {
63*9512fe85Sahl	my($s) = @_;
64*9512fe85Sahl	my($i);
65*9512fe85Sahl
66*9512fe85Sahl	$s = substr($s, 0, $i) if (($i = rindex($s, '/')) != -1);
67*9512fe85Sahl	return $i == -1 ? '.' : $i == 0 ? '/' : $s;
68*9512fe85Sahl}
69*9512fe85Sahl
70*9512fe85Sahlsub usage
71*9512fe85Sahl{
72*9512fe85Sahl	print $USAGE;
73*9512fe85Sahl	print "\t -a  execute test suite using anonymous enablings\n";
74*9512fe85Sahl	print "\t -b  execute bad ioctl test program\n";
75*9512fe85Sahl	print "\t -d  specify directory for test results files and cores\n";
76*9512fe85Sahl	print "\t -g  enable libumem debugging when running tests\n";
77*9512fe85Sahl	print "\t -h  display verbose usage message\n";
78*9512fe85Sahl	print "\t -i  specify ISA to test instead of isaexec(3C) default\n";
79*9512fe85Sahl	print "\t -l  save log file of results and PIDs used by tests\n";
80*9512fe85Sahl	print "\t -q  set quiet mode (only report errors and summary)\n";
81*9512fe85Sahl	print "\t -s  save results files even for tests that pass\n";
82*9512fe85Sahl	print "\t -x  pass corresponding -x argument to dtrace(1M)\n";
83*9512fe85Sahl	exit(2);
84*9512fe85Sahl}
85*9512fe85Sahl
86*9512fe85Sahlsub errmsg
87*9512fe85Sahl{
88*9512fe85Sahl	my($msg) = @_;
89*9512fe85Sahl
90*9512fe85Sahl	print STDERR $msg;
91*9512fe85Sahl	print LOG $msg if ($opt_l);
92*9512fe85Sahl	$errs++;
93*9512fe85Sahl}
94*9512fe85Sahl
95*9512fe85Sahlsub fail
96*9512fe85Sahl{
97*9512fe85Sahl	my(@parms) = @_;
98*9512fe85Sahl	my($msg) = $parms[0];
99*9512fe85Sahl	my($errfile) = $parms[1];
100*9512fe85Sahl	my($n) = 0;
101*9512fe85Sahl	my($dest) = basename($file);
102*9512fe85Sahl
103*9512fe85Sahl	while (-d "$opt_d/failure.$n") {
104*9512fe85Sahl		$n++;
105*9512fe85Sahl	}
106*9512fe85Sahl
107*9512fe85Sahl	unless (mkdir "$opt_d/failure.$n") {
108*9512fe85Sahl		warn "ERROR: failed to make directory $opt_d/failure.$n: $!\n";
109*9512fe85Sahl		exit(125);
110*9512fe85Sahl	}
111*9512fe85Sahl
112*9512fe85Sahl	open(README, ">$opt_d/failure.$n/README");
113*9512fe85Sahl	print README "ERROR: " . $file . " " . $msg;
114*9512fe85Sahl
115*9512fe85Sahl	if (scalar @parms > 1) {
116*9512fe85Sahl		print README "; see $errfile\n";
117*9512fe85Sahl	} else {
118*9512fe85Sahl		if (-f "$opt_d/$pid.core") {
119*9512fe85Sahl			print README "; see $pid.core\n";
120*9512fe85Sahl		} else {
121*9512fe85Sahl			print README "\n";
122*9512fe85Sahl		}
123*9512fe85Sahl	}
124*9512fe85Sahl
125*9512fe85Sahl	close(README);
126*9512fe85Sahl
127*9512fe85Sahl	if (-f "$opt_d/$pid.out") {
128*9512fe85Sahl		rename("$opt_d/$pid.out", "$opt_d/failure.$n/$pid.out");
129*9512fe85Sahl		link("$file.out", "$opt_d/failure.$n/$dest.out");
130*9512fe85Sahl	}
131*9512fe85Sahl
132*9512fe85Sahl	if (-f "$opt_d/$pid.err") {
133*9512fe85Sahl		rename("$opt_d/$pid.err", "$opt_d/failure.$n/$pid.err");
134*9512fe85Sahl		link("$file.err", "$opt_d/failure.$n/$dest.err");
135*9512fe85Sahl	}
136*9512fe85Sahl
137*9512fe85Sahl	if (-f "$opt_d/$pid.core") {
138*9512fe85Sahl		rename("$opt_d/$pid.core", "$opt_d/failure.$n/$pid.core");
139*9512fe85Sahl	}
140*9512fe85Sahl
141*9512fe85Sahl	link("$file", "$opt_d/failure.$n/$dest");
142*9512fe85Sahl
143*9512fe85Sahl	$msg = "ERROR: " . $dest . " " . $msg;
144*9512fe85Sahl
145*9512fe85Sahl	if (scalar @parms > 1) {
146*9512fe85Sahl		$msg = $msg . "; see $errfile in failure.$n\n";
147*9512fe85Sahl	} else {
148*9512fe85Sahl		$msg = $msg . "; details in failure.$n\n";
149*9512fe85Sahl	}
150*9512fe85Sahl
151*9512fe85Sahl	errmsg($msg);
152*9512fe85Sahl}
153*9512fe85Sahl
154*9512fe85Sahlsub logmsg
155*9512fe85Sahl{
156*9512fe85Sahl	my($msg) = @_;
157*9512fe85Sahl
158*9512fe85Sahl	print STDOUT $msg unless ($opt_q);
159*9512fe85Sahl	print LOG $msg if ($opt_l);
160*9512fe85Sahl}
161*9512fe85Sahl
162*9512fe85Sahldie $USAGE unless (getopts('abd:ghi:lqsux:'));
163*9512fe85Sahlusage() if ($opt_h);
164*9512fe85Sahl
165*9512fe85Sahlforeach $arg (@ARGV) {
166*9512fe85Sahl	if (-f $arg) {
167*9512fe85Sahl		push(@files, $arg);
168*9512fe85Sahl	} elsif (-d $arg) {
169*9512fe85Sahl		find(\&wanted, $arg);
170*9512fe85Sahl	} else {
171*9512fe85Sahl		die "$PNAME: $arg is not a valid file or directory\n";
172*9512fe85Sahl	}
173*9512fe85Sahl}
174*9512fe85Sahl
175*9512fe85Sahl$defdir = -d '/opt/SUNWdtrt/tst' ? '/opt/SUNWdtrt/tst' : '.';
176*9512fe85Sahl$bindir = -d '/opt/SUNWdtrt/bin' ? '/opt/SUNWdtrt/bin' : '.';
177*9512fe85Sahl
178*9512fe85Sahlfind(\&wanted, "$defdir/common") if (scalar(@ARGV) == 0);
179*9512fe85Sahlfind(\&wanted, "$defdir/$MACH") if (scalar(@ARGV) == 0);
180*9512fe85Sahldie $USAGE if (scalar(@files) == 0);
181*9512fe85Sahl
182*9512fe85Sahlif ($opt_d) {
183*9512fe85Sahl	die "$PNAME: -d arg must be absolute path\n" unless ($opt_d =~ /^\//);
184*9512fe85Sahl	die "$PNAME: -d arg $opt_d is not a directory\n" unless (-d "$opt_d");
185*9512fe85Sahl	system("coreadm -p $opt_d/%p.core");
186*9512fe85Sahl} else {
187*9512fe85Sahl	my $dir = getcwd;
188*9512fe85Sahl	system("coreadm -p $dir/%p.core");
189*9512fe85Sahl	$opt_d = '.';
190*9512fe85Sahl}
191*9512fe85Sahl
192*9512fe85Sahlif ($opt_i) {
193*9512fe85Sahl	$dtrace_path = "/usr/sbin/$opt_i/dtrace";
194*9512fe85Sahl	die "$PNAME: dtrace(1M) for ISA $opt_i not found\n"
195*9512fe85Sahl	    unless (-x "$dtrace_path");
196*9512fe85Sahl}
197*9512fe85Sahl
198*9512fe85Sahlif ($opt_x) {
199*9512fe85Sahl	push(@dtrace_argv, '-x');
200*9512fe85Sahl	push(@dtrace_argv, $opt_x);
201*9512fe85Sahl}
202*9512fe85Sahl
203*9512fe85Sahldie "$PNAME: failed to open $PNAME.$$.log: $!\n"
204*9512fe85Sahl    unless (!$opt_l || open(LOG, ">$PNAME.$$.log"));
205*9512fe85Sahl
206*9512fe85Sahlif ($opt_g) {
207*9512fe85Sahl	$ENV{'UMEM_DEBUG'} = 'default,verbose';
208*9512fe85Sahl	$ENV{'UMEM_LOGGING'} = 'fail,contents';
209*9512fe85Sahl	$ENV{'LD_PRELOAD'} = 'libumem.so';
210*9512fe85Sahl}
211*9512fe85Sahl
212*9512fe85Sahl#
213*9512fe85Sahl# Ensure that $PATH contains a cc(1) so that we can execute the
214*9512fe85Sahl# test programs that require compilation of C code.
215*9512fe85Sahl#
216*9512fe85Sahl$ENV{'PATH'} = $ENV{'PATH'} . ':/ws/on10-tools/SUNWspro/SOS8/bin';
217*9512fe85Sahl
218*9512fe85Sahlif ($opt_b) {
219*9512fe85Sahl	logmsg("badioctl'ing ... ");
220*9512fe85Sahl
221*9512fe85Sahl	if (($badioctl = fork()) == -1) {
222*9512fe85Sahl		errmsg("ERROR: failed to fork to run badioctl: $!\n");
223*9512fe85Sahl		next;
224*9512fe85Sahl	}
225*9512fe85Sahl
226*9512fe85Sahl	if ($badioctl == 0) {
227*9512fe85Sahl		open(STDIN, '</dev/null');
228*9512fe85Sahl		exit(125) unless open(STDOUT, ">$opt_d/$$.out");
229*9512fe85Sahl		exit(125) unless open(STDERR, ">$opt_d/$$.err");
230*9512fe85Sahl
231*9512fe85Sahl		exec($bindir . "/badioctl");
232*9512fe85Sahl		warn "ERROR: failed to exec badioctl: $!\n";
233*9512fe85Sahl		exit(127);
234*9512fe85Sahl	}
235*9512fe85Sahl
236*9512fe85Sahl
237*9512fe85Sahl	logmsg("[$badioctl]\n");
238*9512fe85Sahl
239*9512fe85Sahl	#
240*9512fe85Sahl	# If we're going to be bad, we're just going to iterate over each
241*9512fe85Sahl	# test file.
242*9512fe85Sahl	#
243*9512fe85Sahl	foreach $file (sort @files) {
244*9512fe85Sahl		($name = $file) =~ s:.*/::;
245*9512fe85Sahl		$dir = dirname($file);
246*9512fe85Sahl
247*9512fe85Sahl		if (!($name =~ /^tst\./ && $name =~ /\.d$/)) {
248*9512fe85Sahl			next;
249*9512fe85Sahl		}
250*9512fe85Sahl
251*9512fe85Sahl		logmsg("baddof'ing $file ... ");
252*9512fe85Sahl
253*9512fe85Sahl		if (($pid = fork()) == -1) {
254*9512fe85Sahl			errmsg("ERROR: failed to fork to run baddof: $!\n");
255*9512fe85Sahl			next;
256*9512fe85Sahl		}
257*9512fe85Sahl
258*9512fe85Sahl		if ($pid == 0) {
259*9512fe85Sahl			open(STDIN, '</dev/null');
260*9512fe85Sahl			exit(125) unless open(STDOUT, ">$opt_d/$$.out");
261*9512fe85Sahl			exit(125) unless open(STDERR, ">$opt_d/$$.err");
262*9512fe85Sahl
263*9512fe85Sahl			unless (chdir($dir)) {
264*9512fe85Sahl				warn "ERROR: failed to chdir for $file: $!\n";
265*9512fe85Sahl				exit(126);
266*9512fe85Sahl			}
267*9512fe85Sahl
268*9512fe85Sahl			exec($bindir . "/baddof", $name);
269*9512fe85Sahl
270*9512fe85Sahl			warn "ERROR: failed to exec for $file: $!\n";
271*9512fe85Sahl			exit(127);
272*9512fe85Sahl		}
273*9512fe85Sahl
274*9512fe85Sahl		sleep 60;
275*9512fe85Sahl		kill(9, $pid);
276*9512fe85Sahl		waitpid($pid, 0);
277*9512fe85Sahl
278*9512fe85Sahl		logmsg("[$pid]\n");
279*9512fe85Sahl
280*9512fe85Sahl		unless ($opt_s) {
281*9512fe85Sahl			unlink($pid . '.out');
282*9512fe85Sahl			unlink($pid . '.err');
283*9512fe85Sahl		}
284*9512fe85Sahl	}
285*9512fe85Sahl
286*9512fe85Sahl	kill(9, $badioctl);
287*9512fe85Sahl	waitpid($badioctl, 0);
288*9512fe85Sahl
289*9512fe85Sahl	unless ($opt_s) {
290*9512fe85Sahl		unlink($badioctl . '.out');
291*9512fe85Sahl		unlink($badioctl . '.err');
292*9512fe85Sahl	}
293*9512fe85Sahl
294*9512fe85Sahl	exit(0);
295*9512fe85Sahl}
296*9512fe85Sahl
297*9512fe85Sahlif ($opt_u) {
298*9512fe85Sahl	logmsg "spawning module unloading process... ";
299*9512fe85Sahl
300*9512fe85Sahl	$unloader = fork;
301*9512fe85Sahl
302*9512fe85Sahl	if ($unloader != 0 && !defined $unloader) {
303*9512fe85Sahl		#
304*9512fe85Sahl		# Couldn't fork for some reason.
305*9512fe85Sahl		#
306*9512fe85Sahl		die "couldn't fork: $!\n";
307*9512fe85Sahl	}
308*9512fe85Sahl
309*9512fe85Sahl	if ($unloader == 0) {
310*9512fe85Sahl		#
311*9512fe85Sahl		# We're in the child.  Go modunload krazy.
312*9512fe85Sahl		#
313*9512fe85Sahl		for (;;) {
314*9512fe85Sahl			system("modunload -i 0");
315*9512fe85Sahl		}
316*9512fe85Sahl	} else {
317*9512fe85Sahl		logmsg "[$unloader]\n";
318*9512fe85Sahl
319*9512fe85Sahl		$SIG{INT} = sub {
320*9512fe85Sahl			kill 9, $unloader;
321*9512fe85Sahl			exit($errs != 0);
322*9512fe85Sahl		};
323*9512fe85Sahl	}
324*9512fe85Sahl}
325*9512fe85Sahl
326*9512fe85Sahl#
327*9512fe85Sahl# Iterate over the set of test files specified on the command-line or located
328*9512fe85Sahl# by a find on "." and execute each one.  If the test file is executable, we
329*9512fe85Sahl# assume it is a #! script and run it.  Otherwise we run dtrace -s on it.
330*9512fe85Sahl# If the file is named tst.* we assume it should return exit status 0.
331*9512fe85Sahl# If the file is named err.* we assume it should return exit status 1.
332*9512fe85Sahl# If the file is named err.D_[A-Z0-9]+[.*].d we use dtrace -xerrtags and
333*9512fe85Sahl# examine stderr to ensure that a matching error tag was produced.
334*9512fe85Sahl# If the file is named drp.[A-Z0-9]+[.*].d we use dtrace -xdroptags and
335*9512fe85Sahl# examine stderr to ensure that a matching drop tag was produced.
336*9512fe85Sahl# If any *.out or *.err files are found we perform output comparisons.
337*9512fe85Sahl#
338*9512fe85Sahlforeach $file (sort @files) {
339*9512fe85Sahl	$file =~ m:.*/((.*)\.(\w+)):;
340*9512fe85Sahl	$name = $1;
341*9512fe85Sahl	$base = $2;
342*9512fe85Sahl	$ext = $3;
343*9512fe85Sahl
344*9512fe85Sahl	$dir = dirname($file);
345*9512fe85Sahl	$isksh = 0;
346*9512fe85Sahl	$tag = 0;
347*9512fe85Sahl	$droptag = 0;
348*9512fe85Sahl
349*9512fe85Sahl	if ($name =~ /^tst\./) {
350*9512fe85Sahl		$isksh = ($ext eq 'ksh');
351*9512fe85Sahl		$status = 0;
352*9512fe85Sahl	} elsif ($name =~ /^err\.(D_[A-Z0-9_]+)\./) {
353*9512fe85Sahl		$status = 1;
354*9512fe85Sahl		$tag = $1;
355*9512fe85Sahl	} elsif ($name =~ /^err\./) {
356*9512fe85Sahl		$status = 1;
357*9512fe85Sahl	} elsif ($name =~ /^drp\.([A-Z0-9_]+)\./) {
358*9512fe85Sahl		$status = 0;
359*9512fe85Sahl		$droptag = $1;
360*9512fe85Sahl	} else {
361*9512fe85Sahl		errmsg("ERROR: $file is not a valid test file name\n");
362*9512fe85Sahl		next;
363*9512fe85Sahl	}
364*9512fe85Sahl
365*9512fe85Sahl	$fullname = "$dir/$name";
366*9512fe85Sahl	$exe = "$dir/$base.exe";
367*9512fe85Sahl	$exe_pid = -1;
368*9512fe85Sahl
369*9512fe85Sahl	if ($opt_a && ($status != 0 || $tag != 0 || $droptag != 0 ||
370*9512fe85Sahl	    -x $exe || $isksh || -x $fullname)) {
371*9512fe85Sahl		$bypassed++;
372*9512fe85Sahl		next;
373*9512fe85Sahl	}
374*9512fe85Sahl
375*9512fe85Sahl	if (!$isksh && -x $exe) {
376*9512fe85Sahl		if (($exe_pid = fork()) == -1) {
377*9512fe85Sahl			errmsg("ERROR: failed to fork to run $exe: $!\n");
378*9512fe85Sahl			next;
379*9512fe85Sahl		}
380*9512fe85Sahl
381*9512fe85Sahl		if ($exe_pid == 0) {
382*9512fe85Sahl			open(STDIN, '</dev/null');
383*9512fe85Sahl
384*9512fe85Sahl			exec($exe);
385*9512fe85Sahl
386*9512fe85Sahl			warn "ERROR: failed to exec $exe: $!\n";
387*9512fe85Sahl		}
388*9512fe85Sahl	}
389*9512fe85Sahl
390*9512fe85Sahl	logmsg("testing $file ... ");
391*9512fe85Sahl
392*9512fe85Sahl	if (($pid = fork()) == -1) {
393*9512fe85Sahl		errmsg("ERROR: failed to fork to run test $file: $!\n");
394*9512fe85Sahl		next;
395*9512fe85Sahl	}
396*9512fe85Sahl
397*9512fe85Sahl	if ($pid == 0) {
398*9512fe85Sahl		open(STDIN, '</dev/null');
399*9512fe85Sahl		exit(125) unless open(STDOUT, ">$opt_d/$$.out");
400*9512fe85Sahl		exit(125) unless open(STDERR, ">$opt_d/$$.err");
401*9512fe85Sahl
402*9512fe85Sahl		unless (chdir($dir)) {
403*9512fe85Sahl			warn "ERROR: failed to chdir for $file: $!\n";
404*9512fe85Sahl			exit(126);
405*9512fe85Sahl		}
406*9512fe85Sahl
407*9512fe85Sahl		push(@dtrace_argv, '-xerrtags') if ($tag);
408*9512fe85Sahl		push(@dtrace_argv, '-xdroptags') if ($droptag);
409*9512fe85Sahl		push(@dtrace_argv, $exe_pid) if ($exe_pid != -1);
410*9512fe85Sahl
411*9512fe85Sahl		if ($isksh) {
412*9512fe85Sahl			exit(123) unless open(STDIN, "<$name");
413*9512fe85Sahl			exec($ksh_path);
414*9512fe85Sahl		} elsif (-x $name) {
415*9512fe85Sahl		        warn "ERROR: $name is executable\n";
416*9512fe85Sahl			exit(1);
417*9512fe85Sahl		} else {
418*9512fe85Sahl			if ($tag == 0 && $status == $0 && $opt_a) {
419*9512fe85Sahl				push(@dtrace_argv, '-A');
420*9512fe85Sahl			}
421*9512fe85Sahl
422*9512fe85Sahl			push(@dtrace_argv, '-C');
423*9512fe85Sahl			push(@dtrace_argv, '-s');
424*9512fe85Sahl			push(@dtrace_argv, $name);
425*9512fe85Sahl			exec($dtrace_path, @dtrace_argv);
426*9512fe85Sahl		}
427*9512fe85Sahl
428*9512fe85Sahl		warn "ERROR: failed to exec for $file: $!\n";
429*9512fe85Sahl		exit(127);
430*9512fe85Sahl	}
431*9512fe85Sahl
432*9512fe85Sahl	if (waitpid($pid, 0) == -1) {
433*9512fe85Sahl		errmsg("ERROR: timed out waiting for $file\n");
434*9512fe85Sahl		kill(9, $exe_pid) if ($exe_pid != -1);
435*9512fe85Sahl		kill(9, $pid);
436*9512fe85Sahl		next;
437*9512fe85Sahl	}
438*9512fe85Sahl
439*9512fe85Sahl	kill(9, $exe_pid) if ($exe_pid != -1);
440*9512fe85Sahl
441*9512fe85Sahl	if ($tag == 0 && $status == $0 && $opt_a) {
442*9512fe85Sahl		#
443*9512fe85Sahl		# We can chuck the earler output.
444*9512fe85Sahl		#
445*9512fe85Sahl		unlink($pid . '.out');
446*9512fe85Sahl		unlink($pid . '.err');
447*9512fe85Sahl
448*9512fe85Sahl		#
449*9512fe85Sahl		# This is an anonymous enabling.  We need to get the module
450*9512fe85Sahl		# unloaded.
451*9512fe85Sahl		#
452*9512fe85Sahl		system("dtrace -ae 1> /dev/null 2> /dev/null");
453*9512fe85Sahl		system("svcadm disable -s svc:/network/nfs/mapid:default");
454*9512fe85Sahl		system("modunload -i 0 ; modunload -i 0 ; modunload -i 0");
455*9512fe85Sahl		if (!system("modinfo | grep dtrace")) {
456*9512fe85Sahl			warn "ERROR: couldn't unload dtrace\n";
457*9512fe85Sahl			system("svcadm enable " .
458*9512fe85Sahl			    "-s svc:/network/nfs/mapid:default");
459*9512fe85Sahl			exit(124);
460*9512fe85Sahl		}
461*9512fe85Sahl
462*9512fe85Sahl		#
463*9512fe85Sahl		# DTrace is gone.  Now update_drv(1M), and rip everything out
464*9512fe85Sahl		# again.
465*9512fe85Sahl		#
466*9512fe85Sahl		system("update_drv dtrace");
467*9512fe85Sahl		system("dtrace -ae 1> /dev/null 2> /dev/null");
468*9512fe85Sahl		system("modunload -i 0 ; modunload -i 0 ; modunload -i 0");
469*9512fe85Sahl		if (!system("modinfo | grep dtrace")) {
470*9512fe85Sahl			warn "ERROR: couldn't unload dtrace\n";
471*9512fe85Sahl			system("svcadm enable " .
472*9512fe85Sahl			    "-s svc:/network/nfs/mapid:default");
473*9512fe85Sahl			exit(124);
474*9512fe85Sahl		}
475*9512fe85Sahl
476*9512fe85Sahl		#
477*9512fe85Sahl		# Now bring DTrace back in.
478*9512fe85Sahl		#
479*9512fe85Sahl		system("sync ; sync");
480*9512fe85Sahl		system("dtrace -l -n bogusprobe 1> /dev/null 2> /dev/null");
481*9512fe85Sahl		system("svcadm enable -s svc:/network/nfs/mapid:default");
482*9512fe85Sahl
483*9512fe85Sahl		#
484*9512fe85Sahl		# That should have caused DTrace to reload with the new
485*9512fe85Sahl		# configuration file.  Now we can try to snag our anonymous
486*9512fe85Sahl		# state.
487*9512fe85Sahl		#
488*9512fe85Sahl		if (($pid = fork()) == -1) {
489*9512fe85Sahl			errmsg("ERROR: failed to fork to run test $file: $!\n");
490*9512fe85Sahl			next;
491*9512fe85Sahl		}
492*9512fe85Sahl
493*9512fe85Sahl		if ($pid == 0) {
494*9512fe85Sahl			open(STDIN, '</dev/null');
495*9512fe85Sahl			exit(125) unless open(STDOUT, ">$opt_d/$$.out");
496*9512fe85Sahl			exit(125) unless open(STDERR, ">$opt_d/$$.err");
497*9512fe85Sahl
498*9512fe85Sahl			push(@dtrace_argv, '-a');
499*9512fe85Sahl
500*9512fe85Sahl			unless (chdir($dir)) {
501*9512fe85Sahl				warn "ERROR: failed to chdir for $file: $!\n";
502*9512fe85Sahl				exit(126);
503*9512fe85Sahl			}
504*9512fe85Sahl
505*9512fe85Sahl			exec($dtrace_path, @dtrace_argv);
506*9512fe85Sahl			warn "ERROR: failed to exec for $file: $!\n";
507*9512fe85Sahl			exit(127);
508*9512fe85Sahl		}
509*9512fe85Sahl
510*9512fe85Sahl		if (waitpid($pid, 0) == -1) {
511*9512fe85Sahl			errmsg("ERROR: timed out waiting for $file\n");
512*9512fe85Sahl			kill(9, $pid);
513*9512fe85Sahl			next;
514*9512fe85Sahl		}
515*9512fe85Sahl	}
516*9512fe85Sahl
517*9512fe85Sahl	logmsg("[$pid]\n");
518*9512fe85Sahl	$wstat = $?;
519*9512fe85Sahl	$wifexited = ($wstat & 0xFF) == 0;
520*9512fe85Sahl	$wexitstat = ($wstat >> 8) & 0xFF;
521*9512fe85Sahl	$wtermsig = ($wstat & 0x7F);
522*9512fe85Sahl
523*9512fe85Sahl	if (!$wifexited) {
524*9512fe85Sahl		fail("died from signal $wtermsig");
525*9512fe85Sahl		next;
526*9512fe85Sahl	}
527*9512fe85Sahl
528*9512fe85Sahl	if ($wexitstat == 125) {
529*9512fe85Sahl		die "$PNAME: failed to create output file in $opt_d " .
530*9512fe85Sahl		    "(cd elsewhere or use -d)\n";
531*9512fe85Sahl	}
532*9512fe85Sahl
533*9512fe85Sahl	if ($wexitstat != $status) {
534*9512fe85Sahl		fail("returned $wexitstat instead of $status");
535*9512fe85Sahl		next;
536*9512fe85Sahl	}
537*9512fe85Sahl
538*9512fe85Sahl	if (-f "$file.out" && system("cmp -s $file.out $opt_d/$pid.out") != 0) {
539*9512fe85Sahl		fail("stdout mismatch", "$pid.out");
540*9512fe85Sahl		next;
541*9512fe85Sahl	}
542*9512fe85Sahl
543*9512fe85Sahl	if (-f "$file.err" && system("cmp -s $file.err $opt_d/$pid.err") != 0) {
544*9512fe85Sahl		fail("stderr mismatch: see $pid.err");
545*9512fe85Sahl		next;
546*9512fe85Sahl	}
547*9512fe85Sahl
548*9512fe85Sahl	if ($tag) {
549*9512fe85Sahl		open(TSTERR, "<$opt_d/$pid.err");
550*9512fe85Sahl		$tsterr = <TSTERR>;
551*9512fe85Sahl		close(TSTERR);
552*9512fe85Sahl
553*9512fe85Sahl		unless ($tsterr =~ /: \[$tag\] line \d+:/) {
554*9512fe85Sahl			fail("errtag mismatch: see $pid.err");
555*9512fe85Sahl			next;
556*9512fe85Sahl		}
557*9512fe85Sahl	}
558*9512fe85Sahl
559*9512fe85Sahl	if ($droptag) {
560*9512fe85Sahl		$found = 0;
561*9512fe85Sahl		open(TSTERR, "<$opt_d/$pid.err");
562*9512fe85Sahl
563*9512fe85Sahl		while (<TSTERR>) {
564*9512fe85Sahl			if (/\[$droptag\] /) {
565*9512fe85Sahl				$found = 1;
566*9512fe85Sahl				last;
567*9512fe85Sahl			}
568*9512fe85Sahl		}
569*9512fe85Sahl
570*9512fe85Sahl		close (TSTERR);
571*9512fe85Sahl
572*9512fe85Sahl		unless ($found) {
573*9512fe85Sahl			fail("droptag mismatch: see $pid.err");
574*9512fe85Sahl			next;
575*9512fe85Sahl		}
576*9512fe85Sahl	}
577*9512fe85Sahl
578*9512fe85Sahl	unless ($opt_s) {
579*9512fe85Sahl		unlink($pid . '.out');
580*9512fe85Sahl		unlink($pid . '.err');
581*9512fe85Sahl	}
582*9512fe85Sahl}
583*9512fe85Sahl
584*9512fe85Sahlif ($opt_a) {
585*9512fe85Sahl	#
586*9512fe85Sahl	# If we're running with anonymous enablings, we need to restore the
587*9512fe85Sahl	# .conf file.
588*9512fe85Sahl	#
589*9512fe85Sahl	system("dtrace -A 1> /dev/null 2> /dev/null");
590*9512fe85Sahl	system("dtrace -ae 1> /dev/null 2> /dev/null");
591*9512fe85Sahl	system("modunload -i 0 ; modunload -i 0 ; modunload -i 0");
592*9512fe85Sahl	system("update_drv dtrace");
593*9512fe85Sahl}
594*9512fe85Sahl
595*9512fe85Sahl$opt_q = 0; # force final summary to appear regardless of -q option
596*9512fe85Sahl
597*9512fe85Sahllogmsg("\n==== TEST RESULTS ====\n");
598*9512fe85Sahllogmsg("   passed: " . (scalar(@files) - $errs - $bypassed) . "\n");
599*9512fe85Sahl
600*9512fe85Sahlif ($bypassed) {
601*9512fe85Sahl	logmsg(" bypassed: " . $bypassed . "\n");
602*9512fe85Sahl}
603*9512fe85Sahl
604*9512fe85Sahllogmsg("   failed: " . $errs . "\n");
605*9512fe85Sahllogmsg("    total: " . scalar(@files) . "\n");
606*9512fe85Sahl
607*9512fe85Sahlif ($opt_u) {
608*9512fe85Sahl	kill 9, $unloader;
609*9512fe85Sahl	waitpid $unloader, 0;
610*9512fe85Sahl}
611*9512fe85Sahl
612*9512fe85Sahlexit($errs != 0);
613