19512fe85Sahl#!/usr/perl5/bin/perl
29512fe85Sahl#
39512fe85Sahl# CDDL HEADER START
49512fe85Sahl#
59512fe85Sahl# The contents of this file are subject to the terms of the
69512fe85Sahl# Common Development and Distribution License (the "License").
79512fe85Sahl# You may not use this file except in compliance with the License.
89512fe85Sahl#
99512fe85Sahl# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
109512fe85Sahl# or http://www.opensolaris.org/os/licensing.
119512fe85Sahl# See the License for the specific language governing permissions
129512fe85Sahl# and limitations under the License.
139512fe85Sahl#
149512fe85Sahl# When distributing Covered Code, include this CDDL HEADER in each
159512fe85Sahl# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
169512fe85Sahl# If applicable, add the following below this CDDL HEADER, with the
179512fe85Sahl# fields enclosed by brackets "[]" replaced with your own identifying
189512fe85Sahl# information: Portions Copyright [yyyy] [name of copyright owner]
199512fe85Sahl#
209512fe85Sahl# CDDL HEADER END
219512fe85Sahl#
229512fe85Sahl
239512fe85Sahl#
249512fe85Sahl# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
259512fe85Sahl# Use is subject to license terms.
269512fe85Sahl#
272b6e762cSahl# ident	"%Z%%M%	%I%	%E% SMI"
289512fe85Sahl
299512fe85Sahlrequire 5.6.1;
309512fe85Sahl
319512fe85Sahluse File::Find;
329512fe85Sahluse File::Basename;
339512fe85Sahluse Getopt::Std;
349512fe85Sahluse Cwd;
35*23b5c241Stomeeuse Cwd 'abs_path';
369512fe85Sahl
379512fe85Sahl$PNAME = $0;
389512fe85Sahl$PNAME =~ s:.*/::;
39*23b5c241Stomee$OPTSTR = 'abd:ghi:lqsux:';
409512fe85Sahl$USAGE = "Usage: $PNAME [-abghlqsu] [-d dir] [-i isa] "
419512fe85Sahl    . "[-x opt[=arg]] [file | dir ...]\n";
429512fe85Sahl($MACH = `uname -p`) =~ s/\W*\n//;
439512fe85Sahl
449512fe85Sahl$dtrace_path = '/usr/sbin/dtrace';
459512fe85Sahl@dtrace_argv = ();
469512fe85Sahl
479512fe85Sahl$ksh_path = '/usr/bin/ksh';
489512fe85Sahl
499512fe85Sahl@files = ();
50*23b5c241Stomee%exceptions = ();
519512fe85Sahl$errs = 0;
529512fe85Sahl$bypassed = 0;
539512fe85Sahl
549512fe85Sahl#
559512fe85Sahl# If no test files are specified on the command-line, execute a find on "."
569512fe85Sahl# and append any tst.*.d, tst.*.ksh, err.*.d or drp.*.d files found within
579512fe85Sahl# the directory tree.
589512fe85Sahl#
599512fe85Sahlsub wanted
609512fe85Sahl{
619512fe85Sahl	push(@files, $File::Find::name)
629512fe85Sahl	    if ($_ =~ /^(tst|err|drp)\..+\.(d|ksh)$/ && -f "$_");
639512fe85Sahl}
649512fe85Sahl
659512fe85Sahlsub dirname {
669512fe85Sahl	my($s) = @_;
679512fe85Sahl	my($i);
689512fe85Sahl
699512fe85Sahl	$s = substr($s, 0, $i) if (($i = rindex($s, '/')) != -1);
709512fe85Sahl	return $i == -1 ? '.' : $i == 0 ? '/' : $s;
719512fe85Sahl}
729512fe85Sahl
739512fe85Sahlsub usage
749512fe85Sahl{
759512fe85Sahl	print $USAGE;
769512fe85Sahl	print "\t -a  execute test suite using anonymous enablings\n";
779512fe85Sahl	print "\t -b  execute bad ioctl test program\n";
789512fe85Sahl	print "\t -d  specify directory for test results files and cores\n";
799512fe85Sahl	print "\t -g  enable libumem debugging when running tests\n";
809512fe85Sahl	print "\t -h  display verbose usage message\n";
819512fe85Sahl	print "\t -i  specify ISA to test instead of isaexec(3C) default\n";
829512fe85Sahl	print "\t -l  save log file of results and PIDs used by tests\n";
839512fe85Sahl	print "\t -q  set quiet mode (only report errors and summary)\n";
849512fe85Sahl	print "\t -s  save results files even for tests that pass\n";
859512fe85Sahl	print "\t -x  pass corresponding -x argument to dtrace(1M)\n";
86*23b5c241Stomee	print "\n\tUse \"-i java\" to run tests using the ";
87*23b5c241Stomee	print "Java DTrace API.\n";
889512fe85Sahl	exit(2);
899512fe85Sahl}
909512fe85Sahl
919512fe85Sahlsub errmsg
929512fe85Sahl{
939512fe85Sahl	my($msg) = @_;
949512fe85Sahl
959512fe85Sahl	print STDERR $msg;
969512fe85Sahl	print LOG $msg if ($opt_l);
979512fe85Sahl	$errs++;
989512fe85Sahl}
999512fe85Sahl
1009512fe85Sahlsub fail
1019512fe85Sahl{
1029512fe85Sahl	my(@parms) = @_;
1039512fe85Sahl	my($msg) = $parms[0];
1049512fe85Sahl	my($errfile) = $parms[1];
1059512fe85Sahl	my($n) = 0;
1069512fe85Sahl	my($dest) = basename($file);
1079512fe85Sahl
1089512fe85Sahl	while (-d "$opt_d/failure.$n") {
1099512fe85Sahl		$n++;
1109512fe85Sahl	}
1119512fe85Sahl
1129512fe85Sahl	unless (mkdir "$opt_d/failure.$n") {
1139512fe85Sahl		warn "ERROR: failed to make directory $opt_d/failure.$n: $!\n";
1149512fe85Sahl		exit(125);
1159512fe85Sahl	}
1169512fe85Sahl
1179512fe85Sahl	open(README, ">$opt_d/failure.$n/README");
1189512fe85Sahl	print README "ERROR: " . $file . " " . $msg;
1199512fe85Sahl
1209512fe85Sahl	if (scalar @parms > 1) {
1219512fe85Sahl		print README "; see $errfile\n";
1229512fe85Sahl	} else {
1239512fe85Sahl		if (-f "$opt_d/$pid.core") {
1249512fe85Sahl			print README "; see $pid.core\n";
1259512fe85Sahl		} else {
1269512fe85Sahl			print README "\n";
1279512fe85Sahl		}
1289512fe85Sahl	}
1299512fe85Sahl
1309512fe85Sahl	close(README);
1319512fe85Sahl
1329512fe85Sahl	if (-f "$opt_d/$pid.out") {
1339512fe85Sahl		rename("$opt_d/$pid.out", "$opt_d/failure.$n/$pid.out");
1349512fe85Sahl		link("$file.out", "$opt_d/failure.$n/$dest.out");
1359512fe85Sahl	}
1369512fe85Sahl
1379512fe85Sahl	if (-f "$opt_d/$pid.err") {
1389512fe85Sahl		rename("$opt_d/$pid.err", "$opt_d/failure.$n/$pid.err");
1399512fe85Sahl		link("$file.err", "$opt_d/failure.$n/$dest.err");
1409512fe85Sahl	}
1419512fe85Sahl
1429512fe85Sahl	if (-f "$opt_d/$pid.core") {
1439512fe85Sahl		rename("$opt_d/$pid.core", "$opt_d/failure.$n/$pid.core");
1449512fe85Sahl	}
1459512fe85Sahl
1469512fe85Sahl	link("$file", "$opt_d/failure.$n/$dest");
1479512fe85Sahl
1489512fe85Sahl	$msg = "ERROR: " . $dest . " " . $msg;
1499512fe85Sahl
1509512fe85Sahl	if (scalar @parms > 1) {
1519512fe85Sahl		$msg = $msg . "; see $errfile in failure.$n\n";
1529512fe85Sahl	} else {
1539512fe85Sahl		$msg = $msg . "; details in failure.$n\n";
1549512fe85Sahl	}
1559512fe85Sahl
1569512fe85Sahl	errmsg($msg);
1579512fe85Sahl}
1589512fe85Sahl
1599512fe85Sahlsub logmsg
1609512fe85Sahl{
1619512fe85Sahl	my($msg) = @_;
1629512fe85Sahl
1639512fe85Sahl	print STDOUT $msg unless ($opt_q);
1649512fe85Sahl	print LOG $msg if ($opt_l);
1659512fe85Sahl}
1669512fe85Sahl
167*23b5c241Stomee# Trim leading and trailing whitespace
168*23b5c241Stomeesub trim {
169*23b5c241Stomee	my($s) = @_;
170*23b5c241Stomee
171*23b5c241Stomee	$s =~ s/^\s*//;
172*23b5c241Stomee	$s =~ s/\s*$//;
173*23b5c241Stomee	return $s;
174*23b5c241Stomee}
175*23b5c241Stomee
176*23b5c241Stomee# Loads exception set of skipped tests
177*23b5c241Stomeesub load_exceptions {
178*23b5c241Stomee	my($listfile) = @_;
179*23b5c241Stomee	my($line) = "";
180*23b5c241Stomee
181*23b5c241Stomee	exit(123) unless open(STDIN, "<$listfile");
182*23b5c241Stomee	while (<STDIN>) {
183*23b5c241Stomee		chomp;
184*23b5c241Stomee		$line = $_;
185*23b5c241Stomee		# line is non-empty and not a comment
186*23b5c241Stomee		if ((length($line) > 0) && ($line =~ /^\s*[^\s#]/ )) {
187*23b5c241Stomee			$exceptions{trim($line)} = 1;
188*23b5c241Stomee		}
189*23b5c241Stomee	}
190*23b5c241Stomee	return 0;
191*23b5c241Stomee}
192*23b5c241Stomee
193*23b5c241Stomee# Return 1 if file name found in exception set, 0 otherwise
194*23b5c241Stomeesub is_exception {
195*23b5c241Stomee	my($file) = @_;
196*23b5c241Stomee	my($i) = -1;
197*23b5c241Stomee
198*23b5c241Stomee	# hash absolute pathname after $dt_tst/
199*23b5c241Stomee	$file = abs_path($file);
200*23b5c241Stomee	$i = index($file, $dt_tst);
201*23b5c241Stomee	if ($i == 0) {
202*23b5c241Stomee		$file = substr($file, length($dt_tst) + 1);
203*23b5c241Stomee		return $exceptions{$file};
204*23b5c241Stomee	}
205*23b5c241Stomee	return 0;
206*23b5c241Stomee}
207*23b5c241Stomee
208*23b5c241Stomeedie $USAGE unless (getopts($OPTSTR));
2099512fe85Sahlusage() if ($opt_h);
2109512fe85Sahl
2119512fe85Sahlforeach $arg (@ARGV) {
2129512fe85Sahl	if (-f $arg) {
2139512fe85Sahl		push(@files, $arg);
2149512fe85Sahl	} elsif (-d $arg) {
2159512fe85Sahl		find(\&wanted, $arg);
2169512fe85Sahl	} else {
2179512fe85Sahl		die "$PNAME: $arg is not a valid file or directory\n";
2189512fe85Sahl	}
2199512fe85Sahl}
2209512fe85Sahl
221*23b5c241Stomee$dt_tst = '/opt/SUNWdtrt/tst';
222*23b5c241Stomee$dt_bin = '/opt/SUNWdtrt/bin';
223*23b5c241Stomee$defdir = -d $dt_tst ? $dt_tst : '.';
224*23b5c241Stomee$bindir = -d $dt_bin ? $dt_bin : '.';
2259512fe85Sahl
2269512fe85Sahlfind(\&wanted, "$defdir/common") if (scalar(@ARGV) == 0);
2279512fe85Sahlfind(\&wanted, "$defdir/$MACH") if (scalar(@ARGV) == 0);
2289512fe85Sahldie $USAGE if (scalar(@files) == 0);
2299512fe85Sahl
2309512fe85Sahlif ($opt_d) {
2319512fe85Sahl	die "$PNAME: -d arg must be absolute path\n" unless ($opt_d =~ /^\//);
2329512fe85Sahl	die "$PNAME: -d arg $opt_d is not a directory\n" unless (-d "$opt_d");
2339512fe85Sahl	system("coreadm -p $opt_d/%p.core");
2349512fe85Sahl} else {
2359512fe85Sahl	my $dir = getcwd;
2369512fe85Sahl	system("coreadm -p $dir/%p.core");
2379512fe85Sahl	$opt_d = '.';
2389512fe85Sahl}
2399512fe85Sahl
2409512fe85Sahlif ($opt_i) {
241*23b5c241Stomee	if ($opt_i eq "java") {
242*23b5c241Stomee		$dtrace_path = $bindir . "/jdtrace";
243*23b5c241Stomee		die "$PNAME: jdtrace not found\n"
244*23b5c241Stomee		    unless (-x "$dtrace_path");
245*23b5c241Stomee		load_exceptions($bindir . "/exception.lst");
246*23b5c241Stomee	} else {
247*23b5c241Stomee		$dtrace_path = "/usr/sbin/$opt_i/dtrace";
248*23b5c241Stomee		die "$PNAME: dtrace(1M) for ISA $opt_i not found\n"
249*23b5c241Stomee		    unless (-x "$dtrace_path");
250*23b5c241Stomee	}
2519512fe85Sahl}
2529512fe85Sahl
2539512fe85Sahlif ($opt_x) {
2549512fe85Sahl	push(@dtrace_argv, '-x');
2559512fe85Sahl	push(@dtrace_argv, $opt_x);
2569512fe85Sahl}
2579512fe85Sahl
2589512fe85Sahldie "$PNAME: failed to open $PNAME.$$.log: $!\n"
2599512fe85Sahl    unless (!$opt_l || open(LOG, ">$PNAME.$$.log"));
2609512fe85Sahl
2619512fe85Sahlif ($opt_g) {
2629512fe85Sahl	$ENV{'UMEM_DEBUG'} = 'default,verbose';
2639512fe85Sahl	$ENV{'UMEM_LOGGING'} = 'fail,contents';
2649512fe85Sahl	$ENV{'LD_PRELOAD'} = 'libumem.so';
2659512fe85Sahl}
2669512fe85Sahl
2679512fe85Sahl#
2689512fe85Sahl# Ensure that $PATH contains a cc(1) so that we can execute the
2699512fe85Sahl# test programs that require compilation of C code.
2709512fe85Sahl#
2712b6e762cSahl$ENV{'PATH'} = $ENV{'PATH'} . ':/ws/onnv-tools/SUNWspro/SS11/bin';
2729512fe85Sahl
2739512fe85Sahlif ($opt_b) {
2749512fe85Sahl	logmsg("badioctl'ing ... ");
2759512fe85Sahl
2769512fe85Sahl	if (($badioctl = fork()) == -1) {
2779512fe85Sahl		errmsg("ERROR: failed to fork to run badioctl: $!\n");
2789512fe85Sahl		next;
2799512fe85Sahl	}
2809512fe85Sahl
2819512fe85Sahl	if ($badioctl == 0) {
2829512fe85Sahl		open(STDIN, '</dev/null');
2839512fe85Sahl		exit(125) unless open(STDOUT, ">$opt_d/$$.out");
2849512fe85Sahl		exit(125) unless open(STDERR, ">$opt_d/$$.err");
2859512fe85Sahl
2869512fe85Sahl		exec($bindir . "/badioctl");
2879512fe85Sahl		warn "ERROR: failed to exec badioctl: $!\n";
2889512fe85Sahl		exit(127);
2899512fe85Sahl	}
2909512fe85Sahl
2919512fe85Sahl
2929512fe85Sahl	logmsg("[$badioctl]\n");
2939512fe85Sahl
2949512fe85Sahl	#
2959512fe85Sahl	# If we're going to be bad, we're just going to iterate over each
2969512fe85Sahl	# test file.
2979512fe85Sahl	#
2989512fe85Sahl	foreach $file (sort @files) {
2999512fe85Sahl		($name = $file) =~ s:.*/::;
3009512fe85Sahl		$dir = dirname($file);
3019512fe85Sahl
3029512fe85Sahl		if (!($name =~ /^tst\./ && $name =~ /\.d$/)) {
3039512fe85Sahl			next;
3049512fe85Sahl		}
3059512fe85Sahl
3069512fe85Sahl		logmsg("baddof'ing $file ... ");
3079512fe85Sahl
3089512fe85Sahl		if (($pid = fork()) == -1) {
3099512fe85Sahl			errmsg("ERROR: failed to fork to run baddof: $!\n");
3109512fe85Sahl			next;
3119512fe85Sahl		}
3129512fe85Sahl
3139512fe85Sahl		if ($pid == 0) {
3149512fe85Sahl			open(STDIN, '</dev/null');
3159512fe85Sahl			exit(125) unless open(STDOUT, ">$opt_d/$$.out");
3169512fe85Sahl			exit(125) unless open(STDERR, ">$opt_d/$$.err");
3179512fe85Sahl
3189512fe85Sahl			unless (chdir($dir)) {
3199512fe85Sahl				warn "ERROR: failed to chdir for $file: $!\n";
3209512fe85Sahl				exit(126);
3219512fe85Sahl			}
3229512fe85Sahl
3239512fe85Sahl			exec($bindir . "/baddof", $name);
3249512fe85Sahl
3259512fe85Sahl			warn "ERROR: failed to exec for $file: $!\n";
3269512fe85Sahl			exit(127);
3279512fe85Sahl		}
3289512fe85Sahl
3299512fe85Sahl		sleep 60;
3309512fe85Sahl		kill(9, $pid);
3319512fe85Sahl		waitpid($pid, 0);
3329512fe85Sahl
3339512fe85Sahl		logmsg("[$pid]\n");
3349512fe85Sahl
3359512fe85Sahl		unless ($opt_s) {
3369512fe85Sahl			unlink($pid . '.out');
3379512fe85Sahl			unlink($pid . '.err');
3389512fe85Sahl		}
3399512fe85Sahl	}
3409512fe85Sahl
3419512fe85Sahl	kill(9, $badioctl);
3429512fe85Sahl	waitpid($badioctl, 0);
3439512fe85Sahl
3449512fe85Sahl	unless ($opt_s) {
3459512fe85Sahl		unlink($badioctl . '.out');
3469512fe85Sahl		unlink($badioctl . '.err');
3479512fe85Sahl	}
3489512fe85Sahl
3499512fe85Sahl	exit(0);
3509512fe85Sahl}
3519512fe85Sahl
3529512fe85Sahlif ($opt_u) {
3539512fe85Sahl	logmsg "spawning module unloading process... ";
3549512fe85Sahl
3559512fe85Sahl	$unloader = fork;
3569512fe85Sahl
3579512fe85Sahl	if ($unloader != 0 && !defined $unloader) {
3589512fe85Sahl		#
3599512fe85Sahl		# Couldn't fork for some reason.
3609512fe85Sahl		#
3619512fe85Sahl		die "couldn't fork: $!\n";
3629512fe85Sahl	}
3639512fe85Sahl
3649512fe85Sahl	if ($unloader == 0) {
3659512fe85Sahl		#
3669512fe85Sahl		# We're in the child.  Go modunload krazy.
3679512fe85Sahl		#
3689512fe85Sahl		for (;;) {
3699512fe85Sahl			system("modunload -i 0");
3709512fe85Sahl		}
3719512fe85Sahl	} else {
3729512fe85Sahl		logmsg "[$unloader]\n";
3739512fe85Sahl
3749512fe85Sahl		$SIG{INT} = sub {
3759512fe85Sahl			kill 9, $unloader;
3769512fe85Sahl			exit($errs != 0);
3779512fe85Sahl		};
3789512fe85Sahl	}
3799512fe85Sahl}
3809512fe85Sahl
3819512fe85Sahl#
3829512fe85Sahl# Iterate over the set of test files specified on the command-line or located
3839512fe85Sahl# by a find on "." and execute each one.  If the test file is executable, we
3849512fe85Sahl# assume it is a #! script and run it.  Otherwise we run dtrace -s on it.
3859512fe85Sahl# If the file is named tst.* we assume it should return exit status 0.
3869512fe85Sahl# If the file is named err.* we assume it should return exit status 1.
3879512fe85Sahl# If the file is named err.D_[A-Z0-9]+[.*].d we use dtrace -xerrtags and
3889512fe85Sahl# examine stderr to ensure that a matching error tag was produced.
3899512fe85Sahl# If the file is named drp.[A-Z0-9]+[.*].d we use dtrace -xdroptags and
3909512fe85Sahl# examine stderr to ensure that a matching drop tag was produced.
3919512fe85Sahl# If any *.out or *.err files are found we perform output comparisons.
3929512fe85Sahl#
3939512fe85Sahlforeach $file (sort @files) {
3949512fe85Sahl	$file =~ m:.*/((.*)\.(\w+)):;
3959512fe85Sahl	$name = $1;
3969512fe85Sahl	$base = $2;
3979512fe85Sahl	$ext = $3;
3989512fe85Sahl
3999512fe85Sahl	$dir = dirname($file);
4009512fe85Sahl	$isksh = 0;
4019512fe85Sahl	$tag = 0;
4029512fe85Sahl	$droptag = 0;
4039512fe85Sahl
4049512fe85Sahl	if ($name =~ /^tst\./) {
4059512fe85Sahl		$isksh = ($ext eq 'ksh');
4069512fe85Sahl		$status = 0;
4079512fe85Sahl	} elsif ($name =~ /^err\.(D_[A-Z0-9_]+)\./) {
4089512fe85Sahl		$status = 1;
4099512fe85Sahl		$tag = $1;
4109512fe85Sahl	} elsif ($name =~ /^err\./) {
4119512fe85Sahl		$status = 1;
4129512fe85Sahl	} elsif ($name =~ /^drp\.([A-Z0-9_]+)\./) {
4139512fe85Sahl		$status = 0;
4149512fe85Sahl		$droptag = $1;
4159512fe85Sahl	} else {
4169512fe85Sahl		errmsg("ERROR: $file is not a valid test file name\n");
4179512fe85Sahl		next;
4189512fe85Sahl	}
4199512fe85Sahl
4209512fe85Sahl	$fullname = "$dir/$name";
4219512fe85Sahl	$exe = "$dir/$base.exe";
4229512fe85Sahl	$exe_pid = -1;
4239512fe85Sahl
4249512fe85Sahl	if ($opt_a && ($status != 0 || $tag != 0 || $droptag != 0 ||
4259512fe85Sahl	    -x $exe || $isksh || -x $fullname)) {
4269512fe85Sahl		$bypassed++;
4279512fe85Sahl		next;
4289512fe85Sahl	}
4299512fe85Sahl
430*23b5c241Stomee	if ($opt_i eq "java") {
431*23b5c241Stomee		if (is_exception("$dir/$name")) {
432*23b5c241Stomee			$bypassed++;
433*23b5c241Stomee			next;
434*23b5c241Stomee		}
435*23b5c241Stomee	}
436*23b5c241Stomee
4379512fe85Sahl	if (!$isksh && -x $exe) {
4389512fe85Sahl		if (($exe_pid = fork()) == -1) {
4399512fe85Sahl			errmsg("ERROR: failed to fork to run $exe: $!\n");
4409512fe85Sahl			next;
4419512fe85Sahl		}
4429512fe85Sahl
4439512fe85Sahl		if ($exe_pid == 0) {
4449512fe85Sahl			open(STDIN, '</dev/null');
4459512fe85Sahl
4469512fe85Sahl			exec($exe);
4479512fe85Sahl
4489512fe85Sahl			warn "ERROR: failed to exec $exe: $!\n";
4499512fe85Sahl		}
4509512fe85Sahl	}
4519512fe85Sahl
4529512fe85Sahl	logmsg("testing $file ... ");
4539512fe85Sahl
4549512fe85Sahl	if (($pid = fork()) == -1) {
4559512fe85Sahl		errmsg("ERROR: failed to fork to run test $file: $!\n");
4569512fe85Sahl		next;
4579512fe85Sahl	}
4589512fe85Sahl
4599512fe85Sahl	if ($pid == 0) {
4609512fe85Sahl		open(STDIN, '</dev/null');
4619512fe85Sahl		exit(125) unless open(STDOUT, ">$opt_d/$$.out");
4629512fe85Sahl		exit(125) unless open(STDERR, ">$opt_d/$$.err");
4639512fe85Sahl
4649512fe85Sahl		unless (chdir($dir)) {
4659512fe85Sahl			warn "ERROR: failed to chdir for $file: $!\n";
4669512fe85Sahl			exit(126);
4679512fe85Sahl		}
4689512fe85Sahl
4699512fe85Sahl		push(@dtrace_argv, '-xerrtags') if ($tag);
4709512fe85Sahl		push(@dtrace_argv, '-xdroptags') if ($droptag);
4719512fe85Sahl		push(@dtrace_argv, $exe_pid) if ($exe_pid != -1);
4729512fe85Sahl
4739512fe85Sahl		if ($isksh) {
4749512fe85Sahl			exit(123) unless open(STDIN, "<$name");
475*23b5c241Stomee			exec("$ksh_path /dev/stdin $dtrace_path");
4769512fe85Sahl		} elsif (-x $name) {
4779512fe85Sahl		        warn "ERROR: $name is executable\n";
4789512fe85Sahl			exit(1);
4799512fe85Sahl		} else {
4809512fe85Sahl			if ($tag == 0 && $status == $0 && $opt_a) {
4819512fe85Sahl				push(@dtrace_argv, '-A');
4829512fe85Sahl			}
4839512fe85Sahl
4849512fe85Sahl			push(@dtrace_argv, '-C');
4859512fe85Sahl			push(@dtrace_argv, '-s');
4869512fe85Sahl			push(@dtrace_argv, $name);
4879512fe85Sahl			exec($dtrace_path, @dtrace_argv);
4889512fe85Sahl		}
4899512fe85Sahl
4909512fe85Sahl		warn "ERROR: failed to exec for $file: $!\n";
4919512fe85Sahl		exit(127);
4929512fe85Sahl	}
4939512fe85Sahl
4949512fe85Sahl	if (waitpid($pid, 0) == -1) {
4959512fe85Sahl		errmsg("ERROR: timed out waiting for $file\n");
4969512fe85Sahl		kill(9, $exe_pid) if ($exe_pid != -1);
4979512fe85Sahl		kill(9, $pid);
4989512fe85Sahl		next;
4999512fe85Sahl	}
5009512fe85Sahl
5019512fe85Sahl	kill(9, $exe_pid) if ($exe_pid != -1);
5029512fe85Sahl
5039512fe85Sahl	if ($tag == 0 && $status == $0 && $opt_a) {
5049512fe85Sahl		#
5059512fe85Sahl		# We can chuck the earler output.
5069512fe85Sahl		#
5079512fe85Sahl		unlink($pid . '.out');
5089512fe85Sahl		unlink($pid . '.err');
5099512fe85Sahl
5109512fe85Sahl		#
5119512fe85Sahl		# This is an anonymous enabling.  We need to get the module
5129512fe85Sahl		# unloaded.
5139512fe85Sahl		#
5149512fe85Sahl		system("dtrace -ae 1> /dev/null 2> /dev/null");
5159512fe85Sahl		system("svcadm disable -s svc:/network/nfs/mapid:default");
5169512fe85Sahl		system("modunload -i 0 ; modunload -i 0 ; modunload -i 0");
5179512fe85Sahl		if (!system("modinfo | grep dtrace")) {
5189512fe85Sahl			warn "ERROR: couldn't unload dtrace\n";
5199512fe85Sahl			system("svcadm enable " .
5209512fe85Sahl			    "-s svc:/network/nfs/mapid:default");
5219512fe85Sahl			exit(124);
5229512fe85Sahl		}
5239512fe85Sahl
5249512fe85Sahl		#
5259512fe85Sahl		# DTrace is gone.  Now update_drv(1M), and rip everything out
5269512fe85Sahl		# again.
5279512fe85Sahl		#
5289512fe85Sahl		system("update_drv dtrace");
5299512fe85Sahl		system("dtrace -ae 1> /dev/null 2> /dev/null");
5309512fe85Sahl		system("modunload -i 0 ; modunload -i 0 ; modunload -i 0");
5319512fe85Sahl		if (!system("modinfo | grep dtrace")) {
5329512fe85Sahl			warn "ERROR: couldn't unload dtrace\n";
5339512fe85Sahl			system("svcadm enable " .
5349512fe85Sahl			    "-s svc:/network/nfs/mapid:default");
5359512fe85Sahl			exit(124);
5369512fe85Sahl		}
5379512fe85Sahl
5389512fe85Sahl		#
5399512fe85Sahl		# Now bring DTrace back in.
5409512fe85Sahl		#
5419512fe85Sahl		system("sync ; sync");
5429512fe85Sahl		system("dtrace -l -n bogusprobe 1> /dev/null 2> /dev/null");
5439512fe85Sahl		system("svcadm enable -s svc:/network/nfs/mapid:default");
5449512fe85Sahl
5459512fe85Sahl		#
5469512fe85Sahl		# That should have caused DTrace to reload with the new
5479512fe85Sahl		# configuration file.  Now we can try to snag our anonymous
5489512fe85Sahl		# state.
5499512fe85Sahl		#
5509512fe85Sahl		if (($pid = fork()) == -1) {
5519512fe85Sahl			errmsg("ERROR: failed to fork to run test $file: $!\n");
5529512fe85Sahl			next;
5539512fe85Sahl		}
5549512fe85Sahl
5559512fe85Sahl		if ($pid == 0) {
5569512fe85Sahl			open(STDIN, '</dev/null');
5579512fe85Sahl			exit(125) unless open(STDOUT, ">$opt_d/$$.out");
5589512fe85Sahl			exit(125) unless open(STDERR, ">$opt_d/$$.err");
5599512fe85Sahl
5609512fe85Sahl			push(@dtrace_argv, '-a');
5619512fe85Sahl
5629512fe85Sahl			unless (chdir($dir)) {
5639512fe85Sahl				warn "ERROR: failed to chdir for $file: $!\n";
5649512fe85Sahl				exit(126);
5659512fe85Sahl			}
5669512fe85Sahl
5679512fe85Sahl			exec($dtrace_path, @dtrace_argv);
5689512fe85Sahl			warn "ERROR: failed to exec for $file: $!\n";
5699512fe85Sahl			exit(127);
5709512fe85Sahl		}
5719512fe85Sahl
5729512fe85Sahl		if (waitpid($pid, 0) == -1) {
5739512fe85Sahl			errmsg("ERROR: timed out waiting for $file\n");
5749512fe85Sahl			kill(9, $pid);
5759512fe85Sahl			next;
5769512fe85Sahl		}
5779512fe85Sahl	}
5789512fe85Sahl
5799512fe85Sahl	logmsg("[$pid]\n");
5809512fe85Sahl	$wstat = $?;
5819512fe85Sahl	$wifexited = ($wstat & 0xFF) == 0;
5829512fe85Sahl	$wexitstat = ($wstat >> 8) & 0xFF;
5839512fe85Sahl	$wtermsig = ($wstat & 0x7F);
5849512fe85Sahl
5859512fe85Sahl	if (!$wifexited) {
5869512fe85Sahl		fail("died from signal $wtermsig");
5879512fe85Sahl		next;
5889512fe85Sahl	}
5899512fe85Sahl
5909512fe85Sahl	if ($wexitstat == 125) {
5919512fe85Sahl		die "$PNAME: failed to create output file in $opt_d " .
5929512fe85Sahl		    "(cd elsewhere or use -d)\n";
5939512fe85Sahl	}
5949512fe85Sahl
5959512fe85Sahl	if ($wexitstat != $status) {
5969512fe85Sahl		fail("returned $wexitstat instead of $status");
5979512fe85Sahl		next;
5989512fe85Sahl	}
5999512fe85Sahl
6009512fe85Sahl	if (-f "$file.out" && system("cmp -s $file.out $opt_d/$pid.out") != 0) {
6019512fe85Sahl		fail("stdout mismatch", "$pid.out");
6029512fe85Sahl		next;
6039512fe85Sahl	}
6049512fe85Sahl
6059512fe85Sahl	if (-f "$file.err" && system("cmp -s $file.err $opt_d/$pid.err") != 0) {
6069512fe85Sahl		fail("stderr mismatch: see $pid.err");
6079512fe85Sahl		next;
6089512fe85Sahl	}
6099512fe85Sahl
6109512fe85Sahl	if ($tag) {
6119512fe85Sahl		open(TSTERR, "<$opt_d/$pid.err");
6129512fe85Sahl		$tsterr = <TSTERR>;
6139512fe85Sahl		close(TSTERR);
6149512fe85Sahl
6159512fe85Sahl		unless ($tsterr =~ /: \[$tag\] line \d+:/) {
6169512fe85Sahl			fail("errtag mismatch: see $pid.err");
6179512fe85Sahl			next;
6189512fe85Sahl		}
6199512fe85Sahl	}
6209512fe85Sahl
6219512fe85Sahl	if ($droptag) {
6229512fe85Sahl		$found = 0;
6239512fe85Sahl		open(TSTERR, "<$opt_d/$pid.err");
6249512fe85Sahl
6259512fe85Sahl		while (<TSTERR>) {
6269512fe85Sahl			if (/\[$droptag\] /) {
6279512fe85Sahl				$found = 1;
6289512fe85Sahl				last;
6299512fe85Sahl			}
6309512fe85Sahl		}
6319512fe85Sahl
6329512fe85Sahl		close (TSTERR);
6339512fe85Sahl
6349512fe85Sahl		unless ($found) {
6359512fe85Sahl			fail("droptag mismatch: see $pid.err");
6369512fe85Sahl			next;
6379512fe85Sahl		}
6389512fe85Sahl	}
6399512fe85Sahl
6409512fe85Sahl	unless ($opt_s) {
6419512fe85Sahl		unlink($pid . '.out');
6429512fe85Sahl		unlink($pid . '.err');
6439512fe85Sahl	}
6449512fe85Sahl}
6459512fe85Sahl
6469512fe85Sahlif ($opt_a) {
6479512fe85Sahl	#
6489512fe85Sahl	# If we're running with anonymous enablings, we need to restore the
6499512fe85Sahl	# .conf file.
6509512fe85Sahl	#
6519512fe85Sahl	system("dtrace -A 1> /dev/null 2> /dev/null");
6529512fe85Sahl	system("dtrace -ae 1> /dev/null 2> /dev/null");
6539512fe85Sahl	system("modunload -i 0 ; modunload -i 0 ; modunload -i 0");
6549512fe85Sahl	system("update_drv dtrace");
6559512fe85Sahl}
6569512fe85Sahl
6579512fe85Sahl$opt_q = 0; # force final summary to appear regardless of -q option
6589512fe85Sahl
6599512fe85Sahllogmsg("\n==== TEST RESULTS ====\n");
6609512fe85Sahllogmsg("   passed: " . (scalar(@files) - $errs - $bypassed) . "\n");
6619512fe85Sahl
6629512fe85Sahlif ($bypassed) {
6639512fe85Sahl	logmsg(" bypassed: " . $bypassed . "\n");
6649512fe85Sahl}
6659512fe85Sahl
6669512fe85Sahllogmsg("   failed: " . $errs . "\n");
6679512fe85Sahllogmsg("    total: " . scalar(@files) . "\n");
6689512fe85Sahl
6699512fe85Sahlif ($opt_u) {
6709512fe85Sahl	kill 9, $unloader;
6719512fe85Sahl	waitpid $unloader, 0;
6729512fe85Sahl}
6739512fe85Sahl
6749512fe85Sahlexit($errs != 0);
675